mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-02 07:13:54 -06:00
hw/riscv/virt: Add IOMMU as platform device if the option is set
Add a new machine option called 'iommu-sys' that enables a riscv-iommu-sys platform device for the 'virt' machine. The option is default 'off'. The device will use IRQs 36 to 39. We will not support both riscv-iommu-sys and riscv-iommu-pci devices in the same board in this first implementation. If a riscv-iommu-pci device is added in the command line we will disable the riscv-iommu-sys device. Signed-off-by: Sunil V L <sunilvl@ventanamicro.com> Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20241106133407.604587-5-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
This commit is contained in:
parent
5b128435dc
commit
2c12de1460
3 changed files with 109 additions and 3 deletions
104
hw/riscv/virt.c
104
hw/riscv/virt.c
|
@ -33,6 +33,7 @@
|
|||
#include "target/riscv/pmu.h"
|
||||
#include "hw/riscv/riscv_hart.h"
|
||||
#include "hw/riscv/iommu.h"
|
||||
#include "hw/riscv/riscv-iommu-bits.h"
|
||||
#include "hw/riscv/virt.h"
|
||||
#include "hw/riscv/boot.h"
|
||||
#include "hw/riscv/numa.h"
|
||||
|
@ -76,6 +77,7 @@ static const MemMapEntry virt_memmap[] = {
|
|||
[VIRT_CLINT] = { 0x2000000, 0x10000 },
|
||||
[VIRT_ACLINT_SSWI] = { 0x2F00000, 0x4000 },
|
||||
[VIRT_PCIE_PIO] = { 0x3000000, 0x10000 },
|
||||
[VIRT_IOMMU_SYS] = { 0x3010000, 0x1000 },
|
||||
[VIRT_PLATFORM_BUS] = { 0x4000000, 0x2000000 },
|
||||
[VIRT_PLIC] = { 0xc000000, VIRT_PLIC_SIZE(VIRT_CPUS_MAX * 2) },
|
||||
[VIRT_APLIC_M] = { 0xc000000, APLIC_SIZE(VIRT_CPUS_MAX) },
|
||||
|
@ -853,7 +855,8 @@ static void create_fdt_virtio(RISCVVirtState *s, const MemMapEntry *memmap,
|
|||
|
||||
static void create_fdt_pcie(RISCVVirtState *s, const MemMapEntry *memmap,
|
||||
uint32_t irq_pcie_phandle,
|
||||
uint32_t msi_pcie_phandle)
|
||||
uint32_t msi_pcie_phandle,
|
||||
uint32_t iommu_sys_phandle)
|
||||
{
|
||||
g_autofree char *name = NULL;
|
||||
MachineState *ms = MACHINE(s);
|
||||
|
@ -887,6 +890,12 @@ static void create_fdt_pcie(RISCVVirtState *s, const MemMapEntry *memmap,
|
|||
2, virt_high_pcie_memmap.base,
|
||||
2, virt_high_pcie_memmap.base, 2, virt_high_pcie_memmap.size);
|
||||
|
||||
if (virt_is_iommu_sys_enabled(s)) {
|
||||
qemu_fdt_setprop_cells(ms->fdt, name, "iommu-map",
|
||||
0, iommu_sys_phandle, 0, 0, 0,
|
||||
iommu_sys_phandle, 0, 0xffff);
|
||||
}
|
||||
|
||||
create_pcie_irq_map(s, ms->fdt, name, irq_pcie_phandle);
|
||||
}
|
||||
|
||||
|
@ -1033,6 +1042,44 @@ static void create_fdt_virtio_iommu(RISCVVirtState *s, uint16_t bdf)
|
|||
bdf + 1, iommu_phandle, bdf + 1, 0xffff - bdf);
|
||||
}
|
||||
|
||||
static void create_fdt_iommu_sys(RISCVVirtState *s, uint32_t irq_chip,
|
||||
uint32_t *iommu_sys_phandle)
|
||||
{
|
||||
const char comp[] = "riscv,iommu";
|
||||
void *fdt = MACHINE(s)->fdt;
|
||||
uint32_t iommu_phandle;
|
||||
g_autofree char *iommu_node = NULL;
|
||||
hwaddr addr = s->memmap[VIRT_IOMMU_SYS].base;
|
||||
hwaddr size = s->memmap[VIRT_IOMMU_SYS].size;
|
||||
uint32_t iommu_irq_map[RISCV_IOMMU_INTR_COUNT] = {
|
||||
IOMMU_SYS_IRQ + RISCV_IOMMU_INTR_CQ,
|
||||
IOMMU_SYS_IRQ + RISCV_IOMMU_INTR_FQ,
|
||||
IOMMU_SYS_IRQ + RISCV_IOMMU_INTR_PM,
|
||||
IOMMU_SYS_IRQ + RISCV_IOMMU_INTR_PQ,
|
||||
};
|
||||
|
||||
iommu_node = g_strdup_printf("/soc/iommu@%x",
|
||||
(unsigned int) s->memmap[VIRT_IOMMU_SYS].base);
|
||||
iommu_phandle = qemu_fdt_alloc_phandle(fdt);
|
||||
qemu_fdt_add_subnode(fdt, iommu_node);
|
||||
|
||||
qemu_fdt_setprop(fdt, iommu_node, "compatible", comp, sizeof(comp));
|
||||
qemu_fdt_setprop_cell(fdt, iommu_node, "#iommu-cells", 1);
|
||||
qemu_fdt_setprop_cell(fdt, iommu_node, "phandle", iommu_phandle);
|
||||
|
||||
qemu_fdt_setprop_cells(fdt, iommu_node, "reg",
|
||||
addr >> 32, addr, size >> 32, size);
|
||||
qemu_fdt_setprop_cell(fdt, iommu_node, "interrupt-parent", irq_chip);
|
||||
|
||||
qemu_fdt_setprop_cells(fdt, iommu_node, "interrupts",
|
||||
iommu_irq_map[0], FDT_IRQ_TYPE_EDGE_LOW,
|
||||
iommu_irq_map[1], FDT_IRQ_TYPE_EDGE_LOW,
|
||||
iommu_irq_map[2], FDT_IRQ_TYPE_EDGE_LOW,
|
||||
iommu_irq_map[3], FDT_IRQ_TYPE_EDGE_LOW);
|
||||
|
||||
*iommu_sys_phandle = iommu_phandle;
|
||||
}
|
||||
|
||||
static void create_fdt_iommu(RISCVVirtState *s, uint16_t bdf)
|
||||
{
|
||||
const char comp[] = "riscv,pci-iommu";
|
||||
|
@ -1061,6 +1108,7 @@ static void finalize_fdt(RISCVVirtState *s)
|
|||
{
|
||||
uint32_t phandle = 1, irq_mmio_phandle = 1, msi_pcie_phandle = 1;
|
||||
uint32_t irq_pcie_phandle = 1, irq_virtio_phandle = 1;
|
||||
uint32_t iommu_sys_phandle = 1;
|
||||
|
||||
create_fdt_sockets(s, virt_memmap, &phandle, &irq_mmio_phandle,
|
||||
&irq_pcie_phandle, &irq_virtio_phandle,
|
||||
|
@ -1068,7 +1116,11 @@ static void finalize_fdt(RISCVVirtState *s)
|
|||
|
||||
create_fdt_virtio(s, virt_memmap, irq_virtio_phandle);
|
||||
|
||||
create_fdt_pcie(s, virt_memmap, irq_pcie_phandle, msi_pcie_phandle);
|
||||
if (virt_is_iommu_sys_enabled(s)) {
|
||||
create_fdt_iommu_sys(s, irq_mmio_phandle, &iommu_sys_phandle);
|
||||
}
|
||||
create_fdt_pcie(s, virt_memmap, irq_pcie_phandle, msi_pcie_phandle,
|
||||
iommu_sys_phandle);
|
||||
|
||||
create_fdt_reset(s, virt_memmap, &phandle);
|
||||
|
||||
|
@ -1648,6 +1700,22 @@ static void virt_machine_init(MachineState *machine)
|
|||
create_fdt(s, memmap);
|
||||
}
|
||||
|
||||
if (virt_is_iommu_sys_enabled(s)) {
|
||||
DeviceState *iommu_sys = qdev_new(TYPE_RISCV_IOMMU_SYS);
|
||||
|
||||
object_property_set_uint(OBJECT(iommu_sys), "addr",
|
||||
s->memmap[VIRT_IOMMU_SYS].base,
|
||||
&error_fatal);
|
||||
object_property_set_uint(OBJECT(iommu_sys), "base-irq",
|
||||
IOMMU_SYS_IRQ,
|
||||
&error_fatal);
|
||||
object_property_set_link(OBJECT(iommu_sys), "irqchip",
|
||||
OBJECT(mmio_irqchip),
|
||||
&error_fatal);
|
||||
|
||||
sysbus_realize_and_unref(SYS_BUS_DEVICE(iommu_sys), &error_fatal);
|
||||
}
|
||||
|
||||
s->machine_done.notify = virt_machine_done;
|
||||
qemu_add_machine_init_done_notifier(&s->machine_done);
|
||||
}
|
||||
|
@ -1661,6 +1729,7 @@ static void virt_machine_instance_init(Object *obj)
|
|||
s->oem_id = g_strndup(ACPI_BUILD_APPNAME6, 6);
|
||||
s->oem_table_id = g_strndup(ACPI_BUILD_APPNAME8, 8);
|
||||
s->acpi = ON_OFF_AUTO_AUTO;
|
||||
s->iommu_sys = ON_OFF_AUTO_AUTO;
|
||||
}
|
||||
|
||||
static char *virt_get_aia_guests(Object *obj, Error **errp)
|
||||
|
@ -1733,6 +1802,28 @@ static void virt_set_aclint(Object *obj, bool value, Error **errp)
|
|||
s->have_aclint = value;
|
||||
}
|
||||
|
||||
bool virt_is_iommu_sys_enabled(RISCVVirtState *s)
|
||||
{
|
||||
return s->iommu_sys == ON_OFF_AUTO_ON;
|
||||
}
|
||||
|
||||
static void virt_get_iommu_sys(Object *obj, Visitor *v, const char *name,
|
||||
void *opaque, Error **errp)
|
||||
{
|
||||
RISCVVirtState *s = RISCV_VIRT_MACHINE(obj);
|
||||
OnOffAuto iommu_sys = s->iommu_sys;
|
||||
|
||||
visit_type_OnOffAuto(v, name, &iommu_sys, errp);
|
||||
}
|
||||
|
||||
static void virt_set_iommu_sys(Object *obj, Visitor *v, const char *name,
|
||||
void *opaque, Error **errp)
|
||||
{
|
||||
RISCVVirtState *s = RISCV_VIRT_MACHINE(obj);
|
||||
|
||||
visit_type_OnOffAuto(v, name, &s->iommu_sys, errp);
|
||||
}
|
||||
|
||||
bool virt_is_acpi_enabled(RISCVVirtState *s)
|
||||
{
|
||||
return s->acpi != ON_OFF_AUTO_OFF;
|
||||
|
@ -1759,10 +1850,12 @@ static HotplugHandler *virt_machine_get_hotplug_handler(MachineState *machine,
|
|||
DeviceState *dev)
|
||||
{
|
||||
MachineClass *mc = MACHINE_GET_CLASS(machine);
|
||||
RISCVVirtState *s = RISCV_VIRT_MACHINE(machine);
|
||||
|
||||
if (device_is_dynamic_sysbus(mc, dev) ||
|
||||
object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_IOMMU_PCI) ||
|
||||
object_dynamic_cast(OBJECT(dev), TYPE_RISCV_IOMMU_PCI)) {
|
||||
s->iommu_sys = ON_OFF_AUTO_OFF;
|
||||
return HOTPLUG_HANDLER(machine);
|
||||
}
|
||||
|
||||
|
@ -1789,6 +1882,7 @@ static void virt_machine_device_plug_cb(HotplugHandler *hotplug_dev,
|
|||
|
||||
if (object_dynamic_cast(OBJECT(dev), TYPE_RISCV_IOMMU_PCI)) {
|
||||
create_fdt_iommu(s, pci_get_bdf(PCI_DEVICE(dev)));
|
||||
s->iommu_sys = ON_OFF_AUTO_OFF;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1851,6 +1945,12 @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
|
|||
NULL, NULL);
|
||||
object_class_property_set_description(oc, "acpi",
|
||||
"Enable ACPI");
|
||||
|
||||
object_class_property_add(oc, "iommu-sys", "OnOffAuto",
|
||||
virt_get_iommu_sys, virt_set_iommu_sys,
|
||||
NULL, NULL);
|
||||
object_class_property_set_description(oc, "iommu-sys",
|
||||
"Enable IOMMU platform device");
|
||||
}
|
||||
|
||||
static const TypeInfo virt_machine_typeinfo = {
|
||||
|
|
|
@ -37,4 +37,6 @@ typedef struct RISCVIOMMUStatePci RISCVIOMMUStatePci;
|
|||
OBJECT_DECLARE_SIMPLE_TYPE(RISCVIOMMUStateSys, RISCV_IOMMU_SYS)
|
||||
typedef struct RISCVIOMMUStateSys RISCVIOMMUStateSys;
|
||||
|
||||
#define FDT_IRQ_TYPE_EDGE_LOW 1
|
||||
|
||||
#endif
|
||||
|
|
|
@ -62,6 +62,7 @@ struct RISCVVirtState {
|
|||
OnOffAuto acpi;
|
||||
const MemMapEntry *memmap;
|
||||
struct GPEXHost *gpex_host;
|
||||
OnOffAuto iommu_sys;
|
||||
};
|
||||
|
||||
enum {
|
||||
|
@ -84,7 +85,8 @@ enum {
|
|||
VIRT_PCIE_MMIO,
|
||||
VIRT_PCIE_PIO,
|
||||
VIRT_PLATFORM_BUS,
|
||||
VIRT_PCIE_ECAM
|
||||
VIRT_PCIE_ECAM,
|
||||
VIRT_IOMMU_SYS,
|
||||
};
|
||||
|
||||
enum {
|
||||
|
@ -93,6 +95,7 @@ enum {
|
|||
VIRTIO_IRQ = 1, /* 1 to 8 */
|
||||
VIRTIO_COUNT = 8,
|
||||
PCIE_IRQ = 0x20, /* 32 to 35 */
|
||||
IOMMU_SYS_IRQ = 0x24, /* 36-39 */
|
||||
VIRT_PLATFORM_BUS_IRQ = 64, /* 64 to 95 */
|
||||
};
|
||||
|
||||
|
@ -129,6 +132,7 @@ enum {
|
|||
1 + FDT_APLIC_INT_CELLS)
|
||||
|
||||
bool virt_is_acpi_enabled(RISCVVirtState *s);
|
||||
bool virt_is_iommu_sys_enabled(RISCVVirtState *s);
|
||||
void virt_acpi_setup(RISCVVirtState *vms);
|
||||
uint32_t imsic_num_bits(uint32_t count);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue