diff options
Diffstat (limited to 'hw')
32 files changed, 249 insertions, 145 deletions
diff --git a/hw/arm/allwinner-a10.c b/hw/arm/allwinner-a10.c index ff249af335..43dc0a12de 100644 --- a/hw/arm/allwinner-a10.c +++ b/hw/arm/allwinner-a10.c @@ -103,6 +103,12 @@ static void aw_a10_class_init(ObjectClass *oc, void *data) DeviceClass *dc = DEVICE_CLASS(oc); dc->realize = aw_a10_realize; + + /* + * Reason: creates an ARM CPU, thus use after free(), see + * arm_cpu_class_init() + */ + dc->cannot_destroy_with_object_finalize_yet = true; } static const TypeInfo aw_a10_type_info = { diff --git a/hw/arm/digic.c b/hw/arm/digic.c index ec8c330602..90f8190c48 100644 --- a/hw/arm/digic.c +++ b/hw/arm/digic.c @@ -97,6 +97,12 @@ static void digic_class_init(ObjectClass *oc, void *data) DeviceClass *dc = DEVICE_CLASS(oc); dc->realize = digic_realize; + + /* + * Reason: creates an ARM CPU, thus use after free(), see + * arm_cpu_class_init() + */ + dc->cannot_destroy_with_object_finalize_yet = true; } static const TypeInfo digic_type_info = { diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c index ec353f79c4..d94e20777f 100644 --- a/hw/arm/pxa2xx.c +++ b/hw/arm/pxa2xx.c @@ -1959,7 +1959,7 @@ static void pxa2xx_fir_instance_init(Object *obj) PXA2xxFIrState *s = PXA2XX_FIR(obj); SysBusDevice *sbd = SYS_BUS_DEVICE(obj); - memory_region_init_io(&s->iomem, NULL, &pxa2xx_fir_ops, s, + memory_region_init_io(&s->iomem, obj, &pxa2xx_fir_ops, s, "pxa2xx-fir", 0x1000); sysbus_init_mmio(sbd, &s->iomem); sysbus_init_irq(sbd, &s->irq); diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c index 62ef4ceb32..5157565f99 100644 --- a/hw/arm/xlnx-zynqmp.c +++ b/hw/arm/xlnx-zynqmp.c @@ -248,6 +248,12 @@ static void xlnx_zynqmp_class_init(ObjectClass *oc, void *data) dc->props = xlnx_zynqmp_props; dc->realize = xlnx_zynqmp_realize; + + /* + * Reason: creates an ARM CPU, thus use after free(), see + * arm_cpu_class_init() + */ + dc->cannot_destroy_with_object_finalize_yet = true; } static const TypeInfo xlnx_zynqmp_type_info = { diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c index 1556c9cf5a..5625a9fa76 100644 --- a/hw/block/virtio-blk.c +++ b/hw/block/virtio-blk.c @@ -731,7 +731,7 @@ static uint64_t virtio_blk_get_features(VirtIODevice *vdev, uint64_t features, virtio_add_feature(&features, VIRTIO_BLK_F_GEOMETRY); virtio_add_feature(&features, VIRTIO_BLK_F_TOPOLOGY); virtio_add_feature(&features, VIRTIO_BLK_F_BLK_SIZE); - if (__virtio_has_feature(features, VIRTIO_F_VERSION_1)) { + if (virtio_has_feature(features, VIRTIO_F_VERSION_1)) { if (s->conf.scsi) { error_setg(errp, "Please set scsi=off for virtio-blk devices in order to use virtio 1.0"); return 0; @@ -782,10 +782,11 @@ static void virtio_blk_set_status(VirtIODevice *vdev, uint8_t status) * * s->blk would erroneously be placed in writethrough mode. */ - if (!virtio_has_feature(vdev, VIRTIO_BLK_F_CONFIG_WCE)) { + if (!virtio_vdev_has_feature(vdev, VIRTIO_BLK_F_CONFIG_WCE)) { aio_context_acquire(blk_get_aio_context(s->blk)); blk_set_enable_write_cache(s->blk, - virtio_has_feature(vdev, VIRTIO_BLK_F_WCE)); + virtio_vdev_has_feature(vdev, + VIRTIO_BLK_F_WCE)); aio_context_release(blk_get_aio_context(s->blk)); } } @@ -793,6 +794,11 @@ static void virtio_blk_set_status(VirtIODevice *vdev, uint8_t status) static void virtio_blk_save(QEMUFile *f, void *opaque) { VirtIODevice *vdev = VIRTIO_DEVICE(opaque); + VirtIOBlock *s = VIRTIO_BLK(vdev); + + if (s->dataplane) { + virtio_blk_data_plane_stop(s->dataplane); + } virtio_save(vdev, f); } diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c index bc56f5d520..be97058712 100644 --- a/hw/char/virtio-serial-bus.c +++ b/hw/char/virtio-serial-bus.c @@ -76,7 +76,7 @@ static VirtIOSerialPort *find_port_by_name(char *name) static bool use_multiport(VirtIOSerial *vser) { VirtIODevice *vdev = VIRTIO_DEVICE(vser); - return virtio_has_feature(vdev, VIRTIO_CONSOLE_F_MULTIPORT); + return virtio_vdev_has_feature(vdev, VIRTIO_CONSOLE_F_MULTIPORT); } static size_t write_to_port(VirtIOSerialPort *port, diff --git a/hw/display/cg3.c b/hw/display/cg3.c index 34dcbc3119..2d3bd70817 100644 --- a/hw/display/cg3.c +++ b/hw/display/cg3.c @@ -280,12 +280,12 @@ static void cg3_initfn(Object *obj) SysBusDevice *sbd = SYS_BUS_DEVICE(obj); CG3State *s = CG3(obj); - memory_region_init_ram(&s->rom, NULL, "cg3.prom", FCODE_MAX_ROM_SIZE, + memory_region_init_ram(&s->rom, obj, "cg3.prom", FCODE_MAX_ROM_SIZE, &error_abort); memory_region_set_readonly(&s->rom, true); sysbus_init_mmio(sbd, &s->rom); - memory_region_init_io(&s->reg, NULL, &cg3_reg_ops, s, "cg3.reg", + memory_region_init_io(&s->reg, obj, &cg3_reg_ops, s, "cg3.reg", CG3_REG_SIZE); sysbus_init_mmio(sbd, &s->reg); } diff --git a/hw/display/tcx.c b/hw/display/tcx.c index 6acdc2d282..327ce30196 100644 --- a/hw/display/tcx.c +++ b/hw/display/tcx.c @@ -944,7 +944,7 @@ static void tcx_initfn(Object *obj) SysBusDevice *sbd = SYS_BUS_DEVICE(obj); TCXState *s = TCX(obj); - memory_region_init_ram(&s->rom, NULL, "tcx.prom", FCODE_MAX_ROM_SIZE, + memory_region_init_ram(&s->rom, OBJECT(s), "tcx.prom", FCODE_MAX_ROM_SIZE, &error_abort); memory_region_set_readonly(&s->rom, true); sysbus_init_mmio(sbd, &s->rom); diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index 48749c1dc1..378ad60c3c 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -50,7 +50,6 @@ static void ahci_reset_port(AHCIState *s, int port); static void ahci_write_fis_d2h(AHCIDevice *ad, uint8_t *cmd_fis); static void ahci_init_d2h(AHCIDevice *ad); static int ahci_dma_prepare_buf(IDEDMA *dma, int32_t limit); -static void ahci_commit_buf(IDEDMA *dma, uint32_t tx_bytes); static bool ahci_map_clb_address(AHCIDevice *ad); static bool ahci_map_fis_address(AHCIDevice *ad); static void ahci_unmap_clb_address(AHCIDevice *ad); @@ -1290,7 +1289,7 @@ out: s->data_ptr = s->data_end; /* Update number of transferred bytes, destroy sglist */ - ahci_commit_buf(dma, size); + dma_buf_commit(s, size); s->end_transfer_func(s); @@ -1332,9 +1331,8 @@ static void ahci_restart(IDEDMA *dma) } /** - * Called in DMA R/W chains to read the PRDT, utilizing ahci_populate_sglist. - * Not currently invoked by PIO R/W chains, - * which invoke ahci_populate_sglist via ahci_start_transfer. + * Called in DMA and PIO R/W chains to read the PRDT. + * Not shared with NCQ pathways. */ static int32_t ahci_dma_prepare_buf(IDEDMA *dma, int32_t limit) { @@ -1353,21 +1351,16 @@ static int32_t ahci_dma_prepare_buf(IDEDMA *dma, int32_t limit) } /** - * Destroys the scatter-gather list, - * and updates the command header with a bytes-read value. - * called explicitly via ahci_dma_rw_buf (ATAPI DMA), - * and ahci_start_transfer (PIO R/W), - * and called via callback from ide_dma_cb for DMA R/W paths. + * Updates the command header with a bytes-read value. + * Called via dma_buf_commit, for both DMA and PIO paths. + * sglist destruction is handled within dma_buf_commit. */ static void ahci_commit_buf(IDEDMA *dma, uint32_t tx_bytes) { AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma); - IDEState *s = &ad->port.ifs[0]; tx_bytes += le32_to_cpu(ad->cur_cmd->status); ad->cur_cmd->status = cpu_to_le32(tx_bytes); - - qemu_sglist_destroy(&s->sg); } static int ahci_dma_rw_buf(IDEDMA *dma, int is_write) @@ -1388,10 +1381,9 @@ static int ahci_dma_rw_buf(IDEDMA *dma, int is_write) } /* free sglist, update byte count */ - ahci_commit_buf(dma, l); + dma_buf_commit(s, l); s->io_buffer_index += l; - s->io_buffer_offset += l; DPRINTF(ad->port_no, "len=%#x\n", l); diff --git a/hw/ide/core.c b/hw/ide/core.c index 50449cae09..1cc6945d80 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -591,7 +591,6 @@ static void ide_sector_read_cb(void *opaque, int ret) s->nsector -= n; /* Allow the guest to read the io_buffer */ ide_transfer_start(s, s->io_buffer, n * BDRV_SECTOR_SIZE, ide_sector_read); - s->io_buffer_offset += 512 * n; ide_set_irq(s->bus); } @@ -635,11 +634,12 @@ static void ide_sector_read(IDEState *s) ide_sector_read_cb, s); } -static void dma_buf_commit(IDEState *s, uint32_t tx_bytes) +void dma_buf_commit(IDEState *s, uint32_t tx_bytes) { if (s->bus->dma->ops->commit_buf) { s->bus->dma->ops->commit_buf(s->bus->dma, tx_bytes); } + s->io_buffer_offset += tx_bytes; qemu_sglist_destroy(&s->sg); } @@ -842,7 +842,6 @@ static void ide_sector_write_cb(void *opaque, int ret) n = s->req_nb_sectors; } s->nsector -= n; - s->io_buffer_offset += 512 * n; ide_set_sector(s, ide_get_sector(s) + n); if (s->nsector == 0) { @@ -1747,11 +1746,11 @@ static const struct { } ide_cmd_table[0x100] = { /* NOP not implemented, mandatory for CD */ [CFA_REQ_EXT_ERROR_CODE] = { cmd_cfa_req_ext_error_code, CFA_OK }, - [WIN_DSM] = { cmd_data_set_management, ALL_OK }, + [WIN_DSM] = { cmd_data_set_management, HD_CFA_OK }, [WIN_DEVICE_RESET] = { cmd_device_reset, CD_OK }, [WIN_RECAL] = { cmd_nop, HD_CFA_OK | SET_DSC}, [WIN_READ] = { cmd_read_pio, ALL_OK }, - [WIN_READ_ONCE] = { cmd_read_pio, ALL_OK }, + [WIN_READ_ONCE] = { cmd_read_pio, HD_CFA_OK }, [WIN_READ_EXT] = { cmd_read_pio, HD_CFA_OK }, [WIN_READDMA_EXT] = { cmd_read_dma, HD_CFA_OK }, [WIN_READ_NATIVE_MAX_EXT] = { cmd_read_native_max, HD_CFA_OK | SET_DSC }, @@ -1770,12 +1769,12 @@ static const struct { [CFA_TRANSLATE_SECTOR] = { cmd_cfa_translate_sector, CFA_OK }, [WIN_DIAGNOSE] = { cmd_exec_dev_diagnostic, ALL_OK }, [WIN_SPECIFY] = { cmd_nop, HD_CFA_OK | SET_DSC }, - [WIN_STANDBYNOW2] = { cmd_nop, ALL_OK }, - [WIN_IDLEIMMEDIATE2] = { cmd_nop, ALL_OK }, - [WIN_STANDBY2] = { cmd_nop, ALL_OK }, - [WIN_SETIDLE2] = { cmd_nop, ALL_OK }, - [WIN_CHECKPOWERMODE2] = { cmd_check_power_mode, ALL_OK | SET_DSC }, - [WIN_SLEEPNOW2] = { cmd_nop, ALL_OK }, + [WIN_STANDBYNOW2] = { cmd_nop, HD_CFA_OK }, + [WIN_IDLEIMMEDIATE2] = { cmd_nop, HD_CFA_OK }, + [WIN_STANDBY2] = { cmd_nop, HD_CFA_OK }, + [WIN_SETIDLE2] = { cmd_nop, HD_CFA_OK }, + [WIN_CHECKPOWERMODE2] = { cmd_check_power_mode, HD_CFA_OK | SET_DSC }, + [WIN_SLEEPNOW2] = { cmd_nop, HD_CFA_OK }, [WIN_PACKETCMD] = { cmd_packet, CD_OK }, [WIN_PIDENTIFY] = { cmd_identify_packet, CD_OK }, [WIN_SMART] = { cmd_smart, HD_CFA_OK | SET_DSC }, @@ -1789,19 +1788,19 @@ static const struct { [WIN_WRITEDMA] = { cmd_write_dma, HD_CFA_OK }, [WIN_WRITEDMA_ONCE] = { cmd_write_dma, HD_CFA_OK }, [CFA_WRITE_MULTI_WO_ERASE] = { cmd_write_multiple, CFA_OK }, - [WIN_STANDBYNOW1] = { cmd_nop, ALL_OK }, - [WIN_IDLEIMMEDIATE] = { cmd_nop, ALL_OK }, - [WIN_STANDBY] = { cmd_nop, ALL_OK }, - [WIN_SETIDLE1] = { cmd_nop, ALL_OK }, - [WIN_CHECKPOWERMODE1] = { cmd_check_power_mode, ALL_OK | SET_DSC }, - [WIN_SLEEPNOW1] = { cmd_nop, ALL_OK }, + [WIN_STANDBYNOW1] = { cmd_nop, HD_CFA_OK }, + [WIN_IDLEIMMEDIATE] = { cmd_nop, HD_CFA_OK }, + [WIN_STANDBY] = { cmd_nop, HD_CFA_OK }, + [WIN_SETIDLE1] = { cmd_nop, HD_CFA_OK }, + [WIN_CHECKPOWERMODE1] = { cmd_check_power_mode, HD_CFA_OK | SET_DSC }, + [WIN_SLEEPNOW1] = { cmd_nop, HD_CFA_OK }, [WIN_FLUSH_CACHE] = { cmd_flush_cache, ALL_OK }, [WIN_FLUSH_CACHE_EXT] = { cmd_flush_cache, HD_CFA_OK }, [WIN_IDENTIFY] = { cmd_identify, ALL_OK }, [WIN_SETFEATURES] = { cmd_set_features, ALL_OK | SET_DSC }, [IBM_SENSE_CONDITION] = { cmd_ibm_sense_condition, CFA_OK | SET_DSC }, [CFA_WEAR_LEVEL] = { cmd_cfa_erase_sectors, HD_CFA_OK | SET_DSC }, - [WIN_READ_NATIVE_MAX] = { cmd_read_native_max, ALL_OK | SET_DSC }, + [WIN_READ_NATIVE_MAX] = { cmd_read_native_max, HD_CFA_OK | SET_DSC }, }; static bool ide_cmd_permitted(IDEState *s, uint32_t cmd) diff --git a/hw/ide/internal.h b/hw/ide/internal.h index 30fdcbc5fa..7288a677a4 100644 --- a/hw/ide/internal.h +++ b/hw/ide/internal.h @@ -536,6 +536,7 @@ int64_t ide_get_sector(IDEState *s); void ide_set_sector(IDEState *s, int64_t sector_num); void ide_start_dma(IDEState *s, BlockCompletionFunc *cb); +void dma_buf_commit(IDEState *s, uint32_t tx_bytes); void ide_dma_error(IDEState *s); void ide_atapi_cmd_ok(IDEState *s); diff --git a/hw/input/virtio-input.c b/hw/input/virtio-input.c index 7b25d27693..1f5a40de35 100644 --- a/hw/input/virtio-input.c +++ b/hw/input/virtio-input.c @@ -20,6 +20,10 @@ void virtio_input_send(VirtIOInput *vinput, virtio_input_event *event) unsigned have, need; int i, len; + if (!vinput->active) { + return; + } + /* queue up events ... */ if (vinput->qindex == vinput->qsize) { vinput->qsize++; diff --git a/hw/misc/arm_integrator_debug.c b/hw/misc/arm_integrator_debug.c index 99b720fbb9..6d9dd74e38 100644 --- a/hw/misc/arm_integrator_debug.c +++ b/hw/misc/arm_integrator_debug.c @@ -79,7 +79,7 @@ static void intdbg_control_init(Object *obj) SysBusDevice *sd = SYS_BUS_DEVICE(obj); IntegratorDebugState *s = INTEGRATOR_DEBUG(obj); - memory_region_init_io(&s->iomem, NULL, &intdbg_control_ops, + memory_region_init_io(&s->iomem, obj, &intdbg_control_ops, NULL, "dbg-leds", 0x1000000); sysbus_init_mmio(sd, &s->iomem); } diff --git a/hw/misc/macio/cuda.c b/hw/misc/macio/cuda.c index f3984e3a20..5d7043e99c 100644 --- a/hw/misc/macio/cuda.c +++ b/hw/misc/macio/cuda.c @@ -713,7 +713,7 @@ static void cuda_initfn(Object *obj) CUDAState *s = CUDA(obj); int i; - memory_region_init_io(&s->mem, NULL, &cuda_ops, s, "cuda", 0x2000); + memory_region_init_io(&s->mem, obj, &cuda_ops, s, "cuda", 0x2000); sysbus_init_mmio(d, &s->mem); sysbus_init_irq(d, &s->irq); diff --git a/hw/misc/macio/mac_dbdma.c b/hw/misc/macio/mac_dbdma.c index b25e8511b2..779683cc07 100644 --- a/hw/misc/macio/mac_dbdma.c +++ b/hw/misc/macio/mac_dbdma.c @@ -590,10 +590,11 @@ dbdma_control_write(DBDMA_channel *ch) if ((ch->regs[DBDMA_STATUS] & RUN) && !(status & RUN)) { /* RUN is cleared */ status &= ~(ACTIVE|DEAD); - if ((status & FLUSH) && ch->flush) { - ch->flush(&ch->io); - status &= ~FLUSH; - } + } + + if ((status & FLUSH) && ch->flush) { + ch->flush(&ch->io); + status &= ~FLUSH; } DBDMA_DPRINTF(" status 0x%08x\n", status); @@ -603,9 +604,6 @@ dbdma_control_write(DBDMA_channel *ch) if (status & ACTIVE) { DBDMA_kick(dbdma_from_ch(ch)); } - if ((status & FLUSH) && ch->flush) { - ch->flush(&ch->io); - } } static void dbdma_write(void *opaque, hwaddr addr, diff --git a/hw/misc/macio/macio.c b/hw/misc/macio/macio.c index e3c0242d41..c661f86c21 100644 --- a/hw/misc/macio/macio.c +++ b/hw/misc/macio/macio.c @@ -105,10 +105,10 @@ static void macio_escc_legacy_setup(MacIOState *macio_state) 0xF0, 0xE0, }; - memory_region_init(escc_legacy, NULL, "escc-legacy", 256); + memory_region_init(escc_legacy, OBJECT(macio_state), "escc-legacy", 256); for (i = 0; i < ARRAY_SIZE(maps); i += 2) { MemoryRegion *port = g_new(MemoryRegion, 1); - memory_region_init_alias(port, NULL, "escc-legacy-port", + memory_region_init_alias(port, OBJECT(macio_state), "escc-legacy-port", macio_state->escc_mem, maps[i+1], 0x2); memory_region_add_subregion(escc_legacy, maps[i], port); } @@ -131,6 +131,10 @@ static void macio_common_realize(PCIDevice *d, Error **errp) MacIOState *s = MACIO(d); SysBusDevice *sysbus_dev; Error *err = NULL; + MemoryRegion *dbdma_mem; + + s->dbdma = DBDMA_init(&dbdma_mem); + memory_region_add_subregion(&s->bar, 0x08000, dbdma_mem); object_property_set_bool(OBJECT(&s->cuda), true, "realized", &err); if (err) { @@ -328,16 +332,12 @@ static void macio_newworld_init(Object *obj) static void macio_instance_init(Object *obj) { MacIOState *s = MACIO(obj); - MemoryRegion *dbdma_mem; - memory_region_init(&s->bar, NULL, "macio", 0x80000); + memory_region_init(&s->bar, obj, "macio", 0x80000); object_initialize(&s->cuda, sizeof(s->cuda), TYPE_CUDA); qdev_set_parent_bus(DEVICE(&s->cuda), sysbus_get_default()); object_property_add_child(obj, "cuda", OBJECT(&s->cuda), NULL); - - s->dbdma = DBDMA_init(&dbdma_mem); - memory_region_add_subregion(&s->bar, 0x08000, dbdma_mem); } static const VMStateDescription vmstate_macio_oldworld = { diff --git a/hw/misc/zynq_slcr.c b/hw/misc/zynq_slcr.c index 964f2532ff..3d7870850b 100644 --- a/hw/misc/zynq_slcr.c +++ b/hw/misc/zynq_slcr.c @@ -393,12 +393,12 @@ static void zynq_slcr_write(void *opaque, hwaddr offset, return; } - if (!s->regs[LOCKSTA]) { - s->regs[offset / 4] = val; - } else { - DB_PRINT("SCLR registers are locked. Unlock them first\n"); + if (s->regs[LOCKSTA]) { + qemu_log_mask(LOG_GUEST_ERROR, + "SCLR registers are locked. Unlock them first\n"); return; } + s->regs[offset] = val; switch (offset) { case PSS_RST_CTRL: diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c index edbb61ccf3..cb51613eb3 100644 --- a/hw/net/rtl8139.c +++ b/hw/net/rtl8139.c @@ -1148,7 +1148,9 @@ static ssize_t rtl8139_do_receive(NetClientState *nc, const uint8_t *buf, size_t /* if receiver buffer is empty then avail == 0 */ - if (avail != 0 && size + 8 >= avail) +#define RX_ALIGN(x) (((x) + 3) & ~0x3) + + if (avail != 0 && RX_ALIGN(size + 8) >= avail) { DPRINTF("rx overflow: rx buffer length %d head 0x%04x " "read 0x%04x === available 0x%04x need 0x%04x\n", @@ -1157,7 +1159,7 @@ static ssize_t rtl8139_do_receive(NetClientState *nc, const uint8_t *buf, size_t s->IntrStatus |= RxOverflow; ++s->RxMissed; rtl8139_update_irq(s); - return size_; + return 0; } packet_header |= RxStatusOK; @@ -1176,7 +1178,7 @@ static ssize_t rtl8139_do_receive(NetClientState *nc, const uint8_t *buf, size_t rtl8139_write_buffer(s, (uint8_t *)&val, 4); /* correct buffer write pointer */ - s->RxBufAddr = MOD2((s->RxBufAddr + 3) & ~0x3, s->RxBufferSize); + s->RxBufAddr = MOD2(RX_ALIGN(s->RxBufAddr), s->RxBufferSize); /* now we can signal we have received something */ diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c index 5c1d11f517..1d76b94c84 100644 --- a/hw/net/vhost_net.c +++ b/hw/net/vhost_net.c @@ -197,7 +197,7 @@ static int vhost_net_set_vnet_endian(VirtIODevice *dev, NetClientState *peer, { int r = 0; - if (virtio_has_feature(dev, VIRTIO_F_VERSION_1) || + if (virtio_vdev_has_feature(dev, VIRTIO_F_VERSION_1) || (virtio_legacy_is_cross_endian(dev) && !virtio_is_big_endian(dev))) { r = qemu_set_vnet_le(peer, set); if (r) { diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index 1510839547..4aa93fb931 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -86,8 +86,8 @@ static void virtio_net_set_config(VirtIODevice *vdev, const uint8_t *config) memcpy(&netcfg, config, n->config_size); - if (!virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_MAC_ADDR) && - !virtio_has_feature(vdev, VIRTIO_F_VERSION_1) && + if (!virtio_vdev_has_feature(vdev, VIRTIO_NET_F_CTRL_MAC_ADDR) && + !virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1) && memcmp(netcfg.mac, n->mac, ETH_ALEN)) { memcpy(n->mac, netcfg.mac, ETH_ALEN); qemu_format_nic_info_str(qemu_get_queue(n->nic), n->mac); @@ -304,7 +304,7 @@ static RxFilterInfo *virtio_net_query_rxfilter(NetClientState *nc) info->multicast_table = str_list; info->vlan_table = get_vlan_table(n); - if (!virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_VLAN)) { + if (!virtio_vdev_has_feature(vdev, VIRTIO_NET_F_CTRL_VLAN)) { info->vlan = RX_STATE_ALL; } else if (!info->vlan_table) { info->vlan = RX_STATE_NONE; @@ -529,13 +529,13 @@ static void virtio_net_set_features(VirtIODevice *vdev, uint64_t features) int i; virtio_net_set_multiqueue(n, - __virtio_has_feature(features, VIRTIO_NET_F_MQ)); + virtio_has_feature(features, VIRTIO_NET_F_MQ)); virtio_net_set_mrg_rx_bufs(n, - __virtio_has_feature(features, - VIRTIO_NET_F_MRG_RXBUF), - __virtio_has_feature(features, - VIRTIO_F_VERSION_1)); + virtio_has_feature(features, + VIRTIO_NET_F_MRG_RXBUF), + virtio_has_feature(features, + VIRTIO_F_VERSION_1)); if (n->has_vnet_hdr) { n->curr_guest_offloads = @@ -552,7 +552,7 @@ static void virtio_net_set_features(VirtIODevice *vdev, uint64_t features) vhost_net_ack_features(get_vhost_net(nc->peer), features); } - if (__virtio_has_feature(features, VIRTIO_NET_F_CTRL_VLAN)) { + if (virtio_has_feature(features, VIRTIO_NET_F_CTRL_VLAN)) { memset(n->vlans, 0, MAX_VLAN >> 3); } else { memset(n->vlans, 0xff, MAX_VLAN >> 3); @@ -599,7 +599,7 @@ static int virtio_net_handle_offloads(VirtIONet *n, uint8_t cmd, uint64_t offloads; size_t s; - if (!virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS)) { + if (!virtio_vdev_has_feature(vdev, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS)) { return VIRTIO_NET_ERR; } @@ -1086,13 +1086,7 @@ static ssize_t virtio_net_receive(NetClientState *nc, const uint8_t *buf, size_t * must have consumed the complete packet. * Otherwise, drop it. */ if (!n->mergeable_rx_bufs && offset < size) { -#if 0 - error_report("virtio-net truncated non-mergeable packet: " - "i %zd mergeable %d offset %zd, size %zd, " - "guest hdr len %zd, host hdr len %zd", - i, n->mergeable_rx_bufs, - offset, size, n->guest_hdr_len, n->host_hdr_len); -#endif + virtqueue_discard(q->rx_vq, &elem, total); return size; } @@ -1453,7 +1447,7 @@ static void virtio_net_save_device(VirtIODevice *vdev, QEMUFile *f) } } - if (virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS)) { + if (virtio_vdev_has_feature(vdev, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS)) { qemu_put_be64(f, n->curr_guest_offloads); } } @@ -1462,11 +1456,33 @@ static int virtio_net_load(QEMUFile *f, void *opaque, int version_id) { VirtIONet *n = opaque; VirtIODevice *vdev = VIRTIO_DEVICE(n); + int ret; if (version_id < 2 || version_id > VIRTIO_NET_VM_VERSION) return -EINVAL; - return virtio_load(vdev, f, version_id); + ret = virtio_load(vdev, f, version_id); + if (ret) { + return ret; + } + + if (virtio_vdev_has_feature(vdev, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS)) { + n->curr_guest_offloads = qemu_get_be64(f); + } else { + n->curr_guest_offloads = virtio_net_supported_guest_offloads(n); + } + + if (peer_has_vnet_hdr(n)) { + virtio_net_apply_guest_offloads(n); + } + + if (virtio_vdev_has_feature(vdev, VIRTIO_NET_F_GUEST_ANNOUNCE) && + virtio_vdev_has_feature(vdev, VIRTIO_NET_F_CTRL_VQ)) { + n->announce_counter = SELF_ANNOUNCE_ROUNDS; + timer_mod(n->announce_timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL)); + } + + return 0; } static int virtio_net_load_device(VirtIODevice *vdev, QEMUFile *f, @@ -1479,7 +1495,8 @@ static int virtio_net_load_device(VirtIODevice *vdev, QEMUFile *f, n->vqs[0].tx_waiting = qemu_get_be32(f); virtio_net_set_mrg_rx_bufs(n, qemu_get_be32(f), - virtio_has_feature(vdev, VIRTIO_F_VERSION_1)); + virtio_vdev_has_feature(vdev, + VIRTIO_F_VERSION_1)); if (version_id >= 3) n->status = qemu_get_be16(f); @@ -1562,16 +1579,6 @@ static int virtio_net_load_device(VirtIODevice *vdev, QEMUFile *f, } } - if (virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS)) { - n->curr_guest_offloads = qemu_get_be64(f); - } else { - n->curr_guest_offloads = virtio_net_supported_guest_offloads(n); - } - - if (peer_has_vnet_hdr(n)) { - virtio_net_apply_guest_offloads(n); - } - virtio_net_set_queues(n); /* Find the first multicast entry in the saved MAC filter */ @@ -1589,12 +1596,6 @@ static int virtio_net_load_device(VirtIODevice *vdev, QEMUFile *f, qemu_get_subqueue(n->nic, i)->link_down = link_down; } - if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_ANNOUNCE) && - virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_VQ)) { - n->announce_counter = SELF_ANNOUNCE_ROUNDS; - timer_mod(n->announce_timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL)); - } - return 0; } diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c index 59b06b8412..2504425cf9 100644 --- a/hw/net/vmxnet3.c +++ b/hw/net/vmxnet3.c @@ -1988,7 +1988,6 @@ static void vmxnet3_set_link_status(NetClientState *nc) static NetClientInfo net_vmxnet3_info = { .type = NET_CLIENT_OPTIONS_KIND_NIC, .size = sizeof(NICState), - .can_receive = vmxnet3_can_receive, .receive = vmxnet3_receive, .link_status_changed = vmxnet3_set_link_status, }; diff --git a/hw/pci-host/versatile.c b/hw/pci-host/versatile.c index 6d23553094..7172b90958 100644 --- a/hw/pci-host/versatile.c +++ b/hw/pci-host/versatile.c @@ -500,6 +500,8 @@ static void pci_vpb_class_init(ObjectClass *klass, void *data) dc->reset = pci_vpb_reset; dc->vmsd = &pci_vpb_vmstate; dc->props = pci_vpb_properties; + /* Reason: object_unref() hangs */ + dc->cannot_destroy_with_object_finalize_yet = true; } static const TypeInfo pci_vpb_info = { @@ -521,10 +523,19 @@ static void pci_realview_init(Object *obj) s->mem_win_size[2] = 0x08000000; } +static void pci_realview_class_init(ObjectClass *class, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(class); + + /* Reason: object_unref() hangs */ + dc->cannot_destroy_with_object_finalize_yet = true; +} + static const TypeInfo pci_realview_info = { .name = "realview_pci", .parent = TYPE_VERSATILE_PCI, .instance_init = pci_realview_init, + .class_init = pci_realview_class_init, }; static void versatile_pci_register_types(void) diff --git a/hw/pcmcia/pxa2xx.c b/hw/pcmcia/pxa2xx.c index a7e187743d..812716e1c8 100644 --- a/hw/pcmcia/pxa2xx.c +++ b/hw/pcmcia/pxa2xx.c @@ -163,7 +163,7 @@ static void pxa2xx_pcmcia_initfn(Object *obj) sysbus_init_mmio(sbd, &s->container_mem); /* Socket I/O Memory Space */ - memory_region_init_io(&s->iomem, NULL, &pxa2xx_pcmcia_io_ops, s, + memory_region_init_io(&s->iomem, obj, &pxa2xx_pcmcia_io_ops, s, "pxa2xx-pcmcia-io", 0x04000000); memory_region_add_subregion(&s->container_mem, 0x00000000, &s->iomem); @@ -171,13 +171,13 @@ static void pxa2xx_pcmcia_initfn(Object *obj) /* Then next 64 MB is reserved */ /* Socket Attribute Memory Space */ - memory_region_init_io(&s->attr_iomem, NULL, &pxa2xx_pcmcia_attr_ops, s, + memory_region_init_io(&s->attr_iomem, obj, &pxa2xx_pcmcia_attr_ops, s, "pxa2xx-pcmcia-attribute", 0x04000000); memory_region_add_subregion(&s->container_mem, 0x08000000, &s->attr_iomem); /* Socket Common Memory Space */ - memory_region_init_io(&s->common_iomem, NULL, &pxa2xx_pcmcia_common_ops, s, + memory_region_init_io(&s->common_iomem, obj, &pxa2xx_pcmcia_common_ops, s, "pxa2xx-pcmcia-common", 0x04000000); memory_region_add_subregion(&s->container_mem, 0x0c000000, &s->common_iomem); diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index a8f79d8003..119fa5e465 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -955,6 +955,7 @@ static int spapr_populate_pci_child_dt(PCIDevice *dev, void *fdt, int offset, int pci_status, err; char *buf = NULL; uint32_t drc_index = spapr_phb_get_pci_drc_index(sphb, dev); + uint32_t max_msi, max_msix; if (pci_default_read_config(dev, PCI_HEADER_TYPE, 1) == PCI_HEADER_TYPE_BRIDGE) { @@ -1035,8 +1036,15 @@ static int spapr_populate_pci_child_dt(PCIDevice *dev, void *fdt, int offset, RESOURCE_CELLS_ADDRESS)); _FDT(fdt_setprop_cell(fdt, offset, "#size-cells", RESOURCE_CELLS_SIZE)); - _FDT(fdt_setprop_cell(fdt, offset, "ibm,req#msi-x", - RESOURCE_CELLS_SIZE)); + + max_msi = msi_nr_vectors_allocated(dev); + if (max_msi) { + _FDT(fdt_setprop_cell(fdt, offset, "ibm,req#msi", max_msi)); + } + max_msix = dev->msix_entries_nr; + if (max_msix) { + _FDT(fdt_setprop_cell(fdt, offset, "ibm,req#msi-x", max_msix)); + } populate_resource_props(dev, &rp); _FDT(fdt_setprop(fdt, offset, "reg", (uint8_t *)rp.reg, rp.reg_len)); diff --git a/hw/s390x/css.c b/hw/s390x/css.c index 5df450e00b..97d93d56df 100644 --- a/hw/s390x/css.c +++ b/hw/s390x/css.c @@ -392,6 +392,8 @@ static void sch_handle_start_func(SubchDev *sch, ORB *orb) path = 0x80; if (!(s->ctrl & SCSW_ACTL_SUSP)) { + s->cstat = 0; + s->dstat = 0; /* Look at the orb and try to execute the channel program. */ assert(orb != NULL); /* resume does not pass an orb */ p->intparm = orb->intparm; diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c index 64f0694734..0e0bc64400 100644 --- a/hw/scsi/scsi-disk.c +++ b/hw/scsi/scsi-disk.c @@ -1683,6 +1683,10 @@ static void scsi_write_same_complete(void *opaque, int ret) if (data->iov.iov_len) { block_acct_start(blk_get_stats(s->qdev.conf.blk), &r->acct, data->iov.iov_len, BLOCK_ACCT_WRITE); + /* blk_aio_write doesn't like the qiov size being different from + * nb_sectors, make sure they match. + */ + qemu_iovec_init_external(&data->qiov, &data->iov, 1); r->req.aiocb = blk_aio_writev(s->qdev.conf.blk, data->sector, &data->qiov, data->iov.iov_len / 512, scsi_write_same_complete, data); diff --git a/hw/scsi/vhost-scsi.c b/hw/scsi/vhost-scsi.c index a69918bef8..62d91003bf 100644 --- a/hw/scsi/vhost-scsi.c +++ b/hw/scsi/vhost-scsi.c @@ -291,7 +291,7 @@ static char *vhost_scsi_get_fw_dev_path(FWPathProvider *p, BusState *bus, { VHostSCSI *s = VHOST_SCSI(dev); /* format: channel@channel/vhost-scsi@target,lun */ - return g_strdup_printf("channel@%x/%s@%x,%x", s->channel, + return g_strdup_printf("/channel@%x/%s@%x,%x", s->channel, qdev_fw_name(dev), s->target, s->lun); } diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c index 811c3da8bd..93c33e11f8 100644 --- a/hw/scsi/virtio-scsi.c +++ b/hw/scsi/virtio-scsi.c @@ -145,7 +145,7 @@ static int virtio_scsi_parse_req(VirtIOSCSIReq *req, * * TODO: always disable this workaround for virtio 1.0 devices. */ - if (!virtio_has_feature(vdev, VIRTIO_F_ANY_LAYOUT)) { + if (!virtio_vdev_has_feature(vdev, VIRTIO_F_ANY_LAYOUT)) { if (req->elem.out_num) { req_size = req->elem.out_sg[0].iov_len; } @@ -662,6 +662,11 @@ static void virtio_scsi_reset(VirtIODevice *vdev) static void virtio_scsi_save(QEMUFile *f, void *opaque) { VirtIODevice *vdev = VIRTIO_DEVICE(opaque); + VirtIOSCSI *s = VIRTIO_SCSI(vdev); + + if (s->dataplane_started) { + virtio_scsi_dataplane_stop(s); + } virtio_save(vdev, f); } @@ -754,7 +759,7 @@ static void virtio_scsi_change(SCSIBus *bus, SCSIDevice *dev, SCSISense sense) VirtIOSCSI *s = container_of(bus, VirtIOSCSI, bus); VirtIODevice *vdev = VIRTIO_DEVICE(s); - if (virtio_has_feature(vdev, VIRTIO_SCSI_F_CHANGE) && + if (virtio_vdev_has_feature(vdev, VIRTIO_SCSI_F_CHANGE) && dev->type != TYPE_ROM) { virtio_scsi_push_event(s, dev, VIRTIO_SCSI_T_PARAM_CHANGE, sense.asc | (sense.ascq << 8)); @@ -778,7 +783,7 @@ static void virtio_scsi_hotplug(HotplugHandler *hotplug_dev, DeviceState *dev, aio_context_release(s->ctx); } - if (virtio_has_feature(vdev, VIRTIO_SCSI_F_HOTPLUG)) { + if (virtio_vdev_has_feature(vdev, VIRTIO_SCSI_F_HOTPLUG)) { virtio_scsi_push_event(s, sd, VIRTIO_SCSI_T_TRANSPORT_RESET, VIRTIO_SCSI_EVT_RESET_RESCAN); @@ -792,7 +797,7 @@ static void virtio_scsi_hotunplug(HotplugHandler *hotplug_dev, DeviceState *dev, VirtIOSCSI *s = VIRTIO_SCSI(vdev); SCSIDevice *sd = SCSI_DEVICE(dev); - if (virtio_has_feature(vdev, VIRTIO_SCSI_F_HOTPLUG)) { + if (virtio_vdev_has_feature(vdev, VIRTIO_SCSI_F_HOTPLUG)) { virtio_scsi_push_event(s, sd, VIRTIO_SCSI_T_TRANSPORT_RESET, VIRTIO_SCSI_EVT_RESET_REMOVED); diff --git a/hw/virtio/dataplane/vring.c b/hw/virtio/dataplane/vring.c index 07fd69c69e..68f1994434 100644 --- a/hw/virtio/dataplane/vring.c +++ b/hw/virtio/dataplane/vring.c @@ -67,22 +67,53 @@ static void vring_unmap(void *buffer, bool is_write) /* Map the guest's vring to host memory */ bool vring_setup(Vring *vring, VirtIODevice *vdev, int n) { - hwaddr vring_addr = virtio_queue_get_ring_addr(vdev, n); - hwaddr vring_size = virtio_queue_get_ring_size(vdev, n); - void *vring_ptr; + struct vring *vr = &vring->vr; + hwaddr addr; + hwaddr size; + void *ptr; vring->broken = false; - - vring_ptr = vring_map(&vring->mr, vring_addr, vring_size, true); - if (!vring_ptr) { - error_report("Failed to map vring " - "addr %#" HWADDR_PRIx " size %" HWADDR_PRIu, - vring_addr, vring_size); - vring->broken = true; - return false; + vr->num = virtio_queue_get_num(vdev, n); + + addr = virtio_queue_get_desc_addr(vdev, n); + size = virtio_queue_get_desc_size(vdev, n); + /* Map the descriptor area as read only */ + ptr = vring_map(&vring->mr_desc, addr, size, false); + if (!ptr) { + error_report("Failed to map 0x%" HWADDR_PRIx " byte for vring desc " + "at 0x%" HWADDR_PRIx, + size, addr); + goto out_err_desc; } - - vring_init(&vring->vr, virtio_queue_get_num(vdev, n), vring_ptr, 4096); + vr->desc = ptr; + + addr = virtio_queue_get_avail_addr(vdev, n); + size = virtio_queue_get_avail_size(vdev, n); + /* Add the size of the used_event_idx */ + size += sizeof(uint16_t); + /* Map the driver area as read only */ + ptr = vring_map(&vring->mr_avail, addr, size, false); + if (!ptr) { + error_report("Failed to map 0x%" HWADDR_PRIx " byte for vring avail " + "at 0x%" HWADDR_PRIx, + size, addr); + goto out_err_avail; + } + vr->avail = ptr; + + addr = virtio_queue_get_used_addr(vdev, n); + size = virtio_queue_get_used_size(vdev, n); + /* Add the size of the avail_event_idx */ + size += sizeof(uint16_t); + /* Map the device area as read-write */ + ptr = vring_map(&vring->mr_used, addr, size, true); + if (!ptr) { + error_report("Failed to map 0x%" HWADDR_PRIx " byte for vring used " + "at 0x%" HWADDR_PRIx, + size, addr); + goto out_err_used; + } + vr->used = ptr; vring->last_avail_idx = virtio_queue_get_last_avail_idx(vdev, n); vring->last_used_idx = vring_get_used_idx(vdev, vring); @@ -92,6 +123,14 @@ bool vring_setup(Vring *vring, VirtIODevice *vdev, int n) trace_vring_setup(virtio_queue_get_ring_addr(vdev, n), vring->vr.desc, vring->vr.avail, vring->vr.used); return true; + +out_err_used: + memory_region_unref(vring->mr_avail); +out_err_avail: + memory_region_unref(vring->mr_desc); +out_err_desc: + vring->broken = true; + return false; } void vring_teardown(Vring *vring, VirtIODevice *vdev, int n) @@ -99,13 +138,15 @@ void vring_teardown(Vring *vring, VirtIODevice *vdev, int n) virtio_queue_set_last_avail_idx(vdev, n, vring->last_avail_idx); virtio_queue_invalidate_signalled_used(vdev, n); - memory_region_unref(vring->mr); + memory_region_unref(vring->mr_desc); + memory_region_unref(vring->mr_avail); + memory_region_unref(vring->mr_used); } /* Disable guest->host notifies */ void vring_disable_notification(VirtIODevice *vdev, Vring *vring) { - if (!virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) { + if (!virtio_vdev_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) { vring_set_used_flags(vdev, vring, VRING_USED_F_NO_NOTIFY); } } @@ -116,7 +157,7 @@ void vring_disable_notification(VirtIODevice *vdev, Vring *vring) */ bool vring_enable_notification(VirtIODevice *vdev, Vring *vring) { - if (virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) { + if (virtio_vdev_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) { vring_avail_event(&vring->vr) = vring->vr.avail->idx; } else { vring_clear_used_flags(vdev, vring, VRING_USED_F_NO_NOTIFY); @@ -135,12 +176,12 @@ bool vring_should_notify(VirtIODevice *vdev, Vring *vring) * interrupts. */ smp_mb(); - if (virtio_has_feature(vdev, VIRTIO_F_NOTIFY_ON_EMPTY) && + if (virtio_vdev_has_feature(vdev, VIRTIO_F_NOTIFY_ON_EMPTY) && unlikely(!vring_more_avail(vdev, vring))) { return true; } - if (!virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) { + if (!virtio_vdev_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) { return !(vring_get_avail_flags(vdev, vring) & VRING_AVAIL_F_NO_INTERRUPT); } @@ -402,7 +443,7 @@ int vring_pop(VirtIODevice *vdev, Vring *vring, /* On success, increment avail index. */ vring->last_avail_idx++; - if (virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) { + if (virtio_vdev_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) { vring_avail_event(&vring->vr) = virtio_tswap16(vdev, vring->last_avail_idx); } diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index 2712c6fc0a..a08c36bb45 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -742,7 +742,7 @@ static int vhost_virtqueue_start(struct vhost_dev *dev, return -errno; } - if (!virtio_has_feature(vdev, VIRTIO_F_VERSION_1) && + if (!virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1) && virtio_legacy_is_cross_endian(vdev)) { r = vhost_virtqueue_set_vring_endian_legacy(dev, virtio_is_big_endian(vdev), @@ -839,7 +839,7 @@ static void vhost_virtqueue_stop(struct vhost_dev *dev, /* In the cross-endian case, we need to reset the vring endianness to * native as legacy devices expect so by default. */ - if (!virtio_has_feature(vdev, VIRTIO_F_VERSION_1) && + if (!virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1) && virtio_legacy_is_cross_endian(vdev)) { r = vhost_virtqueue_set_vring_endian_legacy(dev, !virtio_is_big_endian(vdev), diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c index 3577b7af91..c419b17143 100644 --- a/hw/virtio/virtio-balloon.c +++ b/hw/virtio/virtio-balloon.c @@ -70,7 +70,7 @@ static inline void reset_stats(VirtIOBalloon *dev) static bool balloon_stats_supported(const VirtIOBalloon *s) { VirtIODevice *vdev = VIRTIO_DEVICE(s); - return virtio_has_feature(vdev, VIRTIO_BALLOON_F_STATS_VQ); + return virtio_vdev_has_feature(vdev, VIRTIO_BALLOON_F_STATS_VQ); } static bool balloon_stats_enabled(const VirtIOBalloon *s) diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index 788b556a74..d24f77551a 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -220,7 +220,7 @@ static inline void vring_set_avail_event(VirtQueue *vq, uint16_t val) void virtio_queue_set_notification(VirtQueue *vq, int enable) { vq->notification = enable; - if (virtio_has_feature(vq->vdev, VIRTIO_RING_F_EVENT_IDX)) { + if (virtio_vdev_has_feature(vq->vdev, VIRTIO_RING_F_EVENT_IDX)) { vring_set_avail_event(vq, vring_avail_idx(vq)); } else if (enable) { vring_used_flags_unset_bit(vq, VRING_USED_F_NO_NOTIFY); @@ -243,14 +243,12 @@ int virtio_queue_empty(VirtQueue *vq) return vring_avail_idx(vq) == vq->last_avail_idx; } -void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem, - unsigned int len, unsigned int idx) +static void virtqueue_unmap_sg(VirtQueue *vq, const VirtQueueElement *elem, + unsigned int len) { unsigned int offset; int i; - trace_virtqueue_fill(vq, elem, len, idx); - offset = 0; for (i = 0; i < elem->in_num; i++) { size_t size = MIN(len - offset, elem->in_sg[i].iov_len); @@ -266,6 +264,21 @@ void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem, cpu_physical_memory_unmap(elem->out_sg[i].iov_base, elem->out_sg[i].iov_len, 0, elem->out_sg[i].iov_len); +} + +void virtqueue_discard(VirtQueue *vq, const VirtQueueElement *elem, + unsigned int len) +{ + vq->last_avail_idx--; + virtqueue_unmap_sg(vq, elem, len); +} + +void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem, + unsigned int len, unsigned int idx) +{ + trace_virtqueue_fill(vq, elem, len, idx); + + virtqueue_unmap_sg(vq, elem, len); idx = (idx + vring_used_idx(vq)) % vq->vring.num; @@ -471,7 +484,7 @@ int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem) max = vq->vring.num; i = head = virtqueue_get_head(vq, vq->last_avail_idx++); - if (virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) { + if (virtio_vdev_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) { vring_set_avail_event(vq, vq->last_avail_idx); } @@ -560,7 +573,7 @@ int virtio_set_status(VirtIODevice *vdev, uint8_t val) VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); trace_virtio_set_status(vdev, val); - if (virtio_has_feature(vdev, VIRTIO_F_VERSION_1)) { + if (virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1)) { if (!(vdev->status & VIRTIO_CONFIG_S_FEATURES_OK) && val & VIRTIO_CONFIG_S_FEATURES_OK) { int ret = virtio_validate_features(vdev); @@ -898,7 +911,7 @@ void virtio_queue_set_align(VirtIODevice *vdev, int n, int align) VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); /* virtio-1 compliant devices cannot change the alignment */ - if (virtio_has_feature(vdev, VIRTIO_F_VERSION_1)) { + if (virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1)) { error_report("tried to modify queue alignment for virtio-1 device"); return; } @@ -993,12 +1006,12 @@ static bool vring_notify(VirtIODevice *vdev, VirtQueue *vq) /* We need to expose used array entries before checking used event. */ smp_mb(); /* Always notify when queue is empty (when feature acknowledge) */ - if (virtio_has_feature(vdev, VIRTIO_F_NOTIFY_ON_EMPTY) && + if (virtio_vdev_has_feature(vdev, VIRTIO_F_NOTIFY_ON_EMPTY) && !vq->inuse && vring_avail_idx(vq) == vq->last_avail_idx) { return true; } - if (!virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) { + if (!virtio_vdev_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) { return !(vring_avail_flags(vq) & VRING_AVAIL_F_NO_INTERRUPT); } @@ -1035,7 +1048,7 @@ static bool virtio_device_endian_needed(void *opaque) VirtIODevice *vdev = opaque; assert(vdev->device_endian != VIRTIO_DEVICE_ENDIAN_UNKNOWN); - if (!virtio_has_feature(vdev, VIRTIO_F_VERSION_1)) { + if (!virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1)) { return vdev->device_endian != virtio_default_endian(); } /* Devices conforming to VIRTIO 1.0 or later are always LE. */ |