hw/arm/virt: Add the virtio-iommu device tree mappings
Adds the "virtio,pci-iommu" node in the host bridge node and the RID mapping, excluding the IOMMU RID. This is done in the virtio-iommu-pci hotplug handler which gets called only if no firmware is loaded or if -no-acpi is passed on the command line. As non DT integration is not yet supported by the kernel we must make sure we are in DT mode. This limitation will be removed as soon as the topology description feature gets supported. Signed-off-by: Eric Auger <eric.auger@redhat.com> Message-Id: <20200214132745.23392-10-eric.auger@redhat.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com> Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
parent
8b4eb09e32
commit
70e89132c9
@ -32,6 +32,7 @@
|
||||
#include "qemu-common.h"
|
||||
#include "qemu/units.h"
|
||||
#include "qemu/option.h"
|
||||
#include "monitor/qdev.h"
|
||||
#include "qapi/error.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "hw/boards.h"
|
||||
@ -54,6 +55,7 @@
|
||||
#include "qemu/error-report.h"
|
||||
#include "qemu/module.h"
|
||||
#include "hw/pci-host/gpex.h"
|
||||
#include "hw/virtio/virtio-pci.h"
|
||||
#include "hw/arm/sysbus-fdt.h"
|
||||
#include "hw/platform-bus.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
@ -71,6 +73,7 @@
|
||||
#include "hw/mem/pc-dimm.h"
|
||||
#include "hw/mem/nvdimm.h"
|
||||
#include "hw/acpi/generic_event_device.h"
|
||||
#include "hw/virtio/virtio-iommu.h"
|
||||
|
||||
#define DEFINE_VIRT_MACHINE_LATEST(major, minor, latest) \
|
||||
static void virt_##major##_##minor##_class_init(ObjectClass *oc, \
|
||||
@ -1180,6 +1183,30 @@ static void create_smmu(const VirtMachineState *vms,
|
||||
g_free(node);
|
||||
}
|
||||
|
||||
static void create_virtio_iommu_dt_bindings(VirtMachineState *vms, Error **errp)
|
||||
{
|
||||
const char compat[] = "virtio,pci-iommu";
|
||||
uint16_t bdf = vms->virtio_iommu_bdf;
|
||||
char *node;
|
||||
|
||||
vms->iommu_phandle = qemu_fdt_alloc_phandle(vms->fdt);
|
||||
|
||||
node = g_strdup_printf("%s/virtio_iommu@%d", vms->pciehb_nodename, bdf);
|
||||
qemu_fdt_add_subnode(vms->fdt, node);
|
||||
qemu_fdt_setprop(vms->fdt, node, "compatible", compat, sizeof(compat));
|
||||
qemu_fdt_setprop_sized_cells(vms->fdt, node, "reg",
|
||||
1, bdf << 8, 1, 0, 1, 0,
|
||||
1, 0, 1, 0);
|
||||
|
||||
qemu_fdt_setprop_cell(vms->fdt, node, "#iommu-cells", 1);
|
||||
qemu_fdt_setprop_cell(vms->fdt, node, "phandle", vms->iommu_phandle);
|
||||
g_free(node);
|
||||
|
||||
qemu_fdt_setprop_cells(vms->fdt, vms->pciehb_nodename, "iommu-map",
|
||||
0x0, vms->iommu_phandle, 0x0, bdf,
|
||||
bdf + 1, vms->iommu_phandle, bdf + 1, 0xffff - bdf);
|
||||
}
|
||||
|
||||
static void create_pcie(VirtMachineState *vms)
|
||||
{
|
||||
hwaddr base_mmio = vms->memmap[VIRT_PCIE_MMIO].base;
|
||||
@ -1258,7 +1285,7 @@ static void create_pcie(VirtMachineState *vms)
|
||||
}
|
||||
}
|
||||
|
||||
nodename = g_strdup_printf("/pcie@%" PRIx64, base);
|
||||
nodename = vms->pciehb_nodename = g_strdup_printf("/pcie@%" PRIx64, base);
|
||||
qemu_fdt_add_subnode(vms->fdt, nodename);
|
||||
qemu_fdt_setprop_string(vms->fdt, nodename,
|
||||
"compatible", "pci-host-ecam-generic");
|
||||
@ -1301,13 +1328,16 @@ static void create_pcie(VirtMachineState *vms)
|
||||
if (vms->iommu) {
|
||||
vms->iommu_phandle = qemu_fdt_alloc_phandle(vms->fdt);
|
||||
|
||||
create_smmu(vms, pci->bus);
|
||||
|
||||
qemu_fdt_setprop_cells(vms->fdt, nodename, "iommu-map",
|
||||
0x0, vms->iommu_phandle, 0x0, 0x10000);
|
||||
switch (vms->iommu) {
|
||||
case VIRT_IOMMU_SMMUV3:
|
||||
create_smmu(vms, pci->bus);
|
||||
qemu_fdt_setprop_cells(vms->fdt, nodename, "iommu-map",
|
||||
0x0, vms->iommu_phandle, 0x0, 0x10000);
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
}
|
||||
|
||||
g_free(nodename);
|
||||
}
|
||||
|
||||
static void create_platform_bus(VirtMachineState *vms)
|
||||
@ -1976,6 +2006,13 @@ static void virt_machine_device_plug_cb(HotplugHandler *hotplug_dev,
|
||||
if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
|
||||
virt_memory_plug(hotplug_dev, dev, errp);
|
||||
}
|
||||
if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_IOMMU_PCI)) {
|
||||
PCIDevice *pdev = PCI_DEVICE(dev);
|
||||
|
||||
vms->iommu = VIRT_IOMMU_VIRTIO;
|
||||
vms->virtio_iommu_bdf = pci_get_bdf(pdev);
|
||||
create_virtio_iommu_dt_bindings(vms, errp);
|
||||
}
|
||||
}
|
||||
|
||||
static void virt_machine_device_unplug_request_cb(HotplugHandler *hotplug_dev,
|
||||
@ -1992,7 +2029,13 @@ static HotplugHandler *virt_machine_get_hotplug_handler(MachineState *machine,
|
||||
(object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM))) {
|
||||
return HOTPLUG_HANDLER(machine);
|
||||
}
|
||||
if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_IOMMU_PCI)) {
|
||||
VirtMachineState *vms = VIRT_MACHINE(machine);
|
||||
|
||||
if (!vms->bootinfo.firmware_loaded || !acpi_enabled) {
|
||||
return HOTPLUG_HANDLER(machine);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -125,8 +125,10 @@ typedef struct {
|
||||
bool virt;
|
||||
int32_t gic_version;
|
||||
VirtIOMMUType iommu;
|
||||
uint16_t virtio_iommu_bdf;
|
||||
struct arm_boot_info bootinfo;
|
||||
MemMapEntry *memmap;
|
||||
char *pciehb_nodename;
|
||||
const int *irqmap;
|
||||
int smp_cpus;
|
||||
void *fdt;
|
||||
|
Loading…
Reference in New Issue
Block a user