diff options
Diffstat (limited to 'hw')
120 files changed, 2200 insertions, 734 deletions
diff --git a/hw/9pfs/9p-proxy.h b/hw/9pfs/9p-proxy.h index ba9ca203de..b84301d001 100644 --- a/hw/9pfs/9p-proxy.h +++ b/hw/9pfs/9p-proxy.h @@ -9,8 +9,9 @@ * This work is licensed under the terms of the GNU GPL, version 2. See * the COPYING file in the top-level directory. */ -#ifndef _QEMU_9P_PROXY_H -#define _QEMU_9P_PROXY_H + +#ifndef QEMU_9P_PROXY_H +#define QEMU_9P_PROXY_H #define PROXY_MAX_IO_SZ (64 * 1024) #define V9FS_FD_VALID INT_MAX diff --git a/hw/9pfs/9p-synth.h b/hw/9pfs/9p-synth.h index 7c8441bd6c..6bcb44ace2 100644 --- a/hw/9pfs/9p-synth.h +++ b/hw/9pfs/9p-synth.h @@ -10,9 +10,9 @@ * the COPYING file in the top-level directory. * */ -#ifndef HW_9PFS_SYNTH_H -#define HW_9PFS_SYNTH_H 1 +#ifndef QEMU_9P_SYNTH_H +#define QEMU_9P_SYNTH_H typedef struct V9fsSynthNode V9fsSynthNode; typedef ssize_t (*v9fs_synth_read)(void *buf, int len, off_t offset, diff --git a/hw/9pfs/9p-xattr.h b/hw/9pfs/9p-xattr.h index 4d39a20262..a853ea641c 100644 --- a/hw/9pfs/9p-xattr.h +++ b/hw/9pfs/9p-xattr.h @@ -10,8 +10,9 @@ * the COPYING file in the top-level directory. * */ -#ifndef _QEMU_9P_XATTR_H -#define _QEMU_9P_XATTR_H + +#ifndef QEMU_9P_XATTR_H +#define QEMU_9P_XATTR_H #include "qemu/xattr.h" diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c index 9acff9293c..b6b02b46a9 100644 --- a/hw/9pfs/9p.c +++ b/hw/9pfs/9p.c @@ -3278,8 +3278,8 @@ void pdu_submit(V9fsPDU *pdu) if (is_ro_export(&s->ctx) && !is_read_only_op(pdu)) { handler = v9fs_fs_ro; } - co = qemu_coroutine_create(handler); - qemu_coroutine_enter(co, pdu); + co = qemu_coroutine_create(handler, pdu); + qemu_coroutine_enter(co); } /* Returns 0 on success, 1 on failure. */ diff --git a/hw/9pfs/9p.h b/hw/9pfs/9p.h index d2030fdf56..b4f757ab54 100644 --- a/hw/9pfs/9p.h +++ b/hw/9pfs/9p.h @@ -1,5 +1,5 @@ -#ifndef _QEMU_9P_H -#define _QEMU_9P_H +#ifndef QEMU_9P_H +#define QEMU_9P_H #include <dirent.h> #include <utime.h> diff --git a/hw/9pfs/coth.c b/hw/9pfs/coth.c index 9b1151b60e..89018de6bf 100644 --- a/hw/9pfs/coth.c +++ b/hw/9pfs/coth.c @@ -22,14 +22,14 @@ static void coroutine_enter_cb(void *opaque, int ret) { Coroutine *co = opaque; - qemu_coroutine_enter(co, NULL); + qemu_coroutine_enter(co); } /* Called from worker thread. */ static int coroutine_enter_func(void *arg) { Coroutine *co = arg; - qemu_coroutine_enter(co, NULL); + qemu_coroutine_enter(co); return 0; } diff --git a/hw/9pfs/coth.h b/hw/9pfs/coth.h index 5b02a63ad9..3c7424e423 100644 --- a/hw/9pfs/coth.h +++ b/hw/9pfs/coth.h @@ -12,8 +12,8 @@ * */ -#ifndef _QEMU_9P_COTH_H -#define _QEMU_9P_COTH_H +#ifndef QEMU_9P_COTH_H +#define QEMU_9P_COTH_H #include "qemu/thread.h" #include "qemu/coroutine.h" diff --git a/hw/9pfs/virtio-9p.h b/hw/9pfs/virtio-9p.h index 7f6d885539..7586b792d6 100644 --- a/hw/9pfs/virtio-9p.h +++ b/hw/9pfs/virtio-9p.h @@ -1,5 +1,5 @@ -#ifndef _QEMU_VIRTIO_9P_H -#define _QEMU_VIRTIO_9P_H +#ifndef QEMU_VIRTIO_9P_H +#define QEMU_VIRTIO_9P_H #include "standard-headers/linux/virtio_9p.h" #include "hw/virtio/virtio.h" diff --git a/hw/alpha/alpha_sys.h b/hw/alpha/alpha_sys.h index fcaeb2b7aa..ed911f22a1 100644 --- a/hw/alpha/alpha_sys.h +++ b/hw/alpha/alpha_sys.h @@ -1,7 +1,7 @@ /* Alpha cores and system support chips. */ -#ifndef HW_ALPHA_H -#define HW_ALPHA_H 1 +#ifndef HW_ALPHA_SYS_H +#define HW_ALPHA_SYS_H #include "target-alpha/cpu-qom.h" #include "hw/pci/pci.h" diff --git a/hw/arm/strongarm.h b/hw/arm/strongarm.h index cd32bbdb0e..1470eac4f5 100644 --- a/hw/arm/strongarm.h +++ b/hw/arm/strongarm.h @@ -1,5 +1,5 @@ -#ifndef _STRONGARM_H -#define _STRONGARM_H +#ifndef STRONGARM_H +#define STRONGARM_H #include "exec/memory.h" #include "target-arm/cpu-qom.h" diff --git a/hw/audio/fmopl.h b/hw/audio/fmopl.h index 24ba5f4802..fdda7f9f51 100644 --- a/hw/audio/fmopl.h +++ b/hw/audio/fmopl.h @@ -1,5 +1,5 @@ -#ifndef __FMOPL_H_ -#define __FMOPL_H_ +#ifndef FMOPL_H +#define FMOPL_H /* --- select emulation chips --- */ #define BUILD_YM3812 (HAS_YM3812) diff --git a/hw/audio/gusemu.h b/hw/audio/gusemu.h index b7f0751268..9aec7bf8e7 100644 --- a/hw/audio/gusemu.h +++ b/hw/audio/gusemu.h @@ -101,4 +101,4 @@ void gus_irqgen(GUSEmuState *state, unsigned int elapsed_time); /* lower values won´t provide any benefit at all, higher values can cause audible timing delays */ /* note: masked timers are also calculated by this function, thus it might be needed even without any IRQs in use! */ -#endif /* gusemu.h */ +#endif /* GUSEMU_H */ diff --git a/hw/audio/gustate.h b/hw/audio/gustate.h index ece903abb9..d16297110d 100644 --- a/hw/audio/gustate.h +++ b/hw/audio/gustate.h @@ -129,4 +129,4 @@ #define gusdataend (VSRegsEnd+4) -#endif /* gustate.h */ +#endif /* GUSTATE_H */ diff --git a/hw/audio/lm4549.h b/hw/audio/lm4549.h index 812a7a4440..74c3ee8934 100644 --- a/hw/audio/lm4549.h +++ b/hw/audio/lm4549.h @@ -40,4 +40,4 @@ uint32_t lm4549_read(lm4549_state *s, hwaddr offset); void lm4549_write(lm4549_state *s, hwaddr offset, uint32_t value); uint32_t lm4549_write_samples(lm4549_state *s, uint32_t left, uint32_t right); -#endif /* #ifndef HW_LM4549_H */ +#endif /* HW_LM4549_H */ diff --git a/hw/audio/pl041.h b/hw/audio/pl041.h index 427ab6d6f8..515db4756b 100644 --- a/hw/audio/pl041.h +++ b/hw/audio/pl041.h @@ -132,4 +132,4 @@ enum { #define RXTOFEC3 (1 << 11) #define RXTOFEC4 (1 << 12) -#endif /* #ifndef HW_PL041_H */ +#endif /* HW_PL041_H */ diff --git a/hw/block/block.c b/hw/block/block.c index 97a59d4fa2..8dc9d84a39 100644 --- a/hw/block/block.c +++ b/hw/block/block.c @@ -51,6 +51,34 @@ void blkconf_blocksizes(BlockConf *conf) } } +void blkconf_apply_backend_options(BlockConf *conf) +{ + BlockBackend *blk = conf->blk; + BlockdevOnError rerror, werror; + bool wce; + + switch (conf->wce) { + case ON_OFF_AUTO_ON: wce = true; break; + case ON_OFF_AUTO_OFF: wce = false; break; + case ON_OFF_AUTO_AUTO: wce = blk_enable_write_cache(blk); break; + default: + abort(); + } + + rerror = conf->rerror; + if (rerror == BLOCKDEV_ON_ERROR_AUTO) { + rerror = blk_get_on_error(blk, true); + } + + werror = conf->werror; + if (werror == BLOCKDEV_ON_ERROR_AUTO) { + werror = blk_get_on_error(blk, false); + } + + blk_set_enable_write_cache(blk, wce); + blk_set_on_error(blk, rerror, werror); +} + void blkconf_geometry(BlockConf *conf, int *ptrans, unsigned cyls_max, unsigned heads_max, unsigned secs_max, Error **errp) diff --git a/hw/block/nvme.c b/hw/block/nvme.c index 9faad29fad..2ded2475ee 100644 --- a/hw/block/nvme.c +++ b/hw/block/nvme.c @@ -21,10 +21,10 @@ */ #include "qemu/osdep.h" -#include <hw/block/block.h> -#include <hw/hw.h> -#include <hw/pci/msix.h> -#include <hw/pci/pci.h> +#include "hw/block/block.h" +#include "hw/hw.h" +#include "hw/pci/msix.h" +#include "hw/pci/pci.h" #include "sysemu/sysemu.h" #include "qapi/error.h" #include "qapi/visitor.h" @@ -803,6 +803,7 @@ static int nvme_init(PCIDevice *pci_dev) return -1; } blkconf_blocksizes(&n->conf); + blkconf_apply_backend_options(&n->conf); pci_conf = pci_dev->config; pci_conf[PCI_INTERRUPT_PIN] = 1; diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c index ae86e944ea..357ff9081e 100644 --- a/hw/block/virtio-blk.c +++ b/hw/block/virtio-blk.c @@ -897,6 +897,7 @@ static void virtio_blk_device_realize(DeviceState *dev, Error **errp) } blkconf_serial(&conf->conf, &conf->serial); + blkconf_apply_backend_options(&conf->conf); s->original_wce = blk_enable_write_cache(conf->conf.blk); blkconf_geometry(&conf->conf, NULL, 65535, 255, 255, &err); if (err) { @@ -959,6 +960,7 @@ static void virtio_blk_instance_init(Object *obj) static Property virtio_blk_properties[] = { DEFINE_BLOCK_PROPERTIES(VirtIOBlock, conf.conf), + DEFINE_BLOCK_ERROR_PROPERTIES(VirtIOBlock, conf.conf), DEFINE_BLOCK_CHS_PROPERTIES(VirtIOBlock, conf.conf), DEFINE_PROP_STRING("serial", VirtIOBlock, conf.serial), DEFINE_PROP_BIT("config-wce", VirtIOBlock, conf.config_wce, 0, true), diff --git a/hw/block/xen_blkif.h b/hw/block/xen_blkif.h index 0738684410..3300b6fc0a 100644 --- a/hw/block/xen_blkif.h +++ b/hw/block/xen_blkif.h @@ -1,5 +1,5 @@ -#ifndef __XEN_BLKIF_H__ -#define __XEN_BLKIF_H__ +#ifndef XEN_BLKIF_H +#define XEN_BLKIF_H #include <xen/io/ring.h> #include <xen/io/blkif.h> @@ -143,4 +143,4 @@ static inline void blkif_get_x86_64_req(blkif_request_t *dst, } } -#endif /* __XEN_BLKIF_H__ */ +#endif /* XEN_BLKIF_H */ diff --git a/hw/bt/hci.c b/hw/bt/hci.c index 7d52205093..351123fab7 100644 --- a/hw/bt/hci.c +++ b/hw/bt/hci.c @@ -426,11 +426,7 @@ static void bt_submit_raw_acl(struct bt_piconet_s *net, int length, uint8_t *dat * be continuously allocated. We do it though, to preserve similar * behaviour between hosts. Some things, like the BD_ADDR cannot be * preserved though (for example if a real hci is used). */ -#ifdef HOST_WORDS_BIGENDIAN -# define HNDL(raw) bswap16(raw) -#else -# define HNDL(raw) (raw) -#endif +#define HNDL(raw) cpu_to_le16(raw) static const uint8_t bt_event_reserved_mask[8] = { 0xff, 0x9f, 0xfb, 0xff, 0x07, 0x18, 0x00, 0x00, @@ -1504,8 +1500,8 @@ static void bt_submit_hci(struct HCIInfo *info, return; #define PARAM(cmd, param) (((cmd##_cp *) data)->param) -#define PARAM16(cmd, param) le16_to_cpup(&PARAM(cmd, param)) -#define PARAMHANDLE(cmd) HNDL(PARAM(cmd, handle)) +#define PARAM16(cmd, param) lduw_le_p(&PARAM(cmd, param)) +#define PARAMHANDLE(cmd) PARAM16(cmd, handle) #define LENGTH_CHECK(cmd) if (length < sizeof(cmd##_cp)) goto short_hci /* Note: the supported commands bitmask in bt_hci_read_local_commands_rp * needs to be updated every time a command is implemented here! */ diff --git a/hw/bt/l2cap.c b/hw/bt/l2cap.c index dfc95ed048..e342045140 100644 --- a/hw/bt/l2cap.c +++ b/hw/bt/l2cap.c @@ -526,9 +526,9 @@ static int l2cap_channel_config(struct l2cap_instance_s *l2cap, } /* MTU */ - val = le16_to_cpup((void *) opt->val); + val = lduw_le_p(opt->val); if (val < ch->min_mtu) { - cpu_to_le16w((void *) opt->val, ch->min_mtu); + stw_le_p(opt->val, ch->min_mtu); result = L2CAP_CONF_UNACCEPT; break; } @@ -543,7 +543,7 @@ static int l2cap_channel_config(struct l2cap_instance_s *l2cap, } /* Flush Timeout */ - val = le16_to_cpup((void *) opt->val); + val = lduw_le_p(opt->val); if (val < 0x0001) { opt->val[0] = 0xff; opt->val[1] = 0xff; @@ -987,7 +987,7 @@ static void l2cap_bframe_in(struct l2cap_chan_s *ch, uint16_t cid, static void l2cap_iframe_in(struct l2cap_chan_s *ch, uint16_t cid, const l2cap_hdr *hdr, int len) { - uint16_t fcs = le16_to_cpup((void *) (hdr->data + len - 2)); + uint16_t fcs = lduw_le_p(hdr->data + len - 2); if (len < 4) goto len_error; @@ -1002,7 +1002,7 @@ static void l2cap_iframe_in(struct l2cap_chan_s *ch, uint16_t cid, /* TODO: Signal an error? */ return; } - l2cap_sframe_in(ch, le16_to_cpup((void *) hdr->data)); + l2cap_sframe_in(ch, lduw_le_p(hdr->data)); return; } @@ -1022,7 +1022,7 @@ static void l2cap_iframe_in(struct l2cap_chan_s *ch, uint16_t cid, if (len - 6 > ch->mps) goto len_error; - ch->len_total = le16_to_cpup((void *) (hdr->data + 2)); + ch->len_total = lduw_le_p(hdr->data + 2); if (len >= 6 + ch->len_total) goto seg_error; diff --git a/hw/char/sclpconsole.c b/hw/char/sclpconsole.c index 15a5b2b2b5..d22464826b 100644 --- a/hw/char/sclpconsole.c +++ b/hw/char/sclpconsole.c @@ -13,7 +13,7 @@ */ #include "qemu/osdep.h" -#include <hw/qdev.h> +#include "hw/qdev.h" #include "qemu/thread.h" #include "qemu/error-report.h" diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c index 65d9fa9f53..ab1bc5e945 100644 --- a/hw/core/qdev-properties-system.c +++ b/hw/core/qdev-properties-system.c @@ -72,12 +72,21 @@ static void parse_drive(DeviceState *dev, const char *str, void **ptr, const char *propname, Error **errp) { BlockBackend *blk; + bool blk_created = false; blk = blk_by_name(str); if (!blk) { + BlockDriverState *bs = bdrv_lookup_bs(NULL, str, NULL); + if (bs) { + blk = blk_new(); + blk_insert_bs(blk, bs); + blk_created = true; + } + } + if (!blk) { error_setg(errp, "Property '%s.%s' can't find value '%s'", object_get_typename(OBJECT(dev)), propname, str); - return; + goto fail; } if (blk_attach_dev(blk, dev) < 0) { DriveInfo *dinfo = blk_legacy_dinfo(blk); @@ -91,9 +100,16 @@ static void parse_drive(DeviceState *dev, const char *str, void **ptr, error_setg(errp, "Drive '%s' is already in use by another device", str); } - return; + goto fail; } + *ptr = blk; + +fail: + if (blk_created) { + /* If we need to keep a reference, blk_attach_dev() took it */ + blk_unref(blk); + } } static void release_drive(Object *obj, const char *name, void *opaque) @@ -103,8 +119,8 @@ static void release_drive(Object *obj, const char *name, void *opaque) BlockBackend **ptr = qdev_get_prop_ptr(dev, prop); if (*ptr) { - blk_detach_dev(*ptr, dev); blockdev_auto_del(*ptr); + blk_detach_dev(*ptr, dev); } } @@ -127,7 +143,7 @@ static void set_drive(Object *obj, Visitor *v, const char *name, void *opaque, PropertyInfo qdev_prop_drive = { .name = "str", - .description = "ID of a drive to use as a backend", + .description = "Node name or ID of a block device to use as a backend", .get = get_drive, .set = set_drive, .release = release_drive, @@ -362,8 +378,19 @@ PropertyInfo qdev_prop_vlan = { void qdev_prop_set_drive(DeviceState *dev, const char *name, BlockBackend *value, Error **errp) { - object_property_set_str(OBJECT(dev), value ? blk_name(value) : "", - name, errp); + const char *ref = ""; + + if (value) { + ref = blk_name(value); + if (!*ref) { + BlockDriverState *bs = blk_bs(value); + if (bs) { + ref = bdrv_get_node_name(bs); + } + } + } + + object_property_set_str(OBJECT(dev), ref, name, errp); } void qdev_prop_set_chr(DeviceState *dev, const char *name, diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c index 3c20c8e4b2..14e544ab17 100644 --- a/hw/core/qdev-properties.c +++ b/hw/core/qdev-properties.c @@ -539,6 +539,19 @@ PropertyInfo qdev_prop_losttickpolicy = { .set = set_enum, }; +/* --- Block device error handling policy --- */ + +QEMU_BUILD_BUG_ON(sizeof(BlockdevOnError) != sizeof(int)); + +PropertyInfo qdev_prop_blockdev_on_error = { + .name = "BlockdevOnError", + .description = "Error handling policy, " + "report/ignore/enospc/stop/auto", + .enum_table = BlockdevOnError_lookup, + .get = get_enum, + .set = set_enum, +}; + /* --- BIOS CHS translation */ QEMU_BUILD_BUG_ON(sizeof(BiosAtaTranslation) != sizeof(int)); diff --git a/hw/core/uboot_image.h b/hw/core/uboot_image.h index 9fc2760b53..34c11a70a6 100644 --- a/hw/core/uboot_image.h +++ b/hw/core/uboot_image.h @@ -26,8 +26,8 @@ ******************************************************************** */ -#ifndef __UBOOT_IMAGE_H__ -#define __UBOOT_IMAGE_H__ +#ifndef UBOOT_IMAGE_H +#define UBOOT_IMAGE_H /* * Operating System Codes @@ -155,4 +155,4 @@ typedef struct uboot_image_header { } uboot_image_header_t; -#endif /* __IMAGE_H__ */ +#endif /* UBOOT_IMAGE_H */ diff --git a/hw/cris/boot.h b/hw/cris/boot.h index c4d3fa6f6f..218854e5d1 100644 --- a/hw/cris/boot.h +++ b/hw/cris/boot.h @@ -1,5 +1,5 @@ -#ifndef _CRIS_BOOT_H -#define HW_CRIS_BOOT_H 1 +#ifndef HW_CRIS_BOOT_H +#define HW_CRIS_BOOT_H struct cris_load_info { diff --git a/hw/display/qxl.h b/hw/display/qxl.h index fdb619d4a7..d2d49dd933 100644 --- a/hw/display/qxl.h +++ b/hw/display/qxl.h @@ -1,5 +1,5 @@ #ifndef HW_QXL_H -#define HW_QXL_H 1 +#define HW_QXL_H #include "qemu-common.h" diff --git a/hw/display/vga.h b/hw/display/vga.h index d917046da6..16886f5eed 100644 --- a/hw/display/vga.h +++ b/hw/display/vga.h @@ -14,8 +14,8 @@ * */ -#ifndef __linux_video_vga_h__ -#define __linux_video_vga_h__ +#ifndef LINUX_VIDEO_VGA_H +#define LINUX_VIDEO_VGA_H /* Some of the code below is taken from SVGAlib. The original, unmodified copyright notice for that code is below. */ @@ -156,4 +156,4 @@ /* VGA graphics controller bit masks */ #define VGA_GR06_GRAPHICS_MODE 0x01 -#endif /* __linux_video_vga_h__ */ +#endif /* LINUX_VIDEO_VGA_H */ diff --git a/hw/display/vga_int.h b/hw/display/vga_int.h index 3ce5544efd..dd6c958da3 100644 --- a/hw/display/vga_int.h +++ b/hw/display/vga_int.h @@ -21,10 +21,11 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + #ifndef HW_VGA_INT_H -#define HW_VGA_INT_H 1 +#define HW_VGA_INT_H -#include <hw/hw.h> +#include "hw/hw.h" #include "exec/memory.h" #define ST01_V_RETRACE 0x08 diff --git a/hw/display/virtio-gpu-3d.c b/hw/display/virtio-gpu-3d.c index d6c8c6e2dc..758d33a09d 100644 --- a/hw/display/virtio-gpu-3d.c +++ b/hw/display/virtio-gpu-3d.c @@ -21,7 +21,7 @@ #ifdef CONFIG_VIRGL -#include "virglrenderer.h" +#include <virglrenderer.h> static struct virgl_renderer_callbacks virtio_gpu_3d_cbs; diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c index f8b0274752..929c3c8b8a 100644 --- a/hw/display/virtio-gpu.c +++ b/hw/display/virtio-gpu.c @@ -28,7 +28,7 @@ static struct virtio_gpu_simple_resource* virtio_gpu_find_resource(VirtIOGPU *g, uint32_t resource_id); #ifdef CONFIG_VIRGL -#include "virglrenderer.h" +#include <virglrenderer.h> #define VIRGL(_g, _virgl, _simple, ...) \ do { \ if (_g->use_virgl_renderer) { \ diff --git a/hw/i386/kvm/i8254.c b/hw/i386/kvm/i8254.c index 734992ead0..521a58498a 100644 --- a/hw/i386/kvm/i8254.c +++ b/hw/i386/kvm/i8254.c @@ -22,14 +22,15 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + #include "qemu/osdep.h" +#include <linux/kvm.h> #include "qapi/error.h" #include "qemu/timer.h" #include "sysemu/sysemu.h" #include "hw/timer/i8254.h" #include "hw/timer/i8254_internal.h" #include "sysemu/kvm.h" -#include "linux/kvm.h" #define KVM_PIT_REINJECT_BIT 0 diff --git a/hw/i386/kvm/pci-assign.c b/hw/i386/kvm/pci-assign.c index 3623aa1965..1a429e5402 100644 --- a/hw/i386/kvm/pci-assign.c +++ b/hw/i386/kvm/pci-assign.c @@ -20,7 +20,9 @@ * Copyright (C) 2008, Red Hat, Amit Shah (amit.shah@redhat.com) * Copyright (C) 2008, IBM, Muli Ben-Yehuda (muli@il.ibm.com) */ + #include "qemu/osdep.h" +#include <linux/kvm.h> #include "qapi/error.h" #include "hw/hw.h" #include "hw/i386/pc.h" @@ -32,7 +34,6 @@ #include "sysemu/sysemu.h" #include "hw/pci/pci.h" #include "hw/pci/msi.h" -#include "linux/kvm.h" #include "kvm_i386.h" #include "hw/pci/pci-assign.h" diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index b1a7b65a7b..bcb9ff9e1b 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -22,17 +22,17 @@ */ #include "qemu/osdep.h" -#include <hw/hw.h> -#include <hw/pci/msi.h> -#include <hw/i386/pc.h> -#include <hw/pci/pci.h> +#include "hw/hw.h" +#include "hw/pci/msi.h" +#include "hw/i386/pc.h" +#include "hw/pci/pci.h" #include "qemu/error-report.h" #include "sysemu/block-backend.h" #include "sysemu/dma.h" -#include <hw/ide/internal.h> -#include <hw/ide/pci.h> -#include <hw/ide/ahci.h> +#include "hw/ide/internal.h" +#include "hw/ide/pci.h" +#include "hw/ide/ahci.h" #define DEBUG_AHCI 0 diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c index 49294a5314..9ebb8d4fb2 100644 --- a/hw/ide/cmd646.c +++ b/hw/ide/cmd646.c @@ -23,15 +23,15 @@ * THE SOFTWARE. */ #include "qemu/osdep.h" -#include <hw/hw.h> -#include <hw/i386/pc.h> -#include <hw/pci/pci.h> -#include <hw/isa/isa.h> +#include "hw/hw.h" +#include "hw/i386/pc.h" +#include "hw/pci/pci.h" +#include "hw/isa/isa.h" #include "sysemu/block-backend.h" #include "sysemu/sysemu.h" #include "sysemu/dma.h" -#include <hw/ide/pci.h> +#include "hw/ide/pci.h" /* CMD646 specific */ #define CFR 0x50 diff --git a/hw/ide/core.c b/hw/ide/core.c index 029f6b9b12..f2d131b0d3 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -23,10 +23,10 @@ * THE SOFTWARE. */ #include "qemu/osdep.h" -#include <hw/hw.h> -#include <hw/i386/pc.h> -#include <hw/pci/pci.h> -#include <hw/isa/isa.h> +#include "hw/hw.h" +#include "hw/i386/pc.h" +#include "hw/pci/pci.h" +#include "hw/isa/isa.h" #include "qemu/error-report.h" #include "qemu/timer.h" #include "sysemu/sysemu.h" @@ -35,7 +35,7 @@ #include "sysemu/block-backend.h" #include "qemu/cutils.h" -#include <hw/ide/internal.h> +#include "hw/ide/internal.h" /* These values were based on a Seagate ST3500418AS but have been modified to make more sense in QEMU */ diff --git a/hw/ide/ich.c b/hw/ide/ich.c index 920ec276ed..459916977e 100644 --- a/hw/ide/ich.c +++ b/hw/ide/ich.c @@ -61,15 +61,15 @@ */ #include "qemu/osdep.h" -#include <hw/hw.h> -#include <hw/pci/msi.h> -#include <hw/i386/pc.h> -#include <hw/pci/pci.h> -#include <hw/isa/isa.h> +#include "hw/hw.h" +#include "hw/pci/msi.h" +#include "hw/i386/pc.h" +#include "hw/pci/pci.h" +#include "hw/isa/isa.h" #include "sysemu/block-backend.h" #include "sysemu/dma.h" -#include <hw/ide/pci.h> -#include <hw/ide/ahci.h> +#include "hw/ide/pci.h" +#include "hw/ide/ahci.h" #define ICH9_MSI_CAP_OFFSET 0x80 #define ICH9_SATA_CAP_OFFSET 0xA8 diff --git a/hw/ide/isa.c b/hw/ide/isa.c index eba567c877..40213d662c 100644 --- a/hw/ide/isa.c +++ b/hw/ide/isa.c @@ -23,13 +23,13 @@ * THE SOFTWARE. */ #include "qemu/osdep.h" -#include <hw/hw.h> -#include <hw/i386/pc.h> -#include <hw/isa/isa.h> +#include "hw/hw.h" +#include "hw/i386/pc.h" +#include "hw/isa/isa.h" #include "sysemu/block-backend.h" #include "sysemu/dma.h" -#include <hw/ide/internal.h> +#include "hw/ide/internal.h" /***********************************************************/ /* ISA IDE definitions */ diff --git a/hw/ide/macio.c b/hw/ide/macio.c index 56cc50661f..5a326afd96 100644 --- a/hw/ide/macio.c +++ b/hw/ide/macio.c @@ -29,7 +29,7 @@ #include "sysemu/block-backend.h" #include "sysemu/dma.h" -#include <hw/ide/internal.h> +#include "hw/ide/internal.h" /* debug MACIO */ // #define DEBUG_MACIO diff --git a/hw/ide/microdrive.c b/hw/ide/microdrive.c index 5c9db8047d..e3fd30e457 100644 --- a/hw/ide/microdrive.c +++ b/hw/ide/microdrive.c @@ -23,13 +23,13 @@ * THE SOFTWARE. */ #include "qemu/osdep.h" -#include <hw/hw.h> -#include <hw/i386/pc.h> -#include <hw/pcmcia.h> +#include "hw/hw.h" +#include "hw/i386/pc.h" +#include "hw/pcmcia.h" #include "sysemu/block-backend.h" #include "sysemu/dma.h" -#include <hw/ide/internal.h> +#include "hw/ide/internal.h" #define TYPE_MICRODRIVE "microdrive" #define MICRODRIVE(obj) OBJECT_CHECK(MicroDriveState, (obj), TYPE_MICRODRIVE) diff --git a/hw/ide/mmio.c b/hw/ide/mmio.c index 493f65a1d0..6f12f456ed 100644 --- a/hw/ide/mmio.c +++ b/hw/ide/mmio.c @@ -28,7 +28,7 @@ #include "sysemu/block-backend.h" #include "sysemu/dma.h" -#include <hw/ide/internal.h> +#include "hw/ide/internal.h" /***********************************************************/ /* MMIO based ide port diff --git a/hw/ide/pci.c b/hw/ide/pci.c index 8d56a00b1b..3cfb510afe 100644 --- a/hw/ide/pci.c +++ b/hw/ide/pci.c @@ -23,14 +23,14 @@ * THE SOFTWARE. */ #include "qemu/osdep.h" -#include <hw/hw.h> -#include <hw/i386/pc.h> -#include <hw/pci/pci.h> -#include <hw/isa/isa.h> +#include "hw/hw.h" +#include "hw/i386/pc.h" +#include "hw/pci/pci.h" +#include "hw/isa/isa.h" #include "sysemu/block-backend.h" #include "sysemu/dma.h" #include "qemu/error-report.h" -#include <hw/ide/pci.h> +#include "hw/ide/pci.h" #define BMDMA_PAGE_SIZE 4096 diff --git a/hw/ide/piix.c b/hw/ide/piix.c index 6d76ce980b..c190fcaa3c 100644 --- a/hw/ide/piix.c +++ b/hw/ide/piix.c @@ -24,15 +24,15 @@ */ #include "qemu/osdep.h" -#include <hw/hw.h> -#include <hw/i386/pc.h> -#include <hw/pci/pci.h> -#include <hw/isa/isa.h> +#include "hw/hw.h" +#include "hw/i386/pc.h" +#include "hw/pci/pci.h" +#include "hw/isa/isa.h" #include "sysemu/block-backend.h" #include "sysemu/sysemu.h" #include "sysemu/dma.h" -#include <hw/ide/pci.h> +#include "hw/ide/pci.h" static uint64_t bmdma_read(void *opaque, hwaddr addr, unsigned size) { diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c index 6842a5596a..67c76bfcd6 100644 --- a/hw/ide/qdev.c +++ b/hw/ide/qdev.c @@ -17,11 +17,11 @@ * License along with this library; if not, see <http://www.gnu.org/licenses/>. */ #include "qemu/osdep.h" -#include <hw/hw.h> +#include "hw/hw.h" #include "sysemu/dma.h" #include "qapi/error.h" #include "qemu/error-report.h" -#include <hw/ide/internal.h> +#include "hw/ide/internal.h" #include "sysemu/block-backend.h" #include "sysemu/blockdev.h" #include "hw/block/block.h" @@ -180,6 +180,7 @@ static int ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind) return -1; } } + blkconf_apply_backend_options(&dev->conf); if (ide_init_drive(s, dev->conf.blk, kind, dev->version, dev->serial, dev->model, dev->wwn, @@ -263,6 +264,7 @@ static int ide_drive_initfn(IDEDevice *dev) #define DEFINE_IDE_DEV_PROPERTIES() \ DEFINE_BLOCK_PROPERTIES(IDEDrive, dev.conf), \ + DEFINE_BLOCK_ERROR_PROPERTIES(IDEDrive, dev.conf), \ DEFINE_PROP_STRING("ver", IDEDrive, dev.version), \ DEFINE_PROP_UINT64("wwn", IDEDrive, dev.wwn, 0), \ DEFINE_PROP_STRING("serial", IDEDrive, dev.serial),\ diff --git a/hw/ide/via.c b/hw/ide/via.c index d3f72267a1..5b32ecb386 100644 --- a/hw/ide/via.c +++ b/hw/ide/via.c @@ -24,15 +24,15 @@ * THE SOFTWARE. */ #include "qemu/osdep.h" -#include <hw/hw.h> -#include <hw/i386/pc.h> -#include <hw/pci/pci.h> -#include <hw/isa/isa.h> +#include "hw/hw.h" +#include "hw/i386/pc.h" +#include "hw/pci/pci.h" +#include "hw/isa/isa.h" #include "sysemu/block-backend.h" #include "sysemu/sysemu.h" #include "sysemu/dma.h" -#include <hw/ide/pci.h> +#include "hw/ide/pci.h" static uint64_t bmdma_read(void *opaque, hwaddr addr, unsigned size) diff --git a/hw/input/hid.c b/hw/input/hid.c index d92c7463ba..5e2850e655 100644 --- a/hw/input/hid.c +++ b/hw/input/hid.c @@ -27,6 +27,7 @@ #include "ui/console.h" #include "qemu/timer.h" #include "hw/input/hid.h" +#include "trace.h" #define HID_USAGE_ERROR_ROLLOVER 0x01 #define HID_USAGE_POSTFAIL 0x02 @@ -234,7 +235,7 @@ static void hid_keyboard_event(DeviceState *dev, QemuConsole *src, key->down, scancodes); if (hs->n + count > QUEUE_LENGTH) { - fprintf(stderr, "usb-kbd: warning: key event queue full\n"); + trace_hid_kbd_queue_full(); return; } for (i = 0; i < count; i++) { diff --git a/hw/input/trace-events b/hw/input/trace-events index 00fcec12b9..f24dff2f8b 100644 --- a/hw/input/trace-events +++ b/hw/input/trace-events @@ -23,3 +23,9 @@ milkymist_softusb_memory_write(uint32_t addr, uint32_t value) "addr %08x value % milkymist_softusb_mevt(uint8_t m) "m %d" milkymist_softusb_kevt(uint8_t m) "m %d" milkymist_softusb_pulse_irq(void) "Pulse IRQ" + +# hw/input/hid.c +hid_kbd_queue_full(void) "queue full" + +# hw/input/virtio +virtio_input_queue_full(void) "queue full" diff --git a/hw/input/virtio-input.c b/hw/input/virtio-input.c index f59749a943..edf69903a6 100644 --- a/hw/input/virtio-input.c +++ b/hw/input/virtio-input.c @@ -7,6 +7,7 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "qemu/iov.h" +#include "trace.h" #include "hw/qdev.h" #include "hw/virtio/virtio.h" @@ -47,7 +48,7 @@ void virtio_input_send(VirtIOInput *vinput, virtio_input_event *event) virtqueue_get_avail_bytes(vinput->evt, &have, NULL, need, 0); if (have < need) { vinput->qindex = 0; - fprintf(stderr, "%s: ENOSPC in vq, dropping events\n", __func__); + trace_virtio_input_queue_full(); return; } diff --git a/hw/intc/Makefile.objs b/hw/intc/Makefile.objs index 530df2eba6..05ec21b21e 100644 --- a/hw/intc/Makefile.objs +++ b/hw/intc/Makefile.objs @@ -37,3 +37,4 @@ obj-$(CONFIG_S390_FLIC) += s390_flic.o obj-$(CONFIG_S390_FLIC_KVM) += s390_flic_kvm.o obj-$(CONFIG_ASPEED_SOC) += aspeed_vic.o obj-$(CONFIG_ARM_GIC) += arm_gicv3_cpuif.o +obj-$(CONFIG_MIPS_CPS) += mips_gic.o diff --git a/hw/intc/gic_internal.h b/hw/intc/gic_internal.h index 20c1e8a242..3f311740da 100644 --- a/hw/intc/gic_internal.h +++ b/hw/intc/gic_internal.h @@ -100,4 +100,4 @@ static inline bool gic_test_pending(GICState *s, int irq, int cm) } } -#endif /* !QEMU_ARM_GIC_INTERNAL_H */ +#endif /* QEMU_ARM_GIC_INTERNAL_H */ diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h index 6ce5d49bde..8f3567edaa 100644 --- a/hw/intc/gicv3_internal.h +++ b/hw/intc/gicv3_internal.h @@ -328,4 +328,4 @@ static inline void gicv3_cache_all_target_cpustates(GICv3State *s) } } -#endif /* !QEMU_ARM_GIC_INTERNAL_H */ +#endif /* QEMU_ARM_GICV3_INTERNAL_H */ diff --git a/hw/intc/mips_gic.c b/hw/intc/mips_gic.c new file mode 100644 index 0000000000..6e257730f8 --- /dev/null +++ b/hw/intc/mips_gic.c @@ -0,0 +1,460 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. + * Authors: Sanjay Lal <sanjayl@kymasys.com> + * + * Copyright (C) 2016 Imagination Technologies + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qapi/error.h" +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "exec/memory.h" +#include "sysemu/sysemu.h" +#include "sysemu/kvm.h" +#include "kvm_mips.h" +#include "hw/intc/mips_gic.h" + +static void mips_gic_set_vp_irq(MIPSGICState *gic, int vp, int pin, int level) +{ + int ored_level = level; + int i; + + /* ORing pending registers sharing same pin */ + if (!ored_level) { + for (i = 0; i < gic->num_irq; i++) { + if ((gic->irq_state[i].map_pin & GIC_MAP_MSK) == pin && + gic->irq_state[i].map_vp == vp && + gic->irq_state[i].enabled) { + ored_level |= gic->irq_state[i].pending; + } + if (ored_level) { + /* no need to iterate all interrupts */ + break; + } + } + if (((gic->vps[vp].compare_map & GIC_MAP_MSK) == pin) && + (gic->vps[vp].mask & GIC_VP_MASK_CMP_MSK)) { + /* ORing with local pending register (count/compare) */ + ored_level |= (gic->vps[vp].pend & GIC_VP_MASK_CMP_MSK) >> + GIC_VP_MASK_CMP_SHF; + } + } + if (kvm_enabled()) { + kvm_mips_set_ipi_interrupt(mips_env_get_cpu(gic->vps[vp].env), + pin + GIC_CPU_PIN_OFFSET, + ored_level); + } else { + qemu_set_irq(gic->vps[vp].env->irq[pin + GIC_CPU_PIN_OFFSET], + ored_level); + } +} + +static void gic_set_irq(void *opaque, int n_IRQ, int level) +{ + MIPSGICState *gic = (MIPSGICState *) opaque; + int vp = gic->irq_state[n_IRQ].map_vp; + int pin = gic->irq_state[n_IRQ].map_pin & GIC_MAP_MSK; + + gic->irq_state[n_IRQ].pending = (uint8_t) level; + if (!gic->irq_state[n_IRQ].enabled) { + /* GIC interrupt source disabled */ + return; + } + if (vp < 0 || vp >= gic->num_vps) { + return; + } + mips_gic_set_vp_irq(gic, vp, pin, level); +} + +#define OFFSET_CHECK(c) \ + do { \ + if (!(c)) { \ + goto bad_offset; \ + } \ + } while (0) + +/* GIC Read VP Local/Other Registers */ +static uint64_t gic_read_vp(MIPSGICState *gic, uint32_t vp_index, hwaddr addr, + unsigned size) +{ + switch (addr) { + case GIC_VP_CTL_OFS: + return gic->vps[vp_index].ctl; + case GIC_VP_PEND_OFS: + mips_gictimer_get_sh_count(gic->gic_timer); + return gic->vps[vp_index].pend; + case GIC_VP_MASK_OFS: + return gic->vps[vp_index].mask; + case GIC_VP_COMPARE_MAP_OFS: + return gic->vps[vp_index].compare_map; + case GIC_VP_OTHER_ADDR_OFS: + return gic->vps[vp_index].other_addr; + case GIC_VP_IDENT_OFS: + return vp_index; + case GIC_VP_COMPARE_LO_OFS: + return mips_gictimer_get_vp_compare(gic->gic_timer, vp_index); + case GIC_VP_COMPARE_HI_OFS: + return 0; + default: + qemu_log_mask(LOG_UNIMP, "Read %d bytes at GIC offset LOCAL/OTHER 0x%" + PRIx64 "\n", size, addr); + break; + } + return 0; +} + +static uint64_t gic_read(void *opaque, hwaddr addr, unsigned size) +{ + MIPSGICState *gic = (MIPSGICState *) opaque; + uint32_t vp_index = current_cpu->cpu_index; + uint64_t ret = 0; + int i, base, irq_src; + uint32_t other_index; + + switch (addr) { + case GIC_SH_CONFIG_OFS: + ret = gic->sh_config | (mips_gictimer_get_countstop(gic->gic_timer) << + GIC_SH_CONFIG_COUNTSTOP_SHF); + break; + case GIC_SH_COUNTERLO_OFS: + ret = mips_gictimer_get_sh_count(gic->gic_timer); + break; + case GIC_SH_COUNTERHI_OFS: + ret = 0; + break; + case GIC_SH_PEND_OFS ... GIC_SH_PEND_LAST_OFS: + /* each bit represents pending status for an interrupt pin */ + base = (addr - GIC_SH_PEND_OFS) * 8; + OFFSET_CHECK((base + size * 8) <= gic->num_irq); + for (i = 0; i < size * 8; i++) { + ret |= (uint64_t) (gic->irq_state[base + i].pending) << i; + } + break; + case GIC_SH_MASK_OFS ... GIC_SH_MASK_LAST_OFS: + /* each bit represents status for an interrupt pin */ + base = (addr - GIC_SH_MASK_OFS) * 8; + OFFSET_CHECK((base + size * 8) <= gic->num_irq); + for (i = 0; i < size * 8; i++) { + ret |= (uint64_t) (gic->irq_state[base + i].enabled) << i; + } + break; + case GIC_SH_MAP0_PIN_OFS ... GIC_SH_MAP255_PIN_OFS: + /* 32 bits per a pin */ + irq_src = (addr - GIC_SH_MAP0_PIN_OFS) / 4; + OFFSET_CHECK(irq_src < gic->num_irq); + ret = gic->irq_state[irq_src].map_pin; + break; + case GIC_SH_MAP0_VP_OFS ... GIC_SH_MAP255_VP_LAST_OFS: + /* up to 32 bytes per a pin */ + irq_src = (addr - GIC_SH_MAP0_VP_OFS) / 32; + OFFSET_CHECK(irq_src < gic->num_irq); + if ((gic->irq_state[irq_src].map_vp) >= 0) { + ret = (uint64_t) 1 << (gic->irq_state[irq_src].map_vp); + } else { + ret = 0; + } + break; + /* VP-Local Register */ + case VP_LOCAL_SECTION_OFS ... (VP_LOCAL_SECTION_OFS + GIC_VL_BRK_GROUP): + ret = gic_read_vp(gic, vp_index, addr - VP_LOCAL_SECTION_OFS, size); + break; + /* VP-Other Register */ + case VP_OTHER_SECTION_OFS ... (VP_OTHER_SECTION_OFS + GIC_VL_BRK_GROUP): + other_index = gic->vps[vp_index].other_addr; + ret = gic_read_vp(gic, other_index, addr - VP_OTHER_SECTION_OFS, size); + break; + /* User-Mode Visible section */ + case USM_VISIBLE_SECTION_OFS + GIC_USER_MODE_COUNTERLO: + ret = mips_gictimer_get_sh_count(gic->gic_timer); + break; + case USM_VISIBLE_SECTION_OFS + GIC_USER_MODE_COUNTERHI: + ret = 0; + break; + default: + qemu_log_mask(LOG_UNIMP, "Read %d bytes at GIC offset 0x%" PRIx64 "\n", + size, addr); + break; + } + return ret; +bad_offset: + qemu_log_mask(LOG_GUEST_ERROR, "Wrong GIC offset at 0x%" PRIx64 "\n", addr); + return 0; +} + +static void gic_timer_expire_cb(void *opaque, uint32_t vp_index) +{ + MIPSGICState *gic = opaque; + + gic->vps[vp_index].pend |= (1 << GIC_LOCAL_INT_COMPARE); + if (gic->vps[vp_index].pend & + (gic->vps[vp_index].mask & GIC_VP_MASK_CMP_MSK)) { + if (gic->vps[vp_index].compare_map & GIC_MAP_TO_PIN_MSK) { + /* it is safe to set the irq high regardless of other GIC IRQs */ + uint32_t pin = (gic->vps[vp_index].compare_map & GIC_MAP_MSK); + qemu_irq_raise(gic->vps[vp_index].env->irq + [pin + GIC_CPU_PIN_OFFSET]); + } + } +} + +static void gic_timer_store_vp_compare(MIPSGICState *gic, uint32_t vp_index, + uint64_t compare) +{ + gic->vps[vp_index].pend &= ~(1 << GIC_LOCAL_INT_COMPARE); + if (gic->vps[vp_index].compare_map & GIC_MAP_TO_PIN_MSK) { + uint32_t pin = (gic->vps[vp_index].compare_map & GIC_MAP_MSK); + mips_gic_set_vp_irq(gic, vp_index, pin, 0); + } + mips_gictimer_store_vp_compare(gic->gic_timer, vp_index, compare); +} + +/* GIC Write VP Local/Other Registers */ +static void gic_write_vp(MIPSGICState *gic, uint32_t vp_index, hwaddr addr, + uint64_t data, unsigned size) +{ + switch (addr) { + case GIC_VP_CTL_OFS: + /* EIC isn't supported */ + break; + case GIC_VP_RMASK_OFS: + gic->vps[vp_index].mask &= ~(data & GIC_VP_SET_RESET_MSK) & + GIC_VP_SET_RESET_MSK; + break; + case GIC_VP_SMASK_OFS: + gic->vps[vp_index].mask |= data & GIC_VP_SET_RESET_MSK; + break; + case GIC_VP_COMPARE_MAP_OFS: + /* EIC isn't supported */ + OFFSET_CHECK((data & GIC_MAP_MSK) <= GIC_CPU_INT_MAX); + gic->vps[vp_index].compare_map = data & GIC_MAP_TO_PIN_REG_MSK; + break; + case GIC_VP_OTHER_ADDR_OFS: + OFFSET_CHECK(data < gic->num_vps); + gic->vps[vp_index].other_addr = data; + break; + case GIC_VP_COMPARE_LO_OFS: + gic_timer_store_vp_compare(gic, vp_index, data); + break; + default: + qemu_log_mask(LOG_UNIMP, "Write %d bytes at GIC offset LOCAL/OTHER " + "0x%" PRIx64" 0x%08" PRIx64 "\n", size, addr, data); + break; + } + return; +bad_offset: + qemu_log_mask(LOG_GUEST_ERROR, "Wrong GIC offset at 0x%" PRIx64 "\n", addr); + return; +} + +static void gic_write(void *opaque, hwaddr addr, uint64_t data, unsigned size) +{ + int intr; + MIPSGICState *gic = (MIPSGICState *) opaque; + uint32_t vp_index = current_cpu->cpu_index; + int i, base, irq_src; + uint32_t other_index; + + switch (addr) { + case GIC_SH_CONFIG_OFS: + { + uint32_t pre_cntstop = mips_gictimer_get_countstop(gic->gic_timer); + uint32_t new_cntstop = (data & GIC_SH_CONFIG_COUNTSTOP_MSK) >> + GIC_SH_CONFIG_COUNTSTOP_SHF; + if (pre_cntstop != new_cntstop) { + if (new_cntstop == 1) { + mips_gictimer_stop_count(gic->gic_timer); + } else { + mips_gictimer_start_count(gic->gic_timer); + } + } + } + break; + case GIC_SH_COUNTERLO_OFS: + if (mips_gictimer_get_countstop(gic->gic_timer)) { + mips_gictimer_store_sh_count(gic->gic_timer, data); + } + break; + case GIC_SH_RMASK_OFS ... GIC_SH_RMASK_LAST_OFS: + /* up to 64 bits per a pin */ + base = (addr - GIC_SH_RMASK_OFS) * 8; + OFFSET_CHECK((base + size * 8) <= gic->num_irq); + for (i = 0; i < size * 8; i++) { + gic->irq_state[base + i].enabled &= !((data >> i) & 1); + } + break; + case GIC_SH_WEDGE_OFS: + /* Figure out which VP/HW Interrupt this maps to */ + intr = data & ~GIC_SH_WEDGE_RW_MSK; + /* Mask/Enabled Checks */ + OFFSET_CHECK(intr < gic->num_irq); + if (data & GIC_SH_WEDGE_RW_MSK) { + gic_set_irq(gic, intr, 1); + } else { + gic_set_irq(gic, intr, 0); + } + break; + case GIC_SH_SMASK_OFS ... GIC_SH_SMASK_LAST_OFS: + /* up to 64 bits per a pin */ + base = (addr - GIC_SH_SMASK_OFS) * 8; + OFFSET_CHECK((base + size * 8) <= gic->num_irq); + for (i = 0; i < size * 8; i++) { + gic->irq_state[base + i].enabled |= (data >> i) & 1; + } + break; + case GIC_SH_MAP0_PIN_OFS ... GIC_SH_MAP255_PIN_OFS: + /* 32 bits per a pin */ + irq_src = (addr - GIC_SH_MAP0_PIN_OFS) / 4; + OFFSET_CHECK(irq_src < gic->num_irq); + /* EIC isn't supported */ + OFFSET_CHECK((data & GIC_MAP_MSK) <= GIC_CPU_INT_MAX); + gic->irq_state[irq_src].map_pin = data & GIC_MAP_TO_PIN_REG_MSK; + break; + case GIC_SH_MAP0_VP_OFS ... GIC_SH_MAP255_VP_LAST_OFS: + /* up to 32 bytes per a pin */ + irq_src = (addr - GIC_SH_MAP0_VP_OFS) / 32; + OFFSET_CHECK(irq_src < gic->num_irq); + data = data ? ctz64(data) : -1; + OFFSET_CHECK(data < gic->num_vps); + gic->irq_state[irq_src].map_vp = data; + break; + case VP_LOCAL_SECTION_OFS ... (VP_LOCAL_SECTION_OFS + GIC_VL_BRK_GROUP): + gic_write_vp(gic, vp_index, addr - VP_LOCAL_SECTION_OFS, data, size); + break; + case VP_OTHER_SECTION_OFS ... (VP_OTHER_SECTION_OFS + GIC_VL_BRK_GROUP): + other_index = gic->vps[vp_index].other_addr; + gic_write_vp(gic, other_index, addr - VP_OTHER_SECTION_OFS, data, size); + break; + case USM_VISIBLE_SECTION_OFS + GIC_USER_MODE_COUNTERLO: + case USM_VISIBLE_SECTION_OFS + GIC_USER_MODE_COUNTERHI: + /* do nothing. Read-only section */ + break; + default: + qemu_log_mask(LOG_UNIMP, "Write %d bytes at GIC offset 0x%" PRIx64 + " 0x%08" PRIx64 "\n", size, addr, data); + break; + } + return; +bad_offset: + qemu_log_mask(LOG_GUEST_ERROR, "Wrong GIC offset at 0x%" PRIx64 "\n", addr); +} + +static void gic_reset(void *opaque) +{ + int i; + MIPSGICState *gic = (MIPSGICState *) opaque; + int numintrs = (gic->num_irq / 8) - 1; + + gic->sh_config = /* COUNTSTOP = 0 it is accessible via MIPSGICTimer*/ + /* CounterHi not implemented */ + (0 << GIC_SH_CONFIG_COUNTBITS_SHF) | + (numintrs << GIC_SH_CONFIG_NUMINTRS_SHF) | + (gic->num_vps << GIC_SH_CONFIG_PVPS_SHF); + for (i = 0; i < gic->num_vps; i++) { + gic->vps[i].ctl = 0x0; + gic->vps[i].pend = 0x0; + /* PERFCNT, TIMER and WD not implemented */ + gic->vps[i].mask = 0x32; + gic->vps[i].compare_map = GIC_MAP_TO_PIN_MSK; + mips_gictimer_store_vp_compare(gic->gic_timer, i, 0xffffffff); + gic->vps[i].other_addr = 0x0; + } + for (i = 0; i < gic->num_irq; i++) { + gic->irq_state[i].enabled = 0; + gic->irq_state[i].pending = 0; + gic->irq_state[i].map_pin = GIC_MAP_TO_PIN_MSK; + gic->irq_state[i].map_vp = -1; + } + mips_gictimer_store_sh_count(gic->gic_timer, 0); + /* COUNTSTOP = 0 */ + mips_gictimer_start_count(gic->gic_timer); +} + +static const MemoryRegionOps gic_ops = { + .read = gic_read, + .write = gic_write, + .endianness = DEVICE_NATIVE_ENDIAN, + .impl = { + .max_access_size = 8, + }, +}; + +static void mips_gic_init(Object *obj) +{ + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + MIPSGICState *s = MIPS_GIC(obj); + + memory_region_init_io(&s->mr, OBJECT(s), &gic_ops, s, + "mips-gic", GIC_ADDRSPACE_SZ); + sysbus_init_mmio(sbd, &s->mr); + qemu_register_reset(gic_reset, s); +} + +static void mips_gic_realize(DeviceState *dev, Error **errp) +{ + MIPSGICState *s = MIPS_GIC(dev); + CPUState *cs = first_cpu; + int i; + + if (s->num_vps > GIC_MAX_VPS) { + error_setg(errp, "Exceeded maximum CPUs %d", s->num_vps); + return; + } + if ((s->num_irq > GIC_MAX_INTRS) || (s->num_irq % 8) || (s->num_irq <= 0)) { + error_setg(errp, "GIC supports up to %d external interrupts in " + "multiples of 8 : %d", GIC_MAX_INTRS, s->num_irq); + return; + } + s->vps = g_new(MIPSGICVPState, s->num_vps); + s->irq_state = g_new(MIPSGICIRQState, s->num_irq); + /* Register the env for all VPs with the GIC */ + for (i = 0; i < s->num_vps; i++) { + if (cs != NULL) { + s->vps[i].env = cs->env_ptr; + cs = CPU_NEXT(cs); + } else { + error_setg(errp, + "Unable to initialize GIC, CPUState for CPU#%d not valid.", i); + return; + } + } + s->gic_timer = mips_gictimer_init(s, s->num_vps, gic_timer_expire_cb); + qdev_init_gpio_in(dev, gic_set_irq, s->num_irq); + for (i = 0; i < s->num_irq; i++) { + s->irq_state[i].irq = qdev_get_gpio_in(dev, i); + } +} + +static Property mips_gic_properties[] = { + DEFINE_PROP_INT32("num-vp", MIPSGICState, num_vps, 1), + DEFINE_PROP_INT32("num-irq", MIPSGICState, num_irq, 256), + DEFINE_PROP_END_OF_LIST(), +}; + +static void mips_gic_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->props = mips_gic_properties; + dc->realize = mips_gic_realize; +} + +static const TypeInfo mips_gic_info = { + .name = TYPE_MIPS_GIC, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(MIPSGICState), + .instance_init = mips_gic_init, + .class_init = mips_gic_class_init, +}; + +static void mips_gic_register_types(void) +{ + type_register_static(&mips_gic_info); +} + +type_init(mips_gic_register_types) diff --git a/hw/lm32/lm32.h b/hw/lm32/lm32.h index e338bfeae5..db9eb29ea4 100644 --- a/hw/lm32/lm32.h +++ b/hw/lm32/lm32.h @@ -1,5 +1,5 @@ #ifndef HW_LM32_H -#define HW_LM32_H 1 +#define HW_LM32_H #include "hw/char/lm32_juart.h" diff --git a/hw/lm32/milkymist-hw.h b/hw/lm32/milkymist-hw.h index eb6a3a2559..4418b44ca9 100644 --- a/hw/lm32/milkymist-hw.h +++ b/hw/lm32/milkymist-hw.h @@ -1,5 +1,5 @@ -#ifndef QEMU_HW_MILKYMIST_H -#define QEMU_HW_MILKYMIST_H +#ifndef QEMU_HW_MILKYMIST_HW_H +#define QEMU_HW_MILKYMIST_HW_H #include "hw/qdev.h" #include "net/net.h" @@ -203,4 +203,4 @@ static inline DeviceState *milkymist_softusb_create(hwaddr base, return dev; } -#endif /* QEMU_HW_MILKYMIST_H */ +#endif /* QEMU_HW_MILKYMIST_HW_H */ diff --git a/hw/microblaze/boot.h b/hw/microblaze/boot.h index 0eb7f8e4f6..dd1090d8b5 100644 --- a/hw/microblaze/boot.h +++ b/hw/microblaze/boot.h @@ -1,5 +1,5 @@ -#ifndef __MICROBLAZE_BOOT__ -#define __MICROBLAZE_BOOT__ +#ifndef MICROBLAZE_BOOT_H +#define MICROBLAZE_BOOT_H #include "hw/hw.h" @@ -9,4 +9,4 @@ void microblaze_load_kernel(MicroBlazeCPU *cpu, hwaddr ddr_base, const char *dtb_filename, void (*machine_cpu_reset)(MicroBlazeCPU *)); -#endif /* __MICROBLAZE_BOOT __ */ +#endif /* MICROBLAZE_BOOT_H */ diff --git a/hw/mips/cps.c b/hw/mips/cps.c index 61208f8c69..77c621797a 100644 --- a/hw/mips/cps.c +++ b/hw/mips/cps.c @@ -26,13 +26,8 @@ qemu_irq get_cps_irq(MIPSCPSState *s, int pin_number) { - MIPSCPU *cpu = MIPS_CPU(first_cpu); - CPUMIPSState *env = &cpu->env; - assert(pin_number < s->num_irq); - - /* TODO: return GIC pins once implemented */ - return env->irq[pin_number]; + return s->gic.irq_state[pin_number].irq; } static void mips_cps_init(Object *obj) @@ -130,6 +125,21 @@ static void mips_cps_realize(DeviceState *dev, Error **errp) memory_region_add_subregion(&s->container, 0, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->cpc), 0)); + /* Global Interrupt Controller */ + object_initialize(&s->gic, sizeof(s->gic), TYPE_MIPS_GIC); + qdev_set_parent_bus(DEVICE(&s->gic), sysbus_get_default()); + + object_property_set_int(OBJECT(&s->gic), s->num_vp, "num-vp", &err); + object_property_set_int(OBJECT(&s->gic), 128, "num-irq", &err); + object_property_set_bool(OBJECT(&s->gic), true, "realized", &err); + if (err != NULL) { + error_propagate(errp, err); + return; + } + + memory_region_add_subregion(&s->container, 0, + sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->gic), 0)); + /* Global Configuration Registers */ gcr_base = env->CP0_CMGCRBase << 4; @@ -139,6 +149,7 @@ static void mips_cps_realize(DeviceState *dev, Error **errp) object_property_set_int(OBJECT(&s->gcr), s->num_vp, "num-vp", &err); object_property_set_int(OBJECT(&s->gcr), 0x800, "gcr-rev", &err); object_property_set_int(OBJECT(&s->gcr), gcr_base, "gcr-base", &err); + object_property_set_link(OBJECT(&s->gcr), OBJECT(&s->gic.mr), "gic", &err); object_property_set_link(OBJECT(&s->gcr), OBJECT(&s->cpc.mr), "cpc", &err); object_property_set_bool(OBJECT(&s->gcr), true, "realized", &err); if (err != NULL) { @@ -152,7 +163,7 @@ static void mips_cps_realize(DeviceState *dev, Error **errp) static Property mips_cps_properties[] = { DEFINE_PROP_UINT32("num-vp", MIPSCPSState, num_vp, 1), - DEFINE_PROP_UINT32("num-irq", MIPSCPSState, num_irq, 8), + DEFINE_PROP_UINT32("num-irq", MIPSCPSState, num_irq, 256), DEFINE_PROP_STRING("cpu-model", MIPSCPSState, cpu_model), DEFINE_PROP_END_OF_LIST() }; diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c index 5c8ba44c62..34d41ef44a 100644 --- a/hw/mips/mips_malta.c +++ b/hw/mips/mips_malta.c @@ -955,9 +955,7 @@ static void create_cps(MaltaState *s, const char *cpu_model, sysbus_mmio_map_overlap(SYS_BUS_DEVICE(s->cps), 0, 0, 1); - /* FIXME: When GIC is present then we should use GIC's IRQ 3. - Until then CPS exposes CPU's IRQs thus use the default IRQ 2. */ - *i8259_irq = get_cps_irq(s->cps, 2); + *i8259_irq = get_cps_irq(s->cps, 3); *cbus_irq = NULL; } diff --git a/hw/misc/hyperv_testdev.c b/hw/misc/hyperv_testdev.c index 1883fd7f20..6cae9e9010 100644 --- a/hw/misc/hyperv_testdev.c +++ b/hw/misc/hyperv_testdev.c @@ -12,11 +12,11 @@ */ #include "qemu/osdep.h" +#include <linux/kvm.h> #include "hw/hw.h" #include "hw/qdev.h" #include "hw/isa/isa.h" #include "sysemu/kvm.h" -#include "linux/kvm.h" #include "target-i386/hyperv.h" #include "kvm_i386.h" diff --git a/hw/misc/mips_cmgcr.c b/hw/misc/mips_cmgcr.c index 40f34643e3..b3ba16694e 100644 --- a/hw/misc/mips_cmgcr.c +++ b/hw/misc/mips_cmgcr.c @@ -17,12 +17,18 @@ #include "sysemu/sysemu.h" #include "hw/misc/mips_cmgcr.h" #include "hw/misc/mips_cpc.h" +#include "hw/intc/mips_gic.h" static inline bool is_cpc_connected(MIPSGCRState *s) { return s->cpc_mr != NULL; } +static inline bool is_gic_connected(MIPSGCRState *s) +{ + return s->gic_mr != NULL; +} + static inline void update_cpc_base(MIPSGCRState *gcr, uint64_t val) { if (is_cpc_connected(gcr)) { @@ -36,10 +42,25 @@ static inline void update_cpc_base(MIPSGCRState *gcr, uint64_t val) } } +static inline void update_gic_base(MIPSGCRState *gcr, uint64_t val) +{ + if (is_gic_connected(gcr)) { + gcr->gic_base = val & GCR_GIC_BASE_MSK; + memory_region_transaction_begin(); + memory_region_set_address(gcr->gic_mr, + gcr->gic_base & GCR_GIC_BASE_GICBASE_MSK); + memory_region_set_enabled(gcr->gic_mr, + gcr->gic_base & GCR_GIC_BASE_GICEN_MSK); + memory_region_transaction_commit(); + } +} + /* Read GCR registers */ static uint64_t gcr_read(void *opaque, hwaddr addr, unsigned size) { MIPSGCRState *gcr = (MIPSGCRState *) opaque; + MIPSGCRVPState *current_vps = &gcr->vps[current_cpu->cpu_index]; + MIPSGCRVPState *other_vps = &gcr->vps[current_vps->other]; switch (addr) { /* Global Control Block Register */ @@ -50,8 +71,12 @@ static uint64_t gcr_read(void *opaque, hwaddr addr, unsigned size) return gcr->gcr_base; case GCR_REV_OFS: return gcr->gcr_rev; + case GCR_GIC_BASE_OFS: + return gcr->gic_base; case GCR_CPC_BASE_OFS: return gcr->cpc_base; + case GCR_GIC_STATUS_OFS: + return is_gic_connected(gcr); case GCR_CPC_STATUS_OFS: return is_cpc_connected(gcr); case GCR_L2_CONFIG_OFS: @@ -62,8 +87,14 @@ static uint64_t gcr_read(void *opaque, hwaddr addr, unsigned size) case MIPS_COCB_OFS + GCR_CL_CONFIG_OFS: /* Set PVP to # of VPs - 1 */ return gcr->num_vps - 1; + case MIPS_CLCB_OFS + GCR_CL_RESETBASE_OFS: + return current_vps->reset_base; + case MIPS_COCB_OFS + GCR_CL_RESETBASE_OFS: + return other_vps->reset_base; case MIPS_CLCB_OFS + GCR_CL_OTHER_OFS: - return 0; + return current_vps->other; + case MIPS_COCB_OFS + GCR_CL_OTHER_OFS: + return other_vps->other; default: qemu_log_mask(LOG_UNIMP, "Read %d bytes at GCR offset 0x%" HWADDR_PRIx "\n", size, addr); @@ -72,15 +103,46 @@ static uint64_t gcr_read(void *opaque, hwaddr addr, unsigned size) return 0; } +static inline target_ulong get_exception_base(MIPSGCRVPState *vps) +{ + /* TODO: BEV_BASE and SELECT_BEV */ + return (int32_t)(vps->reset_base & GCR_CL_RESET_BASE_RESETBASE_MSK); +} + /* Write GCR registers */ static void gcr_write(void *opaque, hwaddr addr, uint64_t data, unsigned size) { MIPSGCRState *gcr = (MIPSGCRState *)opaque; + MIPSGCRVPState *current_vps = &gcr->vps[current_cpu->cpu_index]; + MIPSGCRVPState *other_vps = &gcr->vps[current_vps->other]; switch (addr) { + case GCR_GIC_BASE_OFS: + update_gic_base(gcr, data); + break; case GCR_CPC_BASE_OFS: update_cpc_base(gcr, data); break; + case MIPS_CLCB_OFS + GCR_CL_RESETBASE_OFS: + current_vps->reset_base = data & GCR_CL_RESET_BASE_MSK; + cpu_set_exception_base(current_cpu->cpu_index, + get_exception_base(current_vps)); + break; + case MIPS_COCB_OFS + GCR_CL_RESETBASE_OFS: + other_vps->reset_base = data & GCR_CL_RESET_BASE_MSK; + cpu_set_exception_base(current_vps->other, + get_exception_base(other_vps)); + break; + case MIPS_CLCB_OFS + GCR_CL_OTHER_OFS: + if ((data & GCR_CL_OTHER_MSK) < gcr->num_vps) { + current_vps->other = data & GCR_CL_OTHER_MSK; + } + break; + case MIPS_COCB_OFS + GCR_CL_OTHER_OFS: + if ((data & GCR_CL_OTHER_MSK) < gcr->num_vps) { + other_vps->other = data & GCR_CL_OTHER_MSK; + } + break; default: qemu_log_mask(LOG_UNIMP, "Write %d bytes at GCR offset 0x%" HWADDR_PRIx " 0x%" PRIx64 "\n", size, addr, data); @@ -102,6 +164,12 @@ static void mips_gcr_init(Object *obj) SysBusDevice *sbd = SYS_BUS_DEVICE(obj); MIPSGCRState *s = MIPS_GCR(obj); + object_property_add_link(obj, "gic", TYPE_MEMORY_REGION, + (Object **)&s->gic_mr, + qdev_prop_allow_set_link_before_realize, + OBJ_PROP_LINK_UNREF_ON_RELEASE, + &error_abort); + object_property_add_link(obj, "cpc", TYPE_MEMORY_REGION, (Object **)&s->cpc_mr, qdev_prop_allow_set_link_before_realize, @@ -116,8 +184,16 @@ static void mips_gcr_init(Object *obj) static void mips_gcr_reset(DeviceState *dev) { MIPSGCRState *s = MIPS_GCR(dev); + int i; + update_gic_base(s, 0); update_cpc_base(s, 0); + + for (i = 0; i < s->num_vps; i++) { + s->vps[i].other = 0; + s->vps[i].reset_base = 0xBFC00000 & GCR_CL_RESET_BASE_MSK; + cpu_set_exception_base(i, get_exception_base(&s->vps[i])); + } } static const VMStateDescription vmstate_mips_gcr = { @@ -137,12 +213,21 @@ static Property mips_gcr_properties[] = { DEFINE_PROP_END_OF_LIST(), }; +static void mips_gcr_realize(DeviceState *dev, Error **errp) +{ + MIPSGCRState *s = MIPS_GCR(dev); + + /* Create local set of registers for each VP */ + s->vps = g_new(MIPSGCRVPState, s->num_vps); +} + static void mips_gcr_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); dc->props = mips_gcr_properties; dc->vmsd = &vmstate_mips_gcr; dc->reset = mips_gcr_reset; + dc->realize = mips_gcr_realize; } static const TypeInfo mips_gcr_info = { diff --git a/hw/misc/mips_cpc.c b/hw/misc/mips_cpc.c index e6a35dd6a0..6d345745f6 100644 --- a/hw/misc/mips_cpc.c +++ b/hw/misc/mips_cpc.c @@ -37,7 +37,7 @@ static void cpc_run_vp(MIPSCPCState *cpc, uint64_t vp_run) CPU_FOREACH(cs) { uint64_t i = 1ULL << cs->cpu_index; if (i & vp_run & ~cpc->vp_running) { - cpu_interrupt(cs, CPU_INTERRUPT_WAKE); + cpu_reset(cs); cpc->vp_running |= i; } } @@ -50,8 +50,7 @@ static void cpc_stop_vp(MIPSCPCState *cpc, uint64_t vp_stop) CPU_FOREACH(cs) { uint64_t i = 1ULL << cs->cpu_index; if (i & vp_stop & cpc->vp_running) { - cs->halted = 1; - cpu_reset_interrupt(cs, CPU_INTERRUPT_WAKE); + cpu_interrupt(cs, CPU_INTERRUPT_HALT); cpc->vp_running &= ~i; } } diff --git a/hw/net/e1000_regs.h b/hw/net/e1000_regs.h index c1acd458f2..23eed50b9c 100644 --- a/hw/net/e1000_regs.h +++ b/hw/net/e1000_regs.h @@ -29,9 +29,8 @@ * Structures, enums, and macros for the MAC */ -#ifndef _E1000_HW_H_ -#define _E1000_HW_H_ - +#ifndef HW_E1000_REGS_H +#define HW_E1000_REGS_H /* PCI Device IDs */ #define E1000_DEV_ID_82542 0x1000 @@ -1248,4 +1247,4 @@ struct e1000_data_desc { #define E1000_IOADDR 0x00 #define E1000_IODATA 0x04 -#endif /* _E1000_HW_H_ */ +#endif /* HW_E1000_REGS_H */ diff --git a/hw/net/fsl_etsec/etsec.h b/hw/net/fsl_etsec/etsec.h index e7dc0a4b90..30c828e241 100644 --- a/hw/net/fsl_etsec/etsec.h +++ b/hw/net/fsl_etsec/etsec.h @@ -21,8 +21,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#ifndef _ETSEC_H_ -#define _ETSEC_H_ + +#ifndef ETSEC_H +#define ETSEC_H #include "hw/qdev.h" #include "hw/sysbus.h" @@ -173,4 +174,4 @@ void etsec_write_miim(eTSEC *etsec, void etsec_miim_link_status(eTSEC *etsec, NetClientState *nc); -#endif /* ! _ETSEC_H_ */ +#endif /* ETSEC_H */ diff --git a/hw/net/fsl_etsec/registers.h b/hw/net/fsl_etsec/registers.h index 6fb96842b8..c4ed2b9d62 100644 --- a/hw/net/fsl_etsec/registers.h +++ b/hw/net/fsl_etsec/registers.h @@ -21,9 +21,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#ifndef _ETSEC_REGISTERS_H_ -#define _ETSEC_REGISTERS_H_ +#ifndef ETSEC_REGISTERS_H +#define ETSEC_REGISTERS_H enum eTSEC_Register_Access_Type { ACC_RW = 1, /* Read/Write */ @@ -316,4 +316,4 @@ extern const eTSEC_Register_Definition eTSEC_registers_def[]; #define TMR_ETTS2_H (0xEA8 / 4) #define TMR_ETTS2_L (0xEAC / 4) -#endif /* ! _ETSEC_REGISTERS_H_ */ +#endif /* ETSEC_REGISTERS_H */ diff --git a/hw/net/ne2000.h b/hw/net/ne2000.h index d022b28fc2..d213dccae3 100644 --- a/hw/net/ne2000.h +++ b/hw/net/ne2000.h @@ -1,5 +1,5 @@ #ifndef HW_NE2000_H -#define HW_NE2000_H 1 +#define HW_NE2000_H #define NE2000_PMEM_SIZE (32*1024) #define NE2000_PMEM_START (16*1024) diff --git a/hw/net/pcnet.h b/hw/net/pcnet.h index dec8de834c..40831a7845 100644 --- a/hw/net/pcnet.h +++ b/hw/net/pcnet.h @@ -1,5 +1,5 @@ #ifndef HW_PCNET_H -#define HW_PCNET_H 1 +#define HW_PCNET_H #define PCNET_IOPORT_SIZE 0x20 #define PCNET_PNPMMIO_SIZE 0x20 diff --git a/hw/net/rocker/rocker.h b/hw/net/rocker/rocker.h index f9c80f8013..7ae0495d9e 100644 --- a/hw/net/rocker/rocker.h +++ b/hw/net/rocker/rocker.h @@ -16,8 +16,8 @@ * GNU General Public License for more details. */ -#ifndef _ROCKER_H_ -#define _ROCKER_H_ +#ifndef ROCKER_H +#define ROCKER_H #include "qemu/sockets.h" @@ -81,4 +81,4 @@ int rx_produce(World *world, uint32_t pport, int rocker_port_eg(Rocker *r, uint32_t pport, const struct iovec *iov, int iovcnt); -#endif /* _ROCKER_H_ */ +#endif /* ROCKER_H */ diff --git a/hw/net/rocker/rocker_desc.h b/hw/net/rocker/rocker_desc.h index d4041f5c4c..1dec335614 100644 --- a/hw/net/rocker/rocker_desc.h +++ b/hw/net/rocker/rocker_desc.h @@ -14,9 +14,8 @@ * GNU General Public License for more details. */ - -#ifndef _ROCKER_DESC_H_ -#define _ROCKER_DESC_H_ +#ifndef ROCKER_DESC_H +#define ROCKER_DESC_H #include "rocker_hw.h" diff --git a/hw/net/rocker/rocker_fp.h b/hw/net/rocker/rocker_fp.h index 04592bbfd2..dbe1dd329a 100644 --- a/hw/net/rocker/rocker_fp.h +++ b/hw/net/rocker/rocker_fp.h @@ -14,8 +14,8 @@ * GNU General Public License for more details. */ -#ifndef _ROCKER_FP_H_ -#define _ROCKER_FP_H_ +#ifndef ROCKER_FP_H +#define ROCKER_FP_H #include "net/net.h" #include "qemu/iov.h" @@ -51,4 +51,4 @@ FpPort *fp_port_alloc(Rocker *r, char *sw_name, void fp_port_free(FpPort *port); void fp_port_reset(FpPort *port); -#endif /* _ROCKER_FP_H_ */ +#endif /* ROCKER_FP_H */ diff --git a/hw/net/rocker/rocker_hw.h b/hw/net/rocker/rocker_hw.h index 8c50830325..1786323fa4 100644 --- a/hw/net/rocker/rocker_hw.h +++ b/hw/net/rocker/rocker_hw.h @@ -6,8 +6,8 @@ * */ -#ifndef _ROCKER_HW_ -#define _ROCKER_HW_ +#ifndef ROCKER_HW_H +#define ROCKER_HW_H #define __le16 uint16_t #define __le32 uint32_t @@ -490,4 +490,4 @@ enum rocker_of_dpa_overlay_type { */ #define ROCKER_CONTROL_RESET (1 << 0) -#endif /* _ROCKER_HW_ */ +#endif /* ROCKER_HW_H */ diff --git a/hw/net/rocker/rocker_of_dpa.h b/hw/net/rocker/rocker_of_dpa.h index f3f6d77807..01c7a97d0d 100644 --- a/hw/net/rocker/rocker_of_dpa.h +++ b/hw/net/rocker/rocker_of_dpa.h @@ -14,9 +14,9 @@ * GNU General Public License for more details. */ -#ifndef _ROCKER_OF_DPA_H_ -#define _ROCKER_OF_DPA_H_ +#ifndef ROCKER_OF_DPA_H +#define ROCKER_OF_DPA_H World *of_dpa_world_alloc(Rocker *r); -#endif /* _ROCKER_OF_DPA_H_ */ +#endif /* ROCKER_OF_DPA_H */ diff --git a/hw/net/rocker/rocker_tlv.h b/hw/net/rocker/rocker_tlv.h index 88561648f0..dd28d08443 100644 --- a/hw/net/rocker/rocker_tlv.h +++ b/hw/net/rocker/rocker_tlv.h @@ -14,8 +14,8 @@ * GNU General Public License for more details. */ -#ifndef _ROCKER_TLV_H_ -#define _ROCKER_TLV_H_ +#ifndef ROCKER_TLV_H +#define ROCKER_TLV_H #define ROCKER_TLV_ALIGNTO 8U #define ROCKER_TLV_ALIGN(len) \ diff --git a/hw/net/rocker/rocker_world.h b/hw/net/rocker/rocker_world.h index 58ade47335..44f1fe3e19 100644 --- a/hw/net/rocker/rocker_world.h +++ b/hw/net/rocker/rocker_world.h @@ -14,8 +14,8 @@ * GNU General Public License for more details. */ -#ifndef _ROCKER_WORLD_H_ -#define _ROCKER_WORLD_H_ +#ifndef ROCKER_WORLD_H +#define ROCKER_WORLD_H #include "rocker_hw.h" @@ -58,4 +58,4 @@ const char *world_name(World *world); World *rocker_get_world(Rocker *r, enum rocker_world_type type); -#endif /* _ROCKER_WORLD_H_ */ +#endif /* ROCKER_WORLD_H */ diff --git a/hw/net/vmxnet3.h b/hw/net/vmxnet3.h index f7006afe96..f9352c4a27 100644 --- a/hw/net/vmxnet3.h +++ b/hw/net/vmxnet3.h @@ -15,8 +15,8 @@ * */ -#ifndef _QEMU_VMXNET3_H -#define _QEMU_VMXNET3_H +#ifndef QEMU_VMXNET3_H +#define QEMU_VMXNET3_H #define VMXNET3_DEVICE_MAX_TX_QUEUES 8 #define VMXNET3_DEVICE_MAX_RX_QUEUES 8 /* Keep this value as a power of 2 */ diff --git a/hw/net/vmxnet_debug.h b/hw/net/vmxnet_debug.h index 5aab00b050..cb50aa95db 100644 --- a/hw/net/vmxnet_debug.h +++ b/hw/net/vmxnet_debug.h @@ -15,8 +15,8 @@ * */ -#ifndef _QEMU_VMXNET_DEBUG_H -#define _QEMU_VMXNET_DEBUG_H +#ifndef QEMU_VMXNET_DEBUG_H +#define QEMU_VMXNET_DEBUG_H #define VMXNET_DEVICE_NAME "vmxnet3" @@ -142,4 +142,4 @@ } \ } while (0) -#endif /* _QEMU_VMXNET3_DEBUG_H */ +#endif /* QEMU_VMXNET_DEBUG_H */ diff --git a/hw/pci-bridge/dec.h b/hw/pci-bridge/dec.h index 17dc0c2b0a..ae17ca7362 100644 --- a/hw/pci-bridge/dec.h +++ b/hw/pci-bridge/dec.h @@ -1,5 +1,5 @@ -#ifndef DEC_PCI_H -#define DEC_PCI_H +#ifndef HW_PCI_BRIDGE_DEC_H +#define HW_PCI_BRIDGE_DEC_H #include "qemu-common.h" diff --git a/hw/pci-bridge/ioh3420.c b/hw/pci-bridge/ioh3420.c index 93c6f0b7a2..0444b596c6 100644 --- a/hw/pci-bridge/ioh3420.c +++ b/hw/pci-bridge/ioh3420.c @@ -216,12 +216,3 @@ static void ioh3420_register_types(void) } type_init(ioh3420_register_types) - -/* - * Local variables: - * c-indent-level: 4 - * c-basic-offset: 4 - * tab-width: 8 - * indent-tab-mode: nil - * End: - */ diff --git a/hw/pci-bridge/xio3130_downstream.c b/hw/pci-bridge/xio3130_downstream.c index f6149a302d..cef6e1325e 100644 --- a/hw/pci-bridge/xio3130_downstream.c +++ b/hw/pci-bridge/xio3130_downstream.c @@ -203,12 +203,3 @@ static void xio3130_downstream_register_types(void) } type_init(xio3130_downstream_register_types) - -/* - * Local variables: - * c-indent-level: 4 - * c-basic-offset: 4 - * tab-width: 8 - * indent-tab-mode: nil - * End: - */ diff --git a/hw/pci-bridge/xio3130_upstream.c b/hw/pci-bridge/xio3130_upstream.c index 487edacc1d..4ad0440aa1 100644 --- a/hw/pci-bridge/xio3130_upstream.c +++ b/hw/pci-bridge/xio3130_upstream.c @@ -174,13 +174,3 @@ static void xio3130_upstream_register_types(void) } type_init(xio3130_upstream_register_types) - - -/* - * Local variables: - * c-indent-level: 4 - * c-basic-offset: 4 - * tab-width: 8 - * indent-tab-mode: nil - * End: - */ diff --git a/hw/pci-bridge/xio3130_upstream.h b/hw/pci-bridge/xio3130_upstream.h index 08c1d5f75b..d0ab7577e2 100644 --- a/hw/pci-bridge/xio3130_upstream.h +++ b/hw/pci-bridge/xio3130_upstream.h @@ -7,4 +7,4 @@ PCIEPort *xio3130_upstream_init(PCIBus *bus, int devfn, bool multifunction, const char *bus_name, pci_map_irq_fn map_irq, uint8_t port); -#endif /* QEMU_XIO3130_H */ +#endif /* QEMU_XIO3130_UPSTREAM_H */ diff --git a/hw/ppc/mac.h b/hw/ppc/mac.h index 5764b86c28..20cbddb4e4 100644 --- a/hw/ppc/mac.h +++ b/hw/ppc/mac.h @@ -22,8 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#if !defined(__PPC_MAC_H__) -#define __PPC_MAC_H__ + +#ifndef PPC_MAC_H +#define PPC_MAC_H #include "exec/memory.h" #include "hw/sysbus.h" @@ -184,4 +185,4 @@ typedef struct MacIONVRAMState { } MacIONVRAMState; void pmac_format_nvram_partition (MacIONVRAMState *nvr, int len); -#endif /* !defined(__PPC_MAC_H__) */ +#endif /* PPC_MAC_H */ diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h index 1c5f04fae1..c67febca2f 100644 --- a/hw/ppc/ppc405.h +++ b/hw/ppc/ppc405.h @@ -22,8 +22,8 @@ * THE SOFTWARE. */ -#if !defined(PPC_405_H) -#define PPC_405_H +#ifndef PPC405_H +#define PPC405_H #include "hw/ppc/ppc4xx.h" @@ -78,4 +78,4 @@ CPUPPCState *ppc_stb025_init (MemoryRegion ram_memories[2], uint32_t sysclk, qemu_irq **picp, ram_addr_t *offsetp); -#endif /* !defined(PPC_405_H) */ +#endif /* PPC405_H */ diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c index 70b6b0b5ee..9347f0741e 100644 --- a/hw/ppc/spapr_cpu_core.c +++ b/hw/ppc/spapr_cpu_core.c @@ -12,11 +12,11 @@ #include "hw/ppc/spapr.h" #include "hw/boards.h" #include "qapi/error.h" -#include <sysemu/cpus.h> +#include "sysemu/cpus.h" #include "target-ppc/kvm_ppc.h" #include "hw/ppc/ppc.h" #include "target-ppc/mmu-hash64.h" -#include <sysemu/numa.h> +#include "sysemu/numa.h" static void spapr_cpu_reset(void *opaque) { diff --git a/hw/ppc/spapr_pci_vfio.c b/hw/ppc/spapr_pci_vfio.c index f3cb141763..8448e0b024 100644 --- a/hw/ppc/spapr_pci_vfio.c +++ b/hw/ppc/spapr_pci_vfio.c @@ -18,13 +18,13 @@ */ #include "qemu/osdep.h" +#include <linux/vfio.h> #include "qapi/error.h" #include "qemu-common.h" #include "cpu.h" #include "hw/ppc/spapr.h" #include "hw/pci-host/spapr.h" #include "hw/pci/msix.h" -#include "linux/vfio.h" #include "hw/vfio/vfio.h" #include "qemu/error-report.h" #include "sysemu/qtest.h" diff --git a/hw/s390x/Makefile.objs b/hw/s390x/Makefile.objs index 220361782d..41ac4ec325 100644 --- a/hw/s390x/Makefile.objs +++ b/hw/s390x/Makefile.objs @@ -8,6 +8,8 @@ obj-y += ipl.o obj-y += css.o obj-y += s390-virtio-ccw.o obj-y += virtio-ccw.o +obj-y += css-bridge.o +obj-y += ccw-device.o obj-y += s390-pci-bus.o s390-pci-inst.o obj-y += s390-skeys.o obj-$(CONFIG_KVM) += s390-skeys-kvm.o diff --git a/hw/s390x/ccw-device.c b/hw/s390x/ccw-device.c new file mode 100644 index 0000000000..28ea20440e --- /dev/null +++ b/hw/s390x/ccw-device.c @@ -0,0 +1,27 @@ +/* + * Common device infrastructure for devices in the virtual css + * + * Copyright 2016 IBM Corp. + * Author(s): Jing Liu <liujbjl@linux.vnet.ibm.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at + * your option) any later version. See the COPYING file in the top-level + * directory. + */ +#include "qemu/osdep.h" +#include "ccw-device.h" + +static const TypeInfo ccw_device_info = { + .name = TYPE_CCW_DEVICE, + .parent = TYPE_DEVICE, + .instance_size = sizeof(CcwDevice), + .class_size = sizeof(CCWDeviceClass), + .abstract = true, +}; + +static void ccw_device_register(void) +{ + type_register_static(&ccw_device_info); +} + +type_init(ccw_device_register) diff --git a/hw/s390x/ccw-device.h b/hw/s390x/ccw-device.h new file mode 100644 index 0000000000..59ba01b6c5 --- /dev/null +++ b/hw/s390x/ccw-device.h @@ -0,0 +1,43 @@ +/* + * Common device infrastructure for devices in the virtual css + * + * Copyright 2016 IBM Corp. + * Author(s): Jing Liu <liujbjl@linux.vnet.ibm.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at + * your option) any later version. See the COPYING file in the top-level + * directory. + */ + +#ifndef HW_S390X_CCW_DEVICE_H +#define HW_S390X_CCW_DEVICE_H +#include "qom/object.h" +#include "hw/qdev-core.h" +#include "hw/s390x/css.h" + +typedef struct CcwDevice { + DeviceState parent_obj; + SubchDev *sch; + /* <cssid>.<ssid>.<device number> */ + CssDevId bus_id; +} CcwDevice; + +typedef struct CCWDeviceClass { + DeviceClass parent_class; + void (*unplug)(HotplugHandler *, DeviceState *, Error **); +} CCWDeviceClass; + +static inline CcwDevice *to_ccw_dev_fast(DeviceState *d) +{ + return container_of(d, CcwDevice, parent_obj); +} + +#define TYPE_CCW_DEVICE "ccw-device" + +#define CCW_DEVICE(obj) OBJECT_CHECK(CcwDevice, (obj), TYPE_CCW_DEVICE) +#define CCW_DEVICE_GET_CLASS(obj) \ + OBJECT_GET_CLASS(CCWDeviceClass, (obj), TYPE_CCW_DEVICE) +#define CCW_DEVICE_CLASS(klass) \ + OBJECT_CLASS_CHECK(CCWDeviceClass, (klass), TYPE_CCW_DEVICE) + +#endif diff --git a/hw/s390x/css-bridge.c b/hw/s390x/css-bridge.c new file mode 100644 index 0000000000..e4c24e21f3 --- /dev/null +++ b/hw/s390x/css-bridge.c @@ -0,0 +1,124 @@ +/* + * css bridge implementation + * + * Copyright 2012,2016 IBM Corp. + * Author(s): Cornelia Huck <cornelia.huck@de.ibm.com> + * Pierre Morel <pmorel@linux.vnet.ibm.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at + * your option) any later version. See the COPYING file in the top-level + * directory. + */ +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "hw/hotplug.h" +#include "hw/sysbus.h" +#include "qemu/bitops.h" +#include "hw/s390x/css.h" +#include "ccw-device.h" +#include "hw/s390x/css-bridge.h" + +/* + * Invoke device-specific unplug handler, disable the subchannel + * (including sending a channel report to the guest) and remove the + * device from the virtual css bus. + */ +static void ccw_device_unplug(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + CcwDevice *ccw_dev = CCW_DEVICE(dev); + CCWDeviceClass *k = CCW_DEVICE_GET_CLASS(ccw_dev); + SubchDev *sch = ccw_dev->sch; + Error *err = NULL; + + if (k->unplug) { + k->unplug(hotplug_dev, dev, &err); + if (err) { + error_propagate(errp, err); + return; + } + } + + /* + * We should arrive here only for device_del, since we don't support + * direct hot(un)plug of channels. + */ + assert(sch != NULL); + /* Subchannel is now disabled and no longer valid. */ + sch->curr_status.pmcw.flags &= ~(PMCW_FLAGS_MASK_ENA | + PMCW_FLAGS_MASK_DNV); + + css_generate_sch_crws(sch->cssid, sch->ssid, sch->schid, 1, 0); + + object_unparent(OBJECT(dev)); +} + +static void virtual_css_bus_reset(BusState *qbus) +{ + /* This should actually be modelled via the generic css */ + css_reset(); +} + +static void virtual_css_bus_class_init(ObjectClass *klass, void *data) +{ + BusClass *k = BUS_CLASS(klass); + + k->reset = virtual_css_bus_reset; +} + +static const TypeInfo virtual_css_bus_info = { + .name = TYPE_VIRTUAL_CSS_BUS, + .parent = TYPE_BUS, + .instance_size = sizeof(VirtualCssBus), + .class_init = virtual_css_bus_class_init, +}; + +VirtualCssBus *virtual_css_bus_init(void) +{ + VirtualCssBus *cbus; + BusState *bus; + DeviceState *dev; + + /* Create bridge device */ + dev = qdev_create(NULL, TYPE_VIRTUAL_CSS_BRIDGE); + qdev_init_nofail(dev); + + /* Create bus on bridge device */ + bus = qbus_create(TYPE_VIRTUAL_CSS_BUS, dev, "virtual-css"); + cbus = VIRTUAL_CSS_BUS(bus); + + /* Enable hotplugging */ + qbus_set_hotplug_handler(bus, dev, &error_abort); + + return cbus; + } + +/***************** Virtual-css Bus Bridge Device ********************/ + +static void virtual_css_bridge_class_init(ObjectClass *klass, void *data) +{ + HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass); + DeviceClass *dc = DEVICE_CLASS(klass); + + hc->unplug = ccw_device_unplug; + set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); +} + +static const TypeInfo virtual_css_bridge_info = { + .name = TYPE_VIRTUAL_CSS_BRIDGE, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(SysBusDevice), + .class_init = virtual_css_bridge_class_init, + .interfaces = (InterfaceInfo[]) { + { TYPE_HOTPLUG_HANDLER }, + { } + } +}; + +static void virtual_css_register(void) +{ + type_register_static(&virtual_css_bridge_info); + type_register_static(&virtual_css_bus_info); +} + +type_init(virtual_css_register) diff --git a/hw/s390x/css.c b/hw/s390x/css.c index 76668814da..aa61773885 100644 --- a/hw/s390x/css.c +++ b/hw/s390x/css.c @@ -12,7 +12,7 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "qapi/visitor.h" -#include <hw/qdev.h> +#include "hw/qdev.h" #include "qemu/bitops.h" #include "exec/address-spaces.h" #include "cpu.h" @@ -1340,6 +1340,116 @@ SubchDev *css_find_subch(uint8_t m, uint8_t cssid, uint8_t ssid, uint16_t schid) return channel_subsys.css[real_cssid]->sch_set[ssid]->sch[schid]; } +/** + * Return free device number in subchannel set. + * + * Return index of the first free device number in the subchannel set + * identified by @p cssid and @p ssid, beginning the search at @p + * start and wrapping around at MAX_DEVNO. Return a value exceeding + * MAX_SCHID if there are no free device numbers in the subchannel + * set. + */ +static uint32_t css_find_free_devno(uint8_t cssid, uint8_t ssid, + uint16_t start) +{ + uint32_t round; + + for (round = 0; round <= MAX_DEVNO; round++) { + uint16_t devno = (start + round) % MAX_DEVNO; + + if (!css_devno_used(cssid, ssid, devno)) { + return devno; + } + } + return MAX_DEVNO + 1; +} + +/** + * Return first free subchannel (id) in subchannel set. + * + * Return index of the first free subchannel in the subchannel set + * identified by @p cssid and @p ssid, if there is any. Return a value + * exceeding MAX_SCHID if there are no free subchannels in the + * subchannel set. + */ +static uint32_t css_find_free_subch(uint8_t cssid, uint8_t ssid) +{ + uint32_t schid; + + for (schid = 0; schid <= MAX_SCHID; schid++) { + if (!css_find_subch(1, cssid, ssid, schid)) { + return schid; + } + } + return MAX_SCHID + 1; +} + +/** + * Return first free subchannel (id) in subchannel set for a device number + * + * Verify the device number @p devno is not used yet in the subchannel + * set identified by @p cssid and @p ssid. Set @p schid to the index + * of the first free subchannel in the subchannel set, if there is + * any. Return true if everything succeeded and false otherwise. + */ +static bool css_find_free_subch_for_devno(uint8_t cssid, uint8_t ssid, + uint16_t devno, uint16_t *schid, + Error **errp) +{ + uint32_t free_schid; + + assert(schid); + if (css_devno_used(cssid, ssid, devno)) { + error_setg(errp, "Device %x.%x.%04x already exists", + cssid, ssid, devno); + return false; + } + free_schid = css_find_free_subch(cssid, ssid); + if (free_schid > MAX_SCHID) { + error_setg(errp, "No free subchannel found for %x.%x.%04x", + cssid, ssid, devno); + return false; + } + *schid = free_schid; + return true; +} + +/** + * Return first free subchannel (id) and device number + * + * Locate the first free subchannel and first free device number in + * any of the subchannel sets of the channel subsystem identified by + * @p cssid. Return false if no free subchannel / device number could + * be found. Otherwise set @p ssid, @p devno and @p schid to identify + * the available subchannel and device number and return true. + * + * May modify @p ssid, @p devno and / or @p schid even if no free + * subchannel / device number could be found. + */ +static bool css_find_free_subch_and_devno(uint8_t cssid, uint8_t *ssid, + uint16_t *devno, uint16_t *schid, + Error **errp) +{ + uint32_t free_schid, free_devno; + + assert(ssid && devno && schid); + for (*ssid = 0; *ssid <= MAX_SSID; (*ssid)++) { + free_schid = css_find_free_subch(cssid, *ssid); + if (free_schid > MAX_SCHID) { + continue; + } + free_devno = css_find_free_devno(cssid, *ssid, free_schid); + if (free_devno > MAX_DEVNO) { + continue; + } + *schid = free_schid; + *devno = free_devno; + return true; + } + error_setg(errp, "Virtual channel subsystem is full!"); + return false; +} + bool css_subch_visible(SubchDev *sch) { if (sch->ssid > channel_subsys.max_ssid) { @@ -1762,3 +1872,36 @@ PropertyInfo css_devid_propinfo = { .get = get_css_devid, .set = set_css_devid, }; + +SubchDev *css_create_virtual_sch(CssDevId bus_id, Error **errp) +{ + uint16_t schid = 0; + SubchDev *sch; + + if (bus_id.valid) { + /* Enforce use of virtual cssid. */ + if (bus_id.cssid != VIRTUAL_CSSID) { + error_setg(errp, "cssid %hhx not valid for virtual devices", + bus_id.cssid); + return NULL; + } + if (!css_find_free_subch_for_devno(bus_id.cssid, bus_id.ssid, + bus_id.devid, &schid, errp)) { + return NULL; + } + } else { + bus_id.cssid = VIRTUAL_CSSID; + if (!css_find_free_subch_and_devno(bus_id.cssid, &bus_id.ssid, + &bus_id.devid, &schid, errp)) { + return NULL; + } + } + + sch = g_malloc0(sizeof(*sch)); + sch->cssid = bus_id.cssid; + sch->ssid = bus_id.ssid; + sch->devno = bus_id.devid; + sch->schid = schid; + css_subch_assign(sch->cssid, sch->ssid, schid, sch->devno, sch); + return sch; +} diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c index e6bf7cf7c0..2e2664f22e 100644 --- a/hw/s390x/ipl.c +++ b/hw/s390x/ipl.c @@ -69,8 +69,8 @@ static const VMStateDescription vmstate_ipl = { .version_id = 0, .minimum_version_id = 0, .fields = (VMStateField[]) { - VMSTATE_UINT64(start_addr, S390IPLState), - VMSTATE_UINT64(bios_start_addr, S390IPLState), + VMSTATE_UINT64(compat_start_addr, S390IPLState), + VMSTATE_UINT64(compat_bios_start_addr, S390IPLState), VMSTATE_STRUCT(iplb, S390IPLState, 0, vmstate_iplb, IplParameterBlock), VMSTATE_BOOL(iplb_valid, S390IPLState), VMSTATE_UINT8(cssid, S390IPLState), @@ -192,6 +192,13 @@ static void s390_ipl_realize(DeviceState *dev, Error **errp) stq_p(rom_ptr(INITRD_PARM_SIZE), initrd_size); } } + /* + * Don't ever use the migrated values, they could come from a different + * BIOS and therefore don't work. But still migrate the values, so + * QEMUs relying on it don't break. + */ + ipl->compat_start_addr = ipl->start_addr; + ipl->compat_bios_start_addr = ipl->bios_start_addr; qemu_register_reset(qdev_reset_all_fn, dev); error: error_propagate(errp, err); @@ -214,10 +221,14 @@ static bool s390_gen_initial_iplb(S390IPLState *ipl) dev_st = get_boot_device(0); if (dev_st) { - VirtioCcwDevice *ccw_dev = (VirtioCcwDevice *) object_dynamic_cast( - OBJECT(qdev_get_parent_bus(dev_st)->parent), + VirtioCcwDevice *virtio_ccw_dev = (VirtioCcwDevice *) + object_dynamic_cast(OBJECT(qdev_get_parent_bus(dev_st)->parent), TYPE_VIRTIO_CCW_DEVICE); - if (ccw_dev) { + SCSIDevice *sd = (SCSIDevice *) object_dynamic_cast(OBJECT(dev_st), + TYPE_SCSI_DEVICE); + if (virtio_ccw_dev) { + CcwDevice *ccw_dev = CCW_DEVICE(virtio_ccw_dev); + ipl->iplb.len = cpu_to_be32(S390_IPLB_MIN_CCW_LEN); ipl->iplb.blk0_len = cpu_to_be32(S390_IPLB_MIN_CCW_LEN - S390_IPLB_HEADER_LEN); @@ -225,6 +236,22 @@ static bool s390_gen_initial_iplb(S390IPLState *ipl) ipl->iplb.ccw.devno = cpu_to_be16(ccw_dev->sch->devno); ipl->iplb.ccw.ssid = ccw_dev->sch->ssid & 3; return true; + } else if (sd) { + SCSIBus *bus = scsi_bus_from_device(sd); + VirtIOSCSI *vdev = container_of(bus, VirtIOSCSI, bus); + VirtIOSCSICcw *scsi_ccw = container_of(vdev, VirtIOSCSICcw, vdev); + CcwDevice *ccw_dev = CCW_DEVICE(scsi_ccw); + + ipl->iplb.len = cpu_to_be32(S390_IPLB_MIN_QEMU_SCSI_LEN); + ipl->iplb.blk0_len = + cpu_to_be32(S390_IPLB_MIN_QEMU_SCSI_LEN - S390_IPLB_HEADER_LEN); + ipl->iplb.pbt = S390_IPL_TYPE_QEMU_SCSI; + ipl->iplb.scsi.lun = cpu_to_be32(sd->lun); + ipl->iplb.scsi.target = cpu_to_be16(sd->id); + ipl->iplb.scsi.channel = cpu_to_be16(sd->channel); + ipl->iplb.scsi.devno = cpu_to_be16(ccw_dev->sch->devno); + ipl->iplb.scsi.ssid = ccw_dev->sch->ssid & 3; + return true; } } diff --git a/hw/s390x/ipl.h b/hw/s390x/ipl.h index 9aa4d942a7..c89109585a 100644 --- a/hw/s390x/ipl.h +++ b/hw/s390x/ipl.h @@ -46,6 +46,16 @@ struct IplBlockFcp { } QEMU_PACKED; typedef struct IplBlockFcp IplBlockFcp; +struct IplBlockQemuScsi { + uint32_t lun; + uint16_t target; + uint16_t channel; + uint8_t reserved0[77]; + uint8_t ssid; + uint16_t devno; +} QEMU_PACKED; +typedef struct IplBlockQemuScsi IplBlockQemuScsi; + union IplParameterBlock { struct { uint32_t len; @@ -59,6 +69,7 @@ union IplParameterBlock { union { IplBlockCcw ccw; IplBlockFcp fcp; + IplBlockQemuScsi scsi; }; } QEMU_PACKED; struct { @@ -82,7 +93,9 @@ struct S390IPLState { /*< private >*/ DeviceState parent_obj; uint64_t start_addr; + uint64_t compat_start_addr; uint64_t bios_start_addr; + uint64_t compat_bios_start_addr; bool enforce_bios; IplParameterBlock iplb; bool iplb_valid; @@ -102,10 +115,12 @@ typedef struct S390IPLState S390IPLState; #define S390_IPL_TYPE_FCP 0x00 #define S390_IPL_TYPE_CCW 0x02 +#define S390_IPL_TYPE_QEMU_SCSI 0xff #define S390_IPLB_HEADER_LEN 8 #define S390_IPLB_MIN_CCW_LEN 200 #define S390_IPLB_MIN_FCP_LEN 384 +#define S390_IPLB_MIN_QEMU_SCSI_LEN 200 static inline bool iplb_valid_len(IplParameterBlock *iplb) { diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c index a77c10ce9e..47ca853bd2 100644 --- a/hw/s390x/s390-pci-bus.c +++ b/hw/s390x/s390-pci-bus.c @@ -12,13 +12,15 @@ */ #include "qemu/osdep.h" +#include "qapi/error.h" +#include "qapi/visitor.h" #include "qemu-common.h" #include "cpu.h" #include "s390-pci-bus.h" #include "s390-pci-inst.h" -#include <hw/pci/pci_bus.h> -#include <hw/pci/msi.h> -#include <qemu/error-report.h> +#include "hw/pci/pci_bus.h" +#include "hw/pci/msi.h" +#include "qemu/error-report.h" /* #define DEBUG_S390PCI_BUS */ #ifdef DEBUG_S390PCI_BUS @@ -29,6 +31,19 @@ do { } while (0) #endif +static S390pciState *s390_get_phb(void) +{ + static S390pciState *phb; + + if (!phb) { + phb = S390_PCI_HOST_BRIDGE( + object_resolve_path(TYPE_S390_PCI_HOST_BRIDGE, NULL)); + assert(phb != NULL); + } + + return phb; +} + int chsc_sei_nt2_get_event(void *res) { ChscSeiNt2Res *nt2_res = (ChscSeiNt2Res *)res; @@ -36,12 +51,7 @@ int chsc_sei_nt2_get_event(void *res) PciCcdfErr *eccdf; int rc = 1; SeiContainer *sei_cont; - S390pciState *s = S390_PCI_HOST_BRIDGE( - object_resolve_path(TYPE_S390_PCI_HOST_BRIDGE, NULL)); - - if (!s) { - return rc; - } + S390pciState *s = s390_get_phb(); sei_cont = QTAILQ_FIRST(&s->pending_sei); if (sei_cont) { @@ -76,30 +86,40 @@ int chsc_sei_nt2_get_event(void *res) int chsc_sei_nt2_have_event(void) { - S390pciState *s = S390_PCI_HOST_BRIDGE( - object_resolve_path(TYPE_S390_PCI_HOST_BRIDGE, NULL)); + S390pciState *s = s390_get_phb(); - if (!s) { - return 0; + return !QTAILQ_EMPTY(&s->pending_sei); +} + +S390PCIBusDevice *s390_pci_find_next_avail_dev(S390PCIBusDevice *pbdev) +{ + int idx = 0; + S390PCIBusDevice *dev = NULL; + S390pciState *s = s390_get_phb(); + + if (pbdev) { + idx = (pbdev->fh & FH_MASK_INDEX) + 1; } - return !QTAILQ_EMPTY(&s->pending_sei); + for (; idx < PCI_SLOT_MAX; idx++) { + dev = s->pbdev[idx]; + if (dev && dev->state != ZPCI_FS_RESERVED) { + return dev; + } + } + + return NULL; } S390PCIBusDevice *s390_pci_find_dev_by_fid(uint32_t fid) { S390PCIBusDevice *pbdev; int i; - S390pciState *s = S390_PCI_HOST_BRIDGE( - object_resolve_path(TYPE_S390_PCI_HOST_BRIDGE, NULL)); - - if (!s) { - return NULL; - } + S390pciState *s = s390_get_phb(); for (i = 0; i < PCI_SLOT_MAX; i++) { - pbdev = &s->pbdev[i]; - if ((pbdev->fh != 0) && (pbdev->fid == fid)) { + pbdev = s->pbdev[i]; + if (pbdev && pbdev->fid == fid) { return pbdev; } } @@ -118,16 +138,22 @@ void s390_pci_sclp_configure(SCCB *sccb) goto out; } - if (pbdev) { - if (pbdev->configured) { - rc = SCLP_RC_NO_ACTION_REQUIRED; - } else { - pbdev->configured = true; - rc = SCLP_RC_NORMAL_COMPLETION; - } - } else { + if (!pbdev) { DPRINTF("sclp config no dev found\n"); rc = SCLP_RC_ADAPTER_ID_NOT_RECOGNIZED; + goto out; + } + + switch (pbdev->state) { + case ZPCI_FS_RESERVED: + rc = SCLP_RC_ADAPTER_IN_RESERVED_STATE; + break; + case ZPCI_FS_STANDBY: + pbdev->state = ZPCI_FS_DISABLED; + rc = SCLP_RC_NORMAL_COMPLETION; + break; + default: + rc = SCLP_RC_NO_ACTION_REQUIRED; } out: psccb->header.response_code = cpu_to_be16(rc); @@ -144,81 +170,96 @@ void s390_pci_sclp_deconfigure(SCCB *sccb) goto out; } - if (pbdev) { - if (!pbdev->configured) { - rc = SCLP_RC_NO_ACTION_REQUIRED; - } else { - if (pbdev->summary_ind) { - pci_dereg_irqs(pbdev); - } - if (pbdev->iommu_enabled) { - pci_dereg_ioat(pbdev); - } - pbdev->configured = false; - rc = SCLP_RC_NORMAL_COMPLETION; - } - } else { + if (!pbdev) { DPRINTF("sclp deconfig no dev found\n"); rc = SCLP_RC_ADAPTER_ID_NOT_RECOGNIZED; + goto out; + } + + switch (pbdev->state) { + case ZPCI_FS_RESERVED: + rc = SCLP_RC_ADAPTER_IN_RESERVED_STATE; + break; + case ZPCI_FS_STANDBY: + rc = SCLP_RC_NO_ACTION_REQUIRED; + break; + default: + if (pbdev->summary_ind) { + pci_dereg_irqs(pbdev); + } + if (pbdev->iommu_enabled) { + pci_dereg_ioat(pbdev); + } + pbdev->state = ZPCI_FS_STANDBY; + rc = SCLP_RC_NORMAL_COMPLETION; + + if (pbdev->release_timer) { + qdev_unplug(DEVICE(pbdev->pdev), NULL); + } } out: psccb->header.response_code = cpu_to_be16(rc); } -static uint32_t s390_pci_get_pfid(PCIDevice *pdev) +static S390PCIBusDevice *s390_pci_find_dev_by_uid(uint16_t uid) { - return PCI_SLOT(pdev->devfn); -} + int i; + S390PCIBusDevice *pbdev; + S390pciState *s = s390_get_phb(); -static uint32_t s390_pci_get_pfh(PCIDevice *pdev) -{ - return PCI_SLOT(pdev->devfn) | FH_VIRT; + for (i = 0; i < PCI_SLOT_MAX; i++) { + pbdev = s->pbdev[i]; + if (!pbdev) { + continue; + } + + if (pbdev->uid == uid) { + return pbdev; + } + } + + return NULL; } -S390PCIBusDevice *s390_pci_find_dev_by_idx(uint32_t idx) +static S390PCIBusDevice *s390_pci_find_dev_by_target(const char *target) { - S390PCIBusDevice *pbdev; int i; - int j = 0; - S390pciState *s = S390_PCI_HOST_BRIDGE( - object_resolve_path(TYPE_S390_PCI_HOST_BRIDGE, NULL)); + S390PCIBusDevice *pbdev; + S390pciState *s = s390_get_phb(); - if (!s) { + if (!target) { return NULL; } for (i = 0; i < PCI_SLOT_MAX; i++) { - pbdev = &s->pbdev[i]; - - if (pbdev->fh == 0) { + pbdev = s->pbdev[i]; + if (!pbdev) { continue; } - if (j == idx) { + if (!strcmp(pbdev->target, target)) { return pbdev; } - j++; } return NULL; } +S390PCIBusDevice *s390_pci_find_dev_by_idx(uint32_t idx) +{ + S390pciState *s = s390_get_phb(); + + return s->pbdev[idx & FH_MASK_INDEX]; +} + S390PCIBusDevice *s390_pci_find_dev_by_fh(uint32_t fh) { + S390pciState *s = s390_get_phb(); S390PCIBusDevice *pbdev; - int i; - S390pciState *s = S390_PCI_HOST_BRIDGE( - object_resolve_path(TYPE_S390_PCI_HOST_BRIDGE, NULL)); - if (!s || !fh) { - return NULL; - } - - for (i = 0; i < PCI_SLOT_MAX; i++) { - pbdev = &s->pbdev[i]; - if (pbdev->fh == fh) { - return pbdev; - } + pbdev = s->pbdev[fh & FH_MASK_INDEX]; + if (pbdev && pbdev->fh == fh) { + return pbdev; } return NULL; @@ -228,12 +269,7 @@ static void s390_pci_generate_event(uint8_t cc, uint16_t pec, uint32_t fh, uint32_t fid, uint64_t faddr, uint32_t e) { SeiContainer *sei_cont; - S390pciState *s = S390_PCI_HOST_BRIDGE( - object_resolve_path(TYPE_S390_PCI_HOST_BRIDGE, NULL)); - - if (!s) { - return; - } + S390pciState *s = s390_get_phb(); sei_cont = g_malloc0(sizeof(SeiContainer)); sei_cont->fh = fh; @@ -253,9 +289,8 @@ static void s390_pci_generate_plug_event(uint16_t pec, uint32_t fh, s390_pci_generate_event(2, pec, fh, fid, 0, 0); } -static void s390_pci_generate_error_event(uint16_t pec, uint32_t fh, - uint32_t fid, uint64_t faddr, - uint32_t e) +void s390_pci_generate_error_event(uint16_t pec, uint32_t fh, uint32_t fid, + uint64_t faddr, uint32_t e) { s390_pci_generate_event(1, pec, fh, fid, faddr, e); } @@ -357,8 +392,14 @@ static IOMMUTLBEntry s390_translate_iommu(MemoryRegion *iommu, hwaddr addr, .perm = IOMMU_NONE, }; - if (!pbdev->configured || !pbdev->pdev || - !(pbdev->fh & FH_ENABLED) || !pbdev->iommu_enabled) { + switch (pbdev->state) { + case ZPCI_FS_ENABLED: + case ZPCI_FS_BLOCKED: + if (!pbdev->iommu_enabled) { + return ret; + } + break; + default: return ret; } @@ -377,30 +418,13 @@ static IOMMUTLBEntry s390_translate_iommu(MemoryRegion *iommu, hwaddr addr, return ret; } - if (!pbdev->g_iota) { - pbdev->error_state = true; - pbdev->lgstg_blocked = true; - s390_pci_generate_error_event(ERR_EVENT_INVALAS, pbdev->fh, pbdev->fid, - addr, 0); - return ret; - } - if (addr < pbdev->pba || addr > pbdev->pal) { - pbdev->error_state = true; - pbdev->lgstg_blocked = true; - s390_pci_generate_error_event(ERR_EVENT_OORANGE, pbdev->fh, pbdev->fid, - addr, 0); return ret; } pte = s390_guest_io_table_walk(s390_pci_get_table_origin(pbdev->g_iota), addr); - if (!pte) { - pbdev->error_state = true; - pbdev->lgstg_blocked = true; - s390_pci_generate_error_event(ERR_EVENT_SERR, pbdev->fh, pbdev->fid, - addr, ERR_EVENT_Q_BIT); return ret; } @@ -426,7 +450,7 @@ static AddressSpace *s390_pci_dma_iommu(PCIBus *bus, void *opaque, int devfn) { S390pciState *s = opaque; - return &s->pbdev[PCI_SLOT(devfn)].as; + return &s->iommu[PCI_SLOT(devfn)]->as; } static uint8_t set_ind_atomic(uint64_t ind_loc, uint8_t to_be_set) @@ -454,22 +478,22 @@ static void s390_msi_ctrl_write(void *opaque, hwaddr addr, uint64_t data, { S390PCIBusDevice *pbdev; uint32_t io_int_word; - uint32_t fid = data >> ZPCI_MSI_VEC_BITS; + uint32_t idx = data >> ZPCI_MSI_VEC_BITS; uint32_t vec = data & ZPCI_MSI_VEC_MASK; uint64_t ind_bit; uint32_t sum_bit; uint32_t e = 0; - DPRINTF("write_msix data 0x%" PRIx64 " fid %d vec 0x%x\n", data, fid, vec); + DPRINTF("write_msix data 0x%" PRIx64 " idx %d vec 0x%x\n", data, idx, vec); - pbdev = s390_pci_find_dev_by_fid(fid); + pbdev = s390_pci_find_dev_by_idx(idx); if (!pbdev) { e |= (vec << ERR_EVENT_MVN_OFFSET); - s390_pci_generate_error_event(ERR_EVENT_NOMSI, 0, fid, addr, e); + s390_pci_generate_error_event(ERR_EVENT_NOMSI, idx, 0, addr, e); return; } - if (!(pbdev->fh & FH_ENABLED)) { + if (pbdev->state != ZPCI_FS_ENABLED) { return; } @@ -498,17 +522,15 @@ static const MemoryRegionOps s390_msi_ctrl_ops = { void s390_pci_iommu_enable(S390PCIBusDevice *pbdev) { - uint64_t size = pbdev->pal - pbdev->pba + 1; - - memory_region_init_iommu(&pbdev->iommu_mr, OBJECT(&pbdev->mr), - &s390_iommu_ops, "iommu-s390", size); - memory_region_add_subregion(&pbdev->mr, pbdev->pba, &pbdev->iommu_mr); + memory_region_init_iommu(&pbdev->iommu_mr, OBJECT(&pbdev->iommu->mr), + &s390_iommu_ops, "iommu-s390", pbdev->pal + 1); + memory_region_add_subregion(&pbdev->iommu->mr, 0, &pbdev->iommu_mr); pbdev->iommu_enabled = true; } void s390_pci_iommu_disable(S390PCIBusDevice *pbdev) { - memory_region_del_subregion(&pbdev->mr, &pbdev->iommu_mr); + memory_region_del_subregion(&pbdev->iommu->mr, &pbdev->iommu_mr); object_unparent(OBJECT(&pbdev->iommu_mr)); pbdev->iommu_enabled = false; } @@ -516,13 +538,15 @@ void s390_pci_iommu_disable(S390PCIBusDevice *pbdev) static void s390_pcihost_init_as(S390pciState *s) { int i; - S390PCIBusDevice *pbdev; + S390PCIIOMMU *iommu; for (i = 0; i < PCI_SLOT_MAX; i++) { - pbdev = &s->pbdev[i]; - memory_region_init(&pbdev->mr, OBJECT(s), + iommu = g_malloc0(sizeof(S390PCIIOMMU)); + memory_region_init(&iommu->mr, OBJECT(s), "iommu-root-s390", UINT64_MAX); - address_space_init(&pbdev->as, &pbdev->mr, "iommu-pci"); + address_space_init(&iommu->as, &iommu->mr, "iommu-pci"); + + s->iommu[i] = iommu; } memory_region_init_io(&s->msix_notify_mr, OBJECT(s), @@ -549,6 +573,10 @@ static int s390_pcihost_init(SysBusDevice *dev) bus = BUS(b); qbus_set_hotplug_handler(bus, DEVICE(dev), NULL); phb->bus = b; + + s->bus = S390_PCI_BUS(qbus_create(TYPE_S390_PCI_BUS, DEVICE(s), NULL)); + qbus_set_hotplug_handler(BUS(s->bus), DEVICE(s), NULL); + QTAILQ_INIT(&s->pending_sei); return 0; } @@ -581,51 +609,155 @@ static int s390_pcihost_setup_msix(S390PCIBusDevice *pbdev) return 0; } +static S390PCIBusDevice *s390_pci_device_new(const char *target) +{ + DeviceState *dev = NULL; + S390pciState *s = s390_get_phb(); + + dev = qdev_try_create(BUS(s->bus), TYPE_S390_PCI_DEVICE); + if (!dev) { + return NULL; + } + + qdev_prop_set_string(dev, "target", target); + qdev_init_nofail(dev); + + return S390_PCI_DEVICE(dev); +} + static void s390_pcihost_hot_plug(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { - PCIDevice *pci_dev = PCI_DEVICE(dev); - S390PCIBusDevice *pbdev; - S390pciState *s = S390_PCI_HOST_BRIDGE(pci_device_root_bus(pci_dev) - ->qbus.parent); + PCIDevice *pdev = NULL; + S390PCIBusDevice *pbdev = NULL; + S390pciState *s = s390_get_phb(); - pbdev = &s->pbdev[PCI_SLOT(pci_dev->devfn)]; + if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) { + pdev = PCI_DEVICE(dev); - pbdev->fid = s390_pci_get_pfid(pci_dev); - pbdev->pdev = pci_dev; - pbdev->configured = true; - pbdev->fh = s390_pci_get_pfh(pci_dev); + if (!dev->id) { + /* In the case the PCI device does not define an id */ + /* we generate one based on the PCI address */ + dev->id = g_strdup_printf("auto_%02x:%02x.%01x", + pci_bus_num(pdev->bus), + PCI_SLOT(pdev->devfn), + PCI_FUNC(pdev->devfn)); + } - s390_pcihost_setup_msix(pbdev); + pbdev = s390_pci_find_dev_by_target(dev->id); + if (!pbdev) { + pbdev = s390_pci_device_new(dev->id); + if (!pbdev) { + error_setg(errp, "create zpci device failed"); + } + } - if (dev->hotplugged) { - s390_pci_generate_plug_event(HP_EVENT_RESERVED_TO_STANDBY, - pbdev->fh, pbdev->fid); - s390_pci_generate_plug_event(HP_EVENT_TO_CONFIGURED, - pbdev->fh, pbdev->fid); + if (object_dynamic_cast(OBJECT(dev), "vfio-pci")) { + pbdev->fh |= FH_SHM_VFIO; + } else { + pbdev->fh |= FH_SHM_EMUL; + } + + pbdev->pdev = pdev; + pbdev->iommu = s->iommu[PCI_SLOT(pdev->devfn)]; + pbdev->state = ZPCI_FS_STANDBY; + s390_pcihost_setup_msix(pbdev); + + if (dev->hotplugged) { + s390_pci_generate_plug_event(HP_EVENT_RESERVED_TO_STANDBY, + pbdev->fh, pbdev->fid); + } + } else if (object_dynamic_cast(OBJECT(dev), TYPE_S390_PCI_DEVICE)) { + int idx; + + pbdev = S390_PCI_DEVICE(dev); + for (idx = 0; idx < PCI_SLOT_MAX; idx++) { + if (!s->pbdev[idx]) { + s->pbdev[idx] = pbdev; + pbdev->fh = idx; + return; + } + } + + error_setg(errp, "no slot for plugging zpci device"); } } +static void s390_pcihost_timer_cb(void *opaque) +{ + S390PCIBusDevice *pbdev = opaque; + + if (pbdev->summary_ind) { + pci_dereg_irqs(pbdev); + } + if (pbdev->iommu_enabled) { + pci_dereg_ioat(pbdev); + } + + pbdev->state = ZPCI_FS_STANDBY; + s390_pci_generate_plug_event(HP_EVENT_CONFIGURED_TO_STBRES, + pbdev->fh, pbdev->fid); + qdev_unplug(DEVICE(pbdev), NULL); +} + static void s390_pcihost_hot_unplug(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { - PCIDevice *pci_dev = PCI_DEVICE(dev); - S390pciState *s = S390_PCI_HOST_BRIDGE(pci_device_root_bus(pci_dev) - ->qbus.parent); - S390PCIBusDevice *pbdev = &s->pbdev[PCI_SLOT(pci_dev->devfn)]; + int i; + PCIDevice *pci_dev = NULL; + S390PCIBusDevice *pbdev = NULL; + S390pciState *s = s390_get_phb(); + + if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) { + pci_dev = PCI_DEVICE(dev); - if (pbdev->configured) { - pbdev->configured = false; - s390_pci_generate_plug_event(HP_EVENT_CONFIGURED_TO_STBRES, + for (i = 0 ; i < PCI_SLOT_MAX; i++) { + if (s->pbdev[i]->pdev == pci_dev) { + pbdev = s->pbdev[i]; + break; + } + } + + if (!pbdev) { + object_unparent(OBJECT(pci_dev)); + return; + } + } else if (object_dynamic_cast(OBJECT(dev), TYPE_S390_PCI_DEVICE)) { + pbdev = S390_PCI_DEVICE(dev); + pci_dev = pbdev->pdev; + } + + switch (pbdev->state) { + case ZPCI_FS_RESERVED: + goto out; + case ZPCI_FS_STANDBY: + break; + default: + s390_pci_generate_plug_event(HP_EVENT_DECONFIGURE_REQUEST, pbdev->fh, pbdev->fid); + pbdev->release_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, + s390_pcihost_timer_cb, + pbdev); + timer_mod(pbdev->release_timer, + qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + HOT_UNPLUG_TIMEOUT); + return; + } + + if (pbdev->release_timer && timer_pending(pbdev->release_timer)) { + timer_del(pbdev->release_timer); + timer_free(pbdev->release_timer); + pbdev->release_timer = NULL; } s390_pci_generate_plug_event(HP_EVENT_STANDBY_TO_RESERVED, pbdev->fh, pbdev->fid); - pbdev->fh = 0; - pbdev->fid = 0; - pbdev->pdev = NULL; object_unparent(OBJECT(pci_dev)); + pbdev->pdev = NULL; + pbdev->state = ZPCI_FS_RESERVED; +out: + pbdev->fid = 0; + s->pbdev[pbdev->fh & FH_MASK_INDEX] = NULL; + object_unparent(OBJECT(pbdev)); } static void s390_pcihost_class_init(ObjectClass *klass, void *data) @@ -652,9 +784,178 @@ static const TypeInfo s390_pcihost_info = { } }; +static const TypeInfo s390_pcibus_info = { + .name = TYPE_S390_PCI_BUS, + .parent = TYPE_BUS, + .instance_size = sizeof(S390PCIBus), +}; + +static uint16_t s390_pci_generate_uid(void) +{ + uint16_t uid = 0; + + do { + uid++; + if (!s390_pci_find_dev_by_uid(uid)) { + return uid; + } + } while (uid < ZPCI_MAX_UID); + + return UID_UNDEFINED; +} + +static uint32_t s390_pci_generate_fid(Error **errp) +{ + uint32_t fid = 0; + + while (fid <= ZPCI_MAX_FID) { + if (!s390_pci_find_dev_by_fid(fid)) { + return fid; + } + + if (fid == ZPCI_MAX_FID) { + break; + } + + fid++; + } + + error_setg(errp, "no free fid could be found"); + return 0; +} + +static void s390_pci_device_realize(DeviceState *dev, Error **errp) +{ + S390PCIBusDevice *zpci = S390_PCI_DEVICE(dev); + + if (!zpci->target) { + error_setg(errp, "target must be defined"); + return; + } + + if (s390_pci_find_dev_by_target(zpci->target)) { + error_setg(errp, "target %s already has an associated zpci device", + zpci->target); + return; + } + + if (zpci->uid == UID_UNDEFINED) { + zpci->uid = s390_pci_generate_uid(); + if (!zpci->uid) { + error_setg(errp, "no free uid could be found"); + return; + } + } else if (s390_pci_find_dev_by_uid(zpci->uid)) { + error_setg(errp, "uid %u already in use", zpci->uid); + return; + } + + if (!zpci->fid_defined) { + Error *local_error = NULL; + + zpci->fid = s390_pci_generate_fid(&local_error); + if (local_error) { + error_propagate(errp, local_error); + return; + } + } else if (s390_pci_find_dev_by_fid(zpci->fid)) { + error_setg(errp, "fid %u already in use", zpci->fid); + return; + } + + zpci->state = ZPCI_FS_RESERVED; +} + +static void s390_pci_device_reset(DeviceState *dev) +{ + S390PCIBusDevice *pbdev = S390_PCI_DEVICE(dev); + + switch (pbdev->state) { + case ZPCI_FS_RESERVED: + return; + case ZPCI_FS_STANDBY: + break; + default: + pbdev->fh &= ~FH_MASK_ENABLE; + pbdev->state = ZPCI_FS_DISABLED; + break; + } + + if (pbdev->summary_ind) { + pci_dereg_irqs(pbdev); + } + if (pbdev->iommu_enabled) { + pci_dereg_ioat(pbdev); + } + + pbdev->fmb_addr = 0; +} + +static void s390_pci_get_fid(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + Property *prop = opaque; + uint32_t *ptr = qdev_get_prop_ptr(DEVICE(obj), prop); + + visit_type_uint32(v, name, ptr, errp); +} + +static void s390_pci_set_fid(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + DeviceState *dev = DEVICE(obj); + S390PCIBusDevice *zpci = S390_PCI_DEVICE(obj); + Property *prop = opaque; + uint32_t *ptr = qdev_get_prop_ptr(dev, prop); + + if (dev->realized) { + qdev_prop_set_after_realize(dev, name, errp); + return; + } + + visit_type_uint32(v, name, ptr, errp); + zpci->fid_defined = true; +} + +static PropertyInfo s390_pci_fid_propinfo = { + .name = "zpci_fid", + .get = s390_pci_get_fid, + .set = s390_pci_set_fid, +}; + +#define DEFINE_PROP_S390_PCI_FID(_n, _s, _f) \ + DEFINE_PROP(_n, _s, _f, s390_pci_fid_propinfo, uint32_t) + +static Property s390_pci_device_properties[] = { + DEFINE_PROP_UINT16("uid", S390PCIBusDevice, uid, UID_UNDEFINED), + DEFINE_PROP_S390_PCI_FID("fid", S390PCIBusDevice, fid), + DEFINE_PROP_STRING("target", S390PCIBusDevice, target), + DEFINE_PROP_END_OF_LIST(), +}; + +static void s390_pci_device_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->desc = "zpci device"; + dc->reset = s390_pci_device_reset; + dc->bus_type = TYPE_S390_PCI_BUS; + dc->realize = s390_pci_device_realize; + dc->props = s390_pci_device_properties; +} + +static const TypeInfo s390_pci_device_info = { + .name = TYPE_S390_PCI_DEVICE, + .parent = TYPE_DEVICE, + .instance_size = sizeof(S390PCIBusDevice), + .class_init = s390_pci_device_class_init, +}; + static void s390_pci_register_types(void) { type_register_static(&s390_pcihost_info); + type_register_static(&s390_pcibus_info); + type_register_static(&s390_pci_device_info); } type_init(s390_pci_register_types) diff --git a/hw/s390x/s390-pci-bus.h b/hw/s390x/s390-pci-bus.h index 2c852d47fa..4f564e02f2 100644 --- a/hw/s390x/s390-pci-bus.h +++ b/hw/s390x/s390-pci-bus.h @@ -14,23 +14,38 @@ #ifndef HW_S390_PCI_BUS_H #define HW_S390_PCI_BUS_H -#include <hw/pci/pci.h> -#include <hw/pci/pci_host.h> +#include "hw/pci/pci.h" +#include "hw/pci/pci_host.h" #include "hw/s390x/sclp.h" #include "hw/s390x/s390_flic.h" #include "hw/s390x/css.h" #define TYPE_S390_PCI_HOST_BRIDGE "s390-pcihost" -#define FH_VIRT 0x00ff0000 -#define ENABLE_BIT_OFFSET 31 -#define FH_ENABLED (1 << ENABLE_BIT_OFFSET) +#define TYPE_S390_PCI_BUS "s390-pcibus" +#define TYPE_S390_PCI_DEVICE "zpci" +#define FH_MASK_ENABLE 0x80000000 +#define FH_MASK_INSTANCE 0x7f000000 +#define FH_MASK_SHM 0x00ff0000 +#define FH_MASK_INDEX 0x0000001f +#define FH_SHM_VFIO 0x00010000 +#define FH_SHM_EMUL 0x00020000 #define S390_PCIPT_ADAPTER 2 +#define ZPCI_MAX_FID 0xffffffff +#define ZPCI_MAX_UID 0xffff +#define UID_UNDEFINED 0 +#define UID_CHECKING_ENABLED 0x01 +#define HOT_UNPLUG_TIMEOUT (NANOSECONDS_PER_SECOND * 60 * 5) #define S390_PCI_HOST_BRIDGE(obj) \ OBJECT_CHECK(S390pciState, (obj), TYPE_S390_PCI_HOST_BRIDGE) +#define S390_PCI_BUS(obj) \ + OBJECT_CHECK(S390PCIBus, (obj), TYPE_S390_PCI_BUS) +#define S390_PCI_DEVICE(obj) \ + OBJECT_CHECK(S390PCIBusDevice, (obj), TYPE_S390_PCI_DEVICE) #define HP_EVENT_TO_CONFIGURED 0x0301 #define HP_EVENT_RESERVED_TO_STANDBY 0x0302 +#define HP_EVENT_DECONFIGURE_REQUEST 0x0303 #define HP_EVENT_CONFIGURED_TO_STBRES 0x0304 #define HP_EVENT_STANDBY_TO_RESERVED 0x0308 @@ -150,6 +165,34 @@ enum ZpciIoatDtype { #define ZPCI_TABLE_VALID_MASK 0x20 #define ZPCI_TABLE_PROT_MASK 0x200 +/* PCI Function States + * + * reserved: default; device has just been plugged or is in progress of being + * unplugged + * standby: device is present but not configured; transition from any + * configured state/to this state via sclp configure/deconfigure + * + * The following states make up the "configured" meta-state: + * disabled: device is configured but not enabled; transition between this + * state and enabled via clp enable/disable + * enbaled: device is ready for use; transition to disabled via clp disable; + * may enter an error state + * blocked: ignore all DMA and interrupts; transition back to enabled or from + * error state via mpcifc + * error: an error occured; transition back to enabled via mpcifc + * permanent error: an unrecoverable error occured; transition to standby via + * sclp deconfigure + */ +typedef enum { + ZPCI_FS_RESERVED, + ZPCI_FS_STANDBY, + ZPCI_FS_DISABLED, + ZPCI_FS_ENABLED, + ZPCI_FS_BLOCKED, + ZPCI_FS_ERROR, + ZPCI_FS_PERMANENT_ERROR, +} ZpciState; + typedef struct SeiContainer { QTAILQ_ENTRY(SeiContainer) link; uint32_t fid; @@ -214,14 +257,21 @@ typedef struct S390MsixInfo { uint32_t pba_offset; } S390MsixInfo; +typedef struct S390PCIIOMMU { + AddressSpace as; + MemoryRegion mr; +} S390PCIIOMMU; + typedef struct S390PCIBusDevice { + DeviceState qdev; PCIDevice *pdev; - bool configured; - bool error_state; - bool lgstg_blocked; + ZpciState state; bool iommu_enabled; + char *target; + uint16_t uid; uint32_t fh; uint32_t fid; + bool fid_defined; uint64_t g_iota; uint64_t pba; uint64_t pal; @@ -231,16 +281,22 @@ typedef struct S390PCIBusDevice { uint8_t sum; S390MsixInfo msix; AdapterRoutes routes; - AddressSpace as; - MemoryRegion mr; + S390PCIIOMMU *iommu; MemoryRegion iommu_mr; IndAddr *summary_ind; IndAddr *indicator; + QEMUTimer *release_timer; } S390PCIBusDevice; +typedef struct S390PCIBus { + BusState qbus; +} S390PCIBus; + typedef struct S390pciState { PCIHostState parent_obj; - S390PCIBusDevice pbdev[PCI_SLOT_MAX]; + S390PCIBus *bus; + S390PCIBusDevice *pbdev[PCI_SLOT_MAX]; + S390PCIIOMMU *iommu[PCI_SLOT_MAX]; AddressSpace msix_notify_as; MemoryRegion msix_notify_mr; QTAILQ_HEAD(, SeiContainer) pending_sei; @@ -252,8 +308,11 @@ void s390_pci_sclp_configure(SCCB *sccb); void s390_pci_sclp_deconfigure(SCCB *sccb); void s390_pci_iommu_enable(S390PCIBusDevice *pbdev); void s390_pci_iommu_disable(S390PCIBusDevice *pbdev); +void s390_pci_generate_error_event(uint16_t pec, uint32_t fh, uint32_t fid, + uint64_t faddr, uint32_t e); S390PCIBusDevice *s390_pci_find_dev_by_idx(uint32_t idx); S390PCIBusDevice *s390_pci_find_dev_by_fh(uint32_t fh); S390PCIBusDevice *s390_pci_find_dev_by_fid(uint32_t fid); +S390PCIBusDevice *s390_pci_find_next_avail_dev(S390PCIBusDevice *pbdev); #endif diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c index 479375f65d..f069b110b4 100644 --- a/hw/s390x/s390-pci-inst.c +++ b/hw/s390x/s390-pci-inst.c @@ -16,8 +16,8 @@ #include "cpu.h" #include "s390-pci-inst.h" #include "s390-pci-bus.h" -#include <exec/memory-internal.h> -#include <qemu/error-report.h> +#include "exec/memory-internal.h" +#include "qemu/error-report.h" /* #define DEBUG_S390PCI_INST */ #ifdef DEBUG_S390PCI_INST @@ -37,9 +37,9 @@ static void s390_set_status_code(CPUS390XState *env, static int list_pci(ClpReqRspListPci *rrb, uint8_t *cc) { - S390PCIBusDevice *pbdev; - uint32_t res_code, initial_l2, g_l2, finish; - int rc, idx; + S390PCIBusDevice *pbdev = NULL; + uint32_t res_code, initial_l2, g_l2; + int rc, i; uint64_t resume_token; rc = 0; @@ -56,8 +56,7 @@ static int list_pci(ClpReqRspListPci *rrb, uint8_t *cc) } if ((ldl_p(&rrb->request.fmt) & ~CLP_MASK_FMT) != 0 || - ldq_p(&rrb->request.reserved1) != 0 || - ldq_p(&rrb->request.reserved2) != 0) { + ldq_p(&rrb->request.reserved1) != 0) { res_code = CLP_RC_RESNOT0; rc = -EINVAL; goto out; @@ -72,6 +71,8 @@ static int list_pci(ClpReqRspListPci *rrb, uint8_t *cc) rc = -EINVAL; goto out; } + } else { + pbdev = s390_pci_find_next_avail_dev(NULL); } if (lduw_p(&rrb->response.hdr.len) < 48) { @@ -91,43 +92,40 @@ static int list_pci(ClpReqRspListPci *rrb, uint8_t *cc) stl_p(&rrb->response.fmt, 0); stq_p(&rrb->response.reserved1, 0); - stq_p(&rrb->response.reserved2, 0); - stl_p(&rrb->response.mdd, FH_VIRT); + stl_p(&rrb->response.mdd, FH_MASK_SHM); stw_p(&rrb->response.max_fn, PCI_MAX_FUNCTIONS); + rrb->response.flags = UID_CHECKING_ENABLED; rrb->response.entry_size = sizeof(ClpFhListEntry); - finish = 0; - idx = resume_token; + + i = 0; g_l2 = LIST_PCI_HDR_LEN; - do { - pbdev = s390_pci_find_dev_by_idx(idx); - if (!pbdev) { - finish = 1; - break; - } - stw_p(&rrb->response.fh_list[idx - resume_token].device_id, + while (g_l2 < initial_l2 && pbdev) { + stw_p(&rrb->response.fh_list[i].device_id, pci_get_word(pbdev->pdev->config + PCI_DEVICE_ID)); - stw_p(&rrb->response.fh_list[idx - resume_token].vendor_id, + stw_p(&rrb->response.fh_list[i].vendor_id, pci_get_word(pbdev->pdev->config + PCI_VENDOR_ID)); - stl_p(&rrb->response.fh_list[idx - resume_token].config, - pbdev->configured << 31); - stl_p(&rrb->response.fh_list[idx - resume_token].fid, pbdev->fid); - stl_p(&rrb->response.fh_list[idx - resume_token].fh, pbdev->fh); + /* Ignore RESERVED devices. */ + stl_p(&rrb->response.fh_list[i].config, + pbdev->state == ZPCI_FS_STANDBY ? 0 : 1 << 31); + stl_p(&rrb->response.fh_list[i].fid, pbdev->fid); + stl_p(&rrb->response.fh_list[i].fh, pbdev->fh); g_l2 += sizeof(ClpFhListEntry); /* Add endian check for DPRINTF? */ DPRINTF("g_l2 %d vendor id 0x%x device id 0x%x fid 0x%x fh 0x%x\n", - g_l2, - lduw_p(&rrb->response.fh_list[idx - resume_token].vendor_id), - lduw_p(&rrb->response.fh_list[idx - resume_token].device_id), - ldl_p(&rrb->response.fh_list[idx - resume_token].fid), - ldl_p(&rrb->response.fh_list[idx - resume_token].fh)); - idx++; - } while (g_l2 < initial_l2); - - if (finish == 1) { + g_l2, + lduw_p(&rrb->response.fh_list[i].vendor_id), + lduw_p(&rrb->response.fh_list[i].device_id), + ldl_p(&rrb->response.fh_list[i].fid), + ldl_p(&rrb->response.fh_list[i].fh)); + pbdev = s390_pci_find_next_avail_dev(pbdev); + i++; + } + + if (!pbdev) { resume_token = 0; } else { - resume_token = idx; + resume_token = pbdev->fh & FH_MASK_INDEX; } stq_p(&rrb->response.resume_token, resume_token); stw_p(&rrb->response.hdr.len, g_l2); @@ -212,14 +210,35 @@ int clp_service_call(S390CPU *cpu, uint8_t r2) switch (reqsetpci->oc) { case CLP_SET_ENABLE_PCI_FN: - pbdev->fh = pbdev->fh | FH_ENABLED; + switch (reqsetpci->ndas) { + case 0: + stw_p(&ressetpci->hdr.rsp, CLP_RC_SETPCIFN_DMAAS); + goto out; + case 1: + break; + default: + stw_p(&ressetpci->hdr.rsp, CLP_RC_SETPCIFN_RES); + goto out; + } + + if (pbdev->fh & FH_MASK_ENABLE) { + stw_p(&ressetpci->hdr.rsp, CLP_RC_SETPCIFN_FHOP); + goto out; + } + + pbdev->fh |= FH_MASK_ENABLE; + pbdev->state = ZPCI_FS_ENABLED; stl_p(&ressetpci->fh, pbdev->fh); stw_p(&ressetpci->hdr.rsp, CLP_RC_OK); break; case CLP_SET_DISABLE_PCI_FN: - pbdev->fh = pbdev->fh & ~FH_ENABLED; - pbdev->error_state = false; - pbdev->lgstg_blocked = false; + if (!(pbdev->fh & FH_MASK_ENABLE)) { + stw_p(&ressetpci->hdr.rsp, CLP_RC_SETPCIFN_FHOP); + goto out; + } + device_reset(DEVICE(pbdev)); + pbdev->fh &= ~FH_MASK_ENABLE; + pbdev->state = ZPCI_FS_DISABLED; stl_p(&ressetpci->fh, pbdev->fh); stw_p(&ressetpci->hdr.rsp, CLP_RC_OK); break; @@ -256,9 +275,10 @@ int clp_service_call(S390CPU *cpu, uint8_t r2) stq_p(&resquery->sdma, ZPCI_SDMA_ADDR); stq_p(&resquery->edma, ZPCI_EDMA_ADDR); + stl_p(&resquery->fid, pbdev->fid); stw_p(&resquery->pchid, 0); stw_p(&resquery->ug, 1); - stl_p(&resquery->uid, pbdev->fid); + stl_p(&resquery->uid, pbdev->uid); stw_p(&resquery->hdr.rsp, CLP_RC_OK); break; } @@ -317,16 +337,25 @@ int pcilg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2) offset = env->regs[r2 + 1]; pbdev = s390_pci_find_dev_by_fh(fh); - if (!pbdev || !(pbdev->fh & FH_ENABLED)) { + if (!pbdev) { DPRINTF("pcilg no pci dev\n"); setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE); return 0; } - if (pbdev->lgstg_blocked) { + switch (pbdev->state) { + case ZPCI_FS_RESERVED: + case ZPCI_FS_STANDBY: + case ZPCI_FS_DISABLED: + case ZPCI_FS_PERMANENT_ERROR: + setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE); + return 0; + case ZPCI_FS_ERROR: setcc(cpu, ZPCI_PCI_LS_ERR); s390_set_status_code(env, r2, ZPCI_PCI_ST_BLOCKED); return 0; + default: + break; } if (pcias < 6) { @@ -390,7 +419,8 @@ static void update_msix_table_msg_data(S390PCIBusDevice *pbdev, uint64_t offset, msg_data = (uint8_t *)data - offset % PCI_MSIX_ENTRY_SIZE + PCI_MSIX_ENTRY_VECTOR_CTRL; - val = pci_get_long(msg_data) | (pbdev->fid << ZPCI_MSI_VEC_BITS); + val = pci_get_long(msg_data) | + ((pbdev->fh & FH_MASK_INDEX) << ZPCI_MSI_VEC_BITS); pci_set_long(msg_data, val); DPRINTF("update msix msg_data to 0x%" PRIx64 "\n", *data); } @@ -434,16 +464,25 @@ int pcistg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2) offset = env->regs[r2 + 1]; pbdev = s390_pci_find_dev_by_fh(fh); - if (!pbdev || !(pbdev->fh & FH_ENABLED)) { + if (!pbdev) { DPRINTF("pcistg no pci dev\n"); setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE); return 0; } - if (pbdev->lgstg_blocked) { + switch (pbdev->state) { + case ZPCI_FS_RESERVED: + case ZPCI_FS_STANDBY: + case ZPCI_FS_DISABLED: + case ZPCI_FS_PERMANENT_ERROR: + setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE); + return 0; + case ZPCI_FS_ERROR: setcc(cpu, ZPCI_PCI_LS_ERR); s390_set_status_code(env, r2, ZPCI_PCI_ST_BLOCKED); return 0; + default: + break; } data = env->regs[r1]; @@ -525,18 +564,55 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2) end = start + env->regs[r2 + 1]; pbdev = s390_pci_find_dev_by_fh(fh); - if (!pbdev || !(pbdev->fh & FH_ENABLED)) { + if (!pbdev) { DPRINTF("rpcit no pci dev\n"); setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE); goto out; } + switch (pbdev->state) { + case ZPCI_FS_RESERVED: + case ZPCI_FS_STANDBY: + case ZPCI_FS_DISABLED: + case ZPCI_FS_PERMANENT_ERROR: + setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE); + return 0; + case ZPCI_FS_ERROR: + setcc(cpu, ZPCI_PCI_LS_ERR); + s390_set_status_code(env, r1, ZPCI_MOD_ST_ERROR_RECOVER); + return 0; + default: + break; + } + + if (!pbdev->g_iota) { + pbdev->state = ZPCI_FS_ERROR; + setcc(cpu, ZPCI_PCI_LS_ERR); + s390_set_status_code(env, r1, ZPCI_PCI_ST_INSUF_RES); + s390_pci_generate_error_event(ERR_EVENT_INVALAS, pbdev->fh, pbdev->fid, + start, 0); + goto out; + } + + if (end < pbdev->pba || start > pbdev->pal) { + pbdev->state = ZPCI_FS_ERROR; + setcc(cpu, ZPCI_PCI_LS_ERR); + s390_set_status_code(env, r1, ZPCI_PCI_ST_INSUF_RES); + s390_pci_generate_error_event(ERR_EVENT_OORANGE, pbdev->fh, pbdev->fid, + start, 0); + goto out; + } + mr = &pbdev->iommu_mr; while (start < end) { entry = mr->iommu_ops->translate(mr, start, 0); if (!entry.translated_addr) { + pbdev->state = ZPCI_FS_ERROR; setcc(cpu, ZPCI_PCI_LS_ERR); + s390_set_status_code(env, r1, ZPCI_PCI_ST_INSUF_RES); + s390_pci_generate_error_event(ERR_EVENT_SERR, pbdev->fh, pbdev->fid, + start, ERR_EVENT_Q_BIT); goto out; } @@ -589,16 +665,25 @@ int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr, } pbdev = s390_pci_find_dev_by_fh(fh); - if (!pbdev || !(pbdev->fh & FH_ENABLED)) { + if (!pbdev) { DPRINTF("pcistb no pci dev fh 0x%x\n", fh); setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE); return 0; } - if (pbdev->lgstg_blocked) { + switch (pbdev->state) { + case ZPCI_FS_RESERVED: + case ZPCI_FS_STANDBY: + case ZPCI_FS_DISABLED: + case ZPCI_FS_PERMANENT_ERROR: + setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE); + return 0; + case ZPCI_FS_ERROR: setcc(cpu, ZPCI_PCI_LS_ERR); s390_set_status_code(env, r1, ZPCI_PCI_ST_BLOCKED); return 0; + default: + break; } mr = pbdev->pdev->io_regions[pcias].memory; @@ -742,12 +827,23 @@ int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar) } pbdev = s390_pci_find_dev_by_fh(fh); - if (!pbdev || !(pbdev->fh & FH_ENABLED)) { + if (!pbdev) { DPRINTF("mpcifc no pci dev fh 0x%x\n", fh); setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE); return 0; } + switch (pbdev->state) { + case ZPCI_FS_RESERVED: + case ZPCI_FS_STANDBY: + case ZPCI_FS_DISABLED: + case ZPCI_FS_PERMANENT_ERROR: + setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE); + return 0; + default: + break; + } + if (s390_cpu_virt_mem_read(cpu, fiba, ar, (uint8_t *)&fib, sizeof(fib))) { return 0; } @@ -814,11 +910,25 @@ int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar) } break; case ZPCI_MOD_FC_RESET_ERROR: - pbdev->error_state = false; - pbdev->lgstg_blocked = false; + switch (pbdev->state) { + case ZPCI_FS_BLOCKED: + case ZPCI_FS_ERROR: + pbdev->state = ZPCI_FS_ENABLED; + break; + default: + cc = ZPCI_PCI_LS_ERR; + s390_set_status_code(env, r1, ZPCI_MOD_ST_SEQUENCE); + } break; case ZPCI_MOD_FC_RESET_BLOCK: - pbdev->lgstg_blocked = false; + switch (pbdev->state) { + case ZPCI_FS_ERROR: + pbdev->state = ZPCI_FS_BLOCKED; + break; + default: + cc = ZPCI_PCI_LS_ERR; + s390_set_status_code(env, r1, ZPCI_MOD_ST_SEQUENCE); + } break; case ZPCI_MOD_FC_SET_MEASURE: pbdev->fmb_addr = ldq_p(&fib.fmb_addr); @@ -835,6 +945,7 @@ int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar) int stpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar) { CPUS390XState *env = &cpu->env; + uint8_t dmaas; uint32_t fh; ZpciFib fib; S390PCIBusDevice *pbdev; @@ -847,19 +958,59 @@ int stpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar) } fh = env->regs[r1] >> 32; + dmaas = (env->regs[r1] >> 16) & 0xff; + + if (dmaas) { + setcc(cpu, ZPCI_PCI_LS_ERR); + s390_set_status_code(env, r1, ZPCI_STPCIFC_ST_INVAL_DMAAS); + return 0; + } if (fiba & 0x7) { program_interrupt(env, PGM_SPECIFICATION, 6); return 0; } - pbdev = s390_pci_find_dev_by_fh(fh); + pbdev = s390_pci_find_dev_by_idx(fh & FH_MASK_INDEX); if (!pbdev) { setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE); return 0; } memset(&fib, 0, sizeof(fib)); + + switch (pbdev->state) { + case ZPCI_FS_RESERVED: + case ZPCI_FS_STANDBY: + setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE); + return 0; + case ZPCI_FS_DISABLED: + if (fh & FH_MASK_ENABLE) { + setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE); + return 0; + } + goto out; + /* BLOCKED bit is set to one coincident with the setting of ERROR bit. + * FH Enabled bit is set to one in states of ENABLED, BLOCKED or ERROR. */ + case ZPCI_FS_ERROR: + fib.fc |= 0x20; + case ZPCI_FS_BLOCKED: + fib.fc |= 0x40; + case ZPCI_FS_ENABLED: + fib.fc |= 0x80; + if (pbdev->iommu_enabled) { + fib.fc |= 0x10; + } + if (!(fh & FH_MASK_ENABLE)) { + env->regs[r1] |= 1ULL << 63; + } + break; + case ZPCI_FS_PERMANENT_ERROR: + setcc(cpu, ZPCI_PCI_LS_ERR); + s390_set_status_code(env, r1, ZPCI_STPCIFC_ST_PERM_ERROR); + return 0; + } + stq_p(&fib.pba, pbdev->pba); stq_p(&fib.pal, pbdev->pal); stq_p(&fib.iota, pbdev->g_iota); @@ -872,22 +1023,7 @@ int stpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar) ((uint32_t)pbdev->sum << 7) | pbdev->routes.adapter.summary_offset; stl_p(&fib.data, data); - if (pbdev->fh & FH_ENABLED) { - fib.fc |= 0x80; - } - - if (pbdev->error_state) { - fib.fc |= 0x40; - } - - if (pbdev->lgstg_blocked) { - fib.fc |= 0x20; - } - - if (pbdev->g_iota) { - fib.fc |= 0x10; - } - +out: if (s390_cpu_virt_mem_write(cpu, fiba, ar, (uint8_t *)&fib, sizeof(fib))) { return 0; } diff --git a/hw/s390x/s390-pci-inst.h b/hw/s390x/s390-pci-inst.h index b084f2346b..23f4bfa0ed 100644 --- a/hw/s390x/s390-pci-inst.h +++ b/hw/s390x/s390-pci-inst.h @@ -15,7 +15,7 @@ #define HW_S390_PCI_INST_H #include "s390-pci-bus.h" -#include <sysemu/dma.h> +#include "sysemu/dma.h" /* CLP common request & response block size */ #define CLP_BLK_SIZE 4096 @@ -104,7 +104,7 @@ typedef struct ClpRspListPci { uint64_t resume_token; uint32_t mdd; uint16_t max_fn; - uint8_t reserved2; + uint8_t flags; uint8_t entry_size; ClpFhListEntry fh_list[CLP_FH_LIST_NR_ENTRIES]; } QEMU_PACKED ClpRspListPci; @@ -249,6 +249,11 @@ typedef struct ClpReqRspQueryPciGrp { #define ZPCI_MOD_FC_RESET_BLOCK 9 #define ZPCI_MOD_FC_SET_MEASURE 10 +/* Store PCI Function Controls status codes */ +#define ZPCI_STPCIFC_ST_PERM_ERROR 8 +#define ZPCI_STPCIFC_ST_INVAL_DMAAS 28 +#define ZPCI_STPCIFC_ST_ERROR_RECOVER 40 + /* FIB function controls */ #define ZPCI_FIB_FC_ENABLED 0x80 #define ZPCI_FIB_FC_ERROR 0x40 diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index 52f079a884..caf0a682a7 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -27,9 +27,10 @@ #include "hw/compat.h" #include "ipl.h" #include "hw/s390x/s390-virtio-ccw.h" +#include "hw/s390x/css-bridge.h" static const char *const reset_dev_types[] = { - "virtual-css-bridge", + TYPE_VIRTUAL_CSS_BRIDGE, "s390-sclp-event-facility", "s390-flic", "diag288", diff --git a/hw/s390x/s390-virtio.h b/hw/s390x/s390-virtio.h index ffd014cb5b..f588b80a6e 100644 --- a/hw/s390x/s390-virtio.h +++ b/hw/s390x/s390-virtio.h @@ -10,7 +10,7 @@ */ #ifndef HW_S390_VIRTIO_H -#define HW_S390_VIRTIO_H 1 +#define HW_S390_VIRTIO_H #include "hw/nmi.h" #include "standard-headers/asm-s390/kvm_virtio.h" diff --git a/hw/s390x/sclpquiesce.c b/hw/s390x/sclpquiesce.c index c0ecab9c3b..762cb184ac 100644 --- a/hw/s390x/sclpquiesce.c +++ b/hw/s390x/sclpquiesce.c @@ -12,7 +12,7 @@ * */ #include "qemu/osdep.h" -#include <hw/qdev.h> +#include "hw/qdev.h" #include "sysemu/sysemu.h" #include "hw/s390x/sclp.h" #include "hw/s390x/event-facility.h" diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c index 8b709e362e..a554a24d06 100644 --- a/hw/s390x/virtio-ccw.c +++ b/hw/s390x/virtio-ccw.c @@ -33,31 +33,11 @@ #include "hw/s390x/css.h" #include "virtio-ccw.h" #include "trace.h" +#include "hw/s390x/css-bridge.h" static void virtio_ccw_bus_new(VirtioBusState *bus, size_t bus_size, VirtioCcwDevice *dev); -static void virtual_css_bus_reset(BusState *qbus) -{ - /* This should actually be modelled via the generic css */ - css_reset(); -} - - -static void virtual_css_bus_class_init(ObjectClass *klass, void *data) -{ - BusClass *k = BUS_CLASS(klass); - - k->reset = virtual_css_bus_reset; -} - -static const TypeInfo virtual_css_bus_info = { - .name = TYPE_VIRTUAL_CSS_BUS, - .parent = TYPE_BUS, - .instance_size = sizeof(VirtualCssBus), - .class_init = virtual_css_bus_class_init, -}; - VirtIODevice *virtio_ccw_get_vdev(SubchDev *sch) { VirtIODevice *vdev = NULL; @@ -117,32 +97,13 @@ static int virtio_ccw_ioeventfd_assign(DeviceState *d, EventNotifier *notifier, int n, bool assign) { VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d); - SubchDev *sch = dev->sch; + CcwDevice *ccw_dev = CCW_DEVICE(dev); + SubchDev *sch = ccw_dev->sch; uint32_t sch_id = (css_build_subchannel_id(sch) << 16) | sch->schid; return s390_assign_subch_ioeventfd(notifier, sch_id, n, assign); } -VirtualCssBus *virtual_css_bus_init(void) -{ - VirtualCssBus *cbus; - BusState *bus; - DeviceState *dev; - - /* Create bridge device */ - dev = qdev_create(NULL, "virtual-css-bridge"); - qdev_init_nofail(dev); - - /* Create bus on bridge device */ - bus = qbus_create(TYPE_VIRTUAL_CSS_BUS, dev, "virtual-css"); - cbus = VIRTUAL_CSS_BUS(bus); - - /* Enable hotplugging */ - qbus_set_hotplug_handler(bus, dev, &error_abort); - - return cbus; -} - /* Communication blocks used by several channel commands. */ typedef struct VqInfoBlockLegacy { uint64_t queue; @@ -234,6 +195,8 @@ static int virtio_ccw_set_vqs(SubchDev *sch, VqInfoBlock *info, static void virtio_ccw_reset_virtio(VirtioCcwDevice *dev, VirtIODevice *vdev) { + CcwDevice *ccw_dev = CCW_DEVICE(dev); + virtio_ccw_stop_ioeventfd(dev); virtio_reset(vdev); if (dev->indicators) { @@ -248,7 +211,7 @@ static void virtio_ccw_reset_virtio(VirtioCcwDevice *dev, VirtIODevice *vdev) release_indicator(&dev->routes.adapter, dev->summary_indicator); dev->summary_indicator = NULL; } - dev->sch->thinint_active = false; + ccw_dev->sch->thinint_active = false; } static int virtio_ccw_handle_set_vq(SubchDev *sch, CCW1 ccw, bool check_len, @@ -703,116 +666,28 @@ static void virtio_sch_disable_cb(SubchDev *sch) static void virtio_ccw_device_realize(VirtioCcwDevice *dev, Error **errp) { - unsigned int schid; - bool found = false; - SubchDev *sch; - Error *err = NULL; VirtIOCCWDeviceClass *k = VIRTIO_CCW_DEVICE_GET_CLASS(dev); + CcwDevice *ccw_dev = CCW_DEVICE(dev); + SubchDev *sch = css_create_virtual_sch(ccw_dev->bus_id, errp); + Error *err = NULL; - sch = g_malloc0(sizeof(SubchDev)); - - sch->driver_data = dev; - dev->sch = sch; - - dev->indicators = NULL; - - /* Initialize subchannel structure. */ - sch->channel_prog = 0x0; - sch->last_cmd_valid = false; - sch->thinint_active = false; - /* - * Use a device number if provided. Otherwise, fall back to subchannel - * number. - */ - if (dev->bus_id.valid) { - /* Enforce use of virtual cssid. */ - if (dev->bus_id.cssid != VIRTUAL_CSSID) { - error_setg(errp, "cssid %x not valid for virtio devices", - dev->bus_id.cssid); - goto out_err; - } - if (css_devno_used(dev->bus_id.cssid, dev->bus_id.ssid, - dev->bus_id.devid)) { - error_setg(errp, "Device %x.%x.%04x already exists", - dev->bus_id.cssid, dev->bus_id.ssid, - dev->bus_id.devid); - goto out_err; - } - sch->cssid = dev->bus_id.cssid; - sch->ssid = dev->bus_id.ssid; - sch->devno = dev->bus_id.devid; - - /* Find the next free id. */ - for (schid = 0; schid <= MAX_SCHID; schid++) { - if (!css_find_subch(1, sch->cssid, sch->ssid, schid)) { - sch->schid = schid; - css_subch_assign(sch->cssid, sch->ssid, sch->schid, - sch->devno, sch); - found = true; - break; - } - } - if (!found) { - error_setg(errp, "No free subchannel found for %x.%x.%04x", - sch->cssid, sch->ssid, sch->devno); - goto out_err; - } - trace_virtio_ccw_new_device(sch->cssid, sch->ssid, sch->schid, - sch->devno, "user-configured"); - } else { - unsigned int cssid = VIRTUAL_CSSID, ssid, devno; - - for (ssid = 0; ssid <= MAX_SSID; ssid++) { - for (schid = 0; schid <= MAX_SCHID; schid++) { - if (!css_find_subch(1, cssid, ssid, schid)) { - sch->cssid = cssid; - sch->ssid = ssid; - sch->schid = schid; - devno = schid; - /* - * If the devno is already taken, look further in this - * subchannel set. - */ - while (css_devno_used(cssid, ssid, devno)) { - if (devno == MAX_SCHID) { - devno = 0; - } else if (devno == schid - 1) { - error_setg(errp, "No free devno found"); - goto out_err; - } else { - devno++; - } - } - sch->devno = devno; - css_subch_assign(cssid, ssid, schid, devno, sch); - found = true; - break; - } - } - if (found) { - break; - } - } - if (!found) { - error_setg(errp, "Virtual channel subsystem is full!"); - goto out_err; - } - trace_virtio_ccw_new_device(cssid, ssid, schid, devno, - "auto-configured"); + if (!sch) { + return; } - /* Build initial schib. */ - css_sch_build_virtual_schib(sch, 0, VIRTIO_CCW_CHPID_TYPE); - + sch->driver_data = dev; sch->ccw_cb = virtio_ccw_cb; sch->disable_cb = virtio_sch_disable_cb; - - /* Build senseid data. */ - memset(&sch->id, 0, sizeof(SenseId)); sch->id.reserved = 0xff; sch->id.cu_type = VIRTIO_CCW_CU_TYPE; - + ccw_dev->sch = sch; + dev->indicators = NULL; dev->revision = -1; + css_sch_build_virtual_schib(sch, 0, VIRTIO_CCW_CHPID_TYPE); + + trace_virtio_ccw_new_device( + sch->cssid, sch->ssid, sch->schid, sch->devno, + ccw_dev->bus_id.valid ? "user-configured" : "auto-configured"); if (k->realize) { k->realize(dev, &err); @@ -820,19 +695,15 @@ static void virtio_ccw_device_realize(VirtioCcwDevice *dev, Error **errp) if (err) { error_propagate(errp, err); css_subch_assign(sch->cssid, sch->ssid, sch->schid, sch->devno, NULL); - goto out_err; + ccw_dev->sch = NULL; + g_free(sch); } - - return; - -out_err: - dev->sch = NULL; - g_free(sch); } static int virtio_ccw_exit(VirtioCcwDevice *dev) { - SubchDev *sch = dev->sch; + CcwDevice *ccw_dev = CCW_DEVICE(dev); + SubchDev *sch = ccw_dev->sch; if (sch) { css_subch_assign(sch->cssid, sch->ssid, sch->schid, sch->devno, NULL); @@ -1013,7 +884,9 @@ static void virtio_ccw_rng_realize(VirtioCcwDevice *ccw_dev, Error **errp) */ static inline VirtioCcwDevice *to_virtio_ccw_dev_fast(DeviceState *d) { - return container_of(d, VirtioCcwDevice, parent_obj); + CcwDevice *ccw_dev = to_ccw_dev_fast(d); + + return container_of(ccw_dev, VirtioCcwDevice, parent_obj); } static uint8_t virtio_set_ind_atomic(SubchDev *sch, uint64_t ind_loc, @@ -1042,7 +915,8 @@ static uint8_t virtio_set_ind_atomic(SubchDev *sch, uint64_t ind_loc, static void virtio_ccw_notify(DeviceState *d, uint16_t vector) { VirtioCcwDevice *dev = to_virtio_ccw_dev_fast(d); - SubchDev *sch = dev->sch; + CcwDevice *ccw_dev = to_ccw_dev_fast(d); + SubchDev *sch = ccw_dev->sch; uint64_t indicators; /* queue indicators + secondary indicators */ @@ -1100,9 +974,10 @@ static void virtio_ccw_reset(DeviceState *d) { VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d); VirtIODevice *vdev = virtio_bus_get_device(&dev->bus); + CcwDevice *ccw_dev = CCW_DEVICE(d); virtio_ccw_reset_virtio(dev, vdev); - css_reset_sch(dev->sch); + css_reset_sch(ccw_dev->sch); } static void virtio_ccw_vmstate_change(DeviceState *d, bool running) @@ -1118,7 +993,7 @@ static void virtio_ccw_vmstate_change(DeviceState *d, bool running) static bool virtio_ccw_query_guest_notifiers(DeviceState *d) { - VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d); + CcwDevice *dev = CCW_DEVICE(d); return !!(dev->sch->curr_status.pmcw.flags & PMCW_FLAGS_MASK_ENA); } @@ -1126,8 +1001,9 @@ static bool virtio_ccw_query_guest_notifiers(DeviceState *d) static int virtio_ccw_get_mappings(VirtioCcwDevice *dev) { int r; + CcwDevice *ccw_dev = CCW_DEVICE(dev); - if (!dev->sch->thinint_active) { + if (!ccw_dev->sch->thinint_active) { return -EINVAL; } @@ -1249,7 +1125,8 @@ static int virtio_ccw_set_guest_notifiers(DeviceState *d, int nvqs, { VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d); VirtIODevice *vdev = virtio_bus_get_device(&dev->bus); - bool with_irqfd = dev->sch->thinint_active && kvm_irqfds_enabled(); + CcwDevice *ccw_dev = CCW_DEVICE(d); + bool with_irqfd = ccw_dev->sch->thinint_active && kvm_irqfds_enabled(); int r, n; if (with_irqfd && assigned) { @@ -1308,7 +1185,8 @@ static int virtio_ccw_load_queue(DeviceState *d, int n, QEMUFile *f) static void virtio_ccw_save_config(DeviceState *d, QEMUFile *f) { VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d); - SubchDev *s = dev->sch; + CcwDevice *ccw_dev = CCW_DEVICE(d); + SubchDev *s = ccw_dev->sch; VirtIODevice *vdev = virtio_ccw_get_vdev(s); subch_device_save(s, f); @@ -1342,7 +1220,8 @@ static void virtio_ccw_save_config(DeviceState *d, QEMUFile *f) static int virtio_ccw_load_config(DeviceState *d, QEMUFile *f) { VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d); - SubchDev *s = dev->sch; + CcwDevice *ccw_dev = CCW_DEVICE(d); + SubchDev *s = ccw_dev->sch; VirtIODevice *vdev = virtio_ccw_get_vdev(s); int len; @@ -1387,7 +1266,8 @@ static void virtio_ccw_device_plugged(DeviceState *d, Error **errp) { VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d); VirtIODevice *vdev = virtio_bus_get_device(&dev->bus); - SubchDev *sch = dev->sch; + CcwDevice *ccw_dev = CCW_DEVICE(d); + SubchDev *sch = ccw_dev->sch; int n = virtio_get_num_queues(vdev); if (virtio_get_num_queues(vdev) > VIRTIO_CCW_QUEUE_MAX) { @@ -1431,7 +1311,7 @@ static void virtio_ccw_device_unplugged(DeviceState *d) /**************** Virtio-ccw Bus Device Descriptions *******************/ static Property virtio_ccw_net_properties[] = { - DEFINE_PROP_CSS_DEV_ID("devno", VirtioCcwDevice, bus_id), + DEFINE_PROP_CSS_DEV_ID("devno", VirtioCcwDevice, parent_obj.bus_id), DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags, VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true), DEFINE_PROP_UINT32("max_revision", VirtioCcwDevice, max_rev, @@ -1460,7 +1340,7 @@ static const TypeInfo virtio_ccw_net = { }; static Property virtio_ccw_blk_properties[] = { - DEFINE_PROP_CSS_DEV_ID("devno", VirtioCcwDevice, bus_id), + DEFINE_PROP_CSS_DEV_ID("devno", VirtioCcwDevice, parent_obj.bus_id), DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags, VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true), DEFINE_PROP_UINT32("max_revision", VirtioCcwDevice, max_rev, @@ -1489,7 +1369,7 @@ static const TypeInfo virtio_ccw_blk = { }; static Property virtio_ccw_serial_properties[] = { - DEFINE_PROP_CSS_DEV_ID("devno", VirtioCcwDevice, bus_id), + DEFINE_PROP_CSS_DEV_ID("devno", VirtioCcwDevice, parent_obj.bus_id), DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags, VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true), DEFINE_PROP_UINT32("max_revision", VirtioCcwDevice, max_rev, @@ -1518,7 +1398,7 @@ static const TypeInfo virtio_ccw_serial = { }; static Property virtio_ccw_balloon_properties[] = { - DEFINE_PROP_CSS_DEV_ID("devno", VirtioCcwDevice, bus_id), + DEFINE_PROP_CSS_DEV_ID("devno", VirtioCcwDevice, parent_obj.bus_id), DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags, VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true), DEFINE_PROP_UINT32("max_revision", VirtioCcwDevice, max_rev, @@ -1547,7 +1427,7 @@ static const TypeInfo virtio_ccw_balloon = { }; static Property virtio_ccw_scsi_properties[] = { - DEFINE_PROP_CSS_DEV_ID("devno", VirtioCcwDevice, bus_id), + DEFINE_PROP_CSS_DEV_ID("devno", VirtioCcwDevice, parent_obj.bus_id), DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags, VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true), DEFINE_PROP_UINT32("max_revision", VirtioCcwDevice, max_rev, @@ -1577,7 +1457,7 @@ static const TypeInfo virtio_ccw_scsi = { #ifdef CONFIG_VHOST_SCSI static Property vhost_ccw_scsi_properties[] = { - DEFINE_PROP_CSS_DEV_ID("devno", VirtioCcwDevice, bus_id), + DEFINE_PROP_CSS_DEV_ID("devno", VirtioCcwDevice, parent_obj.bus_id), DEFINE_PROP_UINT32("max_revision", VirtioCcwDevice, max_rev, VIRTIO_CCW_MAX_REV), DEFINE_PROP_END_OF_LIST(), @@ -1615,7 +1495,7 @@ static void virtio_ccw_rng_instance_init(Object *obj) } static Property virtio_ccw_rng_properties[] = { - DEFINE_PROP_CSS_DEV_ID("devno", VirtioCcwDevice, bus_id), + DEFINE_PROP_CSS_DEV_ID("devno", VirtioCcwDevice, parent_obj.bus_id), DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags, VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true), DEFINE_PROP_UINT32("max_revision", VirtioCcwDevice, max_rev, @@ -1662,29 +1542,17 @@ static int virtio_ccw_busdev_exit(DeviceState *dev) static void virtio_ccw_busdev_unplug(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { - VirtioCcwDevice *_dev = (VirtioCcwDevice *)dev; - SubchDev *sch = _dev->sch; + VirtioCcwDevice *_dev = to_virtio_ccw_dev_fast(dev); virtio_ccw_stop_ioeventfd(_dev); - - /* - * We should arrive here only for device_del, since we don't support - * direct hot(un)plug of channels, but only through virtio. - */ - assert(sch != NULL); - /* Subchannel is now disabled and no longer valid. */ - sch->curr_status.pmcw.flags &= ~(PMCW_FLAGS_MASK_ENA | - PMCW_FLAGS_MASK_DNV); - - css_generate_sch_crws(sch->cssid, sch->ssid, sch->schid, 1, 0); - - object_unparent(OBJECT(dev)); } static void virtio_ccw_device_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); + CCWDeviceClass *k = CCW_DEVICE_CLASS(dc); + k->unplug = virtio_ccw_busdev_unplug; dc->realize = virtio_ccw_busdev_realize; dc->exit = virtio_ccw_busdev_exit; dc->bus_type = TYPE_VIRTUAL_CSS_BUS; @@ -1692,44 +1560,13 @@ static void virtio_ccw_device_class_init(ObjectClass *klass, void *data) static const TypeInfo virtio_ccw_device_info = { .name = TYPE_VIRTIO_CCW_DEVICE, - .parent = TYPE_DEVICE, + .parent = TYPE_CCW_DEVICE, .instance_size = sizeof(VirtioCcwDevice), .class_init = virtio_ccw_device_class_init, .class_size = sizeof(VirtIOCCWDeviceClass), .abstract = true, }; -/***************** Virtual-css Bus Bridge Device ********************/ -/* Only required to have the virtio bus as child in the system bus */ - -static int virtual_css_bridge_init(SysBusDevice *dev) -{ - /* nothing */ - return 0; -} - -static void virtual_css_bridge_class_init(ObjectClass *klass, void *data) -{ - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass); - DeviceClass *dc = DEVICE_CLASS(klass); - - k->init = virtual_css_bridge_init; - hc->unplug = virtio_ccw_busdev_unplug; - set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); -} - -static const TypeInfo virtual_css_bridge_info = { - .name = "virtual-css-bridge", - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(SysBusDevice), - .class_init = virtual_css_bridge_class_init, - .interfaces = (InterfaceInfo[]) { - { TYPE_HOTPLUG_HANDLER }, - { } - } -}; - /* virtio-ccw-bus */ static void virtio_ccw_bus_new(VirtioBusState *bus, size_t bus_size, @@ -1775,7 +1612,7 @@ static const TypeInfo virtio_ccw_bus_info = { #ifdef CONFIG_VIRTFS static Property virtio_ccw_9p_properties[] = { - DEFINE_PROP_CSS_DEV_ID("devno", VirtioCcwDevice, bus_id), + DEFINE_PROP_CSS_DEV_ID("devno", VirtioCcwDevice, parent_obj.bus_id), DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags, VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true), DEFINE_PROP_UINT32("max_revision", VirtioCcwDevice, max_rev, @@ -1824,7 +1661,6 @@ static const TypeInfo virtio_ccw_9p_info = { static void virtio_ccw_register(void) { type_register_static(&virtio_ccw_bus_info); - type_register_static(&virtual_css_bus_info); type_register_static(&virtio_ccw_device_info); type_register_static(&virtio_ccw_serial); type_register_static(&virtio_ccw_blk); @@ -1835,7 +1671,6 @@ static void virtio_ccw_register(void) type_register_static(&vhost_ccw_scsi); #endif type_register_static(&virtio_ccw_rng); - type_register_static(&virtual_css_bridge_info); #ifdef CONFIG_VIRTFS type_register_static(&virtio_ccw_9p_info); #endif diff --git a/hw/s390x/virtio-ccw.h b/hw/s390x/virtio-ccw.h index 0bfb5d93c6..1c6bc86316 100644 --- a/hw/s390x/virtio-ccw.h +++ b/hw/s390x/virtio-ccw.h @@ -13,21 +13,21 @@ #ifndef HW_S390X_VIRTIO_CCW_H #define HW_S390X_VIRTIO_CCW_H -#include <hw/virtio/virtio-blk.h> -#include <hw/virtio/virtio-net.h> -#include <hw/virtio/virtio-serial.h> -#include <hw/virtio/virtio-scsi.h> +#include "hw/virtio/virtio-blk.h" +#include "hw/virtio/virtio-net.h" +#include "hw/virtio/virtio-serial.h" +#include "hw/virtio/virtio-scsi.h" #ifdef CONFIG_VHOST_SCSI -#include <hw/virtio/vhost-scsi.h> +#include "hw/virtio/vhost-scsi.h" #endif -#include <hw/virtio/virtio-balloon.h> -#include <hw/virtio/virtio-rng.h> -#include <hw/virtio/virtio-bus.h> +#include "hw/virtio/virtio-balloon.h" +#include "hw/virtio/virtio-rng.h" +#include "hw/virtio/virtio-bus.h" -#include <hw/s390x/s390_flic.h> -#include <hw/s390x/css.h> - -#define VIRTUAL_CSSID 0xfe +#include "hw/s390x/s390_flic.h" +#include "hw/s390x/css.h" +#include "ccw-device.h" +#include "hw/s390x/css-bridge.h" #define VIRTIO_CCW_CU_TYPE 0x3832 #define VIRTIO_CCW_CHPID_TYPE 0x32 @@ -67,7 +67,7 @@ typedef struct VirtioBusClass VirtioCcwBusClass; typedef struct VirtioCcwDevice VirtioCcwDevice; typedef struct VirtIOCCWDeviceClass { - DeviceClass parent_class; + CCWDeviceClass parent_class; void (*realize)(VirtioCcwDevice *dev, Error **errp); int (*exit)(VirtioCcwDevice *dev); } VirtIOCCWDeviceClass; @@ -78,9 +78,7 @@ typedef struct VirtIOCCWDeviceClass { #define VIRTIO_CCW_FLAG_USE_IOEVENTFD (1 << VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT) struct VirtioCcwDevice { - DeviceState parent_obj; - SubchDev *sch; - CssDevId bus_id; + CcwDevice parent_obj; int revision; uint32_t max_rev; VirtioBusState bus; @@ -103,15 +101,6 @@ static inline int virtio_ccw_rev_max(VirtioCcwDevice *dev) return dev->max_rev; } -/* virtual css bus type */ -typedef struct VirtualCssBus { - BusState parent_obj; -} VirtualCssBus; - -#define TYPE_VIRTUAL_CSS_BUS "virtual-css-bus" -#define VIRTUAL_CSS_BUS(obj) \ - OBJECT_CHECK(VirtualCssBus, (obj), TYPE_VIRTUAL_CSS_BUS) - /* virtio-scsi-ccw */ #define TYPE_VIRTIO_SCSI_CCW "virtio-scsi-ccw" @@ -191,7 +180,6 @@ typedef struct VirtIORNGCcw { VirtIORNG vdev; } VirtIORNGCcw; -VirtualCssBus *virtual_css_bus_init(void); void virtio_ccw_device_update_status(SubchDev *sch); VirtIODevice *virtio_ccw_get_vdev(SubchDev *sch); diff --git a/hw/scsi/mfi.h b/hw/scsi/mfi.h index 29d41775d4..e67a5c0b47 100644 --- a/hw/scsi/mfi.h +++ b/hw/scsi/mfi.h @@ -30,8 +30,8 @@ * SUCH DAMAGE. */ -#ifndef MFI_REG_H -#define MFI_REG_H +#ifndef SCSI_MFI_H +#define SCSI_MFI_H /* * MegaRAID SAS MFI firmware definitions @@ -1269,4 +1269,4 @@ struct mfi_config_data { #define MFI_SCSI_MAX_CMDS 8 #define MFI_SCSI_MAX_CDB_LEN 16 -#endif /* MFI_REG_H */ +#endif /* SCSI_MFI_H */ diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c index 36f8a85a70..8dbfc10b78 100644 --- a/hw/scsi/scsi-disk.c +++ b/hw/scsi/scsi-disk.c @@ -2309,6 +2309,7 @@ static void scsi_realize(SCSIDevice *dev, Error **errp) return; } } + blkconf_apply_backend_options(&dev->conf); if (s->qdev.conf.discard_granularity == -1) { s->qdev.conf.discard_granularity = @@ -2848,6 +2849,7 @@ static const TypeInfo scsi_disk_base_info = { #define DEFINE_SCSI_DISK_PROPERTIES() \ DEFINE_BLOCK_PROPERTIES(SCSIDiskState, qdev.conf), \ + DEFINE_BLOCK_ERROR_PROPERTIES(SCSIDiskState, qdev.conf), \ DEFINE_PROP_STRING("ver", SCSIDiskState, version), \ DEFINE_PROP_STRING("serial", SCSIDiskState, serial), \ DEFINE_PROP_STRING("vendor", SCSIDiskState, vendor), \ diff --git a/hw/scsi/vhost-scsi.c b/hw/scsi/vhost-scsi.c index 2a00f2f3c8..5b2694615f 100644 --- a/hw/scsi/vhost-scsi.c +++ b/hw/scsi/vhost-scsi.c @@ -15,8 +15,9 @@ */ #include "qemu/osdep.h" -#include "qapi/error.h" +#include <linux/vhost.h> #include <sys/ioctl.h> +#include "qapi/error.h" #include "qemu/error-report.h" #include "qemu/queue.h" #include "monitor/monitor.h" @@ -27,7 +28,6 @@ #include "hw/virtio/virtio-bus.h" #include "hw/virtio/virtio-access.h" #include "hw/fw-path-provider.h" -#include "linux/vhost.h" #include "qemu/cutils.h" /* Features supported by host kernel. */ diff --git a/hw/scsi/virtio-scsi-dataplane.c b/hw/scsi/virtio-scsi-dataplane.c index 18ced31493..b173b94949 100644 --- a/hw/scsi/virtio-scsi-dataplane.c +++ b/hw/scsi/virtio-scsi-dataplane.c @@ -15,9 +15,9 @@ #include "hw/virtio/virtio-scsi.h" #include "qemu/error-report.h" #include "sysemu/block-backend.h" -#include <hw/scsi/scsi.h> -#include <block/scsi.h> -#include <hw/virtio/virtio-bus.h> +#include "hw/scsi/scsi.h" +#include "block/scsi.h" +#include "hw/virtio/virtio-bus.h" #include "hw/virtio/virtio-access.h" /* Context: QEMU global mutex held */ diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c index e8179d6616..722c93e5fc 100644 --- a/hw/scsi/virtio-scsi.c +++ b/hw/scsi/virtio-scsi.c @@ -20,9 +20,9 @@ #include "qemu/error-report.h" #include "qemu/iov.h" #include "sysemu/block-backend.h" -#include <hw/scsi/scsi.h> -#include <block/scsi.h> -#include <hw/virtio/virtio-bus.h> +#include "hw/scsi/scsi.h" +#include "block/scsi.h" +#include "hw/virtio/virtio-bus.h" #include "hw/virtio/virtio-access.h" static inline int virtio_scsi_get_lun(uint8_t *lun) diff --git a/hw/scsi/vmw_pvscsi.c b/hw/scsi/vmw_pvscsi.c index da71c8c8a5..5116f4ad68 100644 --- a/hw/scsi/vmw_pvscsi.c +++ b/hw/scsi/vmw_pvscsi.c @@ -28,7 +28,7 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "hw/scsi/scsi.h" -#include <block/scsi.h> +#include "block/scsi.h" #include "hw/pci/msi.h" #include "vmw_pvscsi.h" #include "trace.h" diff --git a/hw/sh4/sh7750_regnames.h b/hw/sh4/sh7750_regnames.h index 7463709b4c..e3ba88636f 100644 --- a/hw/sh4/sh7750_regnames.h +++ b/hw/sh4/sh7750_regnames.h @@ -1,6 +1,6 @@ -#ifndef _SH7750_REGNAMES_H -#define _SH7750_REGNAMES_H +#ifndef SH7750_REGNAMES_H +#define SH7750_REGNAMES_H const char *regname(uint32_t addr); -#endif /* _SH7750_REGNAMES_H */ +#endif /* SH7750_REGNAMES_H */ diff --git a/hw/sh4/sh7750_regs.h b/hw/sh4/sh7750_regs.h index 534aa48403..3e4554af31 100644 --- a/hw/sh4/sh7750_regs.h +++ b/hw/sh4/sh7750_regs.h @@ -16,8 +16,8 @@ * @(#) sh7750_regs.h,v 1.2.4.1 2003/09/04 18:46:00 joel Exp */ -#ifndef __SH7750_REGS_H__ -#define __SH7750_REGS_H__ +#ifndef SH7750_REGS_H +#define SH7750_REGS_H /* * All register has 2 addresses: in 0xff000000 - 0xffffffff (P4 address) and diff --git a/hw/timer/Makefile.objs b/hw/timer/Makefile.objs index 003c14fa26..7ba8c23c75 100644 --- a/hw/timer/Makefile.objs +++ b/hw/timer/Makefile.objs @@ -26,6 +26,7 @@ obj-$(CONFIG_OMAP) += omap_synctimer.o obj-$(CONFIG_PXA2XX) += pxa2xx_timer.o obj-$(CONFIG_SH4) += sh_timer.o obj-$(CONFIG_DIGIC) += digic-timer.o +obj-$(CONFIG_MIPS_CPS) += mips_gictimer.o obj-$(CONFIG_MC146818RTC) += mc146818rtc.o diff --git a/hw/timer/mips_gictimer.c b/hw/timer/mips_gictimer.c new file mode 100644 index 0000000000..3698889475 --- /dev/null +++ b/hw/timer/mips_gictimer.c @@ -0,0 +1,142 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2016 Imagination Technologies + */ + +#include "qemu/osdep.h" +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "qemu/timer.h" +#include "hw/timer/mips_gictimer.h" + +#define TIMER_PERIOD 10 /* 10 ns period for 100 Mhz frequency */ + +static void gic_vptimer_update(MIPSGICTimerState *gictimer, + uint32_t vp_index, uint64_t now) +{ + uint64_t next; + uint32_t wait; + + wait = gictimer->vptimers[vp_index].comparelo - gictimer->sh_counterlo - + (uint32_t)(now / TIMER_PERIOD); + next = now + (uint64_t)wait * TIMER_PERIOD; + + timer_mod(gictimer->vptimers[vp_index].qtimer, next); +} + +static void gic_vptimer_expire(MIPSGICTimerState *gictimer, uint32_t vp_index, + uint64_t now) +{ + if (gictimer->countstop) { + /* timer stopped */ + return; + } + gictimer->cb(gictimer->opaque, vp_index); + gic_vptimer_update(gictimer, vp_index, now); +} + +static void gic_vptimer_cb(void *opaque) +{ + MIPSGICTimerVPState *vptimer = opaque; + MIPSGICTimerState *gictimer = vptimer->gictimer; + gic_vptimer_expire(gictimer, vptimer->vp_index, + qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)); +} + +uint32_t mips_gictimer_get_sh_count(MIPSGICTimerState *gictimer) +{ + int i; + if (gictimer->countstop) { + return gictimer->sh_counterlo; + } else { + uint64_t now; + now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + for (i = 0; i < gictimer->num_vps; i++) { + if (timer_pending(gictimer->vptimers[i].qtimer) + && timer_expired(gictimer->vptimers[i].qtimer, now)) { + /* The timer has already expired. */ + gic_vptimer_expire(gictimer, i, now); + } + } + return gictimer->sh_counterlo + (uint32_t)(now / TIMER_PERIOD); + } +} + +void mips_gictimer_store_sh_count(MIPSGICTimerState *gictimer, uint64_t count) +{ + int i; + uint64_t now; + + if (gictimer->countstop || !gictimer->vptimers[0].qtimer) { + gictimer->sh_counterlo = count; + } else { + /* Store new count register */ + now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + gictimer->sh_counterlo = count - (uint32_t)(now / TIMER_PERIOD); + /* Update timer timer */ + for (i = 0; i < gictimer->num_vps; i++) { + gic_vptimer_update(gictimer, i, now); + } + } +} + +uint32_t mips_gictimer_get_vp_compare(MIPSGICTimerState *gictimer, + uint32_t vp_index) +{ + return gictimer->vptimers[vp_index].comparelo; +} + +void mips_gictimer_store_vp_compare(MIPSGICTimerState *gictimer, + uint32_t vp_index, uint64_t compare) +{ + gictimer->vptimers[vp_index].comparelo = (uint32_t) compare; + gic_vptimer_update(gictimer, vp_index, + qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)); +} + +uint8_t mips_gictimer_get_countstop(MIPSGICTimerState *gictimer) +{ + return gictimer->countstop; +} + +void mips_gictimer_start_count(MIPSGICTimerState *gictimer) +{ + gictimer->countstop = 0; + mips_gictimer_store_sh_count(gictimer, gictimer->sh_counterlo); +} + +void mips_gictimer_stop_count(MIPSGICTimerState *gictimer) +{ + int i; + + gictimer->countstop = 1; + /* Store the current value */ + gictimer->sh_counterlo += + (uint32_t)(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / TIMER_PERIOD); + for (i = 0; i < gictimer->num_vps; i++) { + timer_del(gictimer->vptimers[i].qtimer); + } +} + +MIPSGICTimerState *mips_gictimer_init(void *opaque, uint32_t nvps, + MIPSGICTimerCB *cb) +{ + int i; + MIPSGICTimerState *gictimer = g_new(MIPSGICTimerState, 1); + gictimer->vptimers = g_new(MIPSGICTimerVPState, nvps); + gictimer->countstop = 1; + gictimer->num_vps = nvps; + gictimer->opaque = opaque; + gictimer->cb = cb; + for (i = 0; i < nvps; i++) { + gictimer->vptimers[i].gictimer = gictimer; + gictimer->vptimers[i].vp_index = i; + gictimer->vptimers[i].qtimer = timer_new_ns(QEMU_CLOCK_VIRTUAL, + &gic_vptimer_cb, + &gictimer->vptimers[i]); + } + return gictimer; +} diff --git a/hw/tpm/tpm_util.h b/hw/tpm/tpm_util.h index e7f354a52d..df76245e6e 100644 --- a/hw/tpm/tpm_util.h +++ b/hw/tpm/tpm_util.h @@ -18,11 +18,12 @@ * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see <http://www.gnu.org/licenses/> */ -#ifndef TPM_TPM_UTILS_H -#define TPM_TPM_UTILS_H + +#ifndef TPM_TPM_UTIL_H +#define TPM_TPM_UTIL_H #include "sysemu/tpm_backend.h" int tpm_util_test_tpmdev(int tpm_fd, TPMVersion *tpm_version); -#endif /* TPM_TPM_UTILS_H */ +#endif /* TPM_TPM_UTIL_H */ diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c index 4d605b8a6a..c607f7606d 100644 --- a/hw/usb/dev-storage.c +++ b/hw/usb/dev-storage.c @@ -603,16 +603,19 @@ static void usb_msd_realize_storage(USBDevice *dev, Error **errp) blkconf_serial(&s->conf, &dev->serial); blkconf_blocksizes(&s->conf); + blkconf_apply_backend_options(&s->conf); /* * Hack alert: this pretends to be a block device, but it's really * a SCSI bus that can serve only a single device, which it * creates automatically. But first it needs to detach from its * blockdev, or else scsi_bus_legacy_add_drive() dies when it - * attaches again. + * attaches again. We also need to take another reference so that + * blk_detach_dev() doesn't free blk while we still need it. * * The hack is probably a bad idea. */ + blk_ref(blk); blk_detach_dev(blk, &s->dev.qdev); s->conf.blk = NULL; @@ -623,6 +626,7 @@ static void usb_msd_realize_storage(USBDevice *dev, Error **errp) scsi_dev = scsi_bus_legacy_add_drive(&s->bus, blk, 0, !!s->removable, s->conf.bootindex, dev->serial, &err); + blk_unref(blk); if (!scsi_dev) { error_propagate(errp, err); return; diff --git a/hw/usb/hcd-ehci.h b/hw/usb/hcd-ehci.h index 30218423c8..3fd7038658 100644 --- a/hw/usb/hcd-ehci.h +++ b/hw/usb/hcd-ehci.h @@ -14,8 +14,9 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, see <http://www.gnu.org/licenses/>. */ -#ifndef HW_USB_EHCI_H -#define HW_USB_EHCI_H 1 + +#ifndef HW_USB_HCD_EHCI_H +#define HW_USB_HCD_EHCI_H #include "hw/hw.h" #include "qemu/timer.h" diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 1a3377f038..976bfb0659 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -2364,6 +2364,8 @@ static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid, slot->uport = uport; slot->ctx = octx; + /* Make sure device is in USB_STATE_DEFAULT state */ + usb_device_reset(dev); if (bsr) { slot_ctx[3] = SLOT_DEFAULT << SLOT_STATE_SHIFT; } else { @@ -2371,7 +2373,6 @@ static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid, uint8_t buf[1]; slot_ctx[3] = (SLOT_ADDRESSED << SLOT_STATE_SHIFT) | slotid; - usb_device_reset(dev); memset(&p, 0, sizeof(p)); usb_packet_addbuf(&p, buf, sizeof(buf)); usb_packet_setup(&p, USB_TOKEN_OUT, diff --git a/hw/usb/xen-usb.c b/hw/usb/xen-usb.c index 0fd34c62c4..799245654a 100644 --- a/hw/usb/xen-usb.c +++ b/hw/usb/xen-usb.c @@ -21,6 +21,7 @@ #include "qemu/osdep.h" #include <libusb.h> +#include <sys/user.h> #include "qemu-common.h" #include "qemu/config-file.h" @@ -31,7 +32,6 @@ #include "qapi/qmp/qbool.h" #include "qapi/qmp/qint.h" #include "qapi/qmp/qstring.h" -#include "sys/user.h" #include <xen/io/ring.h> #include <xen/io/usbif.h> @@ -253,7 +253,8 @@ static int usbback_init_packet(struct usbback_req *usbback_req) case USBIF_PIPE_TYPE_CTRL: packet->parameter = *(uint64_t *)usbback_req->req.u.ctrl; - TR_REQ(xendev, "ctrl parameter: %lx, buflen: %x\n", packet->parameter, + TR_REQ(xendev, "ctrl parameter: %"PRIx64", buflen: %x\n", + packet->parameter, usbback_req->req.buffer_length); break; diff --git a/hw/vfio/common.c b/hw/vfio/common.c index f3c0522e7e..b313e7c2c6 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c @@ -20,6 +20,9 @@ #include "qemu/osdep.h" #include <sys/ioctl.h> +#ifdef CONFIG_KVM +#include <linux/kvm.h> +#endif #include <linux/vfio.h> #include "hw/vfio/vfio-common.h" @@ -30,9 +33,6 @@ #include "qemu/error-report.h" #include "qemu/range.h" #include "sysemu/kvm.h" -#ifdef CONFIG_KVM -#include "linux/kvm.h" -#endif #include "trace.h" struct vfio_group_head vfio_group_list = diff --git a/hw/virtio/vhost-backend.c b/hw/virtio/vhost-backend.c index d62372e597..7681f152f3 100644 --- a/hw/virtio/vhost-backend.c +++ b/hw/virtio/vhost-backend.c @@ -9,12 +9,11 @@ */ #include "qemu/osdep.h" +#include <linux/vhost.h> +#include <sys/ioctl.h> #include "hw/virtio/vhost.h" #include "hw/virtio/vhost-backend.h" #include "qemu/error-report.h" -#include "linux/vhost.h" - -#include <sys/ioctl.h> static int vhost_kernel_call(struct vhost_dev *dev, unsigned long int request, void *arg) diff --git a/hw/xen/xen-host-pci-device.h b/hw/xen/xen-host-pci-device.h index 6acf36e13a..4d8d34ecb0 100644 --- a/hw/xen/xen-host-pci-device.h +++ b/hw/xen/xen-host-pci-device.h @@ -55,4 +55,4 @@ int xen_host_pci_set_block(XenHostPCIDevice *d, int pos, uint8_t *buf, int xen_host_pci_find_ext_cap_offset(XenHostPCIDevice *s, uint32_t cap); -#endif /* !XEN_HOST_PCI_DEVICE_H_ */ +#endif /* XEN_HOST_PCI_DEVICE_H */ diff --git a/hw/xen/xen_pt.h b/hw/xen/xen_pt.h index c2f8e1fc25..191d9caea1 100644 --- a/hw/xen/xen_pt.h +++ b/hw/xen/xen_pt.h @@ -332,4 +332,4 @@ int xen_pt_register_vga_regions(XenHostPCIDevice *dev); int xen_pt_unregister_vga_regions(XenHostPCIDevice *dev); void xen_pt_setup_vga(XenPCIPassthroughState *s, XenHostPCIDevice *dev, Error **errp); -#endif /* !XEN_PT_H */ +#endif /* XEN_PT_H */ diff --git a/hw/xenpv/xen_domainbuild.h b/hw/xenpv/xen_domainbuild.h index 29a91ea7b1..652d9b410f 100644 --- a/hw/xenpv/xen_domainbuild.h +++ b/hw/xenpv/xen_domainbuild.h @@ -1,5 +1,5 @@ #ifndef QEMU_HW_XEN_DOMAINBUILD_H -#define QEMU_HW_XEN_DOMAINBUILD_H 1 +#define QEMU_HW_XEN_DOMAINBUILD_H #include "hw/xen/xen_common.h" diff --git a/hw/xtensa/bootparam.h b/hw/xtensa/bootparam.h index 955f4e86e3..ade7891ec5 100644 --- a/hw/xtensa/bootparam.h +++ b/hw/xtensa/bootparam.h @@ -1,5 +1,5 @@ -#ifndef HW_XTENSA_BOOTPARAM -#define HW_XTENSA_BOOTPARAM +#ifndef HW_XTENSA_BOOTPARAM_H +#define HW_XTENSA_BOOTPARAM_H #define BP_TAG_COMMAND_LINE 0x1001 /* command line (0-terminated string)*/ #define BP_TAG_INITRD 0x1002 /* ramdisk addr and size (bp_meminfo) */ |