- kvm-io-move-websock-resource-release-to-close-method.patch [RHEL-120116] - kvm-io-fix-use-after-free-in-websocket-handshake-code.patch [RHEL-120116] - kvm-vfio-Disable-VFIO-migration-with-MultiFD-support.patch [RHEL-126573] - kvm-hw-arm-virt-Use-ACPI-PCI-hotplug-by-default-from-10..patch [RHEL-67323] - kvm-hw-arm-smmu-common-Check-SMMU-has-PCIe-Root-Complex-.patch [RHEL-73800] - kvm-hw-arm-virt-acpi-build-Re-arrange-SMMUv3-IORT-build.patch [RHEL-73800] - kvm-hw-arm-virt-acpi-build-Update-IORT-for-multiple-smmu.patch [RHEL-73800] - kvm-hw-arm-virt-Factor-out-common-SMMUV3-dt-bindings-cod.patch [RHEL-73800] - kvm-hw-arm-virt-Add-an-SMMU_IO_LEN-macro.patch [RHEL-73800] - kvm-hw-pci-Introduce-pci_setup_iommu_per_bus-for-per-bus.patch [RHEL-73800] - kvm-hw-arm-virt-Allow-user-creatable-SMMUv3-dev-instanti.patch [RHEL-73800] - kvm-qemu-options.hx-Document-the-arm-smmuv3-device.patch [RHEL-73800] - kvm-bios-tables-test-Allow-for-smmuv3-test-data.patch [RHEL-73800] - kvm-qtest-bios-tables-test-Add-tests-for-legacy-smmuv3-a.patch [RHEL-73800] - kvm-qtest-bios-tables-test-Update-tables-for-smmuv3-test.patch [RHEL-73800] - kvm-qtest-Do-not-run-bios-tables-test-on-aarch64.patch [] - Resolves: RHEL-120116 (CVE-2025-11234 qemu-kvm: VNC WebSocket handshake use-after-free [rhel-10.2]) - Resolves: RHEL-126573 (VFIO migration using multifd should be disabled by default) - Resolves: RHEL-67323 ([aarch64] Support ACPI based PCI hotplug on ARM) - Resolves: RHEL-73800 (NVIDIA:Grace-Hopper:Backport support for user-creatable nested SMMUv3 - RHEL 10.1)
216 lines
8.5 KiB
Diff
216 lines
8.5 KiB
Diff
From 20b24c8ae68ff5059392188762c8d8b24c3dfa28 Mon Sep 17 00:00:00 2001
|
||
From: Shameer Kolothum <skolothumtho@nvidia.com>
|
||
Date: Fri, 29 Aug 2025 09:25:29 +0100
|
||
Subject: [PATCH 11/16] hw/arm/virt: Allow user-creatable SMMUv3 dev
|
||
instantiation
|
||
MIME-Version: 1.0
|
||
Content-Type: text/plain; charset=UTF-8
|
||
Content-Transfer-Encoding: 8bit
|
||
|
||
RH-Author: Eric Auger <eric.auger@redhat.com>
|
||
RH-MergeRequest: 423: hw/arm/virt: Add support for user creatable SMMUv3 device
|
||
RH-Jira: RHEL-73800
|
||
RH-Acked-by: Gavin Shan <gshan@redhat.com>
|
||
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
||
RH-Acked-by: Sebastian Ott <sebott@redhat.com>
|
||
RH-Acked-by: Donald Dutile <None>
|
||
RH-Commit: [7/11] 8f4a03c34d5c699023b3916f4919caf669f7a87c (eauger1/centos-qemu-kvm)
|
||
|
||
Allow cold-plugging of an SMMUv3 device on the virt machine when no
|
||
global (legacy) SMMUv3 is present or when a virtio-iommu is specified.
|
||
|
||
This user-created SMMUv3 device is tied to a specific PCI bus provided
|
||
by the user, so ensure the IOMMU ops are configured accordingly.
|
||
|
||
Due to current limitations in QEMU’s device tree support, specifically
|
||
its inability to properly present pxb-pcie based root complexes and
|
||
their devices, the device tree support for the new SMMUv3 device is
|
||
limited to cases where it is attached to the default pcie.0 root complex.
|
||
|
||
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
|
||
Reviewed-by: Eric Auger <eric.auger@redhat.com>
|
||
Tested-by: Nathan Chen <nathanc@nvidia.com>
|
||
Tested-by: Eric Auger <eric.auger@redhat.com>
|
||
Tested-by: Nicolin Chen <nicolinc@nvidia.com>
|
||
Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
|
||
Signed-off-by: Shameer Kolothum <skolothumtho@nvidia.com>
|
||
Reviewed-by: Donald Dutile <ddutile@redhat.com>
|
||
Reviewed-by: Nicolin Chen <nicolinc@nvidia.com>
|
||
Message-id: 20250829082543.7680-8-skolothumtho@nvidia.com
|
||
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
|
||
(cherry picked from commit 66d2f665e163cf1afccd171e3c16f8d3acb3d94a)
|
||
Signed-off-by: Eric Auger <eric.auger@redhat.com>
|
||
---
|
||
hw/arm/smmu-common.c | 8 +++++-
|
||
hw/arm/smmuv3.c | 2 ++
|
||
hw/arm/virt.c | 51 ++++++++++++++++++++++++++++++++++++
|
||
hw/core/sysbus-fdt.c | 3 +++
|
||
include/hw/arm/smmu-common.h | 1 +
|
||
5 files changed, 64 insertions(+), 1 deletion(-)
|
||
|
||
diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
|
||
index 7f64ea48d0..62a7612184 100644
|
||
--- a/hw/arm/smmu-common.c
|
||
+++ b/hw/arm/smmu-common.c
|
||
@@ -961,7 +961,12 @@ static void smmu_base_realize(DeviceState *dev, Error **errp)
|
||
goto out_err;
|
||
}
|
||
}
|
||
- pci_setup_iommu(pci_bus, &smmu_ops, s);
|
||
+
|
||
+ if (s->smmu_per_bus) {
|
||
+ pci_setup_iommu_per_bus(pci_bus, &smmu_ops, s);
|
||
+ } else {
|
||
+ pci_setup_iommu(pci_bus, &smmu_ops, s);
|
||
+ }
|
||
return;
|
||
}
|
||
out_err:
|
||
@@ -986,6 +991,7 @@ static void smmu_base_reset_exit(Object *obj, ResetType type)
|
||
|
||
static const Property smmu_dev_properties[] = {
|
||
DEFINE_PROP_UINT8("bus_num", SMMUState, bus_num, 0),
|
||
+ DEFINE_PROP_BOOL("smmu_per_bus", SMMUState, smmu_per_bus, false),
|
||
DEFINE_PROP_LINK("primary-bus", SMMUState, primary_bus,
|
||
TYPE_PCI_BUS, PCIBus *),
|
||
};
|
||
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
|
||
index ab67972353..bcf8af8dc7 100644
|
||
--- a/hw/arm/smmuv3.c
|
||
+++ b/hw/arm/smmuv3.c
|
||
@@ -1996,6 +1996,8 @@ static void smmuv3_class_init(ObjectClass *klass, const void *data)
|
||
device_class_set_parent_realize(dc, smmu_realize,
|
||
&c->parent_realize);
|
||
device_class_set_props(dc, smmuv3_properties);
|
||
+ dc->hotpluggable = false;
|
||
+ dc->user_creatable = true;
|
||
}
|
||
|
||
static int smmuv3_notify_flag_changed(IOMMUMemoryRegion *iommu,
|
||
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
|
||
index b435efafe1..e8e64fe7fe 100644
|
||
--- a/hw/arm/virt.c
|
||
+++ b/hw/arm/virt.c
|
||
@@ -56,6 +56,7 @@
|
||
#include "qemu/cutils.h"
|
||
#include "qemu/error-report.h"
|
||
#include "qemu/module.h"
|
||
+#include "hw/pci/pci_bus.h"
|
||
#include "hw/pci-host/gpex.h"
|
||
#include "hw/pci-bridge/pci_expander_bridge.h"
|
||
#include "hw/virtio/virtio-pci.h"
|
||
@@ -1510,6 +1511,29 @@ static void create_smmuv3_dt_bindings(const VirtMachineState *vms, hwaddr base,
|
||
g_free(node);
|
||
}
|
||
|
||
+static void create_smmuv3_dev_dtb(VirtMachineState *vms,
|
||
+ DeviceState *dev, PCIBus *bus)
|
||
+{
|
||
+ PlatformBusDevice *pbus = PLATFORM_BUS_DEVICE(vms->platform_bus_dev);
|
||
+ SysBusDevice *sbdev = SYS_BUS_DEVICE(dev);
|
||
+ int irq = platform_bus_get_irqn(pbus, sbdev, 0);
|
||
+ hwaddr base = platform_bus_get_mmio_addr(pbus, sbdev, 0);
|
||
+ MachineState *ms = MACHINE(vms);
|
||
+
|
||
+ if (!(vms->bootinfo.firmware_loaded && virt_is_acpi_enabled(vms)) &&
|
||
+ strcmp("pcie.0", bus->qbus.name)) {
|
||
+ warn_report("SMMUv3 device only supported with pcie.0 for DT");
|
||
+ return;
|
||
+ }
|
||
+ base += vms->memmap[VIRT_PLATFORM_BUS].base;
|
||
+ irq += vms->irqmap[VIRT_PLATFORM_BUS];
|
||
+
|
||
+ vms->iommu_phandle = qemu_fdt_alloc_phandle(ms->fdt);
|
||
+ create_smmuv3_dt_bindings(vms, base, SMMU_IO_LEN, irq);
|
||
+ qemu_fdt_setprop_cells(ms->fdt, vms->pciehb_nodename, "iommu-map",
|
||
+ 0x0, vms->iommu_phandle, 0x0, 0x10000);
|
||
+}
|
||
+
|
||
static void create_smmu(const VirtMachineState *vms,
|
||
PCIBus *bus)
|
||
{
|
||
@@ -3057,6 +3081,16 @@ static void virt_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev,
|
||
qlist_append_str(reserved_regions, resv_prop_str);
|
||
qdev_prop_set_array(dev, "reserved-regions", reserved_regions);
|
||
g_free(resv_prop_str);
|
||
+ } else if (object_dynamic_cast(OBJECT(dev), TYPE_ARM_SMMUV3)) {
|
||
+ if (vms->legacy_smmuv3_present || vms->iommu == VIRT_IOMMU_VIRTIO) {
|
||
+ error_setg(errp, "virt machine already has %s set. "
|
||
+ "Doesn't support incompatible iommus",
|
||
+ (vms->legacy_smmuv3_present) ?
|
||
+ "iommu=smmuv3" : "virtio-iommu");
|
||
+ } else if (vms->iommu == VIRT_IOMMU_NONE) {
|
||
+ /* The new SMMUv3 device is specific to the PCI bus */
|
||
+ object_property_set_bool(OBJECT(dev), "smmu_per_bus", true, NULL);
|
||
+ }
|
||
}
|
||
}
|
||
|
||
@@ -3080,6 +3114,22 @@ static void virt_machine_device_plug_cb(HotplugHandler *hotplug_dev,
|
||
virtio_md_pci_plug(VIRTIO_MD_PCI(dev), MACHINE(hotplug_dev), errp);
|
||
}
|
||
|
||
+ if (object_dynamic_cast(OBJECT(dev), TYPE_ARM_SMMUV3)) {
|
||
+ if (!vms->legacy_smmuv3_present && vms->platform_bus_dev) {
|
||
+ PCIBus *bus;
|
||
+
|
||
+ bus = PCI_BUS(object_property_get_link(OBJECT(dev), "primary-bus",
|
||
+ &error_abort));
|
||
+ if (pci_bus_bypass_iommu(bus)) {
|
||
+ error_setg(errp, "Bypass option cannot be set for SMMUv3 "
|
||
+ "associated PCIe RC");
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ create_smmuv3_dev_dtb(vms, dev, bus);
|
||
+ }
|
||
+ }
|
||
+
|
||
if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_IOMMU_PCI)) {
|
||
PCIDevice *pdev = PCI_DEVICE(dev);
|
||
|
||
@@ -3286,6 +3336,7 @@ static void virt_machine_class_init(ObjectClass *oc, const void *data)
|
||
#endif
|
||
machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE);
|
||
machine_class_allow_dynamic_sysbus_dev(mc, TYPE_UEFI_VARS_SYSBUS);
|
||
+ machine_class_allow_dynamic_sysbus_dev(mc, TYPE_ARM_SMMUV3);
|
||
#ifdef CONFIG_TPM
|
||
machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_TIS_SYSBUS);
|
||
#endif
|
||
diff --git a/hw/core/sysbus-fdt.c b/hw/core/sysbus-fdt.c
|
||
index 1e1966813f..673e083d31 100644
|
||
--- a/hw/core/sysbus-fdt.c
|
||
+++ b/hw/core/sysbus-fdt.c
|
||
@@ -31,6 +31,7 @@
|
||
#include "qemu/error-report.h"
|
||
#include "system/device_tree.h"
|
||
#include "system/tpm.h"
|
||
+#include "hw/arm/smmuv3.h"
|
||
#include "hw/platform-bus.h"
|
||
#include "hw/vfio/vfio-platform.h"
|
||
#include "hw/vfio/vfio-calxeda-xgmac.h"
|
||
@@ -518,6 +519,8 @@ static const BindingEntry bindings[] = {
|
||
#ifdef CONFIG_TPM
|
||
TYPE_BINDING(TYPE_TPM_TIS_SYSBUS, add_tpm_tis_fdt_node),
|
||
#endif
|
||
+ /* No generic DT support for smmuv3 dev. Support added for arm virt only */
|
||
+ TYPE_BINDING(TYPE_ARM_SMMUV3, no_fdt_node),
|
||
TYPE_BINDING(TYPE_RAMFB_DEVICE, no_fdt_node),
|
||
TYPE_BINDING(TYPE_UEFI_VARS_SYSBUS, add_uefi_vars_node),
|
||
TYPE_BINDING("", NULL), /* last element */
|
||
diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h
|
||
index e5e2d09294..80d0fecfde 100644
|
||
--- a/include/hw/arm/smmu-common.h
|
||
+++ b/include/hw/arm/smmu-common.h
|
||
@@ -161,6 +161,7 @@ struct SMMUState {
|
||
QLIST_HEAD(, SMMUDevice) devices_with_notifiers;
|
||
uint8_t bus_num;
|
||
PCIBus *primary_bus;
|
||
+ bool smmu_per_bus; /* SMMU is specific to the primary_bus */
|
||
};
|
||
|
||
struct SMMUBaseClass {
|
||
--
|
||
2.47.3
|
||
|