qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH v4 5/5] Add gicversion option to virt machine


From: Diana Craciun
Subject: Re: [Qemu-devel] [PATCH v4 5/5] Add gicversion option to virt machine
Date: Wed, 15 Jul 2015 17:44:07 +0300
User-agent: Mozilla/5.0 (X11; Linux i686 on x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.7.0

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 <address@hidden>
---
  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





reply via email to

[Prev in Thread] Current Thread [Next in Thread]