From 0bd1909da606a60f50128290fc319db020fa303c Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Sat, 25 Nov 2017 13:16:05 -0200 Subject: machine: Replace has_dynamic_sysbus with list of allowed devices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The existing has_dynamic_sysbus flag makes the machine accept every user-creatable sysbus device type on the command-line. Replace it with a list of allowed device types, so machines can easily accept some sysbus devices while rejecting others. To keep exactly the same behavior as before, the existing has_dynamic_sysbus=true assignments are replaced with a TYPE_SYS_BUS_DEVICE entry on the allowed list. Other patches will replace the TYPE_SYS_BUS_DEVICE entries with more specific lists of devices. Cc: Peter Maydell Cc: Marcel Apfelbaum Cc: "Michael S. Tsirkin" Cc: Alexander Graf Cc: David Gibson Cc: Stefano Stabellini Cc: Anthony Perard Cc: qemu-arm@nongnu.org Cc: qemu-ppc@nongnu.org Cc: xen-devel@lists.xenproject.org Signed-off-by: Eduardo Habkost Message-Id: <20171125151610.20547-2-ehabkost@redhat.com> Reviewed-by: Greg Kurz Reviewed-by: David Gibson Reviewed-by: Marc-André Lureau Reviewed-by: Marcel Apfelbaum Signed-off-by: Eduardo Habkost --- hw/arm/virt.c | 3 ++- hw/core/machine.c | 43 +++++++++++++++++++++++++++++-------------- hw/i386/pc_q35.c | 3 ++- hw/ppc/e500plat.c | 4 +++- hw/ppc/spapr.c | 3 ++- hw/xen/xen_backend.c | 7 ++++++- 6 files changed, 44 insertions(+), 19 deletions(-) (limited to 'hw') diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 543f9bd..7549895 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -1591,7 +1591,8 @@ static void virt_machine_class_init(ObjectClass *oc, void *data) * configuration of the particular instance. */ mc->max_cpus = 255; - mc->has_dynamic_sysbus = true; + /*TODO: allow only sysbus devices that really work with this machine */ + machine_class_allow_dynamic_sysbus_dev(mc, TYPE_SYS_BUS_DEVICE); mc->block_default_type = IF_VIRTIO; mc->no_cdrom = 1; mc->pci_allow_0_address = true; diff --git a/hw/core/machine.c b/hw/core/machine.c index c857f3f..0320a8e 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -334,29 +334,44 @@ static bool machine_get_enforce_config_section(Object *obj, Error **errp) return ms->enforce_config_section; } -static void error_on_sysbus_device(SysBusDevice *sbdev, void *opaque) +void machine_class_allow_dynamic_sysbus_dev(MachineClass *mc, const char *type) { - error_report("Option '-device %s' cannot be handled by this machine", - object_class_get_name(object_get_class(OBJECT(sbdev)))); - exit(1); + strList *item = g_new0(strList, 1); + + item->value = g_strdup(type); + item->next = mc->allowed_dynamic_sysbus_devices; + mc->allowed_dynamic_sysbus_devices = item; } -static void machine_init_notify(Notifier *notifier, void *data) +static void validate_sysbus_device(SysBusDevice *sbdev, void *opaque) { - Object *machine = qdev_get_machine(); - ObjectClass *oc = object_get_class(machine); - MachineClass *mc = MACHINE_CLASS(oc); + MachineState *machine = opaque; + MachineClass *mc = MACHINE_GET_CLASS(machine); + bool allowed = false; + strList *wl; - if (mc->has_dynamic_sysbus) { - /* Our machine can handle dynamic sysbus devices, we're all good */ - return; + for (wl = mc->allowed_dynamic_sysbus_devices; + !allowed && wl; + wl = wl->next) { + allowed |= !!object_dynamic_cast(OBJECT(sbdev), wl->value); } + if (!allowed) { + error_report("Option '-device %s' cannot be handled by this machine", + object_class_get_name(object_get_class(OBJECT(sbdev)))); + exit(1); + } +} + +static void machine_init_notify(Notifier *notifier, void *data) +{ + MachineState *machine = MACHINE(qdev_get_machine()); + /* - * Loop through all dynamically created devices and check whether there - * are sysbus devices among them. If there are, error out. + * Loop through all dynamically created sysbus devices and check if they are + * all allowed. If a device is not allowed, error out. */ - foreach_dynamic_sysbus_device(error_on_sysbus_device, NULL); + foreach_dynamic_sysbus_device(validate_sysbus_device, machine); } HotpluggableCPUList *machine_query_hotpluggable_cpus(MachineState *machine) diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c index 5c6c608..0505730 100644 --- a/hw/i386/pc_q35.c +++ b/hw/i386/pc_q35.c @@ -299,7 +299,8 @@ static void pc_q35_machine_options(MachineClass *m) m->default_machine_opts = "firmware=bios-256k.bin"; m->default_display = "std"; m->no_floppy = 1; - m->has_dynamic_sysbus = true; + /*TODO: allow only sysbus devices that really work with this machine */ + machine_class_allow_dynamic_sysbus_dev(m, TYPE_SYS_BUS_DEVICE); m->max_cpus = 288; } diff --git a/hw/ppc/e500plat.c b/hw/ppc/e500plat.c index e59e80f..438118c 100644 --- a/hw/ppc/e500plat.c +++ b/hw/ppc/e500plat.c @@ -15,6 +15,7 @@ #include "hw/boards.h" #include "sysemu/device_tree.h" #include "sysemu/kvm.h" +#include "hw/sysbus.h" #include "hw/pci/pci.h" #include "hw/ppc/openpic.h" #include "kvm_ppc.h" @@ -63,7 +64,8 @@ static void e500plat_machine_init(MachineClass *mc) mc->desc = "generic paravirt e500 platform"; mc->init = e500plat_init; mc->max_cpus = 32; - mc->has_dynamic_sysbus = true; + /*TODO: allow only sysbus devices that really work with this machine */ + machine_class_allow_dynamic_sysbus_dev(mc, TYPE_SYS_BUS_DEVICE); mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("e500v2_v30"); } diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 499ab64..5847175 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -3843,7 +3843,8 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data) mc->default_boot_order = ""; mc->default_ram_size = 512 * M_BYTE; mc->kvm_type = spapr_kvm_type; - mc->has_dynamic_sysbus = true; + /*TODO: allow only sysbus devices that really work with this machine */ + machine_class_allow_dynamic_sysbus_dev(mc, TYPE_SYS_BUS_DEVICE); mc->pci_allow_0_address = true; mc->get_hotplug_handler = spapr_get_hotplug_handler; hc->pre_plug = spapr_machine_device_pre_plug; diff --git a/hw/xen/xen_backend.c b/hw/xen/xen_backend.c index 0f849a2..82380ea 100644 --- a/hw/xen/xen_backend.c +++ b/hw/xen/xen_backend.c @@ -564,7 +564,12 @@ static void xen_set_dynamic_sysbus(void) ObjectClass *oc = object_get_class(machine); MachineClass *mc = MACHINE_CLASS(oc); - mc->has_dynamic_sysbus = true; + /* + * Emulate old mc->has_dynamic_sysbus=true assignment + * + *TODO: add only Xen devices to the list + */ + machine_class_allow_dynamic_sysbus_dev(mc, TYPE_SYS_BUS_DEVICE); } int xen_be_register(const char *type, struct XenDevOps *ops) -- cgit v1.1 From 6f2062b9758ebc64dfbbda642b0c407c38131ea3 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Sat, 25 Nov 2017 13:16:06 -0200 Subject: hw/arm/virt: Allow only supported dynamic sysbus devices Replace the TYPE_SYS_BUS_DEVICE entry in the allowed sysbus device list with the two device types that are really supported by the virt machine: vfio-amd-xgbe and vfio-calxeda-xgmac. Cc: Peter Maydell Cc: qemu-arm@nongnu.org Signed-off-by: Eduardo Habkost Message-Id: <20171125151610.20547-3-ehabkost@redhat.com> Signed-off-by: Eduardo Habkost --- hw/arm/virt.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'hw') diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 7549895..4a6fdcc 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -34,6 +34,8 @@ #include "hw/arm/arm.h" #include "hw/arm/primecell.h" #include "hw/arm/virt.h" +#include "hw/vfio/vfio-calxeda-xgmac.h" +#include "hw/vfio/vfio-amd-xgbe.h" #include "hw/devices.h" #include "net/net.h" #include "sysemu/block-backend.h" @@ -1591,8 +1593,8 @@ static void virt_machine_class_init(ObjectClass *oc, void *data) * configuration of the particular instance. */ mc->max_cpus = 255; - /*TODO: allow only sysbus devices that really work with this machine */ - machine_class_allow_dynamic_sysbus_dev(mc, TYPE_SYS_BUS_DEVICE); + machine_class_allow_dynamic_sysbus_dev(mc, TYPE_VFIO_CALXEDA_XGMAC); + machine_class_allow_dynamic_sysbus_dev(mc, TYPE_VFIO_AMD_XGBE); mc->block_default_type = IF_VIRTIO; mc->no_cdrom = 1; mc->pci_allow_0_address = true; -- cgit v1.1 From 50d01d240f26a43a1d8c0667078bcab7186f2f96 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Sat, 25 Nov 2017 13:16:07 -0200 Subject: ppc: e500: Allow only supported dynamic sysbus devices platform_bus_create_devtree() already rejects all dynamic sysbus devices except TYPE_ETSEC_COMMON, so register it as the only allowed dynamic sysbus device for the ppce500 machine-type. Cc: Alexander Graf Cc: David Gibson Cc: qemu-ppc@nongnu.org Signed-off-by: Eduardo Habkost Message-Id: <20171125151610.20547-4-ehabkost@redhat.com> Acked-by: David Gibson Reviewed-by: Greg Kurz Signed-off-by: Eduardo Habkost --- hw/ppc/e500plat.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'hw') diff --git a/hw/ppc/e500plat.c b/hw/ppc/e500plat.c index 438118c..81d03e1 100644 --- a/hw/ppc/e500plat.c +++ b/hw/ppc/e500plat.c @@ -12,6 +12,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" #include "e500.h" +#include "hw/net/fsl_etsec/etsec.h" #include "hw/boards.h" #include "sysemu/device_tree.h" #include "sysemu/kvm.h" @@ -64,8 +65,7 @@ static void e500plat_machine_init(MachineClass *mc) mc->desc = "generic paravirt e500 platform"; mc->init = e500plat_init; mc->max_cpus = 32; - /*TODO: allow only sysbus devices that really work with this machine */ - machine_class_allow_dynamic_sysbus_dev(mc, TYPE_SYS_BUS_DEVICE); + machine_class_allow_dynamic_sysbus_dev(mc, TYPE_ETSEC_COMMON); mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("e500v2_v30"); } -- cgit v1.1 From 7da79a167aa11af6fad353bfbc825fbff2db68a2 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Sat, 25 Nov 2017 13:16:08 -0200 Subject: spapr: Allow only supported dynamic sysbus devices TYPE_SPAPR_PCI_HOST_BRIDGE is the only dynamic sysbus device not rejected by ppc_spapr_reset(), so it can be the only entry on the allowed list. Cc: David Gibson Cc: Alexander Graf Cc: qemu-ppc@nongnu.org Signed-off-by: Eduardo Habkost Message-Id: <20171125151610.20547-5-ehabkost@redhat.com> Acked-by: David Gibson Reviewed-by: Greg Kurz Signed-off-by: Eduardo Habkost --- hw/ppc/spapr.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'hw') diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 5847175..278f9de 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -3843,8 +3843,7 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data) mc->default_boot_order = ""; mc->default_ram_size = 512 * M_BYTE; mc->kvm_type = spapr_kvm_type; - /*TODO: allow only sysbus devices that really work with this machine */ - machine_class_allow_dynamic_sysbus_dev(mc, TYPE_SYS_BUS_DEVICE); + machine_class_allow_dynamic_sysbus_dev(mc, TYPE_SPAPR_PCI_HOST_BRIDGE); mc->pci_allow_0_address = true; mc->get_hotplug_handler = spapr_get_hotplug_handler; hc->pre_plug = spapr_machine_device_pre_plug; -- cgit v1.1 From b1b68e1094af0e8c7fcf6faff1a77b7787b3628b Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Sat, 25 Nov 2017 13:16:09 -0200 Subject: xen: Add only xen-sysdev to dynamic sysbus device list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There's no need to make the machine allow every possible sysbus device. We can now just add xen-sysdev to the allowed list. Cc: Stefano Stabellini Cc: Anthony Perard Cc: xen-devel@lists.xenproject.org Cc: Juergen Gross Signed-off-by: Eduardo Habkost Message-Id: <20171125151610.20547-6-ehabkost@redhat.com> Reviewed-by: Marc-André Lureau Acked-by: Anthony PERARD Signed-off-by: Eduardo Habkost --- hw/xen/xen_backend.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'hw') diff --git a/hw/xen/xen_backend.c b/hw/xen/xen_backend.c index 82380ea..7445b50 100644 --- a/hw/xen/xen_backend.c +++ b/hw/xen/xen_backend.c @@ -564,12 +564,7 @@ static void xen_set_dynamic_sysbus(void) ObjectClass *oc = object_get_class(machine); MachineClass *mc = MACHINE_CLASS(oc); - /* - * Emulate old mc->has_dynamic_sysbus=true assignment - * - *TODO: add only Xen devices to the list - */ - machine_class_allow_dynamic_sysbus_dev(mc, TYPE_SYS_BUS_DEVICE); + machine_class_allow_dynamic_sysbus_dev(mc, TYPE_XENSYSDEV); } int xen_be_register(const char *type, struct XenDevOps *ops) -- cgit v1.1 From ef18310d5495c4ce0e1289ed7fc9833d73fe5ee1 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Sat, 25 Nov 2017 13:16:10 -0200 Subject: q35: Allow only supported dynamic sysbus devices The only user-creatable sysbus devices in qemu-system-x86_64 are amd-iommu, intel-iommu, and xen-backend. xen-backend is handled by xen_set_dynamic_sysbus(), so we only need to add amd-iommu and intel-iommu. Cc: "Michael S. Tsirkin" Cc: Marcel Apfelbaum Signed-off-by: Eduardo Habkost Message-Id: <20171125151610.20547-7-ehabkost@redhat.com> Reviewed-by: Marcel Apfelbaum Signed-off-by: Eduardo Habkost --- hw/i386/pc_q35.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'hw') diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c index 0505730..ed3a0b8 100644 --- a/hw/i386/pc_q35.c +++ b/hw/i386/pc_q35.c @@ -42,6 +42,8 @@ #include "exec/address-spaces.h" #include "hw/i386/pc.h" #include "hw/i386/ich9.h" +#include "hw/i386/amd_iommu.h" +#include "hw/i386/intel_iommu.h" #include "hw/smbios/smbios.h" #include "hw/ide/pci.h" #include "hw/ide/ahci.h" @@ -299,8 +301,8 @@ static void pc_q35_machine_options(MachineClass *m) m->default_machine_opts = "firmware=bios-256k.bin"; m->default_display = "std"; m->no_floppy = 1; - /*TODO: allow only sysbus devices that really work with this machine */ - machine_class_allow_dynamic_sysbus_dev(m, TYPE_SYS_BUS_DEVICE); + machine_class_allow_dynamic_sysbus_dev(m, TYPE_AMD_IOMMU_DEVICE); + machine_class_allow_dynamic_sysbus_dev(m, TYPE_INTEL_IOMMU_DEVICE); m->max_cpus = 288; } -- cgit v1.1 From 03fcbd9dc5084ff4676c153fbe04fb0fcf939d09 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Thu, 2 Nov 2017 11:10:06 +0100 Subject: qdev: Check for the availability of a hotplug controller before adding a device The qdev_unplug() function contains a g_assert(hotplug_ctrl) statement, so QEMU crashes when the user tries to device_add + device_del a device that does not have a corresponding hotplug controller. This could be provoked for a couple of devices in the past (see commit 4c93950659487c7ad or 84ebd3e8c7d4fe955 for example), and can currently for example also be triggered like this: $ s390x-softmmu/qemu-system-s390x -M none -nographic QEMU 2.10.50 monitor - type 'help' for more information (qemu) device_add qemu-s390x-cpu,id=x (qemu) device_del x ** ERROR:qemu/qdev-monitor.c:872:qdev_unplug: assertion failed: (hotplug_ctrl) Aborted (core dumped) So devices clearly need a hotplug controller when they should be usable with device_add. The code in qdev_device_add() already checks whether the bus has a proper hotplug controller, but for devices that do not have a corresponding bus, there is no appropriate check available yet. In that case we should check whether the machine itself provides a suitable hotplug controller and refuse to plug the device if none is available. Reviewed-by: Igor Mammedov Signed-off-by: Thomas Huth Message-Id: <1509617407-21191-3-git-send-email-thuth@redhat.com> Reviewed-by: Cornelia Huck Signed-off-by: Eduardo Habkost --- hw/core/qdev.c | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) (limited to 'hw') diff --git a/hw/core/qdev.c b/hw/core/qdev.c index 1111295..f739753 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -253,19 +253,31 @@ void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id, dev->alias_required_for_version = required_for_version; } +HotplugHandler *qdev_get_machine_hotplug_handler(DeviceState *dev) +{ + MachineState *machine; + MachineClass *mc; + Object *m_obj = qdev_get_machine(); + + if (object_dynamic_cast(m_obj, TYPE_MACHINE)) { + machine = MACHINE(m_obj); + mc = MACHINE_GET_CLASS(machine); + if (mc->get_hotplug_handler) { + return mc->get_hotplug_handler(machine, dev); + } + } + + return NULL; +} + HotplugHandler *qdev_get_hotplug_handler(DeviceState *dev) { - HotplugHandler *hotplug_ctrl = NULL; + HotplugHandler *hotplug_ctrl; if (dev->parent_bus && dev->parent_bus->hotplug_handler) { hotplug_ctrl = dev->parent_bus->hotplug_handler; - } else if (object_dynamic_cast(qdev_get_machine(), TYPE_MACHINE)) { - MachineState *machine = MACHINE(qdev_get_machine()); - MachineClass *mc = MACHINE_GET_CLASS(machine); - - if (mc->get_hotplug_handler) { - hotplug_ctrl = mc->get_hotplug_handler(machine, dev); - } + } else { + hotplug_ctrl = qdev_get_machine_hotplug_handler(dev); } return hotplug_ctrl; } -- cgit v1.1 From da6789c27c2ea71765cfab04bad9a42b5426f0bd Mon Sep 17 00:00:00 2001 From: Haozhong Zhang Date: Mon, 11 Dec 2017 15:28:05 +0800 Subject: nvdimm: add a macro for property "label-size" Signed-off-by: Haozhong Zhang Reviewed-by: Stefan Hajnoczi Message-Id: <20171211072806.2812-3-haozhong.zhang@intel.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Eduardo Habkost --- hw/mem/nvdimm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'hw') diff --git a/hw/mem/nvdimm.c b/hw/mem/nvdimm.c index 952fce5..618c3d6 100644 --- a/hw/mem/nvdimm.c +++ b/hw/mem/nvdimm.c @@ -66,7 +66,7 @@ out: static void nvdimm_init(Object *obj) { - object_property_add(obj, "label-size", "int", + object_property_add(obj, NVDIMM_LABLE_SIZE_PROP, "int", nvdimm_get_label_size, nvdimm_set_label_size, NULL, NULL, NULL); } -- cgit v1.1 From cb836434cda103fac3c06174e70bf5c9b7083b8e Mon Sep 17 00:00:00 2001 From: Haozhong Zhang Date: Mon, 11 Dec 2017 15:28:06 +0800 Subject: nvdimm: add 'unarmed' option Currently the only vNVDIMM backend can guarantee the guest write persistence is device DAX on Linux, because no host-side kernel cache is involved in the guest access to it. The approach to detect whether the backend is device DAX needs to access sysfs, which may not work with SELinux. Instead, we add the 'unarmed' option to device 'nvdimm', so that users or management utils, which have enough knowledge about the backend, can control the unarmed flag in guest ACPI NFIT via this option. The guest Linux NVDIMM driver, for example, will mark the corresponding vNVDIMM device read-only if the unarmed flag in guest NFIT is set. The default value of 'unarmed' option is 'off' in order to keep the backwards compatibility. Signed-off-by: Haozhong Zhang Message-Id: <20171211072806.2812-4-haozhong.zhang@intel.com> Reviewed-by: Michael S. Tsirkin Reviewed-by: Stefan Hajnoczi Signed-off-by: Eduardo Habkost --- hw/acpi/nvdimm.c | 7 +++++++ hw/mem/nvdimm.c | 26 ++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) (limited to 'hw') diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c index 6ceea19..59d6e42 100644 --- a/hw/acpi/nvdimm.c +++ b/hw/acpi/nvdimm.c @@ -138,6 +138,8 @@ struct NvdimmNfitMemDev { } QEMU_PACKED; typedef struct NvdimmNfitMemDev NvdimmNfitMemDev; +#define ACPI_NFIT_MEM_NOT_ARMED (1 << 3) + /* * NVDIMM Control Region Structure * @@ -284,6 +286,7 @@ static void nvdimm_build_structure_memdev(GArray *structures, DeviceState *dev) { NvdimmNfitMemDev *nfit_memdev; + NVDIMMDevice *nvdimm = NVDIMM(OBJECT(dev)); uint64_t size = object_property_get_uint(OBJECT(dev), PC_DIMM_SIZE_PROP, NULL); int slot = object_property_get_int(OBJECT(dev), PC_DIMM_SLOT_PROP, @@ -312,6 +315,10 @@ nvdimm_build_structure_memdev(GArray *structures, DeviceState *dev) /* Only one interleave for PMEM. */ nfit_memdev->interleave_ways = cpu_to_le16(1); + + if (nvdimm->unarmed) { + nfit_memdev->flags |= cpu_to_le16(ACPI_NFIT_MEM_NOT_ARMED); + } } /* diff --git a/hw/mem/nvdimm.c b/hw/mem/nvdimm.c index 618c3d6..61e677f 100644 --- a/hw/mem/nvdimm.c +++ b/hw/mem/nvdimm.c @@ -25,6 +25,7 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "qapi/visitor.h" +#include "qapi-visit.h" #include "hw/mem/nvdimm.h" static void nvdimm_get_label_size(Object *obj, Visitor *v, const char *name, @@ -64,11 +65,36 @@ out: error_propagate(errp, local_err); } +static bool nvdimm_get_unarmed(Object *obj, Error **errp) +{ + NVDIMMDevice *nvdimm = NVDIMM(obj); + + return nvdimm->unarmed; +} + +static void nvdimm_set_unarmed(Object *obj, bool value, Error **errp) +{ + NVDIMMDevice *nvdimm = NVDIMM(obj); + Error *local_err = NULL; + + if (memory_region_size(&nvdimm->nvdimm_mr)) { + error_setg(&local_err, "cannot change property value"); + goto out; + } + + nvdimm->unarmed = value; + + out: + error_propagate(errp, local_err); +} + static void nvdimm_init(Object *obj) { object_property_add(obj, NVDIMM_LABLE_SIZE_PROP, "int", nvdimm_get_label_size, nvdimm_set_label_size, NULL, NULL, NULL); + object_property_add_bool(obj, NVDIMM_UNARMED_PROP, + nvdimm_get_unarmed, nvdimm_set_unarmed, NULL); } static MemoryRegion *nvdimm_get_memory_region(PCDIMMDevice *dimm, Error **errp) -- cgit v1.1 From d342eb7662bcfe47c26615b67025ae59a383489d Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Wed, 10 Jan 2018 16:22:50 +0100 Subject: possible_cpus: add CPUArchId::type field Remove dependency of possible_cpus on 1st CPU instance, which decouples configuration data from CPU instances that are created using that data. Also later it would be used for enabling early cpu to numa node configuration at runtime qmp_query_hotpluggable_cpus() should provide a list of available cpu slots at early stage, before machine_init() is called and the 1st cpu is created, so that mgmt might be able to call it and use output to set numa mapping. Use MachineClass::possible_cpu_arch_ids() callback to set cpu type info, along with the rest of possible cpu properties, to let machine define which cpu type* will be used. * for SPAPR it will be a spapr core type and for ARM/s390x/x86 a respective descendant of CPUClass. Move parse_numa_opts() in vl.c after cpu_model is parsed into cpu_type so that possible_cpu_arch_ids() would know which cpu_type to use during layout initialization. Signed-off-by: Igor Mammedov Reviewed-by: David Gibson Message-Id: <1515597770-268979-1-git-send-email-imammedo@redhat.com> Signed-off-by: Eduardo Habkost --- hw/arm/virt.c | 3 ++- hw/core/machine.c | 12 ++++++------ hw/i386/pc.c | 4 +++- hw/ppc/spapr.c | 13 ++++++++----- hw/s390x/s390-virtio-ccw.c | 1 + 5 files changed, 20 insertions(+), 13 deletions(-) (limited to 'hw') diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 4a6fdcc..a4537af 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -1359,7 +1359,7 @@ static void machvirt_init(MachineState *machine) break; } - cpuobj = object_new(machine->cpu_type); + cpuobj = object_new(possible_cpus->cpus[n].type); object_property_set_int(cpuobj, possible_cpus->cpus[n].arch_id, "mp-affinity", NULL); @@ -1575,6 +1575,7 @@ static const CPUArchIdList *virt_possible_cpu_arch_ids(MachineState *ms) sizeof(CPUArchId) * max_cpus); ms->possible_cpus->len = max_cpus; for (n = 0; n < ms->possible_cpus->len; n++) { + ms->possible_cpus->cpus[n].type = ms->cpu_type; ms->possible_cpus->cpus[n].arch_id = virt_cpu_mp_affinity(vms, n); ms->possible_cpus->cpus[n].props.has_thread_id = true; diff --git a/hw/core/machine.c b/hw/core/machine.c index 0320a8e..cdc1163 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -377,18 +377,18 @@ static void machine_init_notify(Notifier *notifier, void *data) HotpluggableCPUList *machine_query_hotpluggable_cpus(MachineState *machine) { int i; - Object *cpu; HotpluggableCPUList *head = NULL; - const char *cpu_type; + MachineClass *mc = MACHINE_GET_CLASS(machine); + + /* force board to initialize possible_cpus if it hasn't been done yet */ + mc->possible_cpu_arch_ids(machine); - cpu = machine->possible_cpus->cpus[0].cpu; - assert(cpu); /* Boot cpu is always present */ - cpu_type = object_get_typename(cpu); for (i = 0; i < machine->possible_cpus->len; i++) { + Object *cpu; HotpluggableCPUList *list_item = g_new0(typeof(*list_item), 1); HotpluggableCPU *cpu_item = g_new0(typeof(*cpu_item), 1); - cpu_item->type = g_strdup(cpu_type); + cpu_item->type = g_strdup(machine->possible_cpus->cpus[i].type); cpu_item->vcpus_count = machine->possible_cpus->cpus[i].vcpus_count; cpu_item->props = g_memdup(&machine->possible_cpus->cpus[i].props, sizeof(*cpu_item->props)); diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 55686bf..ccc50ba 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -1148,7 +1148,8 @@ void pc_cpus_init(PCMachineState *pcms) pcms->apic_id_limit = x86_cpu_apic_id_from_index(max_cpus - 1) + 1; possible_cpus = mc->possible_cpu_arch_ids(ms); for (i = 0; i < smp_cpus; i++) { - pc_new_cpu(ms->cpu_type, possible_cpus->cpus[i].arch_id, &error_fatal); + pc_new_cpu(possible_cpus->cpus[i].type, possible_cpus->cpus[i].arch_id, + &error_fatal); } } @@ -2307,6 +2308,7 @@ static const CPUArchIdList *pc_possible_cpu_arch_ids(MachineState *ms) for (i = 0; i < ms->possible_cpus->len; i++) { X86CPUTopoInfo topo; + ms->possible_cpus->cpus[i].type = ms->cpu_type; ms->possible_cpus->cpus[i].vcpus_count = 1; ms->possible_cpus->cpus[i].arch_id = x86_cpu_apic_id_from_index(i); x86_topo_ids_from_apicid(ms->possible_cpus->cpus[i].arch_id, diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 278f9de..a781dd2 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -2226,11 +2226,6 @@ static void spapr_init_cpus(sPAPRMachineState *spapr) int boot_cores_nr = smp_cpus / smp_threads; int i; - if (!type) { - error_report("Unable to find sPAPR CPU Core definition"); - exit(1); - } - possible_cpus = mc->possible_cpu_arch_ids(machine); if (mc->has_hotpluggable_cpus) { if (smp_cpus % smp_threads) { @@ -3545,6 +3540,7 @@ static int64_t spapr_get_default_cpu_node_id(const MachineState *ms, int idx) static const CPUArchIdList *spapr_possible_cpu_arch_ids(MachineState *machine) { int i; + const char *core_type; int spapr_max_cores = max_cpus / smp_threads; MachineClass *mc = MACHINE_GET_CLASS(machine); @@ -3556,12 +3552,19 @@ static const CPUArchIdList *spapr_possible_cpu_arch_ids(MachineState *machine) return machine->possible_cpus; } + core_type = spapr_get_cpu_core_type(machine->cpu_type); + if (!core_type) { + error_report("Unable to find sPAPR CPU Core definition"); + exit(1); + } + machine->possible_cpus = g_malloc0(sizeof(CPUArchIdList) + sizeof(CPUArchId) * spapr_max_cores); machine->possible_cpus->len = spapr_max_cores; for (i = 0; i < machine->possible_cpus->len; i++) { int core_id = i * smp_threads; + machine->possible_cpus->cpus[i].type = core_type; machine->possible_cpus->cpus[i].vcpus_count = smp_threads; machine->possible_cpus->cpus[i].arch_id = core_id; machine->possible_cpus->cpus[i].props.has_core_id = true; diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index 35df7e1..3807dcb 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -414,6 +414,7 @@ static const CPUArchIdList *s390_possible_cpu_arch_ids(MachineState *ms) sizeof(CPUArchId) * max_cpus); ms->possible_cpus->len = max_cpus; for (i = 0; i < ms->possible_cpus->len; i++) { + ms->possible_cpus->cpus[i].type = ms->cpu_type; ms->possible_cpus->cpus[i].vcpus_count = 1; ms->possible_cpus->cpus[i].arch_id = i; ms->possible_cpus->cpus[i].props.has_core_id = true; -- cgit v1.1 From d6b6abc51dda79a97f2c7bd6652c1940c068f1ec Mon Sep 17 00:00:00 2001 From: Marcel Apfelbaum Date: Mon, 8 Jan 2018 23:50:07 +0200 Subject: fw_cfg: fix memory corruption when all fw_cfg slots are used When all the fw_cfg slots are used, a write is made outside the bounds of the fw_cfg files array as part of the sort algorithm. Fix it by avoiding an unnecessary array element move. Fix also an assert while at it. Signed-off-by: Marcel Apfelbaum Message-Id: <20180108215007.46471-1-marcel@redhat.com> Reviewed-by: Laszlo Ersek Signed-off-by: Eduardo Habkost --- hw/nvram/fw_cfg.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'hw') diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c index 753ac0e..4313484 100644 --- a/hw/nvram/fw_cfg.c +++ b/hw/nvram/fw_cfg.c @@ -784,7 +784,7 @@ void fw_cfg_add_file_callback(FWCfgState *s, const char *filename, * index and "i - 1" is the one being copied from, thus the * unusual start and end in the for statement. */ - for (i = count + 1; i > index; i--) { + for (i = count; i > index; i--) { s->files->f[i] = s->files->f[i - 1]; s->files->f[i].select = cpu_to_be16(FW_CFG_FILE_FIRST + i); s->entries[0][FW_CFG_FILE_FIRST + i] = @@ -833,7 +833,6 @@ void *fw_cfg_modify_file(FWCfgState *s, const char *filename, assert(s->files); index = be32_to_cpu(s->files->count); - assert(index < fw_cfg_file_slots(s)); for (i = 0; i < index; i++) { if (strcmp(filename, s->files->f[i].name) == 0) { @@ -843,6 +842,9 @@ void *fw_cfg_modify_file(FWCfgState *s, const char *filename, return ptr; } } + + assert(index < fw_cfg_file_slots(s)); + /* add new one */ fw_cfg_add_file_callback(s, filename, NULL, NULL, NULL, data, len, true); return NULL; -- cgit v1.1