From 27e57efe32f53a8788cd6b6b9b9bbc08446cc8ae Mon Sep 17 00:00:00 2001 From: Ladi Prosek Date: Thu, 3 Nov 2016 09:55:49 +0100 Subject: virtio: rename virtqueue_discard to virtqueue_unpop The function undoes the effect of virtqueue_pop and doesn't do anything destructive or irreversible so virtqueue_unpop is a more fitting name. Signed-off-by: Ladi Prosek Reviewed-by: Stefan Hajnoczi Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- include/hw/virtio/virtio.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include/hw') diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h index ac65d6a594..6a2f57c1f7 100644 --- a/include/hw/virtio/virtio.h +++ b/include/hw/virtio/virtio.h @@ -160,8 +160,8 @@ void virtqueue_push(VirtQueue *vq, const VirtQueueElement *elem, void virtqueue_flush(VirtQueue *vq, unsigned int count); void virtqueue_detach_element(VirtQueue *vq, const VirtQueueElement *elem, unsigned int len); -void virtqueue_discard(VirtQueue *vq, const VirtQueueElement *elem, - unsigned int len); +void virtqueue_unpop(VirtQueue *vq, const VirtQueueElement *elem, + unsigned int len); bool virtqueue_rewind(VirtQueue *vq, unsigned int num); void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem, unsigned int len, unsigned int idx); -- cgit v1.2.3-55-g7522 From bf91bd27924955aa243abfa5d422ee71e9e84b93 Mon Sep 17 00:00:00 2001 From: Ladi Prosek Date: Thu, 3 Nov 2016 09:55:50 +0100 Subject: virtio: make virtqueue_alloc_element static The function does not fully initialize the returned VirtQueueElement and should be used only internally from the virtio module. Signed-off-by: Ladi Prosek Reviewed-by: Stefan Hajnoczi Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/virtio/virtio.c | 2 +- include/hw/virtio/virtio.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'include/hw') diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index 3a76dc6b8f..1df5f4e5b0 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -632,7 +632,7 @@ void virtqueue_map(VirtQueueElement *elem) VIRTQUEUE_MAX_SIZE, 0); } -void *virtqueue_alloc_element(size_t sz, unsigned out_num, unsigned in_num) +static void *virtqueue_alloc_element(size_t sz, unsigned out_num, unsigned in_num) { VirtQueueElement *elem; size_t in_addr_ofs = QEMU_ALIGN_UP(sz, __alignof__(elem->in_addr[0])); diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h index 6a2f57c1f7..f12a1a8635 100644 --- a/include/hw/virtio/virtio.h +++ b/include/hw/virtio/virtio.h @@ -154,7 +154,6 @@ VirtQueue *virtio_add_queue(VirtIODevice *vdev, int queue_size, void virtio_del_queue(VirtIODevice *vdev, int n); -void *virtqueue_alloc_element(size_t sz, unsigned out_num, unsigned in_num); void virtqueue_push(VirtQueue *vq, const VirtQueueElement *elem, unsigned int len); void virtqueue_flush(VirtQueue *vq, unsigned int count); -- cgit v1.2.3-55-g7522 From 1a43713b02e515575134e18af1f5d0e8c3c26bcc Mon Sep 17 00:00:00 2001 From: Peter Xu Date: Mon, 31 Oct 2016 15:34:38 +0800 Subject: intel_iommu: fix several incorrect endianess and bit fields Signed-off-by: Peter Xu Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/i386/intel_iommu.c | 2 +- include/hw/i386/intel_iommu.h | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) (limited to 'include/hw') diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c index 5a12ae7a93..20c4d2c3b7 100644 --- a/hw/i386/intel_iommu.c +++ b/hw/i386/intel_iommu.c @@ -2180,7 +2180,7 @@ static int vtd_interrupt_remap_msi(IntelIOMMUState *iommu, } addr.data = origin->address & VTD_MSI_ADDR_LO_MASK; - if (le16_to_cpu(addr.addr.__head) != 0xfee) { + if (addr.addr.__head != 0xfee) { VTD_DPRINTF(GENERAL, "error: MSI addr low 32 bits invalid: " "0x%"PRIx32, addr.data); return -VTD_FR_IR_REQ_RSVD; diff --git a/include/hw/i386/intel_iommu.h b/include/hw/i386/intel_iommu.h index 1989c1eec1..405c9d122e 100644 --- a/include/hw/i386/intel_iommu.h +++ b/include/hw/i386/intel_iommu.h @@ -123,7 +123,6 @@ enum { union VTD_IR_TableEntry { struct { #ifdef HOST_WORDS_BIGENDIAN - uint32_t dest_id:32; /* Destination ID */ uint32_t __reserved_1:8; /* Reserved 1 */ uint32_t vector:8; /* Interrupt Vector */ uint32_t irte_mode:1; /* IRTE Mode */ @@ -147,9 +146,9 @@ union VTD_IR_TableEntry { uint32_t irte_mode:1; /* IRTE Mode */ uint32_t vector:8; /* Interrupt Vector */ uint32_t __reserved_1:8; /* Reserved 1 */ - uint32_t dest_id:32; /* Destination ID */ #endif - uint16_t source_id:16; /* Source-ID */ + uint32_t dest_id; /* Destination ID */ + uint16_t source_id; /* Source-ID */ #ifdef HOST_WORDS_BIGENDIAN uint64_t __reserved_2:44; /* Reserved 2 */ uint64_t sid_vtype:2; /* Source-ID Validation Type */ @@ -220,7 +219,7 @@ struct VTD_MSIMessage { uint32_t dest:8; uint32_t __addr_head:12; /* 0xfee */ #endif - uint32_t __addr_hi:32; + uint32_t __addr_hi; } QEMU_PACKED; uint64_t msi_addr; }; @@ -239,7 +238,7 @@ struct VTD_MSIMessage { uint16_t level:1; uint16_t trigger_mode:1; #endif - uint16_t __resved1:16; + uint16_t __resved1; } QEMU_PACKED; uint32_t msi_data; }; -- cgit v1.2.3-55-g7522 From 1b39bc1cf67eee07518ee05ce9306eaa53d868e4 Mon Sep 17 00:00:00 2001 From: Peter Xu Date: Mon, 31 Oct 2016 15:34:39 +0800 Subject: acpi: fix DMAR device scope for IOAPIC We should not use cpu_to_le16() here, instead each of device/function value is stored in a 8 byte field. Signed-off-by: Peter Xu Reviewed-by: Igor Mammedov Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/i386/acpi-build.c | 3 ++- include/hw/acpi/acpi-defs.h | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'include/hw') diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index c02f408ab2..a15585717a 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -2605,7 +2605,8 @@ build_dmar_q35(GArray *table_data, BIOSLinker *linker) scope->length = ioapic_scope_size; scope->enumeration_id = ACPI_BUILD_IOAPIC_ID; scope->bus = Q35_PSEUDO_BUS_PLATFORM; - scope->path[0] = cpu_to_le16(Q35_PSEUDO_DEVFN_IOAPIC); + scope->path[0].device = PCI_SLOT(Q35_PSEUDO_DEVFN_IOAPIC); + scope->path[0].function = PCI_FUNC(Q35_PSEUDO_DEVFN_IOAPIC); build_header(linker, table_data, (void *)(table_data->data + dmar_start), "DMAR", table_data->len - dmar_start, 1, NULL, NULL); diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h index d1d1d61fcb..154f3b82f6 100644 --- a/include/hw/acpi/acpi-defs.h +++ b/include/hw/acpi/acpi-defs.h @@ -619,7 +619,10 @@ struct AcpiDmarDeviceScope { uint16_t reserved; uint8_t enumeration_id; uint8_t bus; - uint16_t path[0]; /* list of dev:func pairs */ + struct { + uint8_t device; + uint8_t function; + } path[0]; } QEMU_PACKED; typedef struct AcpiDmarDeviceScope AcpiDmarDeviceScope; -- cgit v1.2.3-55-g7522 From 9b706dbbbb81f5cb7c67e491d38cd6077205e056 Mon Sep 17 00:00:00 2001 From: Michael S. Tsirkin Date: Fri, 4 Nov 2016 12:04:23 +0200 Subject: virtio: allow per-device-class legacy features Legacy features are those that transitional devices only expose on the legacy interface. Allow different ones per device class. Cc: qemu-stable@nongnu.org # dependency for the next patch Signed-off-by: Michael S. Tsirkin Reviewed-by: Cornelia Huck --- hw/s390x/virtio-ccw.c | 4 +++- hw/virtio/virtio-pci.c | 4 +++- hw/virtio/virtio.c | 2 ++ include/hw/virtio/virtio.h | 5 +++++ 4 files changed, 13 insertions(+), 2 deletions(-) (limited to 'include/hw') diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c index 7d7f8f6e19..f5c1d98192 100644 --- a/hw/s390x/virtio-ccw.c +++ b/hw/s390x/virtio-ccw.c @@ -303,6 +303,8 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw) if (!ccw.cda) { ret = -EFAULT; } else { + VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev); + features.index = address_space_ldub(&address_space_memory, ccw.cda + sizeof(features.features), @@ -312,7 +314,7 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw) if (dev->revision >= 1) { /* Don't offer legacy features for modern devices. */ features.features = (uint32_t) - (vdev->host_features & ~VIRTIO_LEGACY_FEATURES); + (vdev->host_features & ~vdc->legacy_features); } else { features.features = (uint32_t)vdev->host_features; } diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index 62001b46d7..97b32febaf 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -1175,7 +1175,9 @@ static uint64_t virtio_pci_common_read(void *opaque, hwaddr addr, break; case VIRTIO_PCI_COMMON_DF: if (proxy->dfselect <= 1) { - val = (vdev->host_features & ~VIRTIO_LEGACY_FEATURES) >> + VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev); + + val = (vdev->host_features & ~vdc->legacy_features) >> (32 * proxy->dfselect); } break; diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index 1df5f4e5b0..72ee06be6c 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -2214,6 +2214,8 @@ static void virtio_device_class_init(ObjectClass *klass, void *data) dc->props = virtio_properties; vdc->start_ioeventfd = virtio_device_start_ioeventfd_impl; vdc->stop_ioeventfd = virtio_device_stop_ioeventfd_impl; + + vdc->legacy_features |= VIRTIO_LEGACY_FEATURES; } bool virtio_device_ioeventfd_enabled(VirtIODevice *vdev) diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h index f12a1a8635..bdb3c4b46b 100644 --- a/include/hw/virtio/virtio.h +++ b/include/hw/virtio/virtio.h @@ -113,6 +113,11 @@ typedef struct VirtioDeviceClass { void (*set_config)(VirtIODevice *vdev, const uint8_t *config); void (*reset)(VirtIODevice *vdev); void (*set_status)(VirtIODevice *vdev, uint8_t val); + /* For transitional devices, this is a bitmap of features + * that are only exposed on the legacy interface but not + * the modern one. + */ + uint64_t legacy_features; /* Test and clear event pending status. * Should be called after unmask to avoid losing events. * If backend does not support masking, -- cgit v1.2.3-55-g7522 From c7f8d0f3a52b5ef8fdcd305cce438f67d7e06a9f Mon Sep 17 00:00:00 2001 From: Xiao Guangrong Date: Mon, 7 Nov 2016 19:13:36 +0800 Subject: qdev: hotplug: drop HotplugHandler.post_plug callback as nvdimm acpi is okay to build fit when the nvdimm device has not been 'realized' Suggested-by: Igor Mammedov Signed-off-by: Xiao Guangrong Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Stefan Hajnoczi Reviewed-by: Igor Mammedov --- hw/acpi/nvdimm.c | 6 +----- hw/core/hotplug.c | 11 ----------- hw/core/qdev.c | 20 ++++---------------- hw/i386/pc.c | 23 ++++------------------- include/hw/hotplug.h | 11 ----------- 5 files changed, 9 insertions(+), 62 deletions(-) (limited to 'include/hw') diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c index 602ec54485..623bb36ee3 100644 --- a/hw/acpi/nvdimm.c +++ b/hw/acpi/nvdimm.c @@ -38,11 +38,7 @@ static int nvdimm_plugged_device_list(Object *obj, void *opaque) GSList **list = opaque; if (object_dynamic_cast(obj, TYPE_NVDIMM)) { - DeviceState *dev = DEVICE(obj); - - if (dev->realized) { /* only realized NVDIMMs matter */ - *list = g_slist_append(*list, DEVICE(obj)); - } + *list = g_slist_append(*list, DEVICE(obj)); } object_child_foreach(obj, nvdimm_plugged_device_list, opaque); diff --git a/hw/core/hotplug.c b/hw/core/hotplug.c index ab34c19461..17ac986685 100644 --- a/hw/core/hotplug.c +++ b/hw/core/hotplug.c @@ -35,17 +35,6 @@ void hotplug_handler_plug(HotplugHandler *plug_handler, } } -void hotplug_handler_post_plug(HotplugHandler *plug_handler, - DeviceState *plugged_dev, - Error **errp) -{ - HotplugHandlerClass *hdc = HOTPLUG_HANDLER_GET_CLASS(plug_handler); - - if (hdc->post_plug) { - hdc->post_plug(plug_handler, plugged_dev, errp); - } -} - void hotplug_handler_unplug_request(HotplugHandler *plug_handler, DeviceState *plugged_dev, Error **errp) diff --git a/hw/core/qdev.c b/hw/core/qdev.c index d835e6259a..57834423b9 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -945,21 +945,10 @@ static void device_set_realized(Object *obj, bool value, Error **errp) goto child_realize_fail; } } - if (dev->hotplugged) { device_reset(dev); } dev->pending_deleted_event = false; - dev->realized = value; - - if (hotplug_ctrl) { - hotplug_handler_post_plug(hotplug_ctrl, dev, &local_err); - } - - if (local_err != NULL) { - dev->realized = value; - goto post_realize_fail; - } } else if (!value && dev->realized) { Error **local_errp = NULL; QLIST_FOREACH(bus, &dev->child_bus, sibling) { @@ -976,14 +965,13 @@ static void device_set_realized(Object *obj, bool value, Error **errp) } dev->pending_deleted_event = true; DEVICE_LISTENER_CALL(unrealize, Reverse, dev); + } - if (local_err != NULL) { - goto fail; - } - - dev->realized = value; + if (local_err != NULL) { + goto fail; } + dev->realized = value; return; child_realize_fail: diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 2c37a78c7a..cebaad2dc9 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -1715,22 +1715,16 @@ static void pc_dimm_plug(HotplugHandler *hotplug_dev, goto out; } + if (object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM)) { + nvdimm_acpi_hotplug(&pcms->acpi_nvdimm_state); + } + hhc = HOTPLUG_HANDLER_GET_CLASS(pcms->acpi_dev); hhc->plug(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &error_abort); out: error_propagate(errp, local_err); } -static void pc_dimm_post_plug(HotplugHandler *hotplug_dev, - DeviceState *dev, Error **errp) -{ - PCMachineState *pcms = PC_MACHINE(hotplug_dev); - - if (object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM)) { - nvdimm_acpi_hotplug(&pcms->acpi_nvdimm_state); - } -} - static void pc_dimm_unplug_request(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { @@ -2008,14 +2002,6 @@ static void pc_machine_device_plug_cb(HotplugHandler *hotplug_dev, } } -static void pc_machine_device_post_plug_cb(HotplugHandler *hotplug_dev, - DeviceState *dev, Error **errp) -{ - if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { - pc_dimm_post_plug(hotplug_dev, dev, errp); - } -} - static void pc_machine_device_unplug_request_cb(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { @@ -2322,7 +2308,6 @@ static void pc_machine_class_init(ObjectClass *oc, void *data) mc->reset = pc_machine_reset; hc->pre_plug = pc_machine_device_pre_plug_cb; hc->plug = pc_machine_device_plug_cb; - hc->post_plug = pc_machine_device_post_plug_cb; hc->unplug_request = pc_machine_device_unplug_request_cb; hc->unplug = pc_machine_device_unplug_cb; nc->nmi_monitor_handler = x86_nmi; diff --git a/include/hw/hotplug.h b/include/hw/hotplug.h index 10ca5b6504..1a0516a479 100644 --- a/include/hw/hotplug.h +++ b/include/hw/hotplug.h @@ -47,7 +47,6 @@ typedef void (*hotplug_fn)(HotplugHandler *plug_handler, * @parent: Opaque parent interface. * @pre_plug: pre plug callback called at start of device.realize(true) * @plug: plug callback called at end of device.realize(true). - * @post_pug: post plug callback called after device is successfully plugged. * @unplug_request: unplug request callback. * Used as a means to initiate device unplug for devices that * require asynchronous unplug handling. @@ -62,7 +61,6 @@ typedef struct HotplugHandlerClass { /* */ hotplug_fn pre_plug; hotplug_fn plug; - hotplug_fn post_plug; hotplug_fn unplug_request; hotplug_fn unplug; } HotplugHandlerClass; @@ -85,15 +83,6 @@ void hotplug_handler_pre_plug(HotplugHandler *plug_handler, DeviceState *plugged_dev, Error **errp); -/** - * hotplug_handler_post_plug: - * - * Call #HotplugHandlerClass.post_plug callback of @plug_handler. - */ -void hotplug_handler_post_plug(HotplugHandler *plug_handler, - DeviceState *plugged_dev, - Error **errp); - /** * hotplug_handler_unplug_request: * -- cgit v1.2.3-55-g7522 From 12f86b5b3e1bdf75e0a467d771c16cc42f3a1f1a Mon Sep 17 00:00:00 2001 From: Xiao Guangrong Date: Mon, 7 Nov 2016 19:13:37 +0800 Subject: nvdimm acpi: drop the lock of fit buffer as there is a global lock to protect vm-exit handlers and QMP/monitor, this lock can be dropped Suggested-by: Igor Mammedov Signed-off-by: Xiao Guangrong Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Stefan Hajnoczi Reviewed-by: Igor Mammedov --- hw/acpi/nvdimm.c | 11 +---------- include/hw/mem/nvdimm.h | 17 +++++------------ 2 files changed, 6 insertions(+), 22 deletions(-) (limited to 'include/hw') diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c index 623bb36ee3..0fe35471ca 100644 --- a/hw/acpi/nvdimm.c +++ b/hw/acpi/nvdimm.c @@ -371,17 +371,14 @@ static GArray *nvdimm_build_device_structure(void) static void nvdimm_init_fit_buffer(NvdimmFitBuffer *fit_buf) { - qemu_mutex_init(&fit_buf->lock); fit_buf->fit = g_array_new(false, true /* clear */, 1); } static void nvdimm_build_fit_buffer(NvdimmFitBuffer *fit_buf) { - qemu_mutex_lock(&fit_buf->lock); g_array_free(fit_buf->fit, true); fit_buf->fit = nvdimm_build_device_structure(); fit_buf->dirty = true; - qemu_mutex_unlock(&fit_buf->lock); } void nvdimm_acpi_hotplug(AcpiNVDIMMState *state) @@ -395,11 +392,10 @@ static void nvdimm_build_nfit(AcpiNVDIMMState *state, GArray *table_offsets, NvdimmFitBuffer *fit_buf = &state->fit_buf; unsigned int header; - qemu_mutex_lock(&fit_buf->lock); /* NVDIMM device is not plugged? */ if (!fit_buf->fit->len) { - goto exit; + return; } acpi_add_table(table_offsets, table_data); @@ -413,9 +409,6 @@ static void nvdimm_build_nfit(AcpiNVDIMMState *state, GArray *table_offsets, build_header(linker, table_data, (void *)(table_data->data + header), "NFIT", sizeof(NvdimmNfitHeader) + fit_buf->fit->len, 1, NULL, NULL); - -exit: - qemu_mutex_unlock(&fit_buf->lock); } struct NvdimmDsmIn { @@ -544,7 +537,6 @@ static void nvdimm_dsm_func_read_fit(AcpiNVDIMMState *state, NvdimmDsmIn *in, read_fit = (NvdimmFuncReadFITIn *)in->arg3; le32_to_cpus(&read_fit->offset); - qemu_mutex_lock(&fit_buf->lock); fit = fit_buf->fit; nvdimm_debug("Read FIT: offset %#x FIT size %#x Dirty %s.\n", @@ -578,7 +570,6 @@ exit: cpu_physical_memory_write(dsm_mem_addr, read_fit_out, size); g_free(read_fit_out); - qemu_mutex_unlock(&fit_buf->lock); } static void nvdimm_dsm_reserved_root(AcpiNVDIMMState *state, NvdimmDsmIn *in, diff --git a/include/hw/mem/nvdimm.h b/include/hw/mem/nvdimm.h index 33cd421ace..d3ffb2569b 100644 --- a/include/hw/mem/nvdimm.h +++ b/include/hw/mem/nvdimm.h @@ -99,20 +99,13 @@ typedef struct NVDIMMClass NVDIMMClass; #define NVDIMM_ACPI_IO_LEN 4 /* - * The buffer, @fit, saves the FIT info for all the presented NVDIMM - * devices which is updated after the NVDIMM device is plugged or - * unplugged. - * - * Rules to use the buffer: - * 1) the user should hold the @lock to access the buffer. - * 2) mark @dirty whenever the buffer is updated. - * - * These rules preserve NVDIMM ACPI _FIT method to read incomplete - * or obsolete fit info if fit update happens during multiple RFIT - * calls. + * NvdimmFitBuffer: + * @fit: FIT structures for present NVDIMMs. It is updated when + * the NVDIMM device is plugged or unplugged. + * @dirty: It allows OSPM to detect change and restart read in + * progress if there is any. */ struct NvdimmFitBuffer { - QemuMutex lock; GArray *fit; bool dirty; }; -- cgit v1.2.3-55-g7522 From 75f27498220e6ff6f78bf08fbe2cc662ec76ba89 Mon Sep 17 00:00:00 2001 From: Xiao Guangrong Date: Mon, 7 Nov 2016 19:13:38 +0800 Subject: pc: memhp: move nvdimm hotplug out of memory hotplug as they use completely different way to handle hotplug event Suggested-by: Igor Mammedov Signed-off-by: Xiao Guangrong Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Stefan Hajnoczi Reviewed-by: Igor Mammedov --- default-configs/mips-softmmu-common.mak | 1 + docs/specs/acpi_mem_hotplug.txt | 3 --- docs/specs/acpi_nvdimm.txt | 5 +++++ hw/acpi/ich9.c | 8 ++++++-- hw/acpi/memory_hotplug.c | 31 ++++++++----------------------- hw/acpi/nvdimm.c | 7 +++++++ hw/acpi/piix4.c | 7 ++++++- include/hw/mem/nvdimm.h | 1 + 8 files changed, 34 insertions(+), 29 deletions(-) (limited to 'include/hw') diff --git a/default-configs/mips-softmmu-common.mak b/default-configs/mips-softmmu-common.mak index 0394514b93..f0676f52ac 100644 --- a/default-configs/mips-softmmu-common.mak +++ b/default-configs/mips-softmmu-common.mak @@ -17,6 +17,7 @@ CONFIG_FDC=y CONFIG_ACPI=y CONFIG_ACPI_X86=y CONFIG_ACPI_MEMORY_HOTPLUG=y +CONFIG_ACPI_NVDIMM=y CONFIG_ACPI_CPU_HOTPLUG=y CONFIG_APM=y CONFIG_I8257=y diff --git a/docs/specs/acpi_mem_hotplug.txt b/docs/specs/acpi_mem_hotplug.txt index cb26dd27c4..3df3620ce4 100644 --- a/docs/specs/acpi_mem_hotplug.txt +++ b/docs/specs/acpi_mem_hotplug.txt @@ -4,9 +4,6 @@ QEMU<->ACPI BIOS memory hotplug interface ACPI BIOS GPE.3 handler is dedicated for notifying OS about memory hot-add and hot-remove events. -ACPI BIOS GPE.4 handler is dedicated for notifying OS about nvdimm device -hot-add and hot-remove events. - Memory hot-plug interface (IO port 0xa00-0xa17, 1-4 byte access): --------------------------------------------------------------- 0xa00: diff --git a/docs/specs/acpi_nvdimm.txt b/docs/specs/acpi_nvdimm.txt index 4aa5e3de29..d244147691 100644 --- a/docs/specs/acpi_nvdimm.txt +++ b/docs/specs/acpi_nvdimm.txt @@ -127,6 +127,11 @@ _DSM process diagram: | result from the page | | | +--------------------------+ +--------------+ +NVDIMM hotplug +-------------- +ACPI BIOS GPE.4 handler is dedicated for notifying OS about nvdimm device +hot-add event. + Device Handle Reservation ------------------------- As we mentioned above, byte 0 ~ byte 3 in the DSM memory save NVDIMM device diff --git a/hw/acpi/ich9.c b/hw/acpi/ich9.c index e5a3c18e52..830c475127 100644 --- a/hw/acpi/ich9.c +++ b/hw/acpi/ich9.c @@ -490,8 +490,12 @@ void ich9_pm_device_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, if (lpc->pm.acpi_memory_hotplug.is_enabled && object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { - acpi_memory_plug_cb(hotplug_dev, &lpc->pm.acpi_memory_hotplug, - dev, errp); + if (object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM)) { + nvdimm_acpi_plug_cb(hotplug_dev, dev); + } else { + acpi_memory_plug_cb(hotplug_dev, &lpc->pm.acpi_memory_hotplug, + dev, errp); + } } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) { if (lpc->pm.cpu_hotplug_legacy) { legacy_acpi_cpu_plug_cb(hotplug_dev, &lpc->pm.gpe_cpu, dev, errp); diff --git a/hw/acpi/memory_hotplug.c b/hw/acpi/memory_hotplug.c index 70f64517fd..ec4e64b361 100644 --- a/hw/acpi/memory_hotplug.c +++ b/hw/acpi/memory_hotplug.c @@ -2,7 +2,6 @@ #include "hw/acpi/memory_hotplug.h" #include "hw/acpi/pc-hotplug.h" #include "hw/mem/pc-dimm.h" -#include "hw/mem/nvdimm.h" #include "hw/boards.h" #include "hw/qdev-core.h" #include "trace.h" @@ -233,8 +232,11 @@ void acpi_memory_plug_cb(HotplugHandler *hotplug_dev, MemHotplugState *mem_st, DeviceState *dev, Error **errp) { MemStatus *mdev; - AcpiEventStatusBits event; - bool is_nvdimm = object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM); + DeviceClass *dc = DEVICE_GET_CLASS(dev); + + if (!dc->hotpluggable) { + return; + } mdev = acpi_memory_slot_status(mem_st, dev, errp); if (!mdev) { @@ -242,23 +244,10 @@ void acpi_memory_plug_cb(HotplugHandler *hotplug_dev, MemHotplugState *mem_st, } mdev->dimm = dev; - - /* - * do not set is_enabled and is_inserting if the slot is plugged with - * a nvdimm device to stop OSPM inquires memory region from the slot. - */ - if (is_nvdimm) { - event = ACPI_NVDIMM_HOTPLUG_STATUS; - } else { - mdev->is_enabled = true; - event = ACPI_MEMORY_HOTPLUG_STATUS; - } - + mdev->is_enabled = true; if (dev->hotplugged) { - if (!is_nvdimm) { - mdev->is_inserting = true; - } - acpi_send_event(DEVICE(hotplug_dev), event); + mdev->is_inserting = true; + acpi_send_event(DEVICE(hotplug_dev), ACPI_MEMORY_HOTPLUG_STATUS); } } @@ -273,8 +262,6 @@ void acpi_memory_unplug_request_cb(HotplugHandler *hotplug_dev, return; } - /* nvdimm device hot unplug is not supported yet. */ - assert(!object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM)); mdev->is_removing = true; acpi_send_event(DEVICE(hotplug_dev), ACPI_MEMORY_HOTPLUG_STATUS); } @@ -289,8 +276,6 @@ void acpi_memory_unplug_cb(MemHotplugState *mem_st, return; } - /* nvdimm device hot unplug is not supported yet. */ - assert(!object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM)); mdev->is_enabled = false; mdev->dimm = NULL; } diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c index 0fe35471ca..5156565112 100644 --- a/hw/acpi/nvdimm.c +++ b/hw/acpi/nvdimm.c @@ -868,6 +868,13 @@ static const MemoryRegionOps nvdimm_dsm_ops = { }, }; +void nvdimm_acpi_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev) +{ + if (dev->hotplugged) { + acpi_send_event(DEVICE(hotplug_dev), ACPI_NVDIMM_HOTPLUG_STATUS); + } +} + void nvdimm_init_acpi_state(AcpiNVDIMMState *state, MemoryRegion *io, FWCfgState *fw_cfg, Object *owner) { diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c index 2adc246b00..17d36bd595 100644 --- a/hw/acpi/piix4.c +++ b/hw/acpi/piix4.c @@ -378,7 +378,12 @@ static void piix4_device_plug_cb(HotplugHandler *hotplug_dev, if (s->acpi_memory_hotplug.is_enabled && object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { - acpi_memory_plug_cb(hotplug_dev, &s->acpi_memory_hotplug, dev, errp); + if (object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM)) { + nvdimm_acpi_plug_cb(hotplug_dev, dev); + } else { + acpi_memory_plug_cb(hotplug_dev, &s->acpi_memory_hotplug, + dev, errp); + } } else if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) { acpi_pcihp_device_plug_cb(hotplug_dev, &s->acpi_pci_hotplug, dev, errp); } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) { diff --git a/include/hw/mem/nvdimm.h b/include/hw/mem/nvdimm.h index d3ffb2569b..60585c3bbd 100644 --- a/include/hw/mem/nvdimm.h +++ b/include/hw/mem/nvdimm.h @@ -131,4 +131,5 @@ void nvdimm_build_acpi(GArray *table_offsets, GArray *table_data, BIOSLinker *linker, AcpiNVDIMMState *state, uint32_t ram_slots); void nvdimm_acpi_hotplug(AcpiNVDIMMState *state); +void nvdimm_acpi_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev); #endif -- cgit v1.2.3-55-g7522 From 284197e41f0fe98d58ce5e8acd4966c91f28c4bd Mon Sep 17 00:00:00 2001 From: Xiao Guangrong Date: Mon, 7 Nov 2016 19:13:44 +0800 Subject: nvdimm acpi: rename nvdimm_acpi_hotplug Rename it to nvdimm_plug() Suggested-by: Igor Mammedov Signed-off-by: Xiao Guangrong Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Stefan Hajnoczi Reviewed-by: Igor Mammedov --- hw/acpi/nvdimm.c | 2 +- hw/i386/pc.c | 2 +- include/hw/mem/nvdimm.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'include/hw') diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c index 148999ee7a..7733f14aea 100644 --- a/hw/acpi/nvdimm.c +++ b/hw/acpi/nvdimm.c @@ -380,7 +380,7 @@ static void nvdimm_build_fit_buffer(NvdimmFitBuffer *fit_buf) fit_buf->dirty = true; } -void nvdimm_acpi_hotplug(AcpiNVDIMMState *state) +void nvdimm_plug(AcpiNVDIMMState *state) { nvdimm_build_fit_buffer(&state->fit_buf); } diff --git a/hw/i386/pc.c b/hw/i386/pc.c index b69cd4836e..a9b19507f1 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -1716,7 +1716,7 @@ static void pc_dimm_plug(HotplugHandler *hotplug_dev, } if (object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM)) { - nvdimm_acpi_hotplug(&pcms->acpi_nvdimm_state); + nvdimm_plug(&pcms->acpi_nvdimm_state); } hhc = HOTPLUG_HANDLER_GET_CLASS(pcms->acpi_dev); diff --git a/include/hw/mem/nvdimm.h b/include/hw/mem/nvdimm.h index 60585c3bbd..03e1ff9558 100644 --- a/include/hw/mem/nvdimm.h +++ b/include/hw/mem/nvdimm.h @@ -130,6 +130,6 @@ void nvdimm_init_acpi_state(AcpiNVDIMMState *state, MemoryRegion *io, void nvdimm_build_acpi(GArray *table_offsets, GArray *table_data, BIOSLinker *linker, AcpiNVDIMMState *state, uint32_t ram_slots); -void nvdimm_acpi_hotplug(AcpiNVDIMMState *state); +void nvdimm_plug(AcpiNVDIMMState *state); void nvdimm_acpi_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev); #endif -- cgit v1.2.3-55-g7522 From f1f9e6c5961ffb36fd4a81cd7edcded7bfad2ab2 Mon Sep 17 00:00:00 2001 From: Greg Kurz Date: Fri, 4 Nov 2016 09:39:15 +0100 Subject: vhost: adapt vhost_verify_ring_mappings() to virtio 1 ring layout With virtio 1, the vring layout is split in 3 separate regions of contiguous memory for the descriptor table, the available ring and the used ring, as opposed with legacy virtio which uses a single region. In case of memory re-mapping, the code ensures it doesn't affect the vring mapping. This is done in vhost_verify_ring_mappings() which assumes the device is legacy. This patch changes vhost_verify_ring_mappings() to check the mappings of each part of the vring separately. This works for legacy mappings as well. Cc: qemu-stable@nongnu.org Signed-off-by: Greg Kurz Reviewed-by: Cornelia Huck Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/virtio/vhost.c | 79 +++++++++++++++++++++++++++++++++++------------ include/hw/virtio/vhost.h | 4 +++ 2 files changed, 64 insertions(+), 19 deletions(-) (limited to 'include/hw') diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index 25bf67f3cc..d88d34a044 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -421,32 +421,73 @@ static inline void vhost_dev_log_resize(struct vhost_dev *dev, uint64_t size) dev->log_size = size; } + +static int vhost_verify_ring_part_mapping(void *part, + uint64_t part_addr, + uint64_t part_size, + uint64_t start_addr, + uint64_t size) +{ + hwaddr l; + void *p; + int r = 0; + + if (!ranges_overlap(start_addr, size, part_addr, part_size)) { + return 0; + } + l = part_size; + p = cpu_physical_memory_map(part_addr, &l, 1); + if (!p || l != part_size) { + r = -ENOMEM; + } + if (p != part) { + r = -EBUSY; + } + cpu_physical_memory_unmap(p, l, 0, 0); + return r; +} + static int vhost_verify_ring_mappings(struct vhost_dev *dev, uint64_t start_addr, uint64_t size) { - int i; + int i, j; int r = 0; + const char *part_name[] = { + "descriptor table", + "available ring", + "used ring" + }; - for (i = 0; !r && i < dev->nvqs; ++i) { + for (i = 0; i < dev->nvqs; ++i) { struct vhost_virtqueue *vq = dev->vqs + i; - hwaddr l; - void *p; - if (!ranges_overlap(start_addr, size, vq->ring_phys, vq->ring_size)) { - continue; + j = 0; + r = vhost_verify_ring_part_mapping(vq->desc, vq->desc_phys, + vq->desc_size, start_addr, size); + if (!r) { + break; } - l = vq->ring_size; - p = cpu_physical_memory_map(vq->ring_phys, &l, 1); - if (!p || l != vq->ring_size) { - error_report("Unable to map ring buffer for ring %d", i); - r = -ENOMEM; + + j++; + r = vhost_verify_ring_part_mapping(vq->avail, vq->avail_phys, + vq->avail_size, start_addr, size); + if (!r) { + break; } - if (p != vq->ring) { - error_report("Ring buffer relocated for ring %d", i); - r = -EBUSY; + + j++; + r = vhost_verify_ring_part_mapping(vq->used, vq->used_phys, + vq->used_size, start_addr, size); + if (!r) { + break; } - cpu_physical_memory_unmap(p, l, 0, 0); + } + + if (r == -ENOMEM) { + error_report("Unable to map %s for ring %d", part_name[j], i); + } else if (r == -EBUSY) { + error_report("%s relocated for ring %d", part_name[j], i); } return r; } @@ -860,15 +901,15 @@ static int vhost_virtqueue_start(struct vhost_dev *dev, } } - s = l = virtio_queue_get_desc_size(vdev, idx); - a = virtio_queue_get_desc_addr(vdev, idx); + vq->desc_size = s = l = virtio_queue_get_desc_size(vdev, idx); + vq->desc_phys = a = virtio_queue_get_desc_addr(vdev, idx); vq->desc = cpu_physical_memory_map(a, &l, 0); if (!vq->desc || l != s) { r = -ENOMEM; goto fail_alloc_desc; } - s = l = virtio_queue_get_avail_size(vdev, idx); - a = virtio_queue_get_avail_addr(vdev, idx); + vq->avail_size = s = l = virtio_queue_get_avail_size(vdev, idx); + vq->avail_phys = a = virtio_queue_get_avail_addr(vdev, idx); vq->avail = cpu_physical_memory_map(a, &l, 0); if (!vq->avail || l != s) { r = -ENOMEM; diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h index e433089ea9..56b567f199 100644 --- a/include/hw/virtio/vhost.h +++ b/include/hw/virtio/vhost.h @@ -14,6 +14,10 @@ struct vhost_virtqueue { void *avail; void *used; int num; + unsigned long long desc_phys; + unsigned desc_size; + unsigned long long avail_phys; + unsigned avail_size; unsigned long long used_phys; unsigned used_size; void *ring; -- cgit v1.2.3-55-g7522 From 1cdce7c54d26e64f5eddb10a6f4f7dd938dfc2c4 Mon Sep 17 00:00:00 2001 From: Greg Kurz Date: Fri, 4 Nov 2016 09:39:22 +0100 Subject: vhost: drop legacy vring layout bits The legacy vring layout is not used anymore as we use the separate mappings even for legacy devices. This patch simply removes it. This also fixes a bug with virtio 1 devices when the vring descriptor table is mapped at a higher address than the used vring because the following function may return an insanely great value: hwaddr virtio_queue_get_ring_size(VirtIODevice *vdev, int n) { return vdev->vq[n].vring.used - vdev->vq[n].vring.desc + virtio_queue_get_used_size(vdev, n); } and the mapping fails. Signed-off-by: Greg Kurz Reviewed-by: Cornelia Huck Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/virtio/vhost.c | 13 ------------- include/hw/virtio/vhost.h | 3 --- 2 files changed, 16 deletions(-) (limited to 'include/hw') diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index d88d34a044..30aee88a3e 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -923,14 +923,6 @@ static int vhost_virtqueue_start(struct vhost_dev *dev, goto fail_alloc_used; } - vq->ring_size = s = l = virtio_queue_get_ring_size(vdev, idx); - vq->ring_phys = a = virtio_queue_get_ring_addr(vdev, idx); - vq->ring = cpu_physical_memory_map(a, &l, 1); - if (!vq->ring || l != s) { - r = -ENOMEM; - goto fail_alloc_ring; - } - r = vhost_virtqueue_set_addr(dev, vq, vhost_vq_index, dev->log_enabled); if (r < 0) { r = -errno; @@ -971,9 +963,6 @@ static int vhost_virtqueue_start(struct vhost_dev *dev, fail_vector: fail_kick: fail_alloc: - cpu_physical_memory_unmap(vq->ring, virtio_queue_get_ring_size(vdev, idx), - 0, 0); -fail_alloc_ring: cpu_physical_memory_unmap(vq->used, virtio_queue_get_used_size(vdev, idx), 0, 0); fail_alloc_used: @@ -1014,8 +1003,6 @@ static void vhost_virtqueue_stop(struct vhost_dev *dev, vhost_vq_index); } - cpu_physical_memory_unmap(vq->ring, virtio_queue_get_ring_size(vdev, idx), - 0, virtio_queue_get_ring_size(vdev, idx)); cpu_physical_memory_unmap(vq->used, virtio_queue_get_used_size(vdev, idx), 1, virtio_queue_get_used_size(vdev, idx)); cpu_physical_memory_unmap(vq->avail, virtio_queue_get_avail_size(vdev, idx), diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h index 56b567f199..1fe5aadef5 100644 --- a/include/hw/virtio/vhost.h +++ b/include/hw/virtio/vhost.h @@ -20,9 +20,6 @@ struct vhost_virtqueue { unsigned avail_size; unsigned long long used_phys; unsigned used_size; - void *ring; - unsigned long long ring_phys; - unsigned ring_size; EventNotifier masked_notifier; }; -- cgit v1.2.3-55-g7522 From 435346d7484aa2aad1875e35948df3c3f4feee75 Mon Sep 17 00:00:00 2001 From: Greg Kurz Date: Fri, 4 Nov 2016 09:39:29 +0100 Subject: virtio: drop virtio_queue_get_ring_{size,addr}() These are not used anymore. Signed-off-by: Greg Kurz Reviewed-by: Cornelia Huck Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/virtio/virtio.c | 11 ----------- include/hw/virtio/virtio.h | 2 -- 2 files changed, 13 deletions(-) (limited to 'include/hw') diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index 72ee06be6c..55a00cdf9e 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -1935,11 +1935,6 @@ hwaddr virtio_queue_get_used_addr(VirtIODevice *vdev, int n) return vdev->vq[n].vring.used; } -hwaddr virtio_queue_get_ring_addr(VirtIODevice *vdev, int n) -{ - return vdev->vq[n].vring.desc; -} - hwaddr virtio_queue_get_desc_size(VirtIODevice *vdev, int n) { return sizeof(VRingDesc) * vdev->vq[n].vring.num; @@ -1957,12 +1952,6 @@ hwaddr virtio_queue_get_used_size(VirtIODevice *vdev, int n) sizeof(VRingUsedElem) * vdev->vq[n].vring.num; } -hwaddr virtio_queue_get_ring_size(VirtIODevice *vdev, int n) -{ - return vdev->vq[n].vring.used - vdev->vq[n].vring.desc + - virtio_queue_get_used_size(vdev, n); -} - uint16_t virtio_queue_get_last_avail_idx(VirtIODevice *vdev, int n) { return vdev->vq[n].last_avail_idx; diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h index bdb3c4b46b..5951997f22 100644 --- a/include/hw/virtio/virtio.h +++ b/include/hw/virtio/virtio.h @@ -259,11 +259,9 @@ typedef struct VirtIORNGConf VirtIORNGConf; hwaddr virtio_queue_get_desc_addr(VirtIODevice *vdev, int n); hwaddr virtio_queue_get_avail_addr(VirtIODevice *vdev, int n); hwaddr virtio_queue_get_used_addr(VirtIODevice *vdev, int n); -hwaddr virtio_queue_get_ring_addr(VirtIODevice *vdev, int n); hwaddr virtio_queue_get_desc_size(VirtIODevice *vdev, int n); hwaddr virtio_queue_get_avail_size(VirtIODevice *vdev, int n); hwaddr virtio_queue_get_used_size(VirtIODevice *vdev, int n); -hwaddr virtio_queue_get_ring_size(VirtIODevice *vdev, int n); uint16_t virtio_queue_get_last_avail_idx(VirtIODevice *vdev, int n); void virtio_queue_set_last_avail_idx(VirtIODevice *vdev, int n, uint16_t idx); void virtio_queue_invalidate_signalled_used(VirtIODevice *vdev, int n); -- cgit v1.2.3-55-g7522