From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:43199) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZFO9d-0002EN-CS for qemu-devel@nongnu.org; Wed, 15 Jul 2015 10:59:30 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ZFO9Y-00058C-9K for qemu-devel@nongnu.org; Wed, 15 Jul 2015 10:59:25 -0400 Received: from mail-bl2on0108.outbound.protection.outlook.com ([65.55.169.108]:3836 helo=na01-bl2-obe.outbound.protection.outlook.com) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZFO9X-00054N-GK for qemu-devel@nongnu.org; Wed, 15 Jul 2015 10:59:19 -0400 Message-ID: <55A671B7.2010808@freescale.com> Date: Wed, 15 Jul 2015 17:44:07 +0300 From: Diana Craciun MIME-Version: 1.0 References: <0c1f9bfc5a989591cffd59fd6b219cc09ac0b42b.1436859955.git.p.fedin@samsung.com> In-Reply-To: <0c1f9bfc5a989591cffd59fd6b219cc09ac0b42b.1436859955.git.p.fedin@samsung.com> Content-Type: text/plain; charset="windows-1252"; format=flowed Content-Transfer-Encoding: 7bit Subject: Re: [Qemu-devel] [PATCH v4 5/5] Add gicversion option to virt machine List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Pavel Fedin , qemu-devel@nongnu.org Cc: Peter Maydell , Shlomo Pongratz , Eric Auger , Christoffer Dall , Shlomo Pongratz Hi, On 07/14/2015 10:54 AM, Pavel Fedin wrote: > Set kernel_irqchip_type according to value of the option and pass it > around where necessary. Instantiate devices and fdt nodes according > to the choice. > > mac_cpus for virt machine increased to 64. GICv2 compatibility check > happens inside arm_gic_common_realize(). > > Signed-off-by: Pavel Fedin > --- > hw/arm/virt.c | 135 ++++++++++++++++++++++++++++++++++++++++++-------- > include/hw/arm/fdt.h | 2 +- > include/hw/arm/virt.h | 6 ++- > 3 files changed, 120 insertions(+), 23 deletions(-) > > diff --git a/hw/arm/virt.c b/hw/arm/virt.c > index 2e7d858..df69dc8 100644 > --- a/hw/arm/virt.c > +++ b/hw/arm/virt.c > @@ -48,6 +48,8 @@ > #include "hw/arm/sysbus-fdt.h" > #include "hw/platform-bus.h" > #include "hw/arm/fdt.h" > +#include "linux/kvm.h" /* For KVM_DEV_TYPE_ARM_VGIC_V{2|3} */ > +#include "qapi/visitor.h" > > /* Number of external interrupt lines to configure the GIC with */ > #define NUM_IRQS 256 > @@ -67,6 +69,7 @@ typedef struct VirtBoardInfo { > uint32_t clock_phandle; > uint32_t gic_phandle; > uint32_t v2m_phandle; > + const char *class_name; > } VirtBoardInfo; > > typedef struct { > @@ -80,6 +83,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) \ > @@ -106,7 +110,12 @@ static const MemMapEntry a15memmap[] = { > /* GIC distributor and CPU interfaces sit inside the CPU peripheral space */ > [VIRT_GIC_DIST] = { 0x08000000, 0x00010000 }, > [VIRT_GIC_CPU] = { 0x08010000, 0x00010000 }, > - [VIRT_GIC_V2M] = { 0x08020000, 0x00001000 }, > + [VIRT_GIC_V2M] = { 0x08020000, 0x00010000 }, > + /* On v3 VIRT_GIC_DIST_MBI and VIRT_ITS_CONTROL take place of > + * VIRT_GIC_CPU and VIRT_GIC_V2M respectively > + */ > + [VIRT_ITS_TRANSLATION] = { 0x08030000, 0x00010000 }, > + [VIRT_LPI] = { 0x08040000, 0x00800000 }, > [VIRT_UART] = { 0x09000000, 0x00001000 }, > [VIRT_RTC] = { 0x09010000, 0x00001000 }, > [VIRT_FW_CFG] = { 0x09020000, 0x0000000a }, > @@ -256,10 +265,13 @@ static void fdt_add_timer_nodes(const VirtBoardInfo *vbi) > * they are edge-triggered. > */ > ARMCPU *armcpu; > + uint32_t max; > uint32_t irqflags = GIC_FDT_IRQ_FLAGS_EDGE_LO_HI; > > + /* 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, > - GIC_FDT_IRQ_PPI_CPU_WIDTH, (1 << vbi->smp_cpus) - 1); > + GIC_FDT_IRQ_PPI_CPU_WIDTH, (1 << max) - 1); > > qemu_fdt_add_subnode(vbi->fdt, "/timer"); > > @@ -283,6 +295,18 @@ static void fdt_add_cpu_nodes(const VirtBoardInfo *vbi) > { > int cpu; > > + /* > + * From Documentation/devicetree/bindings/arm/cpus.txt > + * On ARM v8 64-bit systems value should be set to 2, > + * that corresponds to the MPIDR_EL1 register size. > + * If MPIDR_EL1[63:32] value is equal to 0 on all CPUs > + * in the system, #address-cells can be set to 1, since > + * MPIDR_EL1[63:32] bits are not used for CPUs > + * identification. > + * > + * Now GIC500 doesn't support affinities 2 & 3 so currently > + * #address-cells can stay 1 until future GIC > + */ > qemu_fdt_add_subnode(vbi->fdt, "/cpus"); > qemu_fdt_setprop_cell(vbi->fdt, "/cpus", "#address-cells", 0x1); > qemu_fdt_setprop_cell(vbi->fdt, "/cpus", "#size-cells", 0x0); > @@ -319,25 +343,36 @@ static void fdt_add_v2m_gic_node(VirtBoardInfo *vbi) > qemu_fdt_setprop_cell(vbi->fdt, "/intc/v2m", "phandle", vbi->v2m_phandle); > } > > -static void fdt_add_gic_node(VirtBoardInfo *vbi) > +static void fdt_add_gic_node(VirtBoardInfo *vbi, int type) > { > vbi->gic_phandle = qemu_fdt_alloc_phandle(vbi->fdt); > qemu_fdt_setprop_cell(vbi->fdt, "/", "interrupt-parent", vbi->gic_phandle); > > qemu_fdt_add_subnode(vbi->fdt, "/intc"); > - /* 'cortex-a15-gic' means 'GIC v2' */ > - qemu_fdt_setprop_string(vbi->fdt, "/intc", "compatible", > - "arm,cortex-a15-gic"); > qemu_fdt_setprop_cell(vbi->fdt, "/intc", "#interrupt-cells", 3); > qemu_fdt_setprop(vbi->fdt, "/intc", "interrupt-controller", NULL, 0); > - qemu_fdt_setprop_sized_cells(vbi->fdt, "/intc", "reg", > - 2, vbi->memmap[VIRT_GIC_DIST].base, > - 2, vbi->memmap[VIRT_GIC_DIST].size, > - 2, vbi->memmap[VIRT_GIC_CPU].base, > - 2, vbi->memmap[VIRT_GIC_CPU].size); > qemu_fdt_setprop_cell(vbi->fdt, "/intc", "#address-cells", 0x2); > qemu_fdt_setprop_cell(vbi->fdt, "/intc", "#size-cells", 0x2); > qemu_fdt_setprop(vbi->fdt, "/intc", "ranges", NULL, 0); > + if (type == KVM_DEV_TYPE_ARM_VGIC_V3) { > + qemu_fdt_setprop_string(vbi->fdt, "/intc", "compatible", > + "arm,gic-v3"); > + qemu_fdt_setprop_sized_cells(vbi->fdt, "/intc", "reg", > + 2, vbi->memmap[VIRT_GIC_DIST].base, > + 2, vbi->memmap[VIRT_GIC_DIST].size, > + 2, vbi->memmap[VIRT_LPI].base, > + 2, vbi->memmap[VIRT_LPI].size); > + } else { > + /* 'cortex-a15-gic' means 'GIC v2' */ > + qemu_fdt_setprop_string(vbi->fdt, "/intc", "compatible", > + "arm,cortex-a15-gic"); > + qemu_fdt_setprop_sized_cells(vbi->fdt, "/intc", "reg", > + 2, vbi->memmap[VIRT_GIC_DIST].base, > + 2, vbi->memmap[VIRT_GIC_DIST].size, > + 2, vbi->memmap[VIRT_GIC_CPU].base, > + 2, vbi->memmap[VIRT_GIC_CPU].size); > + } > + > qemu_fdt_setprop_cell(vbi->fdt, "/intc", "phandle", vbi->gic_phandle); > } > > @@ -360,20 +395,35 @@ static void create_v2m(VirtBoardInfo *vbi, qemu_irq *pic) > fdt_add_v2m_gic_node(vbi); > } > > -static void create_gic(VirtBoardInfo *vbi, qemu_irq *pic) > +static void create_gic(VirtBoardInfo *vbi, qemu_irq *pic, int type) > { > /* We create a standalone GIC v2 */ > DeviceState *gicdev; > SysBusDevice *gicbusdev; > - const char *gictype = "arm_gic"; > + const char *gictype; > int i; > > - if (kvm_irqchip_in_kernel()) { > - gictype = "kvm-arm-gic"; > + if (type == KVM_DEV_TYPE_ARM_VGIC_V3) { > + /* TODO: Software emulation is not implemented yet */ > + if (!kvm_irqchip_in_kernel()) { > + fprintf(stderr, "KVM is currently required for GICv3 emulation\n"); > + exit(1); > + } > + gictype = "kvm-arm-gicv3"; > + } else { > + gictype = kvm_irqchip_in_kernel() ? "kvm-arm-gic" : "arm_gic"; > } > > gicdev = qdev_create(NULL, gictype); > - qdev_prop_set_uint32(gicdev, "revision", 2); > + > + for (i = 0; i < vbi->smp_cpus; i++) { > + CPUState *cpu = qemu_get_cpu(i); > + CPUARMState *env = cpu->env_ptr; > + env->nvic = gicdev; > + } > + > + qdev_prop_set_uint32(gicdev, "revision", > + type == KVM_DEV_TYPE_ARM_VGIC_V3 ? 3 : 2); > qdev_prop_set_uint32(gicdev, "num-cpu", smp_cpus); > /* Note that the num-irq property counts both internal and external > * interrupts; there are always 32 of the former (mandated by GIC spec). > @@ -382,7 +432,11 @@ static void create_gic(VirtBoardInfo *vbi, qemu_irq *pic) > qdev_init_nofail(gicdev); > gicbusdev = SYS_BUS_DEVICE(gicdev); > sysbus_mmio_map(gicbusdev, 0, vbi->memmap[VIRT_GIC_DIST].base); > - sysbus_mmio_map(gicbusdev, 1, vbi->memmap[VIRT_GIC_CPU].base); > + if (type == KVM_DEV_TYPE_ARM_VGIC_V3) { > + sysbus_mmio_map(gicbusdev, 1, vbi->memmap[VIRT_LPI].base); > + } else { > + sysbus_mmio_map(gicbusdev, 1, vbi->memmap[VIRT_GIC_CPU].base); > + } > > /* Wire the outputs from each CPU's generic timer to the > * appropriate GIC PPI inputs, and the GIC's IRQ output to > @@ -409,9 +463,11 @@ static void create_gic(VirtBoardInfo *vbi, qemu_irq *pic) > pic[i] = qdev_get_gpio_in(gicdev, i); > } > > - fdt_add_gic_node(vbi); > + fdt_add_gic_node(vbi, type); > > - create_v2m(vbi, pic); > + if (type == KVM_DEV_TYPE_ARM_VGIC_V2) { > + create_v2m(vbi, pic); > + } > } As we do not have yet support for ITS implementation in QEMU the device tree for a GICv3 guest will have a msi-parent property in the device tree which will point to nothing: "msi-parent = <0x0>" Diana