@samitouri / QOSamiQemu / commits / ee4d1ff3af

hw/arm/virt: Add virtio-mmio-transports property

Windows ARM64 guests detect virtio-mmio devices declared in ACPI tables even when no backend is attached. This causes "Unknown devices" (ACPI\LNRO0005) to appear in Device Manager. Until Windows fixes that by supporting, add a new machine property 'virtio-mmio-transports' to control the number of virtio-mmio transports instantiated. The default remains NUM_VIRTIO_TRANSPORTS (32) for backward compatibility. Setting it to 0 allows users to disable virtio-mmio entirely. Usage: -machine virt,virtio-mmio-transports=0 Signed-off-by: Mohammadfaiz Bawa <mbawa@redhat.com> Message-id: 20260219173256.152743-1-mbawa@redhat.com Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Mohammadfaiz Bawa committed Feb 26, 2026 at 11:27 UTC ee4d1ff3af85418a1dd946647658b954649e43ae
4 files changed +48 -3
docs/system/arm/virt.rst
+5
@@ -226,6 +226,11 @@ dtb-randomness
226 dtb-kaslr-seed
227 A deprecated synonym for dtb-randomness.
228
229 +virtio-mmio-transports
230 + Set the number of virtio-mmio transports to create (between 0 and 32;
231 + the default is 32). Unused transports are harmless, but you can
232 + use this property to avoid exposing them to the guest if you wish.
233 +
234 x-oem-id
235 Set string (up to 6 bytes) to override the default value of field OEMID in ACPI
236 table header.
hw/arm/virt-acpi-build.c
+1 -1
@@ -1154,7 +1154,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
1154 fw_cfg_acpi_dsdt_add(scope, &memmap[VIRT_FW_CFG]);
1155 virtio_acpi_dsdt_add(scope, memmap[VIRT_MMIO].base, memmap[VIRT_MMIO].size,
1156 (irqmap[VIRT_MMIO] + ARM_SPI_BASE),
1157 - 0, NUM_VIRTIO_TRANSPORTS);
1157 + 0, vms->virtio_transports);
1158 acpi_dsdt_add_pci(scope, memmap, irqmap[VIRT_PCIE] + ARM_SPI_BASE, vms);
1159 if (vms->acpi_dev) {
1160 build_ged_aml(scope, "\\_SB."GED_DEVICE,
hw/arm/virt.c
+41 -2
@@ -1208,7 +1208,7 @@ static void create_virtio_devices(const VirtMachineState *vms)
1208 * between kernel versions). For reliable and stable identification
1209 * of disks users must use UUIDs or similar mechanisms.
1210 */
1211 - for (i = 0; i < NUM_VIRTIO_TRANSPORTS; i++) {
1211 + for (i = 0; i < vms->virtio_transports; i++) {
1212 int irq = vms->irqmap[VIRT_MMIO] + i;
1213 hwaddr base = vms->memmap[VIRT_MMIO].base + i * size;
1214
@@ -1223,7 +1223,7 @@ static void create_virtio_devices(const VirtMachineState *vms)
1223 * loop influences virtio device to virtio transport assignment, whereas
1224 * this loop controls how virtio transports are laid out in the dtb.
1225 */
1226 - for (i = NUM_VIRTIO_TRANSPORTS - 1; i >= 0; i--) {
1226 + for (i = vms->virtio_transports - 1; i >= 0; i--) {
1227 char *nodename;
1228 int irq = vms->irqmap[VIRT_MMIO] + i;
1229 hwaddr base = vms->memmap[VIRT_MMIO].base + i * size;
@@ -2826,6 +2826,36 @@ static void virt_set_its(Object *obj, bool value, Error **errp)
2826 }
2827 }
2828
2829 +static void virt_get_virtio_transports(Object *obj, Visitor *v,
2830 + const char *name, void *opaque,
2831 + Error **errp)
2832 +{
2833 + VirtMachineState *vms = VIRT_MACHINE(obj);
2834 + uint8_t transports = vms->virtio_transports;
2835 +
2836 + visit_type_uint8(v, name, &transports, errp);
2837 +}
2838 +
2839 +static void virt_set_virtio_transports(Object *obj, Visitor *v,
2840 + const char *name, void *opaque,
2841 + Error **errp)
2842 +{
2843 + VirtMachineState *vms = VIRT_MACHINE(obj);
2844 + uint8_t transports;
2845 +
2846 + if (!visit_type_uint8(v, name, &transports, errp)) {
2847 + return;
2848 + }
2849 +
2850 + if (transports > NUM_VIRTIO_TRANSPORTS) {
2851 + error_setg(errp, "virtio-mmio-transports must not exceed %d",
2852 + NUM_VIRTIO_TRANSPORTS);
2853 + return;
2854 + }
2855 +
2856 + vms->virtio_transports = transports;
2857 +}
2858 +
2859 static bool virt_get_dtb_randomness(Object *obj, Error **errp)
2860 {
2861 VirtMachineState *vms = VIRT_MACHINE(obj);
@@ -3535,6 +3565,13 @@ static void virt_machine_class_init(ObjectClass *oc, const void *data)
3565 "Set the high memory region size "
3566 "for PCI MMIO");
3567
3568 + object_class_property_add(oc, "virtio-mmio-transports", "uint8",
3569 + virt_get_virtio_transports,
3570 + virt_set_virtio_transports,
3571 + NULL, NULL);
3572 + object_class_property_set_description(oc, "virtio-mmio-transports",
3573 + "Set the number of virtio-mmio transports to instantiate");
3574 +
3575 object_class_property_add_str(oc, "gic-version", virt_get_gic_version,
3576 virt_set_gic_version);
3577 object_class_property_set_description(oc, "gic-version",
@@ -3654,6 +3691,8 @@ static void virt_instance_init(Object *obj)
3691
3692 vms->irqmap = a15irqmap;
3693
3694 + vms->virtio_transports = NUM_VIRTIO_TRANSPORTS;
3695 +
3696 virt_flash_create(vms);
3697
3698 vms->oem_id = g_strndup(ACPI_BUILD_APPNAME6, 6);
include/hw/arm/virt.h
+1
@@ -172,6 +172,7 @@ struct VirtMachineState {
172 uint32_t msi_phandle;
173 uint32_t iommu_phandle;
174 int psci_conduit;
175 + uint8_t virtio_transports;
176 hwaddr highest_gpa;
177 DeviceState *gic;
178 DeviceState *acpi_dev;