diff options
Diffstat (limited to 'hw/arm/virt.c')
| -rw-r--r-- | hw/arm/virt.c | 99 |
1 files changed, 83 insertions, 16 deletions
diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 73113cfc4d..c5c125e920 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -42,6 +42,7 @@ #include "sysemu/sysemu.h" #include "sysemu/kvm.h" #include "hw/boards.h" +#include "hw/compat.h" #include "hw/loader.h" #include "exec/address-spaces.h" #include "qemu/bitops.h" @@ -98,6 +99,36 @@ typedef struct { #define VIRT_MACHINE_CLASS(klass) \ OBJECT_CLASS_CHECK(VirtMachineClass, klass, TYPE_VIRT_MACHINE) + +#define DEFINE_VIRT_MACHINE_LATEST(major, minor, latest) \ + static void virt_##major##_##minor##_class_init(ObjectClass *oc, \ + void *data) \ + { \ + MachineClass *mc = MACHINE_CLASS(oc); \ + virt_machine_##major##_##minor##_options(mc); \ + mc->desc = "QEMU " # major "." # minor " ARM Virtual Machine"; \ + if (latest) { \ + mc->alias = "virt"; \ + } \ + } \ + static const TypeInfo machvirt_##major##_##minor##_info = { \ + .name = MACHINE_TYPE_NAME("virt-" # major "." # minor), \ + .parent = TYPE_VIRT_MACHINE, \ + .instance_init = virt_##major##_##minor##_instance_init, \ + .class_init = virt_##major##_##minor##_class_init, \ + }; \ + static void machvirt_machine_##major##_##minor##_init(void) \ + { \ + type_register_static(&machvirt_##major##_##minor##_info); \ + } \ + type_init(machvirt_machine_##major##_##minor##_init); + +#define DEFINE_VIRT_MACHINE_AS_LATEST(major, minor) \ + DEFINE_VIRT_MACHINE_LATEST(major, minor, true) +#define DEFINE_VIRT_MACHINE(major, minor) \ + DEFINE_VIRT_MACHINE_LATEST(major, minor, false) + + /* RAM limit in GB. Since VIRT_MEM starts at the 1GB mark, this means * RAM can go up to the 256GB mark, leaving 256GB of the physical * address space unallocated and free for future use between 256G and 512G. @@ -436,6 +467,37 @@ static void fdt_add_gic_node(VirtBoardInfo *vbi, int type) qemu_fdt_setprop_cell(vbi->fdt, "/intc", "phandle", vbi->gic_phandle); } +static void fdt_add_pmu_nodes(const VirtBoardInfo *vbi, int gictype) +{ + CPUState *cpu; + ARMCPU *armcpu; + uint32_t irqflags = GIC_FDT_IRQ_FLAGS_LEVEL_HI; + + CPU_FOREACH(cpu) { + armcpu = ARM_CPU(cpu); + if (!armcpu->has_pmu || + !kvm_arm_pmu_create(cpu, PPI(VIRTUAL_PMU_IRQ))) { + return; + } + } + + if (gictype == 2) { + irqflags = deposit32(irqflags, GIC_FDT_IRQ_PPI_CPU_START, + GIC_FDT_IRQ_PPI_CPU_WIDTH, + (1 << vbi->smp_cpus) - 1); + } + + armcpu = ARM_CPU(qemu_get_cpu(0)); + qemu_fdt_add_subnode(vbi->fdt, "/pmu"); + if (arm_feature(&armcpu->env, ARM_FEATURE_V8)) { + const char compat[] = "arm,armv8-pmuv3"; + qemu_fdt_setprop(vbi->fdt, "/pmu", "compatible", + compat, sizeof(compat)); + qemu_fdt_setprop_cells(vbi->fdt, "/pmu", "interrupts", + GIC_FDT_IRQ_TYPE_PPI, VIRTUAL_PMU_IRQ, irqflags); + } +} + static void create_v2m(VirtBoardInfo *vbi, qemu_irq *pic) { int i; @@ -1259,6 +1321,8 @@ static void machvirt_init(MachineState *machine) create_gic(vbi, pic, gic_version, vms->secure); + fdt_add_pmu_nodes(vbi, gic_version); + create_uart(vbi, pic, VIRT_UART, sysmem, serial_hds[0]); if (vms->secure) { @@ -1387,7 +1451,13 @@ static const TypeInfo virt_machine_info = { .class_init = virt_machine_class_init, }; -static void virt_2_6_instance_init(Object *obj) +static void machvirt_machine_init(void) +{ + type_register_static(&virt_machine_info); +} +type_init(machvirt_machine_init); + +static void virt_2_7_instance_init(Object *obj) { VirtMachineState *vms = VIRT_MACHINE(obj); @@ -1420,25 +1490,22 @@ static void virt_2_6_instance_init(Object *obj) "Valid values are 2, 3 and host", NULL); } -static void virt_2_6_class_init(ObjectClass *oc, void *data) +static void virt_machine_2_7_options(MachineClass *mc) { - MachineClass *mc = MACHINE_CLASS(oc); - - mc->desc = "QEMU 2.6 ARM Virtual Machine"; - mc->alias = "virt"; } +DEFINE_VIRT_MACHINE_AS_LATEST(2, 7) -static const TypeInfo machvirt_info = { - .name = MACHINE_TYPE_NAME("virt-2.6"), - .parent = TYPE_VIRT_MACHINE, - .instance_init = virt_2_6_instance_init, - .class_init = virt_2_6_class_init, -}; +#define VIRT_COMPAT_2_6 \ + HW_COMPAT_2_6 -static void machvirt_machine_init(void) +static void virt_2_6_instance_init(Object *obj) { - type_register_static(&virt_machine_info); - type_register_static(&machvirt_info); + virt_2_7_instance_init(obj); } -type_init(machvirt_machine_init); +static void virt_machine_2_6_options(MachineClass *mc) +{ + virt_machine_2_7_options(mc); + SET_MACHINE_COMPAT(mc, VIRT_COMPAT_2_6); +} +DEFINE_VIRT_MACHINE(2, 6) |