[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH RFC V4 4/4] Add virt-v3 machine that uses GIC-500
From: |
Shlomo Pongratz |
Subject: |
[Qemu-devel] [PATCH RFC V4 4/4] Add virt-v3 machine that uses GIC-500 |
Date: |
Thu, 17 Sep 2015 20:38:16 +0300 |
From: Pavel Fedin <address@hidden>
I would like to offer this, slightly improved implementation. The key thing is
a new
kernel_irqchip_type member in Machine class. Currently it it used only by virt
machine for
its internal purposes, however in future it is to be passed to KVM in
kvm_irqchip_create(). The variable is defined as int in order to be
architecture agnostic,
for potential future users.
Signed-off-by: Pavel Fedin <address@hidden>
---
hw/arm/virt.c | 72 +++++++++++++++++++++++++++++++++++++++++++++------
include/hw/arm/fdt.h | 2 ++
include/hw/arm/virt.h | 1 +
target-arm/machine.c | 7 ++++-
4 files changed, 73 insertions(+), 9 deletions(-)
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 4d15309..4c2ae7f 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -71,6 +71,7 @@ typedef struct VirtBoardInfo {
uint32_t clock_phandle;
uint32_t gic_phandle;
uint32_t v2m_phandle;
+ const char *class_name;
} VirtBoardInfo;
typedef struct {
@@ -86,6 +87,7 @@ typedef struct {
} VirtMachineState;
#define TYPE_VIRT_MACHINE "virt"
+#define TYPE_VIRTV3_MACHINE "virt-v3"
#define VIRT_MACHINE(obj) \
OBJECT_CHECK(VirtMachineState, (obj), TYPE_VIRT_MACHINE)
#define VIRT_MACHINE_GET_CLASS(obj) \
@@ -111,6 +113,7 @@ static const MemMapEntry a15memmap[] = {
[VIRT_CPUPERIPHS] = { 0x08000000, 0x00020000 },
/* GIC distributor and CPU interfaces sit inside the CPU peripheral space
*/
[VIRT_GIC_DIST] = { 0x08000000, 0x00010000 },
+ /* Note on GICv3 VIRT_GIC_DIST_SPI takes place of VIRT_GIC_CPU */
[VIRT_GIC_CPU] = { 0x08010000, 0x00010000 },
[VIRT_GIC_V2M] = { 0x08020000, 0x00001000 },
/* The space in between here is reserved for GICv3 CPU/vCPU/HYP */
@@ -145,21 +148,26 @@ static VirtBoardInfo machines[] = {
.cpu_model = "cortex-a15",
.memmap = a15memmap,
.irqmap = a15irqmap,
+ .class_name = TYPE_ARM_CPU,
+
},
{
.cpu_model = "cortex-a53",
.memmap = a15memmap,
.irqmap = a15irqmap,
+ .class_name = TYPE_AARCH64_CPU,
},
{
.cpu_model = "cortex-a57",
.memmap = a15memmap,
.irqmap = a15irqmap,
+ .class_name = TYPE_AARCH64_CPU,
},
{
.cpu_model = "host",
.memmap = a15memmap,
.irqmap = a15irqmap,
+ .class_name = TYPE_ARM_CPU,
},
};
@@ -228,7 +236,6 @@ static void fdt_add_psci_node(const VirtBoardInfo *vbi)
if (armcpu->psci_version == 2) {
const char comp[] = "arm,psci-0.2\0arm,psci";
qemu_fdt_setprop(fdt, "/psci", "compatible", comp, sizeof(comp));
-
cpu_off_fn = QEMU_PSCI_0_2_FN_CPU_OFF;
if (arm_feature(&armcpu->env, ARM_FEATURE_AARCH64)) {
cpu_suspend_fn = QEMU_PSCI_0_2_FN64_CPU_SUSPEND;
@@ -241,7 +248,6 @@ static void fdt_add_psci_node(const VirtBoardInfo *vbi)
}
} else {
qemu_fdt_setprop_string(fdt, "/psci", "compatible", "arm,psci");
-
cpu_suspend_fn = QEMU_PSCI_0_1_FN_CPU_SUSPEND;
cpu_off_fn = QEMU_PSCI_0_1_FN_CPU_OFF;
cpu_on_fn = QEMU_PSCI_0_1_FN_CPU_ON;
@@ -274,6 +280,12 @@ static void fdt_add_timer_nodes(const VirtBoardInfo *vbi,
int gictype)
irqflags = deposit32(irqflags, GIC_FDT_IRQ_PPI_CPU_START,
GIC_FDT_IRQ_PPI_CPU_WIDTH,
(1 << vbi->smp_cpus) - 1);
+ } else if (gictype == 3) {
+ uint32_t max;
+ /* Argument is 32 bit but 8 bits are reserved for flags */
+ max = (vbi->smp_cpus >= 24) ? 24 : vbi->smp_cpus;
+ irqflags = deposit32(irqflags, GIC_FDT_IRQ_PPI_CPU_START,
+ GICV3_FDT_IRQ_PPI_CPU_WIDTH, (1 << max) - 1);
}
qemu_fdt_add_subnode(vbi->fdt, "/timer");
@@ -434,7 +446,12 @@ static void create_gic(VirtBoardInfo *vbi, qemu_irq *pic,
int type, bool secure)
*/
qdev_prop_set_uint32(gicdev, "num-irq", NUM_IRQS + 32);
if (!kvm_irqchip_in_kernel()) {
- qdev_prop_set_bit(gicdev, "has-security-extensions", secure);
+ if (type == 3) {
+ /* AARCH64 has 4 security levels */
+ qdev_prop_set_uint8(gicdev, "security-levels", secure ? 1 : 0);
+ } else {
+ qdev_prop_set_bit(gicdev, "has-security-extensions", secure);
+ }
}
qdev_init_nofail(gicdev);
gicbusdev = SYS_BUS_DEVICE(gicdev);
@@ -445,6 +462,14 @@ static void create_gic(VirtBoardInfo *vbi, qemu_irq *pic,
int type, bool secure)
sysbus_mmio_map(gicbusdev, 1, vbi->memmap[VIRT_GIC_CPU].base);
}
+ if (type == 3) {
+ /* Connect GIC to CPU */
+ for (i = 0; i < smp_cpus; i++) {
+ CPUState *cpu = qemu_get_cpu(i);
+ aatch64_registers_with_opaque_set(OBJECT(cpu), (void *)gicdev);
+ }
+ }
+
/* Wire the outputs from each CPU's generic timer to the
* appropriate GIC PPI inputs, and the GIC's IRQ output to
* the CPU's IRQ input.
@@ -466,7 +491,7 @@ static void create_gic(VirtBoardInfo *vbi, qemu_irq *pic,
int type, bool secure)
for (irq = 0; irq < ARRAY_SIZE(timer_irq); irq++) {
qdev_connect_gpio_out(cpudev, irq,
qdev_get_gpio_in(gicdev,
- ppibase + timer_irq[irq]));
+ ppibase + timer_irq[irq]));
}
sysbus_connect_irq(gicbusdev, i, qdev_get_gpio_in(cpudev,
ARM_CPU_IRQ));
@@ -962,7 +987,7 @@ static void machvirt_init(MachineState *machine)
create_fdt(vbi);
for (n = 0; n < smp_cpus; n++) {
- ObjectClass *oc = cpu_class_by_name(TYPE_ARM_CPU, cpustr[0]);
+ ObjectClass *oc = cpu_class_by_name(vbi->class_name, cpustr[0]);
CPUClass *cc = CPU_CLASS(oc);
Object *cpuobj;
Error *err = NULL;
@@ -1111,7 +1136,7 @@ static void virt_set_gic_version(Object *obj, const char
*value, Error **errp)
}
}
-static void virt_instance_init(Object *obj)
+static void virt_instance_init_common(Object *obj, int32_t version)
{
VirtMachineState *vms = VIRT_MACHINE(obj);
@@ -1135,8 +1160,7 @@ static void virt_instance_init(Object *obj)
"Set on/off to enable/disable using "
"physical address space above 32 bits",
NULL);
- /* Default GIC type is v2 */
- vms->gic_version = 2;
+ vms->gic_version = version;
object_property_add_str(obj, "gic-version", virt_get_gic_version,
virt_set_gic_version, NULL);
object_property_set_description(obj, "gic-version",
@@ -1144,6 +1168,12 @@ static void virt_instance_init(Object *obj)
"Valid values are 2, 3 and host", NULL);
}
+static void virt_instance_init(Object *obj)
+{
+ /* Default GIC type is v2 */
+ virt_instance_init_common(obj, 2);
+}
+
static void virt_class_init(ObjectClass *oc, void *data)
{
MachineClass *mc = MACHINE_CLASS(oc);
@@ -1169,9 +1199,35 @@ static const TypeInfo machvirt_info = {
.class_init = virt_class_init,
};
+static void virtv3_instance_init(Object *obj)
+{
+ virt_instance_init_common(obj, 3);
+}
+
+static void virtv3_class_init(ObjectClass *oc, void *data)
+{
+ MachineClass *mc = MACHINE_CLASS(oc);
+
+ mc->name = TYPE_VIRTV3_MACHINE;
+ mc->desc = "ARM Virtual Machine with GICv3",
+ mc->init = machvirt_init;
+ /* With gic3 full implementation (with bitops) rase the lmit to 128 */
+ mc->max_cpus = 64;
+}
+
+static const TypeInfo machvirtv3_info = {
+ .name = TYPE_VIRTV3_MACHINE,
+ .parent = TYPE_VIRT_MACHINE,
+ .instance_size = sizeof(VirtMachineState),
+ .instance_init = virtv3_instance_init,
+ .class_size = sizeof(VirtMachineClass),
+ .class_init = virtv3_class_init,
+};
+
static void machvirt_machine_init(void)
{
type_register_static(&machvirt_info);
+ type_register_static(&machvirtv3_info);
}
machine_init(machvirt_machine_init);
diff --git a/include/hw/arm/fdt.h b/include/hw/arm/fdt.h
index c3d5015..ad8f85c 100644
--- a/include/hw/arm/fdt.h
+++ b/include/hw/arm/fdt.h
@@ -30,5 +30,7 @@
#define GIC_FDT_IRQ_PPI_CPU_START 8
#define GIC_FDT_IRQ_PPI_CPU_WIDTH 8
+#define GICV3_FDT_IRQ_PPI_CPU_WIDTH 24
+
#endif
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
index f464586..53ff50a 100644
--- a/include/hw/arm/virt.h
+++ b/include/hw/arm/virt.h
@@ -46,6 +46,7 @@ enum {
VIRT_CPUPERIPHS,
VIRT_GIC_DIST,
VIRT_GIC_CPU,
+ VIRT_GIC_DIST_SPI = VIRT_GIC_CPU,
VIRT_GIC_V2M,
VIRT_GIC_ITS,
VIRT_GIC_REDIST,
diff --git a/target-arm/machine.c b/target-arm/machine.c
index 36a0d15..33f28be 100644
--- a/target-arm/machine.c
+++ b/target-arm/machine.c
@@ -341,7 +341,12 @@ const char *gicv3_class_name(void)
#endif
} else {
/* TODO: Software emulation is not implemented yet */
- error_report("KVM is currently required for GICv3 emulation\n");
+#ifdef TARGET_AARCH64
+ return "arm_gicv3";
+#else
+ error_report("KVM GICv3 acceleration is not supported on this "
+ "platform\n");
+#endif
}
exit(1);
--
1.9.1