提交 55ef3233 编写于 作者: L Luc Michel 提交者: Peter Maydell

arm/virt: Add support for GICv2 virtualization extensions

Add support for GICv2 virtualization extensions by mapping the necessary
I/O regions and connecting the maintenance IRQ lines.

Declare those additions in the device tree and in the ACPI tables.
Signed-off-by: NLuc Michel <luc.michel@greensocs.com>
Reviewed-by: NPeter Maydell <peter.maydell@linaro.org>
Message-id: 20180727095421.386-21-luc.michel@greensocs.com
Signed-off-by: NPeter Maydell <peter.maydell@linaro.org>
上级 75b749af
...@@ -659,6 +659,8 @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) ...@@ -659,6 +659,8 @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
gicc->length = sizeof(*gicc); gicc->length = sizeof(*gicc);
if (vms->gic_version == 2) { if (vms->gic_version == 2) {
gicc->base_address = cpu_to_le64(memmap[VIRT_GIC_CPU].base); gicc->base_address = cpu_to_le64(memmap[VIRT_GIC_CPU].base);
gicc->gich_base_address = cpu_to_le64(memmap[VIRT_GIC_HYP].base);
gicc->gicv_base_address = cpu_to_le64(memmap[VIRT_GIC_VCPU].base);
} }
gicc->cpu_interface_number = cpu_to_le32(i); gicc->cpu_interface_number = cpu_to_le32(i);
gicc->arm_mpidr = cpu_to_le64(armcpu->mp_affinity); gicc->arm_mpidr = cpu_to_le64(armcpu->mp_affinity);
...@@ -668,8 +670,8 @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) ...@@ -668,8 +670,8 @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
if (arm_feature(&armcpu->env, ARM_FEATURE_PMU)) { if (arm_feature(&armcpu->env, ARM_FEATURE_PMU)) {
gicc->performance_interrupt = cpu_to_le32(PPI(VIRTUAL_PMU_IRQ)); gicc->performance_interrupt = cpu_to_le32(PPI(VIRTUAL_PMU_IRQ));
} }
if (vms->virt && vms->gic_version == 3) { if (vms->virt) {
gicc->vgic_interrupt = cpu_to_le32(PPI(ARCH_GICV3_MAINT_IRQ)); gicc->vgic_interrupt = cpu_to_le32(PPI(ARCH_GIC_MAINT_IRQ));
} }
} }
......
...@@ -131,6 +131,8 @@ static const MemMapEntry a15memmap[] = { ...@@ -131,6 +131,8 @@ static const MemMapEntry a15memmap[] = {
[VIRT_GIC_DIST] = { 0x08000000, 0x00010000 }, [VIRT_GIC_DIST] = { 0x08000000, 0x00010000 },
[VIRT_GIC_CPU] = { 0x08010000, 0x00010000 }, [VIRT_GIC_CPU] = { 0x08010000, 0x00010000 },
[VIRT_GIC_V2M] = { 0x08020000, 0x00001000 }, [VIRT_GIC_V2M] = { 0x08020000, 0x00001000 },
[VIRT_GIC_HYP] = { 0x08030000, 0x00010000 },
[VIRT_GIC_VCPU] = { 0x08040000, 0x00010000 },
/* The space in between here is reserved for GICv3 CPU/vCPU/HYP */ /* The space in between here is reserved for GICv3 CPU/vCPU/HYP */
[VIRT_GIC_ITS] = { 0x08080000, 0x00020000 }, [VIRT_GIC_ITS] = { 0x08080000, 0x00020000 },
/* This redistributor space allows up to 2*64kB*123 CPUs */ /* This redistributor space allows up to 2*64kB*123 CPUs */
...@@ -440,18 +442,33 @@ static void fdt_add_gic_node(VirtMachineState *vms) ...@@ -440,18 +442,33 @@ static void fdt_add_gic_node(VirtMachineState *vms)
if (vms->virt) { if (vms->virt) {
qemu_fdt_setprop_cells(vms->fdt, nodename, "interrupts", qemu_fdt_setprop_cells(vms->fdt, nodename, "interrupts",
GIC_FDT_IRQ_TYPE_PPI, ARCH_GICV3_MAINT_IRQ, GIC_FDT_IRQ_TYPE_PPI, ARCH_GIC_MAINT_IRQ,
GIC_FDT_IRQ_FLAGS_LEVEL_HI); GIC_FDT_IRQ_FLAGS_LEVEL_HI);
} }
} else { } else {
/* 'cortex-a15-gic' means 'GIC v2' */ /* 'cortex-a15-gic' means 'GIC v2' */
qemu_fdt_setprop_string(vms->fdt, nodename, "compatible", qemu_fdt_setprop_string(vms->fdt, nodename, "compatible",
"arm,cortex-a15-gic"); "arm,cortex-a15-gic");
qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg", if (!vms->virt) {
2, vms->memmap[VIRT_GIC_DIST].base, qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg",
2, vms->memmap[VIRT_GIC_DIST].size, 2, vms->memmap[VIRT_GIC_DIST].base,
2, vms->memmap[VIRT_GIC_CPU].base, 2, vms->memmap[VIRT_GIC_DIST].size,
2, vms->memmap[VIRT_GIC_CPU].size); 2, vms->memmap[VIRT_GIC_CPU].base,
2, vms->memmap[VIRT_GIC_CPU].size);
} else {
qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg",
2, vms->memmap[VIRT_GIC_DIST].base,
2, vms->memmap[VIRT_GIC_DIST].size,
2, vms->memmap[VIRT_GIC_CPU].base,
2, vms->memmap[VIRT_GIC_CPU].size,
2, vms->memmap[VIRT_GIC_HYP].base,
2, vms->memmap[VIRT_GIC_HYP].size,
2, vms->memmap[VIRT_GIC_VCPU].base,
2, vms->memmap[VIRT_GIC_VCPU].size);
qemu_fdt_setprop_cells(vms->fdt, nodename, "interrupts",
GIC_FDT_IRQ_TYPE_PPI, ARCH_GIC_MAINT_IRQ,
GIC_FDT_IRQ_FLAGS_LEVEL_HI);
}
} }
qemu_fdt_setprop_cell(vms->fdt, nodename, "phandle", vms->gic_phandle); qemu_fdt_setprop_cell(vms->fdt, nodename, "phandle", vms->gic_phandle);
...@@ -573,6 +590,11 @@ static void create_gic(VirtMachineState *vms, qemu_irq *pic) ...@@ -573,6 +590,11 @@ static void create_gic(VirtMachineState *vms, qemu_irq *pic)
qdev_prop_set_uint32(gicdev, "redist-region-count[1]", qdev_prop_set_uint32(gicdev, "redist-region-count[1]",
MIN(smp_cpus - redist0_count, redist1_capacity)); MIN(smp_cpus - redist0_count, redist1_capacity));
} }
} else {
if (!kvm_irqchip_in_kernel()) {
qdev_prop_set_bit(gicdev, "has-virtualization-extensions",
vms->virt);
}
} }
qdev_init_nofail(gicdev); qdev_init_nofail(gicdev);
gicbusdev = SYS_BUS_DEVICE(gicdev); gicbusdev = SYS_BUS_DEVICE(gicdev);
...@@ -584,6 +606,10 @@ static void create_gic(VirtMachineState *vms, qemu_irq *pic) ...@@ -584,6 +606,10 @@ static void create_gic(VirtMachineState *vms, qemu_irq *pic)
} }
} else { } else {
sysbus_mmio_map(gicbusdev, 1, vms->memmap[VIRT_GIC_CPU].base); sysbus_mmio_map(gicbusdev, 1, vms->memmap[VIRT_GIC_CPU].base);
if (vms->virt) {
sysbus_mmio_map(gicbusdev, 2, vms->memmap[VIRT_GIC_HYP].base);
sysbus_mmio_map(gicbusdev, 3, vms->memmap[VIRT_GIC_VCPU].base);
}
} }
/* Wire the outputs from each CPU's generic timer and the GICv3 /* Wire the outputs from each CPU's generic timer and the GICv3
...@@ -610,9 +636,17 @@ static void create_gic(VirtMachineState *vms, qemu_irq *pic) ...@@ -610,9 +636,17 @@ static void create_gic(VirtMachineState *vms, qemu_irq *pic)
ppibase + timer_irq[irq])); ppibase + timer_irq[irq]));
} }
qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt", 0, if (type == 3) {
qdev_get_gpio_in(gicdev, ppibase qemu_irq irq = qdev_get_gpio_in(gicdev,
+ ARCH_GICV3_MAINT_IRQ)); ppibase + ARCH_GIC_MAINT_IRQ);
qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt",
0, irq);
} else if (vms->virt) {
qemu_irq irq = qdev_get_gpio_in(gicdev,
ppibase + ARCH_GIC_MAINT_IRQ);
sysbus_connect_irq(gicbusdev, i + 4 * smp_cpus, irq);
}
qdev_connect_gpio_out_named(cpudev, "pmu-interrupt", 0, qdev_connect_gpio_out_named(cpudev, "pmu-interrupt", 0,
qdev_get_gpio_in(gicdev, ppibase qdev_get_gpio_in(gicdev, ppibase
+ VIRTUAL_PMU_IRQ)); + VIRTUAL_PMU_IRQ));
......
...@@ -42,7 +42,7 @@ ...@@ -42,7 +42,7 @@
#define NUM_VIRTIO_TRANSPORTS 32 #define NUM_VIRTIO_TRANSPORTS 32
#define NUM_SMMU_IRQS 4 #define NUM_SMMU_IRQS 4
#define ARCH_GICV3_MAINT_IRQ 9 #define ARCH_GIC_MAINT_IRQ 9
#define ARCH_TIMER_VIRT_IRQ 11 #define ARCH_TIMER_VIRT_IRQ 11
#define ARCH_TIMER_S_EL1_IRQ 13 #define ARCH_TIMER_S_EL1_IRQ 13
...@@ -60,6 +60,8 @@ enum { ...@@ -60,6 +60,8 @@ enum {
VIRT_GIC_DIST, VIRT_GIC_DIST,
VIRT_GIC_CPU, VIRT_GIC_CPU,
VIRT_GIC_V2M, VIRT_GIC_V2M,
VIRT_GIC_HYP,
VIRT_GIC_VCPU,
VIRT_GIC_ITS, VIRT_GIC_ITS,
VIRT_GIC_REDIST, VIRT_GIC_REDIST,
VIRT_GIC_REDIST2, VIRT_GIC_REDIST2,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册