From 7c16b5bbb6c0f797945327d17e4be60f25a4427d Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 3 Feb 2021 14:18:27 +0100 Subject: pci: reject too large ROMs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit get_image_size() returns an int64_t, which pci_add_option_rom() assigns to an "int" without any range checking. A 32-bit BAR could be up to 2 GiB in size, so reject anything above it. In order to accomodate a rounded-up size of 2 GiB, change pci_patch_ids's size argument to unsigned. Reviewed-by: Peter Xu Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Laszlo Ersek Signed-off-by: Paolo Bonzini Message-Id: <20210203131828.156467-2-pbonzini@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: David Edmondson --- hw/pci/pci.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'hw') diff --git a/hw/pci/pci.c b/hw/pci/pci.c index 512e904..58560c0 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -25,6 +25,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" #include "qemu/datadir.h" +#include "qemu/units.h" #include "hw/irq.h" #include "hw/pci/pci.h" #include "hw/pci/pci_bridge.h" @@ -2234,7 +2235,7 @@ static uint8_t pci_find_capability_at_offset(PCIDevice *pdev, uint8_t offset) /* Patch the PCI vendor and device ids in a PCI rom image if necessary. This is needed for an option rom which is used for more than one device. */ -static void pci_patch_ids(PCIDevice *pdev, uint8_t *ptr, int size) +static void pci_patch_ids(PCIDevice *pdev, uint8_t *ptr, uint32_t size) { uint16_t vendor_id; uint16_t device_id; @@ -2292,7 +2293,7 @@ static void pci_patch_ids(PCIDevice *pdev, uint8_t *ptr, int size) static void pci_add_option_rom(PCIDevice *pdev, bool is_default_rom, Error **errp) { - int size; + int64_t size; char *path; void *ptr; char name[32]; @@ -2342,6 +2343,11 @@ static void pci_add_option_rom(PCIDevice *pdev, bool is_default_rom, error_setg(errp, "romfile \"%s\" is empty", pdev->romfile); g_free(path); return; + } else if (size > 2 * GiB) { + error_setg(errp, "romfile \"%s\" too large (size cannot exceed 2 GiB)", + pdev->romfile); + g_free(path); + return; } size = pow2ceil(size); -- cgit v1.1 From 08b1df8ff463e72b0875538fb991d5393047606c Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 3 Feb 2021 14:18:28 +0100 Subject: pci: add romsize property This property can be useful for distros to set up known-good ROM sizes for migration purposes. The VM will fail to start if the ROM is too large, and migration compatibility will not be broken if the ROM is too small. Note that even though romsize is a uint32_t, it has to be between 1 (because empty ROM files are not accepted, and romsize must be greater than the file) and 2^31 (because values above are not powers of two and are rejected). Signed-off-by: Paolo Bonzini Reviewed-by: Dr. David Alan Gilbert Reviewed-by: Peter Xu Message-Id: <20201218182736.1634344-1-pbonzini@redhat.com> Signed-off-by: Paolo Bonzini Message-Id: <20210203131828.156467-3-pbonzini@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: David Edmondson Acked-by: Laszlo Ersek --- hw/pci/pci.c | 19 +++++++++++++++++-- hw/xen/xen_pt_load_rom.c | 14 ++++++++++++-- 2 files changed, 29 insertions(+), 4 deletions(-) (limited to 'hw') diff --git a/hw/pci/pci.c b/hw/pci/pci.c index 58560c0..a9ebef8 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -69,6 +69,7 @@ static void pcibus_reset(BusState *qbus); static Property pci_props[] = { DEFINE_PROP_PCI_DEVFN("addr", PCIDevice, devfn, -1), DEFINE_PROP_STRING("romfile", PCIDevice, romfile), + DEFINE_PROP_UINT32("romsize", PCIDevice, romsize, -1), DEFINE_PROP_UINT32("rombar", PCIDevice, rom_bar, 1), DEFINE_PROP_BIT("multifunction", PCIDevice, cap_present, QEMU_PCI_CAP_MULTIFUNCTION_BITNR, false), @@ -2084,6 +2085,11 @@ static void pci_qdev_realize(DeviceState *qdev, Error **errp) bool is_default_rom; uint16_t class_id; + if (pci_dev->romsize != -1 && !is_power_of_2(pci_dev->romsize)) { + error_setg(errp, "ROM size %u is not a power of two", pci_dev->romsize); + return; + } + /* initialize cap_present for pci_is_express() and pci_config_size(), * Note that hybrid PCIs are not set automatically and need to manage * QEMU_PCI_CAP_EXPRESS manually */ @@ -2349,7 +2355,16 @@ static void pci_add_option_rom(PCIDevice *pdev, bool is_default_rom, g_free(path); return; } - size = pow2ceil(size); + if (pdev->romsize != -1) { + if (size > pdev->romsize) { + error_setg(errp, "romfile \"%s\" (%u bytes) is too large for ROM size %u", + pdev->romfile, (uint32_t)size, pdev->romsize); + g_free(path); + return; + } + } else { + pdev->romsize = pow2ceil(size); + } vmsd = qdev_get_vmsd(DEVICE(pdev)); @@ -2359,7 +2374,7 @@ static void pci_add_option_rom(PCIDevice *pdev, bool is_default_rom, snprintf(name, sizeof(name), "%s.rom", object_get_typename(OBJECT(pdev))); } pdev->has_rom = true; - memory_region_init_rom(&pdev->rom, OBJECT(pdev), name, size, &error_fatal); + memory_region_init_rom(&pdev->rom, OBJECT(pdev), name, pdev->romsize, &error_fatal); ptr = memory_region_get_ram_ptr(&pdev->rom); if (load_image_size(path, ptr, size) < 0) { error_setg(errp, "failed to load romfile \"%s\"", pdev->romfile); diff --git a/hw/xen/xen_pt_load_rom.c b/hw/xen/xen_pt_load_rom.c index a50a808..03422a8 100644 --- a/hw/xen/xen_pt_load_rom.c +++ b/hw/xen/xen_pt_load_rom.c @@ -53,10 +53,20 @@ void *pci_assign_dev_load_option_rom(PCIDevice *dev, } fseek(fp, 0, SEEK_SET); + if (dev->romsize != -1) { + if (st.st_size > dev->romsize) { + error_report("ROM BAR \"%s\" (%ld bytes) is too large for ROM size %u", + rom_file, (long) st.st_size, dev->romsize); + goto close_rom; + } + } else { + dev->romsize = st.st_size; + } + snprintf(name, sizeof(name), "%s.rom", object_get_typename(owner)); - memory_region_init_ram(&dev->rom, owner, name, st.st_size, &error_abort); + memory_region_init_ram(&dev->rom, owner, name, dev->romsize, &error_abort); ptr = memory_region_get_ram_ptr(&dev->rom); - memset(ptr, 0xff, st.st_size); + memset(ptr, 0xff, dev->romsize); if (!fread(ptr, 1, st.st_size, fp)) { error_report("pci-assign: Cannot read from host %s", rom_file); -- cgit v1.1 From c126b4c57e0164549de606ca35d1512762051083 Mon Sep 17 00:00:00 2001 From: Stefano Garzarella Date: Fri, 8 Jan 2021 18:12:52 +0100 Subject: virtio: move 'use-disabled-flag' property to hw_compat_4_2 Commit 9d7bd0826f introduced a new 'use-disabled-flag' property set to true by default. To allow the migration, we set this property to false in the hw_compat, but in the wrong place (hw_compat_4_1). Since commit 9d7bd0826f was released with QEMU 5.0, we move 'use-disabled-flag' property to hw_compat_4_2, so 4.2 machine types will have the pre-patch behavior and the migration can work. The issue was discovered with vhost-vsock device and 4.2 machine type without running any kernel in the VM: $ qemu-4.2 -M pc-q35-4.2,accel=kvm \ -device vhost-vsock-pci,guest-cid=4 \ -monitor stdio -incoming tcp:0:3333 $ qemu-5.2 -M pc-q35-4.2,accel=kvm \ -device vhost-vsock-pci,guest-cid=3 \ -monitor stdio (qemu) migrate -d tcp:0:3333 # qemu-4.2 output qemu-system-x86_64: Failed to load virtio-vhost_vsock:virtio qemu-system-x86_64: error while loading state for instance 0x0 of device '0000:00:03.0/virtio-vhost_vsock' qemu-system-x86_64: load of migration failed: No such file or directory Reported-by: Jing Zhao Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=1907255 Fixes: 9d7bd0826f ("virtio-pci: disable vring processing when bus-mastering is disabled") Cc: mdroth@linux.vnet.ibm.com CC: qemu-stable@nongnu.org Signed-off-by: Stefano Garzarella Message-Id: <20210108171252.209502-1-sgarzare@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/core/machine.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'hw') diff --git a/hw/core/machine.c b/hw/core/machine.c index de3b8f1..5d6163a 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -70,12 +70,12 @@ GlobalProperty hw_compat_4_2[] = { { "qxl", "revision", "4" }, { "qxl-vga", "revision", "4" }, { "fw_cfg", "acpi-mr-restore", "false" }, + { "virtio-device", "use-disabled-flag", "false" }, }; const size_t hw_compat_4_2_len = G_N_ELEMENTS(hw_compat_4_2); GlobalProperty hw_compat_4_1[] = { { "virtio-pci", "x-pcie-flr-init", "off" }, - { "virtio-device", "use-disabled-flag", "false" }, }; const size_t hw_compat_4_1_len = G_N_ELEMENTS(hw_compat_4_1); -- cgit v1.1 From 2d9e7d4cddd901a3cb57d2fc150186c70b7139a7 Mon Sep 17 00:00:00 2001 From: Laurent Vivier Date: Sun, 20 Dec 2020 17:35:39 +0100 Subject: virtio-mmio: fix guest kernel crash with SHM regions In the kernel, virtio_gpu_init() uses virtio_get_shm_region() since commit 6076a9711dc5 ("drm/virtio: implement blob resources: probe for host visible region") but vm_get_shm_region() unconditionally uses VIRTIO_MMIO_SHM_SEL to get the address and the length of the region. commit 38e895487afc ("virtio: Implement get_shm_region for MMIO transport" As this is not implemented in QEMU, address and length are 0 and passed as is to devm_request_mem_region() that triggers a crash: [drm:virtio_gpu_init] *ERROR* Could not reserve host visible region Unable to handle kernel NULL pointer dereference at virtual address (ptrval) According to the comments in the kernel, a non existent shared region has a length of (u64)-1. This is what we return now with this patch to disable the region. Signed-off-by: Laurent Vivier Message-Id: <20201220163539.2255963-1-laurent@vivier.eu> Acked-by: Gerd Hoffmann Reviewed-by: Stefano Garzarella Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/virtio/virtio-mmio.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'hw') diff --git a/hw/virtio/virtio-mmio.c b/hw/virtio/virtio-mmio.c index e1b5c3b..610661d 100644 --- a/hw/virtio/virtio-mmio.c +++ b/hw/virtio/virtio-mmio.c @@ -191,6 +191,14 @@ static uint64_t virtio_mmio_read(void *opaque, hwaddr offset, unsigned size) return 0; } return vdev->generation; + case VIRTIO_MMIO_SHM_LEN_LOW: + case VIRTIO_MMIO_SHM_LEN_HIGH: + /* + * VIRTIO_MMIO_SHM_SEL is unimplemented + * according to the linux driver, if region length is -1 + * the shared memory doesn't exist + */ + return -1; case VIRTIO_MMIO_DEVICE_FEATURES_SEL: case VIRTIO_MMIO_DRIVER_FEATURES: case VIRTIO_MMIO_DRIVER_FEATURES_SEL: -- cgit v1.1 From f6ab64c05f8a6229bf6569d3791c23abb9f6eee4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= Date: Mon, 25 Jan 2021 20:25:05 +0100 Subject: virtio: Add corresponding memory_listener_unregister to unrealize MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Address space is destroyed without proper removal of its listeners with current code. They are expected to be removed in virtio_device_instance_finalize [1], but qemu calls it through object_deinit, after address_space_destroy call through device_set_realized [2]. Move it to virtio_device_unrealize, called before device_set_realized [3] and making it symmetric with memory_listener_register in virtio_device_realize. v2: Delete no-op call of virtio_device_instance_finalize. Add backtraces. [1] #0 virtio_device_instance_finalize (obj=0x555557de5120) at /home/qemu/include/hw/virtio/virtio.h:71 #1 0x0000555555b703c9 in object_deinit (type=0x555556639860, obj=) at ../qom/object.c:671 #2 object_finalize (data=0x555557de5120) at ../qom/object.c:685 #3 object_unref (objptr=0x555557de5120) at ../qom/object.c:1184 #4 0x0000555555b4de9d in bus_free_bus_child (kid=0x555557df0660) at ../hw/core/qdev.c:55 #5 0x0000555555c65003 in call_rcu_thread (opaque=opaque@entry=0x0) at ../util/rcu.c:281 Queued by: #0 bus_remove_child (bus=0x555557de5098, child=child@entry=0x555557de5120) at ../hw/core/qdev.c:60 #1 0x0000555555b4ee31 in device_unparent (obj=) at ../hw/core/qdev.c:984 #2 0x0000555555b70465 in object_finalize_child_property ( obj=, name=, opaque=0x555557de5120) at ../qom/object.c:1725 #3 0x0000555555b6fa17 in object_property_del_child ( child=0x555557de5120, obj=0x555557ddcf90) at ../qom/object.c:645 #4 object_unparent (obj=0x555557de5120) at ../qom/object.c:664 #5 0x0000555555b4c071 in bus_unparent (obj=) at ../hw/core/bus.c:147 #6 0x0000555555b70465 in object_finalize_child_property ( obj=, name=, opaque=0x555557de5098) at ../qom/object.c:1725 #7 0x0000555555b6fa17 in object_property_del_child ( child=0x555557de5098, obj=0x555557ddcf90) at ../qom/object.c:645 #8 object_unparent (obj=0x555557de5098) at ../qom/object.c:664 #9 0x0000555555b4ee19 in device_unparent (obj=) at ../hw/core/qdev.c:981 #10 0x0000555555b70465 in object_finalize_child_property ( obj=, name=, opaque=0x555557ddcf90) at ../qom/object.c:1725 #11 0x0000555555b6fa17 in object_property_del_child ( child=0x555557ddcf90, obj=0x55555685da10) at ../qom/object.c:645 #12 object_unparent (obj=0x555557ddcf90) at ../qom/object.c:664 #13 0x00005555558dc331 in pci_for_each_device_under_bus ( opaque=, fn=, bus=) at ../hw/pci/pci.c:1654 [2] Optimizer omits pci_qdev_unrealize, called by device_set_realized, and do_pci_unregister_device, called by pci_qdev_unrealize and caller of address_space_destroy. #0 address_space_destroy (as=0x555557ddd1b8) at ../softmmu/memory.c:2840 #1 0x0000555555b4fc53 in device_set_realized (obj=0x555557ddcf90, value=, errp=0x7fffeea8f1e0) at ../hw/core/qdev.c:850 #2 0x0000555555b6eaa6 in property_set_bool (obj=0x555557ddcf90, v=, name=, opaque=0x555556650ba0, errp=0x7fffeea8f1e0) at ../qom/object.c:2255 #3 0x0000555555b70e07 in object_property_set ( obj=obj@entry=0x555557ddcf90, name=name@entry=0x555555db99df "realized", v=v@entry=0x7fffe46b7500, errp=errp@entry=0x5555565bbf38 ) at ../qom/object.c:1400 #4 0x0000555555b73c5f in object_property_set_qobject ( obj=obj@entry=0x555557ddcf90, name=name@entry=0x555555db99df "realized", value=value@entry=0x7fffe44f6180, errp=errp@entry=0x5555565bbf38 ) at ../qom/qom-qobject.c:28 #5 0x0000555555b71044 in object_property_set_bool ( obj=0x555557ddcf90, name=0x555555db99df "realized", value=, errp=0x5555565bbf38 ) at ../qom/object.c:1470 #6 0x0000555555921cb7 in pcie_unplug_device (bus=, dev=0x555557ddcf90, opaque=) at /home/qemu/include/hw/qdev-core.h:17 #7 0x00005555558dc331 in pci_for_each_device_under_bus ( opaque=, fn=, bus=) at ../hw/pci/pci.c:1654 [3] #0 virtio_device_unrealize (dev=0x555557de5120) at ../hw/virtio/virtio.c:3680 #1 0x0000555555b4fc63 in device_set_realized (obj=0x555557de5120, value=, errp=0x7fffee28df90) at ../hw/core/qdev.c:850 #2 0x0000555555b6eab6 in property_set_bool (obj=0x555557de5120, v=, name=, opaque=0x555556650ba0, errp=0x7fffee28df90) at ../qom/object.c:2255 #3 0x0000555555b70e17 in object_property_set ( obj=obj@entry=0x555557de5120, name=name@entry=0x555555db99ff "realized", v=v@entry=0x7ffdd8035040, errp=errp@entry=0x5555565bbf38 ) at ../qom/object.c:1400 #4 0x0000555555b73c6f in object_property_set_qobject ( obj=obj@entry=0x555557de5120, name=name@entry=0x555555db99ff "realized", value=value@entry=0x7ffdd8035020, errp=errp@entry=0x5555565bbf38 ) at ../qom/qom-qobject.c:28 #5 0x0000555555b71054 in object_property_set_bool ( obj=0x555557de5120, name=name@entry=0x555555db99ff "realized", value=value@entry=false, errp=0x5555565bbf38 ) at ../qom/object.c:1470 #6 0x0000555555b4edc5 in qdev_unrealize (dev=) at ../hw/core/qdev.c:403 #7 0x0000555555b4c2a9 in bus_set_realized (obj=, value=, errp=) at ../hw/core/bus.c:204 #8 0x0000555555b6eab6 in property_set_bool (obj=0x555557de5098, v=, name=, opaque=0x555557df04c0, errp=0x7fffee28e0a0) at ../qom/object.c:2255 #9 0x0000555555b70e17 in object_property_set ( obj=obj@entry=0x555557de5098, name=name@entry=0x555555db99ff "realized", v=v@entry=0x7ffdd8034f50, errp=errp@entry=0x5555565bbf38 ) at ../qom/object.c:1400 #10 0x0000555555b73c6f in object_property_set_qobject ( obj=obj@entry=0x555557de5098, name=name@entry=0x555555db99ff "realized", value=value@entry=0x7ffdd8020630, errp=errp@entry=0x5555565bbf38 ) at ../qom/qom-qobject.c:28 #11 0x0000555555b71054 in object_property_set_bool ( obj=obj@entry=0x555557de5098, name=name@entry=0x555555db99ff "realized", value=value@entry=false, errp=0x5555565bbf38 ) at ../qom/object.c:1470 #12 0x0000555555b4c725 in qbus_unrealize ( bus=bus@entry=0x555557de5098) at ../hw/core/bus.c:178 #13 0x0000555555b4fc00 in device_set_realized (obj=0x555557ddcf90, value=, errp=0x7fffee28e1e0) at ../hw/core/qdev.c:844 #14 0x0000555555b6eab6 in property_set_bool (obj=0x555557ddcf90, v=, name=, opaque=0x555556650ba0, errp=0x7fffee28e1e0) at ../qom/object.c:2255 #15 0x0000555555b70e17 in object_property_set ( obj=obj@entry=0x555557ddcf90, name=name@entry=0x555555db99ff "realized", v=v@entry=0x7ffdd8020560, errp=errp@entry=0x5555565bbf38 ) at ../qom/object.c:1400 #16 0x0000555555b73c6f in object_property_set_qobject ( obj=obj@entry=0x555557ddcf90, name=name@entry=0x555555db99ff "realized", value=value@entry=0x7ffdd8020540, errp=errp@entry=0x5555565bbf38 ) at ../qom/qom-qobject.c:28 #17 0x0000555555b71054 in object_property_set_bool ( obj=0x555557ddcf90, name=0x555555db99ff "realized", value=, errp=0x5555565bbf38 ) at ../qom/object.c:1470 #18 0x0000555555921cb7 in pcie_unplug_device (bus=, dev=0x555557ddcf90, opaque=) at /home/qemu/include/hw/qdev-core.h:17 #19 0x00005555558dc331 in pci_for_each_device_under_bus ( opaque=, fn=, bus=) at ../hw/pci/pci.c:1654 Fixes: c611c76417f ("virtio: add MemoryListener to cache ring translations") Buglink: https://bugs.launchpad.net/qemu/+bug/1912846 Signed-off-by: Eugenio Pérez Message-Id: <20210125192505.390554-1-eperezma@redhat.com> Reviewed-by: Peter Xu Acked-by: Jason Wang Reviewed-by: Stefano Garzarella Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/virtio/virtio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'hw') diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index b308026..1fd1917 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -3680,6 +3680,7 @@ static void virtio_device_unrealize(DeviceState *dev) VirtIODevice *vdev = VIRTIO_DEVICE(dev); VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(dev); + memory_listener_unregister(&vdev->listener); virtio_bus_device_unplugged(vdev); if (vdc->unrealize != NULL) { @@ -3710,7 +3711,6 @@ static void virtio_device_instance_finalize(Object *obj) { VirtIODevice *vdev = VIRTIO_DEVICE(obj); - memory_listener_unregister(&vdev->listener); virtio_device_free_virtqueues(vdev); g_free(vdev->config); -- cgit v1.1 From 73b123073d5e74f948eac9a2492e0b367006cd87 Mon Sep 17 00:00:00 2001 From: Pankaj Gupta Date: Tue, 17 Nov 2020 12:57:05 +0100 Subject: virtio-pmem: add trace events This patch adds trace events for virtio-pmem functionality. Adding trace events for virtio pmem request, reponse and host side fsync functionality. Signed-off-by: Pankaj Gupta Message-Id: <20201117115705.32195-1-pankaj.gupta.linux@gmail.com> Reviewed-by: David Hildenbrand Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/virtio/trace-events | 5 +++++ hw/virtio/virtio-pmem.c | 4 ++++ 2 files changed, 9 insertions(+) (limited to 'hw') diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events index 2060a14..c62727f 100644 --- a/hw/virtio/trace-events +++ b/hw/virtio/trace-events @@ -122,3 +122,8 @@ virtio_mem_unplug_all_request(void) "" virtio_mem_resized_usable_region(uint64_t old_size, uint64_t new_size) "old_size=0x%" PRIx64 "new_size=0x%" PRIx64 virtio_mem_state_request(uint64_t addr, uint16_t nb_blocks) "addr=0x%" PRIx64 " nb_blocks=%" PRIu16 virtio_mem_state_response(uint16_t state) "state=%" PRIu16 + +# virtio-pmem.c +virtio_pmem_flush_request(void) "flush request" +virtio_pmem_response(void) "flush response" +virtio_pmem_flush_done(int type) "fsync return=%d" diff --git a/hw/virtio/virtio-pmem.c b/hw/virtio/virtio-pmem.c index ddb0125..d83e973 100644 --- a/hw/virtio/virtio-pmem.c +++ b/hw/virtio/virtio-pmem.c @@ -24,6 +24,7 @@ #include "sysemu/hostmem.h" #include "block/aio.h" #include "block/thread-pool.h" +#include "trace.h" typedef struct VirtIODeviceRequest { VirtQueueElement elem; @@ -41,6 +42,7 @@ static int worker_cb(void *opaque) /* flush raw backing image */ err = fsync(req_data->fd); + trace_virtio_pmem_flush_done(err); if (err != 0) { err = 1; } @@ -59,6 +61,7 @@ static void done_cb(void *opaque, int ret) /* Callbacks are serialized, so no need to use atomic ops. */ virtqueue_push(req_data->pmem->rq_vq, &req_data->elem, len); virtio_notify((VirtIODevice *)req_data->pmem, req_data->pmem->rq_vq); + trace_virtio_pmem_response(); g_free(req_data); } @@ -69,6 +72,7 @@ static void virtio_pmem_flush(VirtIODevice *vdev, VirtQueue *vq) HostMemoryBackend *backend = MEMORY_BACKEND(pmem->memdev); ThreadPool *pool = aio_get_thread_pool(qemu_get_aio_context()); + trace_virtio_pmem_flush_request(); req_data = virtqueue_pop(vq, sizeof(VirtIODeviceRequest)); if (!req_data) { virtio_error(vdev, "virtio-pmem missing request data"); -- cgit v1.1 From 958ec334bca3fa9862289e4cfe31bf1019e55816 Mon Sep 17 00:00:00 2001 From: Peter Xu Date: Thu, 4 Feb 2021 14:12:28 -0500 Subject: vhost: Unbreak SMMU and virtio-iommu on dev-iotlb support Previous work on dev-iotlb message broke vhost on either SMMU or virtio-iommu since dev-iotlb (or PCIe ATS) is not yet supported for those archs. An initial idea is that we can let IOMMU to export this information to vhost so that vhost would know whether the vIOMMU would support dev-iotlb, then vhost can conditionally register to dev-iotlb or the old iotlb way. We can work based on some previous patch to introduce PCIIOMMUOps as Yi Liu proposed [1]. However it's not as easy as I thought since vhost_iommu_region_add() does not have a PCIDevice context at all since it's completely a backend. It seems non-trivial to pass over a PCI device to the backend during init. E.g. when the IOMMU notifier registered hdev->vdev is still NULL. To make the fix smaller and easier, this patch goes the other way to leverage the flag_changed() hook of vIOMMUs so that SMMU and virtio-iommu can trap the dev-iotlb registration and fail it. Then vhost could try the fallback solution as using UNMAP invalidation for it's translations. [1] https://lore.kernel.org/qemu-devel/1599735398-6829-4-git-send-email-yi.l.liu@intel.com/ Reported-by: Eric Auger Fixes: b68ba1ca57677acf870d5ab10579e6105c1f5338 Reviewed-by: Eric Auger Tested-by: Eric Auger Signed-off-by: Peter Xu Message-Id: <20210204191228.187550-1-peterx@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/arm/smmuv3.c | 5 +++++ hw/virtio/vhost.c | 13 +++++++++++-- hw/virtio/virtio-iommu.c | 5 +++++ 3 files changed, 21 insertions(+), 2 deletions(-) (limited to 'hw') diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c index 98b99d4..bd1f970 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c @@ -1497,6 +1497,11 @@ static int smmuv3_notify_flag_changed(IOMMUMemoryRegion *iommu, SMMUv3State *s3 = sdev->smmu; SMMUState *s = &(s3->smmu_state); + if (new & IOMMU_NOTIFIER_DEVIOTLB_UNMAP) { + error_setg(errp, "SMMUv3 does not support dev-iotlb yet"); + return -EINVAL; + } + if (new & IOMMU_NOTIFIER_MAP) { error_setg(errp, "device %02x.%02x.%x requires iommu MAP notifier which is " diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index 28c7d78..6e17d63 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -704,6 +704,7 @@ static void vhost_iommu_region_add(MemoryListener *listener, Int128 end; int iommu_idx; IOMMUMemoryRegion *iommu_mr; + int ret; if (!memory_region_is_iommu(section->mr)) { return; @@ -726,8 +727,16 @@ static void vhost_iommu_region_add(MemoryListener *listener, iommu->iommu_offset = section->offset_within_address_space - section->offset_within_region; iommu->hdev = dev; - memory_region_register_iommu_notifier(section->mr, &iommu->n, - &error_fatal); + ret = memory_region_register_iommu_notifier(section->mr, &iommu->n, NULL); + if (ret) { + /* + * Some vIOMMUs do not support dev-iotlb yet. If so, try to use the + * UNMAP legacy message + */ + iommu->n.notifier_flags = IOMMU_NOTIFIER_UNMAP; + memory_region_register_iommu_notifier(section->mr, &iommu->n, + &error_fatal); + } QLIST_INSERT_HEAD(&dev->iommu_list, iommu, iommu_next); /* TODO: can replay help performance here? */ } diff --git a/hw/virtio/virtio-iommu.c b/hw/virtio/virtio-iommu.c index 6b9ef7f..c2883a2 100644 --- a/hw/virtio/virtio-iommu.c +++ b/hw/virtio/virtio-iommu.c @@ -893,6 +893,11 @@ static int virtio_iommu_notify_flag_changed(IOMMUMemoryRegion *iommu_mr, IOMMUNotifierFlag new, Error **errp) { + if (new & IOMMU_NOTIFIER_DEVIOTLB_UNMAP) { + error_setg(errp, "Virtio-iommu does not support dev-iotlb yet"); + return -EINVAL; + } + if (old == IOMMU_NOTIFIER_NONE) { trace_virtio_iommu_notify_flag_add(iommu_mr->parent_obj.name); } else if (new == IOMMU_NOTIFIER_NONE) { -- cgit v1.1 From f862ddbb1a421d72a1a5980f04b4dae90da8adf5 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Wed, 3 Feb 2021 18:18:29 +0100 Subject: hw/i386: Remove the deprecated pc-1.x machine types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit They have been deprecated since QEMU v5.0, time to remove them now. Signed-off-by: Thomas Huth Message-Id: <20210203171832.483176-2-thuth@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Daniel P. Berrangé --- hw/i386/pc_piix.c | 94 ------------------------------------------------------- 1 file changed, 94 deletions(-) (limited to 'hw') diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index 6188c3e..2904b40 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -359,18 +359,6 @@ static void pc_compat_1_4_fn(MachineState *machine) pc_compat_1_5_fn(machine); } -static void pc_compat_1_3(MachineState *machine) -{ - pc_compat_1_4_fn(machine); -} - -/* PC compat function for pc-1.0 to pc-1.2 */ -static void pc_compat_1_2(MachineState *machine) -{ - pc_compat_1_3(machine); - x86_cpu_change_kvm_default("kvm-pv-eoi", NULL); -} - static void pc_init_isa(MachineState *machine) { pc_init1(machine, TYPE_I440FX_PCI_HOST_BRIDGE, TYPE_I440FX_PCI_DEVICE); @@ -772,88 +760,6 @@ static void pc_i440fx_1_4_machine_options(MachineClass *m) DEFINE_I440FX_MACHINE(v1_4, "pc-i440fx-1.4", pc_compat_1_4_fn, pc_i440fx_1_4_machine_options); -static void pc_i440fx_1_3_machine_options(MachineClass *m) -{ - X86MachineClass *x86mc = X86_MACHINE_CLASS(m); - static GlobalProperty compat[] = { - PC_CPU_MODEL_IDS("1.3.0") - { "usb-tablet", "usb_version", "1" }, - { "virtio-net-pci", "ctrl_mac_addr", "off" }, - { "virtio-net-pci", "mq", "off" }, - { "e1000", "autonegotiation", "off" }, - }; - - pc_i440fx_1_4_machine_options(m); - m->hw_version = "1.3.0"; - m->deprecation_reason = "use a newer machine type instead"; - x86mc->compat_apic_id_mode = true; - compat_props_add(m->compat_props, compat, G_N_ELEMENTS(compat)); -} - -DEFINE_I440FX_MACHINE(v1_3, "pc-1.3", pc_compat_1_3, - pc_i440fx_1_3_machine_options); - - -static void pc_i440fx_1_2_machine_options(MachineClass *m) -{ - static GlobalProperty compat[] = { - PC_CPU_MODEL_IDS("1.2.0") - { "nec-usb-xhci", "msi", "off" }, - { "nec-usb-xhci", "msix", "off" }, - { "qxl", "revision", "3" }, - { "qxl-vga", "revision", "3" }, - { "VGA", "mmio", "off" }, - }; - - pc_i440fx_1_3_machine_options(m); - m->hw_version = "1.2.0"; - compat_props_add(m->compat_props, compat, G_N_ELEMENTS(compat)); -} - -DEFINE_I440FX_MACHINE(v1_2, "pc-1.2", pc_compat_1_2, - pc_i440fx_1_2_machine_options); - - -static void pc_i440fx_1_1_machine_options(MachineClass *m) -{ - static GlobalProperty compat[] = { - PC_CPU_MODEL_IDS("1.1.0") - { "virtio-scsi-pci", "hotplug", "off" }, - { "virtio-scsi-pci", "param_change", "off" }, - { "VGA", "vgamem_mb", "8" }, - { "vmware-svga", "vgamem_mb", "8" }, - { "qxl-vga", "vgamem_mb", "8" }, - { "qxl", "vgamem_mb", "8" }, - { "virtio-blk-pci", "config-wce", "off" }, - }; - - pc_i440fx_1_2_machine_options(m); - m->hw_version = "1.1.0"; - compat_props_add(m->compat_props, compat, G_N_ELEMENTS(compat)); -} - -DEFINE_I440FX_MACHINE(v1_1, "pc-1.1", pc_compat_1_2, - pc_i440fx_1_1_machine_options); - -static void pc_i440fx_1_0_machine_options(MachineClass *m) -{ - static GlobalProperty compat[] = { - PC_CPU_MODEL_IDS("1.0") - { TYPE_ISA_FDC, "check_media_rate", "off" }, - { "virtio-balloon-pci", "class", stringify(PCI_CLASS_MEMORY_RAM) }, - { "apic-common", "vapic", "off" }, - { TYPE_USB_DEVICE, "full-path", "no" }, - }; - - pc_i440fx_1_1_machine_options(m); - m->hw_version = "1.0"; - compat_props_add(m->compat_props, compat, G_N_ELEMENTS(compat)); -} - -DEFINE_I440FX_MACHINE(v1_0, "pc-1.0", pc_compat_1_2, - pc_i440fx_1_0_machine_options); - - typedef struct { uint16_t gpu_device_id; uint16_t pch_device_id; -- cgit v1.1 From d8be0c6b68c6dac3e2ded573292b52542a1dc814 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Wed, 3 Feb 2021 18:18:31 +0100 Subject: hw/virtio/virtio-balloon: Remove the "class" property This property was only required for compatibility reasons in the pc-1.0 machine type and earlier. Now that these machine types have been removed, the property is not useful anymore. Signed-off-by: Thomas Huth Message-Id: <20210203171832.483176-4-thuth@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Acked-by: David Hildenbrand --- hw/virtio/virtio-balloon-pci.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) (limited to 'hw') diff --git a/hw/virtio/virtio-balloon-pci.c b/hw/virtio/virtio-balloon-pci.c index a2c5cc7..79a3ba9 100644 --- a/hw/virtio/virtio-balloon-pci.c +++ b/hw/virtio/virtio-balloon-pci.c @@ -34,21 +34,13 @@ struct VirtIOBalloonPCI { VirtIOPCIProxy parent_obj; VirtIOBalloon vdev; }; -static Property virtio_balloon_pci_properties[] = { - DEFINE_PROP_UINT32("class", VirtIOPCIProxy, class_code, 0), - DEFINE_PROP_END_OF_LIST(), -}; static void virtio_balloon_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp) { VirtIOBalloonPCI *dev = VIRTIO_BALLOON_PCI(vpci_dev); DeviceState *vdev = DEVICE(&dev->vdev); - if (vpci_dev->class_code != PCI_CLASS_OTHERS && - vpci_dev->class_code != PCI_CLASS_MEMORY_RAM) { /* qemu < 1.1 */ - vpci_dev->class_code = PCI_CLASS_OTHERS; - } - + vpci_dev->class_code = PCI_CLASS_OTHERS; qdev_realize(vdev, BUS(&vpci_dev->bus), errp); } @@ -59,7 +51,6 @@ static void virtio_balloon_pci_class_init(ObjectClass *klass, void *data) PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass); k->realize = virtio_balloon_pci_realize; set_bit(DEVICE_CATEGORY_MISC, dc->categories); - device_class_set_props(dc, virtio_balloon_pci_properties); pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET; pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_BALLOON; pcidev_k->revision = VIRTIO_PCI_ABI_VERSION; -- cgit v1.1 From 4d1ccc17f40f73313e13c84914f70ec3d40ac738 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= Date: Fri, 29 Jan 2021 10:07:28 +0100 Subject: vhost: Check for valid vdev in vhost_backend_handle_iotlb_msg MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Not checking this can lead to invalid dev->vdev member access in vhost_device_iotlb_miss if backend issue an iotlb message in a bad timing, either maliciously or by a bug. Reproduced rebooting a guest with testpmd in txonly forward mode. #0 0x0000559ffff94394 in vhost_device_iotlb_miss ( dev=dev@entry=0x55a0012f6680, iova=10245279744, write=1) at ../hw/virtio/vhost.c:1013 #1 0x0000559ffff9ac31 in vhost_backend_handle_iotlb_msg ( imsg=0x7ffddcfd32c0, dev=0x55a0012f6680) at ../hw/virtio/vhost-backend.c:411 #2 vhost_backend_handle_iotlb_msg (dev=dev@entry=0x55a0012f6680, imsg=imsg@entry=0x7ffddcfd32c0) at ../hw/virtio/vhost-backend.c:404 #3 0x0000559fffeded7b in slave_read (opaque=0x55a0012f6680) at ../hw/virtio/vhost-user.c:1464 #4 0x000055a0000c541b in aio_dispatch_handler ( ctx=ctx@entry=0x55a0010a2120, node=0x55a0012d9e00) at ../util/aio-posix.c:329 Fixes: 020e571b8b ("vhost: rework IOTLB messaging") Signed-off-by: Eugenio Pérez Message-Id: <20210129090728.831208-1-eperezma@redhat.com> Acked-by: Jason Wang Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/virtio/vhost-backend.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'hw') diff --git a/hw/virtio/vhost-backend.c b/hw/virtio/vhost-backend.c index 222bbcc..31b33bd 100644 --- a/hw/virtio/vhost-backend.c +++ b/hw/virtio/vhost-backend.c @@ -406,6 +406,11 @@ int vhost_backend_handle_iotlb_msg(struct vhost_dev *dev, { int ret = 0; + if (unlikely(!dev->vdev)) { + error_report("Unexpected IOTLB message when virtio device is stopped"); + return -EINVAL; + } + switch (imsg->type) { case VHOST_IOTLB_MISS: ret = vhost_device_iotlb_miss(dev, imsg->iova, -- cgit v1.1 From 602b458201ffd6f261fb8ee16b5175d733d3ec32 Mon Sep 17 00:00:00 2001 From: Marian Postevca Date: Tue, 19 Jan 2021 02:32:13 +0200 Subject: acpi: Permit OEM ID and OEM table ID fields to be changed Qemu's ACPI table generation sets the fields OEM ID and OEM table ID to "BOCHS " and "BXPCxxxx" where "xxxx" is replaced by the ACPI table name. Some games like Red Dead Redemption 2 seem to check the ACPI OEM ID and OEM table ID for the strings "BOCHS" and "BXPC" and if they are found, the game crashes(this may be an intentional detection mechanism to prevent playing the game in a virtualized environment). This patch allows you to override these default values. The feature can be used in this manner: qemu -machine oem-id=ABCDEF,oem-table-id=GHIJKLMN The oem-id string can be up to 6 bytes in size, and the oem-table-id string can be up to 8 bytes in size. If the string are smaller than their respective sizes they will be padded with space. If either of these parameters is not set, the current default values will be used for the one missing. Note that the the OEM Table ID field will not be extended with the name of the table, but will use either the default name or the user provided one. This does not affect the -acpitable option (for user-defined ACPI tables), which has precedence over -machine option. Signed-off-by: Marian Postevca Message-Id: <20210119003216.17637-3-posteuca@mutex.one> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/acpi/aml-build.c | 29 +++++++--------- hw/acpi/ghes.c | 5 +-- hw/acpi/hmat.c | 5 +-- hw/acpi/hmat.h | 3 +- hw/acpi/nvdimm.c | 18 ++++++---- hw/acpi/pci.c | 5 +-- hw/acpi/vmgenid.c | 4 +-- hw/arm/virt-acpi-build.c | 40 ++++++++++++++-------- hw/arm/virt.c | 63 +++++++++++++++++++++++++++++++++++ hw/i386/acpi-build.c | 86 ++++++++++++++++++++++++++++++++---------------- hw/i386/acpi-common.c | 5 +-- hw/i386/acpi-common.h | 3 +- hw/i386/acpi-microvm.c | 13 +++++--- hw/i386/microvm.c | 66 +++++++++++++++++++++++++++++++++++++ hw/i386/pc.c | 64 +++++++++++++++++++++++++++++++++++ 15 files changed, 326 insertions(+), 83 deletions(-) (limited to 'hw') diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c index 7b6ebb0..a2cd7a5 100644 --- a/hw/acpi/aml-build.c +++ b/hw/acpi/aml-build.c @@ -30,6 +30,7 @@ #include "hw/pci/pci_host.h" #include "hw/pci/pci_bus.h" #include "hw/pci/pci_bridge.h" +#include "qemu/cutils.h" static GArray *build_alloc_array(void) { @@ -1674,21 +1675,12 @@ build_header(BIOSLinker *linker, GArray *table_data, h->length = cpu_to_le32(len); h->revision = rev; - if (oem_id) { - strncpy((char *)h->oem_id, oem_id, sizeof h->oem_id); - } else { - memcpy(h->oem_id, ACPI_BUILD_APPNAME6, 6); - } - - if (oem_table_id) { - strncpy((char *)h->oem_table_id, oem_table_id, sizeof(h->oem_table_id)); - } else { - memcpy(h->oem_table_id, ACPI_BUILD_APPNAME4, 4); - memcpy(h->oem_table_id + 4, sig, 4); - } + strpadcpy((char *)h->oem_id, sizeof h->oem_id, oem_id, ' '); + strpadcpy((char *)h->oem_table_id, sizeof h->oem_table_id, + oem_table_id, ' '); h->oem_revision = cpu_to_le32(1); - memcpy(h->asl_compiler_id, ACPI_BUILD_APPNAME4, 4); + memcpy(h->asl_compiler_id, ACPI_BUILD_APPNAME8, 4); h->asl_compiler_revision = cpu_to_le32(1); /* Checksum to be filled in by Guest linker */ bios_linker_loader_add_checksum(linker, ACPI_BUILD_TABLE_FILE, @@ -1871,7 +1863,8 @@ void build_srat_memory(AcpiSratMemoryAffinity *numamem, uint64_t base, * ACPI spec 5.2.17 System Locality Distance Information Table * (Revision 2.0 or later) */ -void build_slit(GArray *table_data, BIOSLinker *linker, MachineState *ms) +void build_slit(GArray *table_data, BIOSLinker *linker, MachineState *ms, + const char *oem_id, const char *oem_table_id) { int slit_start, i, j; slit_start = table_data->len; @@ -1892,7 +1885,7 @@ void build_slit(GArray *table_data, BIOSLinker *linker, MachineState *ms) build_header(linker, table_data, (void *)(table_data->data + slit_start), "SLIT", - table_data->len - slit_start, 1, NULL, NULL); + table_data->len - slit_start, 1, oem_id, oem_table_id); } /* build rev1/rev3/rev5.1 FADT */ @@ -2024,7 +2017,8 @@ build_hdr: * table 7: TCG Hardware Interface Description Table Format for TPM 2.0 * of TCG ACPI Specification, Family “1.2” and “2.0”, Version 1.2, Rev 8 */ -void build_tpm2(GArray *table_data, BIOSLinker *linker, GArray *tcpalog) +void build_tpm2(GArray *table_data, BIOSLinker *linker, GArray *tcpalog, + const char *oem_id, const char *oem_table_id) { uint8_t start_method_params[12] = {}; unsigned log_addr_offset, tpm2_start; @@ -2073,7 +2067,8 @@ void build_tpm2(GArray *table_data, BIOSLinker *linker, GArray *tcpalog) log_addr_offset, 8, ACPI_BUILD_TPMLOG_FILE, 0); build_header(linker, table_data, - tpm2_ptr, "TPM2", table_data->len - tpm2_start, 4, NULL, NULL); + tpm2_ptr, "TPM2", table_data->len - tpm2_start, 4, oem_id, + oem_table_id); } Aml *build_crs(PCIHostState *host, CrsRangeSet *range_set, uint32_t io_offset, diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c index f0ee9f5..a4dac6b 100644 --- a/hw/acpi/ghes.c +++ b/hw/acpi/ghes.c @@ -359,7 +359,8 @@ static void build_ghes_v2(GArray *table_data, int source_id, BIOSLinker *linker) } /* Build Hardware Error Source Table */ -void acpi_build_hest(GArray *table_data, BIOSLinker *linker) +void acpi_build_hest(GArray *table_data, BIOSLinker *linker, + const char *oem_id, const char *oem_table_id) { uint64_t hest_start = table_data->len; @@ -372,7 +373,7 @@ void acpi_build_hest(GArray *table_data, BIOSLinker *linker) build_ghes_v2(table_data, ACPI_HEST_SRC_ID_SEA, linker); build_header(linker, table_data, (void *)(table_data->data + hest_start), - "HEST", table_data->len - hest_start, 1, NULL, NULL); + "HEST", table_data->len - hest_start, 1, oem_id, oem_table_id); } void acpi_ghes_add_fw_cfg(AcpiGhesState *ags, FWCfgState *s, diff --git a/hw/acpi/hmat.c b/hw/acpi/hmat.c index 37806f7..edb3fd9 100644 --- a/hw/acpi/hmat.c +++ b/hw/acpi/hmat.c @@ -253,7 +253,8 @@ static void hmat_build_table_structs(GArray *table_data, NumaState *numa_state) } } -void build_hmat(GArray *table_data, BIOSLinker *linker, NumaState *numa_state) +void build_hmat(GArray *table_data, BIOSLinker *linker, NumaState *numa_state, + const char *oem_id, const char *oem_table_id) { int hmat_start = table_data->len; @@ -264,5 +265,5 @@ void build_hmat(GArray *table_data, BIOSLinker *linker, NumaState *numa_state) build_header(linker, table_data, (void *)(table_data->data + hmat_start), - "HMAT", table_data->len - hmat_start, 2, NULL, NULL); + "HMAT", table_data->len - hmat_start, 2, oem_id, oem_table_id); } diff --git a/hw/acpi/hmat.h b/hw/acpi/hmat.h index e9031ca..b57f0e7 100644 --- a/hw/acpi/hmat.h +++ b/hw/acpi/hmat.h @@ -37,6 +37,7 @@ */ #define HMAT_PROXIMITY_INITIATOR_VALID 0x1 -void build_hmat(GArray *table_data, BIOSLinker *linker, NumaState *numa_state); +void build_hmat(GArray *table_data, BIOSLinker *linker, NumaState *numa_state, + const char *oem_id, const char *oem_table_id); #endif diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c index aa95b0c..e3d5fe1 100644 --- a/hw/acpi/nvdimm.c +++ b/hw/acpi/nvdimm.c @@ -402,7 +402,8 @@ void nvdimm_plug(NVDIMMState *state) } static void nvdimm_build_nfit(NVDIMMState *state, GArray *table_offsets, - GArray *table_data, BIOSLinker *linker) + GArray *table_data, BIOSLinker *linker, + const char *oem_id, const char *oem_table_id) { NvdimmFitBuffer *fit_buf = &state->fit_buf; unsigned int header; @@ -417,7 +418,8 @@ static void nvdimm_build_nfit(NVDIMMState *state, GArray *table_offsets, build_header(linker, table_data, (void *)(table_data->data + header), "NFIT", - sizeof(NvdimmNfitHeader) + fit_buf->fit->len, 1, NULL, NULL); + sizeof(NvdimmNfitHeader) + fit_buf->fit->len, 1, oem_id, + oem_table_id); } #define NVDIMM_DSM_MEMORY_SIZE 4096 @@ -1278,7 +1280,7 @@ static void nvdimm_build_nvdimm_devices(Aml *root_dev, uint32_t ram_slots) static void nvdimm_build_ssdt(GArray *table_offsets, GArray *table_data, BIOSLinker *linker, NVDIMMState *nvdimm_state, - uint32_t ram_slots) + uint32_t ram_slots, const char *oem_id) { Aml *ssdt, *sb_scope, *dev; int mem_addr_offset, nvdimm_ssdt; @@ -1331,7 +1333,7 @@ static void nvdimm_build_ssdt(GArray *table_offsets, GArray *table_data, NVDIMM_DSM_MEM_FILE, 0); build_header(linker, table_data, (void *)(table_data->data + nvdimm_ssdt), - "SSDT", table_data->len - nvdimm_ssdt, 1, NULL, "NVDIMM"); + "SSDT", table_data->len - nvdimm_ssdt, 1, oem_id, "NVDIMM"); free_aml_allocator(); } @@ -1359,7 +1361,8 @@ void nvdimm_build_srat(GArray *table_data) void nvdimm_build_acpi(GArray *table_offsets, GArray *table_data, BIOSLinker *linker, NVDIMMState *state, - uint32_t ram_slots) + uint32_t ram_slots, const char *oem_id, + const char *oem_table_id) { GSList *device_list; @@ -1369,7 +1372,7 @@ void nvdimm_build_acpi(GArray *table_offsets, GArray *table_data, } nvdimm_build_ssdt(table_offsets, table_data, linker, state, - ram_slots); + ram_slots, oem_id); device_list = nvdimm_get_device_list(); /* no NVDIMM device is plugged. */ @@ -1377,6 +1380,7 @@ void nvdimm_build_acpi(GArray *table_offsets, GArray *table_data, return; } - nvdimm_build_nfit(state, table_offsets, table_data, linker); + nvdimm_build_nfit(state, table_offsets, table_data, linker, + oem_id, oem_table_id); g_slist_free(device_list); } diff --git a/hw/acpi/pci.c b/hw/acpi/pci.c index 9510597..ec455c3 100644 --- a/hw/acpi/pci.c +++ b/hw/acpi/pci.c @@ -28,7 +28,8 @@ #include "hw/acpi/pci.h" #include "hw/pci/pcie_host.h" -void build_mcfg(GArray *table_data, BIOSLinker *linker, AcpiMcfgInfo *info) +void build_mcfg(GArray *table_data, BIOSLinker *linker, AcpiMcfgInfo *info, + const char *oem_id, const char *oem_table_id) { int mcfg_start = table_data->len; @@ -56,6 +57,6 @@ void build_mcfg(GArray *table_data, BIOSLinker *linker, AcpiMcfgInfo *info) build_append_int_noprefix(table_data, 0, 4); build_header(linker, table_data, (void *)(table_data->data + mcfg_start), - "MCFG", table_data->len - mcfg_start, 1, NULL, NULL); + "MCFG", table_data->len - mcfg_start, 1, oem_id, oem_table_id); } diff --git a/hw/acpi/vmgenid.c b/hw/acpi/vmgenid.c index 6c92fda..4f41a13 100644 --- a/hw/acpi/vmgenid.c +++ b/hw/acpi/vmgenid.c @@ -24,7 +24,7 @@ #include "sysemu/reset.h" void vmgenid_build_acpi(VmGenIdState *vms, GArray *table_data, GArray *guid, - BIOSLinker *linker) + BIOSLinker *linker, const char *oem_id) { Aml *ssdt, *dev, *scope, *method, *addr, *if_ctx; uint32_t vgia_offset; @@ -118,7 +118,7 @@ void vmgenid_build_acpi(VmGenIdState *vms, GArray *table_data, GArray *guid, build_header(linker, table_data, (void *)(table_data->data + table_data->len - ssdt->buf->len), - "SSDT", ssdt->buf->len, 1, NULL, "VMGENID"); + "SSDT", ssdt->buf->len, 1, oem_id, "VMGENID"); free_aml_allocator(); } diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index 9d9ee24..f9c9df9 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -341,7 +341,8 @@ build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) iort->length = cpu_to_le32(iort_length); build_header(linker, table_data, (void *)(table_data->data + iort_start), - "IORT", table_data->len - iort_start, 0, NULL, NULL); + "IORT", table_data->len - iort_start, 0, vms->oem_id, + vms->oem_table_id); } static void @@ -375,7 +376,8 @@ build_spcr(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) spcr->pci_vendor_id = 0xffff; /* PCI Vendor ID: not a PCI device */ build_header(linker, table_data, (void *)(table_data->data + spcr_start), - "SPCR", table_data->len - spcr_start, 2, NULL, NULL); + "SPCR", table_data->len - spcr_start, 2, vms->oem_id, + vms->oem_table_id); } static void @@ -427,7 +429,8 @@ build_srat(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) } build_header(linker, table_data, (void *)(table_data->data + srat_start), - "SRAT", table_data->len - srat_start, 3, NULL, NULL); + "SRAT", table_data->len - srat_start, 3, vms->oem_id, + vms->oem_table_id); } /* GTDT */ @@ -462,7 +465,8 @@ build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) build_header(linker, table_data, (void *)(table_data->data + gtdt_start), "GTDT", - table_data->len - gtdt_start, 2, NULL, NULL); + table_data->len - gtdt_start, 2, vms->oem_id, + vms->oem_table_id); } /* MADT */ @@ -551,7 +555,8 @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) build_header(linker, table_data, (void *)(table_data->data + madt_start), "APIC", - table_data->len - madt_start, 3, NULL, NULL); + table_data->len - madt_start, 3, vms->oem_id, + vms->oem_table_id); } /* FADT */ @@ -581,7 +586,7 @@ static void build_fadt_rev5(GArray *table_data, BIOSLinker *linker, g_assert_not_reached(); } - build_fadt(table_data, linker, &fadt, NULL, NULL); + build_fadt(table_data, linker, &fadt, vms->oem_id, vms->oem_table_id); } /* DSDT */ @@ -645,7 +650,8 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) g_array_append_vals(table_data, dsdt->buf->data, dsdt->buf->len); build_header(linker, table_data, (void *)(table_data->data + table_data->len - dsdt->buf->len), - "DSDT", dsdt->buf->len, 2, NULL, NULL); + "DSDT", dsdt->buf->len, 2, vms->oem_id, + vms->oem_table_id); free_aml_allocator(); } @@ -704,7 +710,8 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables) .base = vms->memmap[VIRT_ECAM_ID(vms->highmem_ecam)].base, .size = vms->memmap[VIRT_ECAM_ID(vms->highmem_ecam)].size, }; - build_mcfg(tables_blob, tables->linker, &mcfg); + build_mcfg(tables_blob, tables->linker, &mcfg, vms->oem_id, + vms->oem_table_id); } acpi_add_table(table_offsets, tables_blob); @@ -713,7 +720,8 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables) if (vms->ras) { build_ghes_error_table(tables->hardware_errors, tables->linker); acpi_add_table(table_offsets, tables_blob); - acpi_build_hest(tables_blob, tables->linker); + acpi_build_hest(tables_blob, tables->linker, vms->oem_id, + vms->oem_table_id); } if (ms->numa_state->num_nodes > 0) { @@ -721,13 +729,15 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables) build_srat(tables_blob, tables->linker, vms); if (ms->numa_state->have_numa_distance) { acpi_add_table(table_offsets, tables_blob); - build_slit(tables_blob, tables->linker, ms); + build_slit(tables_blob, tables->linker, ms, vms->oem_id, + vms->oem_table_id); } } if (ms->nvdimms_state->is_enabled) { nvdimm_build_acpi(table_offsets, tables_blob, tables->linker, - ms->nvdimms_state, ms->ram_slots); + ms->nvdimms_state, ms->ram_slots, vms->oem_id, + vms->oem_table_id); } if (its_class_name() && !vmc->no_its) { @@ -737,18 +747,20 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables) if (tpm_get_version(tpm_find()) == TPM_VERSION_2_0) { acpi_add_table(table_offsets, tables_blob); - build_tpm2(tables_blob, tables->linker, tables->tcpalog); + build_tpm2(tables_blob, tables->linker, tables->tcpalog, vms->oem_id, + vms->oem_table_id); } /* XSDT is pointed to by RSDP */ xsdt = tables_blob->len; - build_xsdt(tables_blob, tables->linker, table_offsets, NULL, NULL); + build_xsdt(tables_blob, tables->linker, table_offsets, vms->oem_id, + vms->oem_table_id); /* RSDP is in FSEG memory, so allocate it separately */ { AcpiRsdpData rsdp_data = { .revision = 2, - .oem_id = ACPI_BUILD_APPNAME6, + .oem_id = vms->oem_id, .xsdt_tbl_offset = &xsdt, .rsdt_tbl_offset = NULL, }; diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 399da73..0c65fe3 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -2155,6 +2155,49 @@ static void virt_set_its(Object *obj, bool value, Error **errp) vms->its = value; } +static char *virt_get_oem_id(Object *obj, Error **errp) +{ + VirtMachineState *vms = VIRT_MACHINE(obj); + + return g_strdup(vms->oem_id); +} + +static void virt_set_oem_id(Object *obj, const char *value, Error **errp) +{ + VirtMachineState *vms = VIRT_MACHINE(obj); + size_t len = strlen(value); + + if (len > 6) { + error_setg(errp, + "User specified oem-id value is bigger than 6 bytes in size"); + return; + } + + strncpy(vms->oem_id, value, len + 1); +} + +static char *virt_get_oem_table_id(Object *obj, Error **errp) +{ + VirtMachineState *vms = VIRT_MACHINE(obj); + + return g_strdup(vms->oem_table_id); +} + +static void virt_set_oem_table_id(Object *obj, const char *value, + Error **errp) +{ + VirtMachineState *vms = VIRT_MACHINE(obj); + size_t len = strlen(value); + + if (len > 8) { + error_setg(errp, + "User specified oem-table-id value is bigger than 8 bytes in size"); + return; + } + strncpy(vms->oem_table_id, value, len + 1); +} + + bool virt_is_acpi_enabled(VirtMachineState *vms) { if (vms->acpi == ON_OFF_AUTO_OFF) { @@ -2604,6 +2647,23 @@ static void virt_machine_class_init(ObjectClass *oc, void *data) "Set on/off to enable/disable " "ITS instantiation"); + object_class_property_add_str(oc, "oem-id", + virt_get_oem_id, + virt_set_oem_id); + object_class_property_set_description(oc, "oem-id", + "Override the default value of field OEMID " + "in ACPI table header." + "The string may be up to 6 bytes in size"); + + + object_class_property_add_str(oc, "oem-table-id", + virt_get_oem_table_id, + virt_set_oem_table_id); + object_class_property_set_description(oc, "oem-table-id", + "Override the default value of field OEM Table ID " + "in ACPI table header." + "The string may be up to 8 bytes in size"); + } static void virt_instance_init(Object *obj) @@ -2645,6 +2705,9 @@ static void virt_instance_init(Object *obj) vms->irqmap = a15irqmap; virt_flash_create(vms); + + vms->oem_id = g_strndup(ACPI_BUILD_APPNAME6, 6); + vms->oem_table_id = g_strndup(ACPI_BUILD_APPNAME8, 8); } static const TypeInfo virt_machine_info = { diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index f56d699..b9190b9 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -1637,12 +1637,13 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, g_array_append_vals(table_data, dsdt->buf->data, dsdt->buf->len); build_header(linker, table_data, (void *)(table_data->data + table_data->len - dsdt->buf->len), - "DSDT", dsdt->buf->len, 1, NULL, NULL); + "DSDT", dsdt->buf->len, 1, pcms->oem_id, pcms->oem_table_id); free_aml_allocator(); } static void -build_hpet(GArray *table_data, BIOSLinker *linker) +build_hpet(GArray *table_data, BIOSLinker *linker, const char *oem_id, + const char *oem_table_id) { Acpi20Hpet *hpet; @@ -1653,11 +1654,12 @@ build_hpet(GArray *table_data, BIOSLinker *linker) hpet->timer_block_id = cpu_to_le32(0x8086a201); hpet->addr.address = cpu_to_le64(HPET_BASE); build_header(linker, table_data, - (void *)hpet, "HPET", sizeof(*hpet), 1, NULL, NULL); + (void *)hpet, "HPET", sizeof(*hpet), 1, oem_id, oem_table_id); } static void -build_tpm_tcpa(GArray *table_data, BIOSLinker *linker, GArray *tcpalog) +build_tpm_tcpa(GArray *table_data, BIOSLinker *linker, GArray *tcpalog, + const char *oem_id, const char *oem_table_id) { Acpi20Tcpa *tcpa = acpi_data_push(table_data, sizeof *tcpa); unsigned log_addr_size = sizeof(tcpa->log_area_start_address); @@ -1677,7 +1679,7 @@ build_tpm_tcpa(GArray *table_data, BIOSLinker *linker, GArray *tcpalog) ACPI_BUILD_TPMLOG_FILE, 0); build_header(linker, table_data, - (void *)tcpa, "TCPA", sizeof(*tcpa), 2, NULL, NULL); + (void *)tcpa, "TCPA", sizeof(*tcpa), 2, oem_id, oem_table_id); } #define HOLE_640K_START (640 * KiB) @@ -1812,7 +1814,8 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine) build_header(linker, table_data, (void *)(table_data->data + srat_start), "SRAT", - table_data->len - srat_start, 1, NULL, NULL); + table_data->len - srat_start, 1, pcms->oem_id, + pcms->oem_table_id); } /* @@ -1820,7 +1823,8 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine) * (version Oct. 2014 or later) */ static void -build_dmar_q35(GArray *table_data, BIOSLinker *linker) +build_dmar_q35(GArray *table_data, BIOSLinker *linker, const char *oem_id, + const char *oem_table_id) { int dmar_start = table_data->len; @@ -1870,7 +1874,7 @@ build_dmar_q35(GArray *table_data, BIOSLinker *linker) } build_header(linker, table_data, (void *)(table_data->data + dmar_start), - "DMAR", table_data->len - dmar_start, 1, NULL, NULL); + "DMAR", table_data->len - dmar_start, 1, oem_id, oem_table_id); } /* @@ -1881,7 +1885,8 @@ build_dmar_q35(GArray *table_data, BIOSLinker *linker) * Helpful to speedup Windows guests and ignored by others. */ static void -build_waet(GArray *table_data, BIOSLinker *linker) +build_waet(GArray *table_data, BIOSLinker *linker, const char *oem_id, + const char *oem_table_id) { int waet_start = table_data->len; @@ -1897,7 +1902,7 @@ build_waet(GArray *table_data, BIOSLinker *linker) build_append_int_noprefix(table_data, 1 << 1 /* ACPI PM timer good */, 4); build_header(linker, table_data, (void *)(table_data->data + waet_start), - "WAET", table_data->len - waet_start, 1, NULL, NULL); + "WAET", table_data->len - waet_start, 1, oem_id, oem_table_id); } /* @@ -1999,7 +2004,8 @@ ivrs_host_bridges(Object *obj, void *opaque) } static void -build_amd_iommu(GArray *table_data, BIOSLinker *linker) +build_amd_iommu(GArray *table_data, BIOSLinker *linker, const char *oem_id, + const char *oem_table_id) { int ivhd_table_len = 24; int iommu_start = table_data->len; @@ -2094,7 +2100,8 @@ build_amd_iommu(GArray *table_data, BIOSLinker *linker) } build_header(linker, table_data, (void *)(table_data->data + iommu_start), - "IVRS", table_data->len - iommu_start, 1, NULL, NULL); + "IVRS", table_data->len - iommu_start, 1, oem_id, + oem_table_id); } typedef @@ -2150,12 +2157,26 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine) GArray *tables_blob = tables->table_data; AcpiSlicOem slic_oem = { .id = NULL, .table_id = NULL }; Object *vmgenid_dev; + char *oem_id; + char *oem_table_id; acpi_get_pm_info(machine, &pm); acpi_get_misc_info(&misc); acpi_get_pci_holes(&pci_hole, &pci_hole64); acpi_get_slic_oem(&slic_oem); + if (slic_oem.id) { + oem_id = slic_oem.id; + } else { + oem_id = pcms->oem_id; + } + + if (slic_oem.table_id) { + oem_table_id = slic_oem.table_id; + } else { + oem_table_id = pcms->oem_table_id; + } + table_offsets = g_array_new(false, true /* clear */, sizeof(uint32_t)); ACPI_BUILD_DPRINTF("init ACPI tables\n"); @@ -2189,32 +2210,35 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine) pm.fadt.facs_tbl_offset = &facs; pm.fadt.dsdt_tbl_offset = &dsdt; pm.fadt.xdsdt_tbl_offset = &dsdt; - build_fadt(tables_blob, tables->linker, &pm.fadt, - slic_oem.id, slic_oem.table_id); + build_fadt(tables_blob, tables->linker, &pm.fadt, oem_id, oem_table_id); aml_len += tables_blob->len - fadt; acpi_add_table(table_offsets, tables_blob); acpi_build_madt(tables_blob, tables->linker, x86ms, - ACPI_DEVICE_IF(x86ms->acpi_dev)); + ACPI_DEVICE_IF(x86ms->acpi_dev), pcms->oem_id, + pcms->oem_table_id); vmgenid_dev = find_vmgenid_dev(); if (vmgenid_dev) { acpi_add_table(table_offsets, tables_blob); vmgenid_build_acpi(VMGENID(vmgenid_dev), tables_blob, - tables->vmgenid, tables->linker); + tables->vmgenid, tables->linker, pcms->oem_id); } if (misc.has_hpet) { acpi_add_table(table_offsets, tables_blob); - build_hpet(tables_blob, tables->linker); + build_hpet(tables_blob, tables->linker, pcms->oem_id, + pcms->oem_table_id); } if (misc.tpm_version != TPM_VERSION_UNSPEC) { if (misc.tpm_version == TPM_VERSION_1_2) { acpi_add_table(table_offsets, tables_blob); - build_tpm_tcpa(tables_blob, tables->linker, tables->tcpalog); + build_tpm_tcpa(tables_blob, tables->linker, tables->tcpalog, + pcms->oem_id, pcms->oem_table_id); } else { /* TPM_VERSION_2_0 */ acpi_add_table(table_offsets, tables_blob); - build_tpm2(tables_blob, tables->linker, tables->tcpalog); + build_tpm2(tables_blob, tables->linker, tables->tcpalog, + pcms->oem_id, pcms->oem_table_id); } } if (pcms->numa_nodes) { @@ -2222,34 +2246,40 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine) build_srat(tables_blob, tables->linker, machine); if (machine->numa_state->have_numa_distance) { acpi_add_table(table_offsets, tables_blob); - build_slit(tables_blob, tables->linker, machine); + build_slit(tables_blob, tables->linker, machine, pcms->oem_id, + pcms->oem_table_id); } if (machine->numa_state->hmat_enabled) { acpi_add_table(table_offsets, tables_blob); - build_hmat(tables_blob, tables->linker, machine->numa_state); + build_hmat(tables_blob, tables->linker, machine->numa_state, + pcms->oem_id, pcms->oem_table_id); } } if (acpi_get_mcfg(&mcfg)) { acpi_add_table(table_offsets, tables_blob); - build_mcfg(tables_blob, tables->linker, &mcfg); + build_mcfg(tables_blob, tables->linker, &mcfg, pcms->oem_id, + pcms->oem_table_id); } if (x86_iommu_get_default()) { IommuType IOMMUType = x86_iommu_get_type(); if (IOMMUType == TYPE_AMD) { acpi_add_table(table_offsets, tables_blob); - build_amd_iommu(tables_blob, tables->linker); + build_amd_iommu(tables_blob, tables->linker, pcms->oem_id, + pcms->oem_table_id); } else if (IOMMUType == TYPE_INTEL) { acpi_add_table(table_offsets, tables_blob); - build_dmar_q35(tables_blob, tables->linker); + build_dmar_q35(tables_blob, tables->linker, pcms->oem_id, + pcms->oem_table_id); } } if (machine->nvdimms_state->is_enabled) { nvdimm_build_acpi(table_offsets, tables_blob, tables->linker, - machine->nvdimms_state, machine->ram_slots); + machine->nvdimms_state, machine->ram_slots, + pcms->oem_id, pcms->oem_table_id); } acpi_add_table(table_offsets, tables_blob); - build_waet(tables_blob, tables->linker); + build_waet(tables_blob, tables->linker, pcms->oem_id, pcms->oem_table_id); /* Add tables supplied by user (if any) */ for (u = acpi_table_first(); u; u = acpi_table_next(u)) { @@ -2262,13 +2292,13 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine) /* RSDT is pointed to by RSDP */ rsdt = tables_blob->len; build_rsdt(tables_blob, tables->linker, table_offsets, - slic_oem.id, slic_oem.table_id); + oem_id, oem_table_id); /* RSDP is in FSEG memory, so allocate it separately */ { AcpiRsdpData rsdp_data = { .revision = 0, - .oem_id = ACPI_BUILD_APPNAME6, + .oem_id = pcms->oem_id, .xsdt_tbl_offset = NULL, .rsdt_tbl_offset = &rsdt, }; diff --git a/hw/i386/acpi-common.c b/hw/i386/acpi-common.c index a6a30e8..1f5947f 100644 --- a/hw/i386/acpi-common.c +++ b/hw/i386/acpi-common.c @@ -72,7 +72,8 @@ void pc_madt_cpu_entry(AcpiDeviceIf *adev, int uid, } void acpi_build_madt(GArray *table_data, BIOSLinker *linker, - X86MachineState *x86ms, AcpiDeviceIf *adev) + X86MachineState *x86ms, AcpiDeviceIf *adev, + const char *oem_id, const char *oem_table_id) { MachineClass *mc = MACHINE_GET_CLASS(x86ms); const CPUArchIdList *apic_ids = mc->possible_cpu_arch_ids(MACHINE(x86ms)); @@ -157,6 +158,6 @@ void acpi_build_madt(GArray *table_data, BIOSLinker *linker, build_header(linker, table_data, (void *)(table_data->data + madt_start), "APIC", - table_data->len - madt_start, 1, NULL, NULL); + table_data->len - madt_start, 1, oem_id, oem_table_id); } diff --git a/hw/i386/acpi-common.h b/hw/i386/acpi-common.h index c30e461..b12cd73 100644 --- a/hw/i386/acpi-common.h +++ b/hw/i386/acpi-common.h @@ -9,6 +9,7 @@ #define ACPI_BUILD_IOAPIC_ID 0x0 void acpi_build_madt(GArray *table_data, BIOSLinker *linker, - X86MachineState *x86ms, AcpiDeviceIf *adev); + X86MachineState *x86ms, AcpiDeviceIf *adev, + const char *oem_id, const char *oem_table_id); #endif diff --git a/hw/i386/acpi-microvm.c b/hw/i386/acpi-microvm.c index d34a301..54b3af4 100644 --- a/hw/i386/acpi-microvm.c +++ b/hw/i386/acpi-microvm.c @@ -149,7 +149,7 @@ build_dsdt_microvm(GArray *table_data, BIOSLinker *linker, g_array_append_vals(table_data, dsdt->buf->data, dsdt->buf->len); build_header(linker, table_data, (void *)(table_data->data + table_data->len - dsdt->buf->len), - "DSDT", dsdt->buf->len, 2, NULL, NULL); + "DSDT", dsdt->buf->len, 2, mms->oem_id, mms->oem_table_id); free_aml_allocator(); } @@ -201,21 +201,24 @@ static void acpi_build_microvm(AcpiBuildTables *tables, pmfadt.dsdt_tbl_offset = &dsdt; pmfadt.xdsdt_tbl_offset = &dsdt; acpi_add_table(table_offsets, tables_blob); - build_fadt(tables_blob, tables->linker, &pmfadt, NULL, NULL); + build_fadt(tables_blob, tables->linker, &pmfadt, mms->oem_id, + mms->oem_table_id); acpi_add_table(table_offsets, tables_blob); acpi_build_madt(tables_blob, tables->linker, X86_MACHINE(machine), - ACPI_DEVICE_IF(x86ms->acpi_dev)); + ACPI_DEVICE_IF(x86ms->acpi_dev), mms->oem_id, + mms->oem_table_id); xsdt = tables_blob->len; - build_xsdt(tables_blob, tables->linker, table_offsets, NULL, NULL); + build_xsdt(tables_blob, tables->linker, table_offsets, mms->oem_id, + mms->oem_table_id); /* RSDP is in FSEG memory, so allocate it separately */ { AcpiRsdpData rsdp_data = { /* ACPI 2.0: 5.2.4.3 RSDP Structure */ .revision = 2, /* xsdt needs v2 */ - .oem_id = ACPI_BUILD_APPNAME6, + .oem_id = mms->oem_id, .xsdt_tbl_offset = &xsdt, .rsdt_tbl_offset = NULL, }; diff --git a/hw/i386/microvm.c b/hw/i386/microvm.c index edf2b0f..1dc2956 100644 --- a/hw/i386/microvm.c +++ b/hw/i386/microvm.c @@ -648,6 +648,51 @@ static void microvm_powerdown_req(Notifier *notifier, void *data) } } +static char *microvm_machine_get_oem_id(Object *obj, Error **errp) +{ + MicrovmMachineState *mms = MICROVM_MACHINE(obj); + + return g_strdup(mms->oem_id); +} + +static void microvm_machine_set_oem_id(Object *obj, const char *value, + Error **errp) +{ + MicrovmMachineState *mms = MICROVM_MACHINE(obj); + size_t len = strlen(value); + + if (len > 6) { + error_setg(errp, + "User specified "MICROVM_MACHINE_OEM_ID" value is bigger than " + "6 bytes in size"); + return; + } + + strncpy(mms->oem_id, value, len + 1); +} + +static char *microvm_machine_get_oem_table_id(Object *obj, Error **errp) +{ + MicrovmMachineState *mms = MICROVM_MACHINE(obj); + + return g_strdup(mms->oem_table_id); +} + +static void microvm_machine_set_oem_table_id(Object *obj, const char *value, + Error **errp) +{ + MicrovmMachineState *mms = MICROVM_MACHINE(obj); + size_t len = strlen(value); + + if (len > 8) { + error_setg(errp, + "User specified "MICROVM_MACHINE_OEM_TABLE_ID" value is bigger than " + "8 bytes in size"); + return; + } + strncpy(mms->oem_table_id, value, len + 1); +} + static void microvm_machine_initfn(Object *obj) { MicrovmMachineState *mms = MICROVM_MACHINE(obj); @@ -669,6 +714,9 @@ static void microvm_machine_initfn(Object *obj) qemu_add_machine_init_done_notifier(&mms->machine_done); mms->powerdown_req.notify = microvm_powerdown_req; qemu_register_powerdown_notifier(&mms->powerdown_req); + + mms->oem_id = g_strndup(ACPI_BUILD_APPNAME6, 6); + mms->oem_table_id = g_strndup(ACPI_BUILD_APPNAME8, 8); } static void microvm_class_init(ObjectClass *oc, void *data) @@ -757,6 +805,24 @@ static void microvm_class_init(ObjectClass *oc, void *data) MICROVM_MACHINE_AUTO_KERNEL_CMDLINE, "Set off to disable adding virtio-mmio devices to the kernel cmdline"); + object_class_property_add_str(oc, MICROVM_MACHINE_OEM_ID, + microvm_machine_get_oem_id, + microvm_machine_set_oem_id); + object_class_property_set_description(oc, MICROVM_MACHINE_OEM_ID, + "Override the default value of field OEMID " + "in ACPI table header." + "The string may be up to 6 bytes in size"); + + + object_class_property_add_str(oc, MICROVM_MACHINE_OEM_TABLE_ID, + microvm_machine_get_oem_table_id, + microvm_machine_set_oem_table_id); + object_class_property_set_description(oc, MICROVM_MACHINE_OEM_TABLE_ID, + "Override the default value of field OEM Table ID " + "in ACPI table header." + "The string may be up to 8 bytes in size"); + + machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE); } diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 5458f61..437977c 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -1611,6 +1611,50 @@ static void pc_machine_set_max_fw_size(Object *obj, Visitor *v, pcms->max_fw_size = value; } +static char *pc_machine_get_oem_id(Object *obj, Error **errp) +{ + PCMachineState *pcms = PC_MACHINE(obj); + + return g_strdup(pcms->oem_id); +} + +static void pc_machine_set_oem_id(Object *obj, const char *value, Error **errp) +{ + PCMachineState *pcms = PC_MACHINE(obj); + size_t len = strlen(value); + + if (len > 6) { + error_setg(errp, + "User specified "PC_MACHINE_OEM_ID" value is bigger than " + "6 bytes in size"); + return; + } + + strncpy(pcms->oem_id, value, len + 1); +} + +static char *pc_machine_get_oem_table_id(Object *obj, Error **errp) +{ + PCMachineState *pcms = PC_MACHINE(obj); + + return g_strdup(pcms->oem_table_id); +} + +static void pc_machine_set_oem_table_id(Object *obj, const char *value, + Error **errp) +{ + PCMachineState *pcms = PC_MACHINE(obj); + size_t len = strlen(value); + + if (len > 8) { + error_setg(errp, + "User specified "PC_MACHINE_OEM_TABLE_ID" value is bigger than " + "8 bytes in size"); + return; + } + strncpy(pcms->oem_table_id, value, len + 1); +} + static void pc_machine_initfn(Object *obj) { PCMachineState *pcms = PC_MACHINE(obj); @@ -1623,6 +1667,8 @@ static void pc_machine_initfn(Object *obj) pcms->max_ram_below_4g = 0; /* use default */ /* acpi build is enabled by default if machine supports it */ pcms->acpi_build_enabled = PC_MACHINE_GET_CLASS(pcms)->has_acpi_build; + pcms->oem_id = g_strndup(ACPI_BUILD_APPNAME6, 6); + pcms->oem_table_id = g_strndup(ACPI_BUILD_APPNAME8, 8); pcms->smbus_enabled = true; pcms->sata_enabled = true; pcms->pit_enabled = true; @@ -1759,6 +1805,24 @@ static void pc_machine_class_init(ObjectClass *oc, void *data) NULL, NULL); object_class_property_set_description(oc, PC_MACHINE_MAX_FW_SIZE, "Maximum combined firmware size"); + + object_class_property_add_str(oc, PC_MACHINE_OEM_ID, + pc_machine_get_oem_id, + pc_machine_set_oem_id); + object_class_property_set_description(oc, PC_MACHINE_OEM_ID, + "Override the default value of field OEMID " + "in ACPI table header." + "The string may be up to 6 bytes in size"); + + + object_class_property_add_str(oc, PC_MACHINE_OEM_TABLE_ID, + pc_machine_get_oem_table_id, + pc_machine_set_oem_table_id); + object_class_property_set_description(oc, PC_MACHINE_OEM_TABLE_ID, + "Override the default value of field OEM Table ID " + "in ACPI table header." + "The string may be up to 8 bytes in size"); + } static const TypeInfo pc_machine_info = { -- cgit v1.1 From 43e229a52b464099afa9449aef587b9a3419b470 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Tue, 2 Feb 2021 17:52:53 -0500 Subject: acpi: use constants as strncpy limit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit gcc is not smart enough to figure out length was validated before use as strncpy limit, resulting in this warning: inlined from ‘virt_set_oem_table_id’ at ../../hw/arm/virt.c:2197:5: /usr/include/aarch64-linux-gnu/bits/string_fortified.h:106:10: error: ‘__builtin_strncpy’ specified bound depends on the length of the source argument [-Werror=stringop-overflow=] Simplify things by using a constant limit instead. Fixes: 97fc5d507fca ("acpi: Permit OEM ID and OEM table ID fields to be changed") Signed-off-by: Michael S. Tsirkin --- hw/arm/virt.c | 4 ++-- hw/i386/microvm.c | 4 ++-- hw/i386/pc.c | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'hw') diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 0c65fe3..371147f 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -2173,7 +2173,7 @@ static void virt_set_oem_id(Object *obj, const char *value, Error **errp) return; } - strncpy(vms->oem_id, value, len + 1); + strncpy(vms->oem_id, value, 6); } static char *virt_get_oem_table_id(Object *obj, Error **errp) @@ -2194,7 +2194,7 @@ static void virt_set_oem_table_id(Object *obj, const char *value, "User specified oem-table-id value is bigger than 8 bytes in size"); return; } - strncpy(vms->oem_table_id, value, len + 1); + strncpy(vms->oem_table_id, value, 8); } diff --git a/hw/i386/microvm.c b/hw/i386/microvm.c index 1dc2956..4e0cf4c 100644 --- a/hw/i386/microvm.c +++ b/hw/i386/microvm.c @@ -668,7 +668,7 @@ static void microvm_machine_set_oem_id(Object *obj, const char *value, return; } - strncpy(mms->oem_id, value, len + 1); + strncpy(mms->oem_id, value, 6); } static char *microvm_machine_get_oem_table_id(Object *obj, Error **errp) @@ -690,7 +690,7 @@ static void microvm_machine_set_oem_table_id(Object *obj, const char *value, "8 bytes in size"); return; } - strncpy(mms->oem_table_id, value, len + 1); + strncpy(mms->oem_table_id, value, 8); } static void microvm_machine_initfn(Object *obj) diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 437977c..8aa85de 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -1630,7 +1630,7 @@ static void pc_machine_set_oem_id(Object *obj, const char *value, Error **errp) return; } - strncpy(pcms->oem_id, value, len + 1); + strncpy(pcms->oem_id, value, 6); } static char *pc_machine_get_oem_table_id(Object *obj, Error **errp) @@ -1652,7 +1652,7 @@ static void pc_machine_set_oem_table_id(Object *obj, const char *value, "8 bytes in size"); return; } - strncpy(pcms->oem_table_id, value, len + 1); + strncpy(pcms->oem_table_id, value, 8); } static void pc_machine_initfn(Object *obj) -- cgit v1.1