diff options
Diffstat (limited to 'hw')
-rw-r--r-- | hw/ide/ahci.c | 4 | ||||
-rw-r--r-- | hw/ide/ich.c | 12 | ||||
-rw-r--r-- | hw/intel-hda.c | 3 | ||||
-rw-r--r-- | hw/kvm/apic.c | 2 | ||||
-rw-r--r-- | hw/pci_bridge_dev.c | 4 | ||||
-rw-r--r-- | hw/qdev-monitor.c | 27 | ||||
-rw-r--r-- | hw/qdev.c | 1 | ||||
-rw-r--r-- | hw/rtl8139.c | 15 | ||||
-rw-r--r-- | hw/virtio-blk.c | 21 | ||||
-rw-r--r-- | hw/xen_disk.c | 14 |
10 files changed, 86 insertions, 17 deletions
diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index a883a920b..2d7d03d77 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -462,7 +462,7 @@ static void ahci_check_cmd_bh(void *opaque) static void ahci_init_d2h(AHCIDevice *ad) { - uint8_t init_fis[0x20]; + uint8_t init_fis[20]; IDEState *ide_state = &ad->port.ifs[0]; memset(init_fis, 0, sizeof(init_fis)); @@ -619,7 +619,7 @@ static void ahci_write_fis_d2h(AHCIDevice *ad, uint8_t *cmd_fis) d2h_fis[11] = cmd_fis[11]; d2h_fis[12] = cmd_fis[12]; d2h_fis[13] = cmd_fis[13]; - for (i = 14; i < 0x20; i++) { + for (i = 14; i < 20; i++) { d2h_fis[i] = 0; } diff --git a/hw/ide/ich.c b/hw/ide/ich.c index 560ae3761..242254e8d 100644 --- a/hw/ide/ich.c +++ b/hw/ide/ich.c @@ -84,6 +84,14 @@ static const VMStateDescription vmstate_ahci = { .unmigratable = 1, }; +static void pci_ich9_reset(void *opaque) +{ + struct AHCIPCIState *d = opaque; + + msi_reset(&d->card); + ahci_reset(opaque); +} + static int pci_ich9_ahci_init(PCIDevice *dev) { struct AHCIPCIState *d; @@ -102,7 +110,7 @@ static int pci_ich9_ahci_init(PCIDevice *dev) /* XXX Software should program this register */ d->card.config[0x90] = 1 << 6; /* Address Map Register - AHCI mode */ - qemu_register_reset(ahci_reset, d); + qemu_register_reset(pci_ich9_reset, d); msi_init(dev, 0x50, 1, true, false); d->ahci.irq = d->card.irq[0]; @@ -133,7 +141,7 @@ static int pci_ich9_uninit(PCIDevice *dev) d = DO_UPCAST(struct AHCIPCIState, card, dev); msi_uninit(dev); - qemu_unregister_reset(ahci_reset, d); + qemu_unregister_reset(pci_ich9_reset, d); ahci_uninit(&d->ahci); return 0; diff --git a/hw/intel-hda.c b/hw/intel-hda.c index bb11af286..e38861e5d 100644 --- a/hw/intel-hda.c +++ b/hw/intel-hda.c @@ -1107,6 +1107,9 @@ static void intel_hda_reset(DeviceState *dev) DeviceState *qdev; HDACodecDevice *cdev; + if (d->msi) { + msi_reset(&d->pci); + } intel_hda_regs_reset(d); d->wall_base_ns = qemu_get_clock_ns(vm_clock); diff --git a/hw/kvm/apic.c b/hw/kvm/apic.c index ffe7a521b..a0ab50316 100644 --- a/hw/kvm/apic.c +++ b/hw/kvm/apic.c @@ -29,7 +29,7 @@ void kvm_put_apic_state(DeviceState *d, struct kvm_lapic_state *kapic) APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d); int i; - memset(kapic, 0, sizeof(kapic)); + memset(kapic, 0, sizeof(*kapic)); kvm_apic_set_reg(kapic, 0x2, s->id << 24); kvm_apic_set_reg(kapic, 0x8, s->tpr); kvm_apic_set_reg(kapic, 0xd, s->log_dest << 24); diff --git a/hw/pci_bridge_dev.c b/hw/pci_bridge_dev.c index eccaa5831..ad63703c0 100644 --- a/hw/pci_bridge_dev.c +++ b/hw/pci_bridge_dev.c @@ -52,7 +52,7 @@ static int pci_bridge_dev_initfn(PCIDevice *dev) { PCIBridge *br = DO_UPCAST(PCIBridge, dev, dev); PCIBridgeDev *bridge_dev = DO_UPCAST(PCIBridgeDev, bridge, br); - int err; + int err, ret; pci_bridge_map_irq(br, NULL, pci_bridge_dev_map_irq_fn); err = pci_bridge_initfn(dev); if (err) { @@ -86,6 +86,8 @@ slotid_error: shpc_cleanup(dev, &bridge_dev->bar); shpc_error: memory_region_destroy(&bridge_dev->bar); + ret = pci_bridge_exitfn(dev); + assert(!ret); bridge_error: return err; } diff --git a/hw/qdev-monitor.c b/hw/qdev-monitor.c index eed781d2f..405697e76 100644 --- a/hw/qdev-monitor.c +++ b/hw/qdev-monitor.c @@ -20,6 +20,7 @@ #include "qdev.h" #include "monitor.h" #include "qmp-commands.h" +#include "arch_init.h" /* * Aliases were a bad idea from the start. Let's keep them @@ -29,16 +30,18 @@ typedef struct QDevAlias { const char *typename; const char *alias; + uint32_t arch_mask; } QDevAlias; static const QDevAlias qdev_alias_table[] = { - { "virtio-blk-pci", "virtio-blk" }, - { "virtio-net-pci", "virtio-net" }, - { "virtio-serial-pci", "virtio-serial" }, - { "virtio-balloon-pci", "virtio-balloon" }, - { "virtio-blk-s390", "virtio-blk" }, - { "virtio-net-s390", "virtio-net" }, - { "virtio-serial-s390", "virtio-serial" }, + { "virtio-blk-pci", "virtio-blk", QEMU_ARCH_ALL & ~QEMU_ARCH_S390X }, + { "virtio-net-pci", "virtio-net", QEMU_ARCH_ALL & ~QEMU_ARCH_S390X }, + { "virtio-serial-pci", "virtio-serial", QEMU_ARCH_ALL & ~QEMU_ARCH_S390X }, + { "virtio-balloon-pci", "virtio-balloon", + QEMU_ARCH_ALL & ~QEMU_ARCH_S390X }, + { "virtio-blk-s390", "virtio-blk", QEMU_ARCH_S390X }, + { "virtio-net-s390", "virtio-net", QEMU_ARCH_S390X }, + { "virtio-serial-s390", "virtio-serial", QEMU_ARCH_S390X }, { "lsi53c895a", "lsi" }, { "ich9-ahci", "ahci" }, { } @@ -50,6 +53,11 @@ static const char *qdev_class_get_alias(DeviceClass *dc) int i; for (i = 0; qdev_alias_table[i].typename; i++) { + if (qdev_alias_table[i].arch_mask && + !(qdev_alias_table[i].arch_mask & arch_type)) { + continue; + } + if (strcmp(qdev_alias_table[i].typename, typename) == 0) { return qdev_alias_table[i].alias; } @@ -110,6 +118,11 @@ static const char *find_typename_by_alias(const char *alias) int i; for (i = 0; qdev_alias_table[i].alias; i++) { + if (qdev_alias_table[i].arch_mask && + !(qdev_alias_table[i].arch_mask & arch_type)) { + continue; + } + if (strcmp(qdev_alias_table[i].alias, alias) == 0) { return qdev_alias_table[i].typename; } @@ -150,6 +150,7 @@ int qdev_init(DeviceState *dev) rc = dc->init(dev); if (rc < 0) { + object_unparent(OBJECT(dev)); qdev_free(dev); return rc; } diff --git a/hw/rtl8139.c b/hw/rtl8139.c index 2413bc3d2..7b150475f 100644 --- a/hw/rtl8139.c +++ b/hw/rtl8139.c @@ -781,6 +781,13 @@ static inline dma_addr_t rtl8139_addr64(uint32_t low, uint32_t high) #endif } +/* Workaround for buggy guest driver such as linux who allocates rx + * rings after the receiver were enabled. */ +static bool rtl8139_cp_rx_valid(RTL8139State *s) +{ + return !(s->RxRingAddrLO == 0 && s->RxRingAddrHI == 0); +} + static int rtl8139_can_receive(VLANClientState *nc) { RTL8139State *s = DO_UPCAST(NICState, nc, nc)->opaque; @@ -792,14 +799,14 @@ static int rtl8139_can_receive(VLANClientState *nc) if (!rtl8139_receiver_enabled(s)) return 1; - if (rtl8139_cp_receiver_enabled(s)) { + if (rtl8139_cp_receiver_enabled(s) && rtl8139_cp_rx_valid(s)) { /* ??? Flow control not implemented in c+ mode. This is a hack to work around slirp deficiencies anyway. */ return 1; } else { avail = MOD2(s->RxBufferSize + s->RxBufPtr - s->RxBufAddr, s->RxBufferSize); - return (avail == 0 || avail >= 1514); + return (avail == 0 || avail >= 1514 || (s->IntrMask & RxOverflow)); } } @@ -937,6 +944,10 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_ if (rtl8139_cp_receiver_enabled(s)) { + if (!rtl8139_cp_rx_valid(s)) { + return size; + } + DPRINTF("in C+ Rx mode ================\n"); /* begin C+ receiver mode */ diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c index f9e1896ea..fe0774617 100644 --- a/hw/virtio-blk.c +++ b/hw/virtio-blk.c @@ -147,9 +147,11 @@ static VirtIOBlockReq *virtio_blk_get_request(VirtIOBlock *s) static void virtio_blk_handle_scsi(VirtIOBlockReq *req) { +#ifdef __linux__ int ret; - int status = VIRTIO_BLK_S_OK; int i; +#endif + int status = VIRTIO_BLK_S_OK; /* * We require at least one output segment each for the virtio_blk_outhdr @@ -489,7 +491,22 @@ static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config) stw_raw(&blkcfg.min_io_size, s->conf->min_io_size / blk_size); stw_raw(&blkcfg.opt_io_size, s->conf->opt_io_size / blk_size); blkcfg.heads = heads; - blkcfg.sectors = secs & ~s->sector_mask; + /* + * We must ensure that the block device capacity is a multiple of + * the logical block size. If that is not the case, lets use + * sector_mask to adopt the geometry to have a correct picture. + * For those devices where the capacity is ok for the given geometry + * we dont touch the sector value of the geometry, since some devices + * (like s390 dasd) need a specific value. Here the capacity is already + * cyls*heads*secs*blk_size and the sector value is not block size + * divided by 512 - instead it is the amount of blk_size blocks + * per track (cylinder). + */ + if (bdrv_getlength(s->bs) / heads / secs % blk_size) { + blkcfg.sectors = secs & ~s->sector_mask; + } else { + blkcfg.sectors = secs; + } blkcfg.size_max = 0; blkcfg.physical_block_exp = get_physical_block_exp(s->conf); blkcfg.alignment_offset = 0; diff --git a/hw/xen_disk.c b/hw/xen_disk.c index 07594bc0c..de7e8a4a5 100644 --- a/hw/xen_disk.c +++ b/hw/xen_disk.c @@ -537,6 +537,15 @@ static void blk_bh(void *opaque) blk_handle_requests(blkdev); } +/* + * We need to account for the grant allocations requiring contiguous + * chunks; the worst case number would be + * max_req * max_seg + (max_req - 1) * (max_seg - 1) + 1, + * but in order to keep things simple just use + * 2 * max_req * max_seg. + */ +#define MAX_GRANTS(max_req, max_seg) (2 * (max_req) * (max_seg)) + static void blk_alloc(struct XenDevice *xendev) { struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev); @@ -548,6 +557,11 @@ static void blk_alloc(struct XenDevice *xendev) if (xen_mode != XEN_EMULATE) { batch_maps = 1; } + if (xc_gnttab_set_max_grants(xendev->gnttabdev, + MAX_GRANTS(max_requests, BLKIF_MAX_SEGMENTS_PER_REQUEST)) < 0) { + xen_be_printf(xendev, 0, "xc_gnttab_set_max_grants failed: %s\n", + strerror(errno)); + } } static int blk_init(struct XenDevice *xendev) |