From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51138) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Zoabx-0000fu-6a for qemu-devel@nongnu.org; Tue, 20 Oct 2015 13:22:10 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Zoabv-0003aS-Pi for qemu-devel@nongnu.org; Tue, 20 Oct 2015 13:22:09 -0400 Received: from mail-wi0-x233.google.com ([2a00:1450:400c:c05::233]:37021) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Zoabv-0003ZQ-HJ for qemu-devel@nongnu.org; Tue, 20 Oct 2015 13:22:07 -0400 Received: by wicfv8 with SMTP id fv8so39403245wic.0 for ; Tue, 20 Oct 2015 10:22:07 -0700 (PDT) From: Shlomo Pongratz Date: Tue, 20 Oct 2015 20:22:12 +0300 Message-Id: <1445361732-16257-10-git-send-email-shlomopongratz@gmail.com> In-Reply-To: <1445361732-16257-1-git-send-email-shlomopongratz@gmail.com> References: <1445361732-16257-1-git-send-email-shlomopongratz@gmail.com> Subject: [Qemu-devel] [PATCH RFC V5 9/9] hw/arm: Add virt-v3 machine that uses GIC-500 List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: peter.maydell@linaro.org, eric.auger@linaro.org, Shlomo Pongratz , p.fedin@samsung.com, shannon.zhao@linaro.org, ashoks@broadcom.com, imammedo@redhat.com From: Shlomo Pongratz Add virt-v3 machine that uses GIC-500. Registers the CPU system instructions and bind them to the GIC. Pass the cores' affinity to the GIC. Signed-off-by: Shlomo Pongratz --- hw/arm/virt.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++----- include/hw/arm/fdt.h | 2 ++ include/hw/arm/virt.h | 1 + target-arm/machine.c | 7 ++++- 4 files changed, 88 insertions(+), 9 deletions(-) diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 5d38c47..d4fb8f3 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 MACHINE_TYPE_NAME("virt") +#define TYPE_VIRTV3_MACHINE MACHINE_TYPE_NAME("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"); @@ -429,12 +441,32 @@ static void create_gic(VirtBoardInfo *vbi, qemu_irq *pic, int type, bool secure) gicdev = qdev_create(NULL, gictype); qdev_prop_set_uint32(gicdev, "revision", type); qdev_prop_set_uint32(gicdev, "num-cpu", smp_cpus); + +#ifdef TARGET_AARCH64 + if (type == 3) { + qdev_prop_set_uint32(gicdev, "len-mp-affinity", smp_cpus); + /* Connect GIC to CPU */ + for (i = 0; i < smp_cpus; i++) { + char *propname; + CPUState *cpu = qemu_get_cpu(i); + ARMCPU *armcpu = ARM_CPU(cpu); + propname = g_strdup_printf("mp-affinity[%d]", i); + qdev_prop_set_uint64(gicdev, propname, armcpu->mp_affinity); + g_free(propname); + } + } +#endif /* Note that the num-irq property counts both internal and external * interrupts; there are always 32 of the former (mandated by GIC spec). */ 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 +477,16 @@ static void create_gic(VirtBoardInfo *vbi, qemu_irq *pic, int type, bool secure) sysbus_mmio_map(gicbusdev, 1, vbi->memmap[VIRT_GIC_CPU].base); } +#ifdef TARGET_AARCH64 + if (type == 3) { + /* Connect GIC to CPU */ + for (i = 0; i < smp_cpus; i++) { + CPUState *cpu = qemu_get_cpu(i); + aarch64_registers_with_opaque_set(OBJECT(cpu), (void *)gicdev); + } + } +#endif + /* 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 +508,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)); @@ -967,7 +1009,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; @@ -1116,7 +1158,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); @@ -1140,8 +1182,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", @@ -1149,6 +1190,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); @@ -1174,9 +1221,33 @@ 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; +} + +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