All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v2 00/18] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs
@ 2017-01-09 16:05 Peter Maydell
  2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 01/18] hw/intc/arm_gicv3: Add external IRQ lines for VIRQ and VFIQ Peter Maydell
                   ` (18 more replies)
  0 siblings, 19 replies; 37+ messages in thread
From: Peter Maydell @ 2017-01-09 16:05 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: patches, Andrew Jones, Christoffer Dall, Edgar E . Iglesias,
	Alistair Francis

This patchset adds support for the Virtualization extensions to QEMU's
GICv3 emulation. This was the last missing piece that was stopping
us from turning on the EL2 support in the CPU model, so the patchset
also adds support for enabling it all on the virt board via the
'-machine virtualization=on' option.

The result works well enough to allow booting a KVM outer guest kernel
and then running QEMU + an inner guest under KVM inside it. The outer
guest KVM also passes the kvm-unit-tests GIC tests.

Changes v1->v2:
 * rebased on master; some of the earlier patches in v1
   have now gone into master, as has Drew's ACPI cleanup set
 * new patch "psci.c: If EL2 implemented, start CPUs in EL2"
   fixes the problems with SMP configs not starting properly
 * includes Drew's changes to report SMC vs HVC in ACPI
   (slightly tweaked by me)

Patches 1, 4-13, 15, 16 still need review.

Git branch for this:
 https://git.linaro.org/people/peter.maydell/qemu-arm.git gicv3-virt

thanks
-- PMM

Andrew Jones (1):
  hw/arm/virt-acpi-build: use SMC if booting in EL2

Peter Maydell (17):
  hw/intc/arm_gicv3: Add external IRQ lines for VIRQ and VFIQ
  hw/intc/arm_gic: Add external IRQ lines for VIRQ and VFIQ
  target-arm: Expose output GPIO line for VCPU maintenance interrupt
  hw/arm/virt: Wire VIRQ, VFIQ, maintenance irq lines from GIC to CPU
  target-arm: Add ARMCPU fields for GIC CPU i/f config
  hw/intc/gicv3: Add defines for ICH system register fields
  hw/intc/gicv3: Add data fields for virtualization support
  hw/intc/arm_gicv3: Add accessors for ICH_ system registers
  hw/intc/arm_gicv3: Implement ICV_ registers which are just accessors
  hw/intc/arm_gicv3: Implement ICV_ HPPIR, DIR and RPR registers
  hw/intc/arm_gicv3: Implement ICV_ registers EOIR and IAR
  hw/intc/arm_gicv3: Implement gicv3_cpuif_virt_update()
  hw/intc/arm_gicv3: Implement EL2 traps for CPU i/f regs
  hw/arm/virt: Support using SMC for PSCI
  target/arm/psci.c: If EL2 implemented, start CPUs in EL2
  target-arm: Enable EL2 feature bit on A53 and A57
  hw/arm/virt: Add board property to enable EL2

 hw/intc/gicv3_internal.h           |   79 +++
 include/hw/arm/virt.h              |    5 +-
 include/hw/intc/arm_gic_common.h   |    2 +
 include/hw/intc/arm_gicv3_common.h |   21 +
 target/arm/cpu.h                   |    9 +
 hw/arm/virt-acpi-build.c           |   29 +-
 hw/arm/virt.c                      |   87 ++-
 hw/arm/xlnx-zynqmp.c               |    2 +
 hw/intc/arm_gic_common.c           |    6 +
 hw/intc/arm_gicv3_common.c         |   31 +
 hw/intc/arm_gicv3_cpuif.c          | 1351 +++++++++++++++++++++++++++++++++++-
 target/arm/cpu.c                   |   15 +
 target/arm/cpu64.c                 |    8 +
 target/arm/psci.c                  |   25 +-
 hw/intc/trace-events               |   33 +
 15 files changed, 1642 insertions(+), 61 deletions(-)

-- 
2.7.4

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [Qemu-devel] [PATCH v2 01/18] hw/intc/arm_gicv3: Add external IRQ lines for VIRQ and VFIQ
  2017-01-09 16:05 [Qemu-devel] [PATCH v2 00/18] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs Peter Maydell
@ 2017-01-09 16:05 ` Peter Maydell
  2017-01-17 21:49   ` Alistair Francis
  2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 02/18] hw/intc/arm_gic: " Peter Maydell
                   ` (17 subsequent siblings)
  18 siblings, 1 reply; 37+ messages in thread
From: Peter Maydell @ 2017-01-09 16:05 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: patches, Andrew Jones, Christoffer Dall, Edgar E . Iglesias,
	Alistair Francis

Augment the GICv3's QOM device interface by adding two
new sets of sysbus IRQ lines, to signal VIRQ and VFIQ to
each CPU.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 include/hw/intc/arm_gicv3_common.h | 2 ++
 hw/intc/arm_gicv3_common.c         | 6 ++++++
 2 files changed, 8 insertions(+)

diff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h
index 341a311..beb2c77 100644
--- a/include/hw/intc/arm_gicv3_common.h
+++ b/include/hw/intc/arm_gicv3_common.h
@@ -145,6 +145,8 @@ struct GICv3CPUState {
     CPUState *cpu;
     qemu_irq parent_irq;
     qemu_irq parent_fiq;
+    qemu_irq parent_virq;
+    qemu_irq parent_vfiq;
 
     /* Redistributor */
     uint32_t level;                  /* Current IRQ level */
diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
index 0aa9b9c..0ee67a4 100644
--- a/hw/intc/arm_gicv3_common.c
+++ b/hw/intc/arm_gicv3_common.c
@@ -126,6 +126,12 @@ void gicv3_init_irqs_and_mmio(GICv3State *s, qemu_irq_handler handler,
     for (i = 0; i < s->num_cpu; i++) {
         sysbus_init_irq(sbd, &s->cpu[i].parent_fiq);
     }
+    for (i = 0; i < s->num_cpu; i++) {
+        sysbus_init_irq(sbd, &s->cpu[i].parent_virq);
+    }
+    for (i = 0; i < s->num_cpu; i++) {
+        sysbus_init_irq(sbd, &s->cpu[i].parent_vfiq);
+    }
 
     memory_region_init_io(&s->iomem_dist, OBJECT(s), ops, s,
                           "gicv3_dist", 0x10000);
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Qemu-devel] [PATCH v2 02/18] hw/intc/arm_gic: Add external IRQ lines for VIRQ and VFIQ
  2017-01-09 16:05 [Qemu-devel] [PATCH v2 00/18] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs Peter Maydell
  2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 01/18] hw/intc/arm_gicv3: Add external IRQ lines for VIRQ and VFIQ Peter Maydell
@ 2017-01-09 16:05 ` Peter Maydell
  2017-01-10 16:49   ` Edgar E. Iglesias
  2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 03/18] target-arm: Expose output GPIO line for VCPU maintenance interrupt Peter Maydell
                   ` (16 subsequent siblings)
  18 siblings, 1 reply; 37+ messages in thread
From: Peter Maydell @ 2017-01-09 16:05 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: patches, Andrew Jones, Christoffer Dall, Edgar E . Iglesias,
	Alistair Francis

Augment the GIC's QOM device interface by adding two
new sets of sysbus IRQ lines, to signal VIRQ and VFIQ to
each CPU.

We never use these, but it's helpful to keep the v2-and-earlier
GIC's external interface in line with that of the GICv3 to
avoid board code having to add extra code conditional on which
version of the GIC is in use.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
---
 include/hw/intc/arm_gic_common.h | 2 ++
 hw/intc/arm_gic_common.c         | 6 ++++++
 2 files changed, 8 insertions(+)

diff --git a/include/hw/intc/arm_gic_common.h b/include/hw/intc/arm_gic_common.h
index f4c349a..af3ca18 100644
--- a/include/hw/intc/arm_gic_common.h
+++ b/include/hw/intc/arm_gic_common.h
@@ -55,6 +55,8 @@ typedef struct GICState {
 
     qemu_irq parent_irq[GIC_NCPU];
     qemu_irq parent_fiq[GIC_NCPU];
+    qemu_irq parent_virq[GIC_NCPU];
+    qemu_irq parent_vfiq[GIC_NCPU];
     /* GICD_CTLR; for a GIC with the security extensions the NS banked version
      * of this register is just an alias of bit 1 of the S banked version.
      */
diff --git a/hw/intc/arm_gic_common.c b/hw/intc/arm_gic_common.c
index 0a1f56a..4a8df44 100644
--- a/hw/intc/arm_gic_common.c
+++ b/hw/intc/arm_gic_common.c
@@ -110,6 +110,12 @@ void gic_init_irqs_and_mmio(GICState *s, qemu_irq_handler handler,
     for (i = 0; i < s->num_cpu; i++) {
         sysbus_init_irq(sbd, &s->parent_fiq[i]);
     }
+    for (i = 0; i < s->num_cpu; i++) {
+        sysbus_init_irq(sbd, &s->parent_virq[i]);
+    }
+    for (i = 0; i < s->num_cpu; i++) {
+        sysbus_init_irq(sbd, &s->parent_vfiq[i]);
+    }
 
     /* Distributor */
     memory_region_init_io(&s->iomem, OBJECT(s), ops, s, "gic_dist", 0x1000);
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Qemu-devel] [PATCH v2 03/18] target-arm: Expose output GPIO line for VCPU maintenance interrupt
  2017-01-09 16:05 [Qemu-devel] [PATCH v2 00/18] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs Peter Maydell
  2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 01/18] hw/intc/arm_gicv3: Add external IRQ lines for VIRQ and VFIQ Peter Maydell
  2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 02/18] hw/intc/arm_gic: " Peter Maydell
@ 2017-01-09 16:05 ` Peter Maydell
  2017-01-17 21:50   ` Alistair Francis
  2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 04/18] hw/arm/virt: Wire VIRQ, VFIQ, maintenance irq lines from GIC to CPU Peter Maydell
                   ` (15 subsequent siblings)
  18 siblings, 1 reply; 37+ messages in thread
From: Peter Maydell @ 2017-01-09 16:05 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: patches, Andrew Jones, Christoffer Dall, Edgar E . Iglesias,
	Alistair Francis

The GICv3 support for virtualization includes an outbound
maintenance interrupt signal which is asserted when the
CPU interface wants to signal to the hypervisor that it
needs attention. Expose this as an outbound GPIO line from
the CPU object which can be wired up as a physical interrupt
line by the board code (as we do already for the CPU timers).

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
---
 target/arm/cpu.h | 2 ++
 target/arm/cpu.c | 3 +++
 2 files changed, 5 insertions(+)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index ab119e6..764b511 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -555,6 +555,8 @@ struct ARMCPU {
     QEMUTimer *gt_timer[NUM_GTIMERS];
     /* GPIO outputs for generic timer */
     qemu_irq gt_timer_outputs[NUM_GTIMERS];
+    /* GPIO output for GICv3 maintenance interrupt signal */
+    qemu_irq gicv3_maintenance_interrupt;
 
     /* MemoryRegion to use for secure physical accesses */
     MemoryRegion *secure_memory;
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index f5cb30a..8932086 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -466,6 +466,9 @@ static void arm_cpu_initfn(Object *obj)
                                                 arm_gt_stimer_cb, cpu);
     qdev_init_gpio_out(DEVICE(cpu), cpu->gt_timer_outputs,
                        ARRAY_SIZE(cpu->gt_timer_outputs));
+
+    qdev_init_gpio_out_named(DEVICE(cpu), &cpu->gicv3_maintenance_interrupt,
+                             "gicv3-maintenance-interrupt", 1);
 #endif
 
     /* DTB consumers generally don't in fact care what the 'compatible'
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Qemu-devel] [PATCH v2 04/18] hw/arm/virt: Wire VIRQ, VFIQ, maintenance irq lines from GIC to CPU
  2017-01-09 16:05 [Qemu-devel] [PATCH v2 00/18] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs Peter Maydell
                   ` (2 preceding siblings ...)
  2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 03/18] target-arm: Expose output GPIO line for VCPU maintenance interrupt Peter Maydell
@ 2017-01-09 16:05 ` Peter Maydell
  2017-01-10 16:42   ` Edgar E. Iglesias
  2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 05/18] target-arm: Add ARMCPU fields for GIC CPU i/f config Peter Maydell
                   ` (14 subsequent siblings)
  18 siblings, 1 reply; 37+ messages in thread
From: Peter Maydell @ 2017-01-09 16:05 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: patches, Andrew Jones, Christoffer Dall, Edgar E . Iglesias,
	Alistair Francis

Wire the new VIRQ, VFIQ and maintenance interrupt lines from the
GIC to each CPU.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 include/hw/arm/virt.h |  2 ++
 hw/arm/virt.c         | 14 +++++++++++---
 2 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
index eb1c63d..b8a19ec 100644
--- a/include/hw/arm/virt.h
+++ b/include/hw/arm/virt.h
@@ -39,6 +39,8 @@
 #define NUM_GICV2M_SPIS       64
 #define NUM_VIRTIO_TRANSPORTS 32
 
+#define ARCH_GICV3_MAINT_IRQ  9
+
 #define ARCH_TIMER_VIRT_IRQ   11
 #define ARCH_TIMER_S_EL1_IRQ  13
 #define ARCH_TIMER_NS_EL1_IRQ 14
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 7a03f84..b31d302 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -547,9 +547,9 @@ static void create_gic(VirtMachineState *vms, qemu_irq *pic)
         sysbus_mmio_map(gicbusdev, 1, vms->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
-     * the CPU's IRQ input.
+    /* Wire the outputs from each CPU's generic timer and the GICv3
+     * maintenance interrupt signal to the appropriate GIC PPI inputs,
+     * and the GIC's IRQ/FIQ/VIRQ/VFIQ interrupt outputs to the CPU's inputs.
      */
     for (i = 0; i < smp_cpus; i++) {
         DeviceState *cpudev = DEVICE(qemu_get_cpu(i));
@@ -571,9 +571,17 @@ static void create_gic(VirtMachineState *vms, qemu_irq *pic)
                                                    ppibase + timer_irq[irq]));
         }
 
+        qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt", 0,
+                                    qdev_get_gpio_in(gicdev, ppibase
+                                                     + ARCH_GICV3_MAINT_IRQ));
+
         sysbus_connect_irq(gicbusdev, i, qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
         sysbus_connect_irq(gicbusdev, i + smp_cpus,
                            qdev_get_gpio_in(cpudev, ARM_CPU_FIQ));
+        sysbus_connect_irq(gicbusdev, i + 2 * smp_cpus,
+                           qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ));
+        sysbus_connect_irq(gicbusdev, i + 3 * smp_cpus,
+                           qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ));
     }
 
     for (i = 0; i < NUM_IRQS; i++) {
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Qemu-devel] [PATCH v2 05/18] target-arm: Add ARMCPU fields for GIC CPU i/f config
  2017-01-09 16:05 [Qemu-devel] [PATCH v2 00/18] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs Peter Maydell
                   ` (3 preceding siblings ...)
  2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 04/18] hw/arm/virt: Wire VIRQ, VFIQ, maintenance irq lines from GIC to CPU Peter Maydell
@ 2017-01-09 16:05 ` Peter Maydell
  2017-01-17 22:12   ` Alistair Francis
  2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 06/18] hw/intc/gicv3: Add defines for ICH system register fields Peter Maydell
                   ` (13 subsequent siblings)
  18 siblings, 1 reply; 37+ messages in thread
From: Peter Maydell @ 2017-01-09 16:05 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: patches, Andrew Jones, Christoffer Dall, Edgar E . Iglesias,
	Alistair Francis

Add fields to the ARMCPU structure to allow CPU classes to
specify the configurable aspects of their GIC CPU interface.
In particular, the virtualization support allows different
values for number of list registers, priority bits and
preemption bits.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target/arm/cpu.h   | 5 +++++
 target/arm/cpu64.c | 6 ++++++
 2 files changed, 11 insertions(+)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 764b511..28c5d8f 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -659,6 +659,11 @@ struct ARMCPU {
     uint32_t dcz_blocksize;
     uint64_t rvbar;
 
+    /* Configurable aspects of GIC cpu interface (which is part of the CPU) */
+    int gic_num_lrs; /* number of list registers */
+    int gic_vpribits; /* number of virtual priority bits */
+    int gic_vprebits; /* number of virtual preemption bits */
+
     ARMELChangeHook *el_change_hook;
     void *el_change_hook_opaque;
 };
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index 549cb1e..73c7f31 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -147,6 +147,9 @@ static void aarch64_a57_initfn(Object *obj)
     cpu->ccsidr[1] = 0x201fe012; /* 48KB L1 icache */
     cpu->ccsidr[2] = 0x70ffe07a; /* 2048KB L2 cache */
     cpu->dcz_blocksize = 4; /* 64 bytes */
+    cpu->gic_num_lrs = 4;
+    cpu->gic_vpribits = 5;
+    cpu->gic_vprebits = 5;
     define_arm_cp_regs(cpu, cortex_a57_a53_cp_reginfo);
 }
 
@@ -201,6 +204,9 @@ static void aarch64_a53_initfn(Object *obj)
     cpu->ccsidr[1] = 0x201fe00a; /* 32KB L1 icache */
     cpu->ccsidr[2] = 0x707fe07a; /* 1024KB L2 cache */
     cpu->dcz_blocksize = 4; /* 64 bytes */
+    cpu->gic_num_lrs = 4;
+    cpu->gic_vpribits = 5;
+    cpu->gic_vprebits = 5;
     define_arm_cp_regs(cpu, cortex_a57_a53_cp_reginfo);
 }
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Qemu-devel] [PATCH v2 06/18] hw/intc/gicv3: Add defines for ICH system register fields
  2017-01-09 16:05 [Qemu-devel] [PATCH v2 00/18] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs Peter Maydell
                   ` (4 preceding siblings ...)
  2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 05/18] target-arm: Add ARMCPU fields for GIC CPU i/f config Peter Maydell
@ 2017-01-09 16:05 ` Peter Maydell
  2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 07/18] hw/intc/gicv3: Add data fields for virtualization support Peter Maydell
                   ` (12 subsequent siblings)
  18 siblings, 0 replies; 37+ messages in thread
From: Peter Maydell @ 2017-01-09 16:05 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: patches, Andrew Jones, Christoffer Dall, Edgar E . Iglesias,
	Alistair Francis

Add defines to gicv3_internal.h for fields in the ICH_*
system registers which form the GIC virtualization control
interface.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/intc/gicv3_internal.h | 79 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 79 insertions(+)

diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
index 8f3567e..aeb801d 100644
--- a/hw/intc/gicv3_internal.h
+++ b/hw/intc/gicv3_internal.h
@@ -159,6 +159,85 @@
 #define ICC_CTLR_EL3_A3V (1U << 15)
 #define ICC_CTLR_EL3_NDS (1U << 17)
 
+#define ICH_VMCR_EL2_VENG0_SHIFT 0
+#define ICH_VMCR_EL2_VENG0 (1U << ICH_VMCR_EL2_VENG0_SHIFT)
+#define ICH_VMCR_EL2_VENG1_SHIFT 1
+#define ICH_VMCR_EL2_VENG1 (1U << ICH_VMCR_EL2_VENG1_SHIFT)
+#define ICH_VMCR_EL2_VACKCTL (1U << 2)
+#define ICH_VMCR_EL2_VFIQEN (1U << 3)
+#define ICH_VMCR_EL2_VCBPR_SHIFT 4
+#define ICH_VMCR_EL2_VCBPR (1U << ICH_VMCR_EL2_VCBPR_SHIFT)
+#define ICH_VMCR_EL2_VEOIM_SHIFT 9
+#define ICH_VMCR_EL2_VEOIM (1U << ICH_VMCR_EL2_VEOIM_SHIFT)
+#define ICH_VMCR_EL2_VBPR1_SHIFT 18
+#define ICH_VMCR_EL2_VBPR1_LENGTH 3
+#define ICH_VMCR_EL2_VBPR1_MASK (0x7U << ICH_VMCR_EL2_VBPR1_SHIFT)
+#define ICH_VMCR_EL2_VBPR0_SHIFT 21
+#define ICH_VMCR_EL2_VBPR0_LENGTH 3
+#define ICH_VMCR_EL2_VBPR0_MASK (0x7U << ICH_VMCR_EL2_VBPR0_SHIFT)
+#define ICH_VMCR_EL2_VPMR_SHIFT 24
+#define ICH_VMCR_EL2_VPMR_LENGTH 8
+#define ICH_VMCR_EL2_VPMR_MASK (0xffU << ICH_VMCR_EL2_VPMR_SHIFT)
+
+#define ICH_HCR_EL2_EN (1U << 0)
+#define ICH_HCR_EL2_UIE (1U << 1)
+#define ICH_HCR_EL2_LRENPIE (1U << 2)
+#define ICH_HCR_EL2_NPIE (1U << 3)
+#define ICH_HCR_EL2_VGRP0EIE (1U << 4)
+#define ICH_HCR_EL2_VGRP0DIE (1U << 5)
+#define ICH_HCR_EL2_VGRP1EIE (1U << 6)
+#define ICH_HCR_EL2_VGRP1DIE (1U << 7)
+#define ICH_HCR_EL2_TC (1U << 10)
+#define ICH_HCR_EL2_TALL0 (1U << 11)
+#define ICH_HCR_EL2_TALL1 (1U << 12)
+#define ICH_HCR_EL2_TSEI (1U << 13)
+#define ICH_HCR_EL2_TDIR (1U << 14)
+#define ICH_HCR_EL2_EOICOUNT_SHIFT 27
+#define ICH_HCR_EL2_EOICOUNT_LENGTH 5
+#define ICH_HCR_EL2_EOICOUNT_MASK (0x1fU << ICH_HCR_EL2_EOICOUNT_SHIFT)
+
+#define ICH_LR_EL2_VINTID_SHIFT 0
+#define ICH_LR_EL2_VINTID_LENGTH 32
+#define ICH_LR_EL2_VINTID_MASK (0xffffffffULL << ICH_LR_EL2_VINTID_SHIFT)
+#define ICH_LR_EL2_PINTID_SHIFT 32
+#define ICH_LR_EL2_PINTID_LENGTH 10
+#define ICH_LR_EL2_PINTID_MASK (0x3ffULL << ICH_LR_EL2_PINTID_SHIFT)
+/* Note that EOI shares with the top bit of the pINTID field */
+#define ICH_LR_EL2_EOI (1ULL << 41)
+#define ICH_LR_EL2_PRIORITY_SHIFT 48
+#define ICH_LR_EL2_PRIORITY_LENGTH 8
+#define ICH_LR_EL2_PRIORITY_MASK (0xffULL << ICH_LR_EL2_PRIORITY_SHIFT)
+#define ICH_LR_EL2_GROUP (1ULL << 60)
+#define ICH_LR_EL2_HW (1ULL << 61)
+#define ICH_LR_EL2_STATE_SHIFT 62
+#define ICH_LR_EL2_STATE_LENGTH 2
+#define ICH_LR_EL2_STATE_MASK (3ULL << ICH_LR_EL2_STATE_SHIFT)
+/* values for the state field: */
+#define ICH_LR_EL2_STATE_INVALID 0
+#define ICH_LR_EL2_STATE_PENDING 1
+#define ICH_LR_EL2_STATE_ACTIVE 2
+#define ICH_LR_EL2_STATE_ACTIVE_PENDING 3
+#define ICH_LR_EL2_STATE_PENDING_BIT (1ULL << ICH_LR_EL2_STATE_SHIFT)
+#define ICH_LR_EL2_STATE_ACTIVE_BIT (2ULL << ICH_LR_EL2_STATE_SHIFT)
+
+#define ICH_MISR_EL2_EOI (1U << 0)
+#define ICH_MISR_EL2_U (1U << 1)
+#define ICH_MISR_EL2_LRENP (1U << 2)
+#define ICH_MISR_EL2_NP (1U << 3)
+#define ICH_MISR_EL2_VGRP0E (1U << 4)
+#define ICH_MISR_EL2_VGRP0D (1U << 5)
+#define ICH_MISR_EL2_VGRP1E (1U << 6)
+#define ICH_MISR_EL2_VGRP1D (1U << 7)
+
+#define ICH_VTR_EL2_LISTREGS_SHIFT 0
+#define ICH_VTR_EL2_TDS (1U << 19)
+#define ICH_VTR_EL2_NV4 (1U << 20)
+#define ICH_VTR_EL2_A3V (1U << 21)
+#define ICH_VTR_EL2_SEIS (1U << 22)
+#define ICH_VTR_EL2_IDBITS_SHIFT 23
+#define ICH_VTR_EL2_PREBITS_SHIFT 26
+#define ICH_VTR_EL2_PRIBITS_SHIFT 29
+
 /* Special interrupt IDs */
 #define INTID_SECURE 1020
 #define INTID_NONSECURE 1021
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Qemu-devel] [PATCH v2 07/18] hw/intc/gicv3: Add data fields for virtualization support
  2017-01-09 16:05 [Qemu-devel] [PATCH v2 00/18] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs Peter Maydell
                   ` (5 preceding siblings ...)
  2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 06/18] hw/intc/gicv3: Add defines for ICH system register fields Peter Maydell
@ 2017-01-09 16:05 ` Peter Maydell
  2017-01-17 22:13   ` Alistair Francis
  2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 08/18] hw/intc/arm_gicv3: Add accessors for ICH_ system registers Peter Maydell
                   ` (11 subsequent siblings)
  18 siblings, 1 reply; 37+ messages in thread
From: Peter Maydell @ 2017-01-09 16:05 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: patches, Andrew Jones, Christoffer Dall, Edgar E . Iglesias,
	Alistair Francis

As the first step in adding support for the virtualization
extensions to the GICv3 emulation:
 * add the necessary data fields to the state structures
 * add the fields to the migration state, as a subsection
   which is only present if virtualization is enabled

The use of a subsection means we retain migration
compatibility as EL2 is not enabled on any CPUs currently.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 include/hw/intc/arm_gicv3_common.h | 18 ++++++++++++++++++
 hw/intc/arm_gicv3_common.c         | 25 +++++++++++++++++++++++++
 hw/intc/arm_gicv3_cpuif.c          | 13 +++++++++++++
 3 files changed, 56 insertions(+)

diff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h
index beb2c77..665d3f8 100644
--- a/include/hw/intc/arm_gicv3_common.h
+++ b/include/hw/intc/arm_gicv3_common.h
@@ -38,6 +38,9 @@
 /* Number of SGI target-list bits */
 #define GICV3_TARGETLIST_BITS 16
 
+/* Maximum number of list registers (architectural limit) */
+#define GICV3_LR_MAX 16
+
 /* Minimum BPR for Secure, or when security not enabled */
 #define GIC_MIN_BPR 0
 /* Minimum BPR for Nonsecure when security is enabled */
@@ -175,6 +178,21 @@ struct GICv3CPUState {
     uint64_t icc_igrpen[3];
     uint64_t icc_ctlr_el3;
 
+    /* Virtualization control interface */
+    uint64_t ich_apr[3][4]; /* ich_apr[GICV3_G1][x] never used */
+    uint64_t ich_hcr_el2;
+    uint64_t ich_lr_el2[GICV3_LR_MAX];
+    uint64_t ich_vmcr_el2;
+
+    /* Properties of the CPU interface. These are initialized from
+     * the settings in the CPU proper.
+     * If the number of implemented list registers is 0 then the
+     * virtualization support is not implemented.
+     */
+    int num_list_regs;
+    int vpribits; /* number of virtual priority bits */
+    int vprebits; /* number of virtual preemption bits */
+
     /* Current highest priority pending interrupt for this CPU.
      * This is cached information that can be recalculated from the
      * real state above; it doesn't need to be migrated.
diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
index 0ee67a4..16b9b0f 100644
--- a/hw/intc/arm_gicv3_common.c
+++ b/hw/intc/arm_gicv3_common.c
@@ -49,6 +49,27 @@ static int gicv3_post_load(void *opaque, int version_id)
     return 0;
 }
 
+static bool virt_state_needed(void *opaque)
+{
+    GICv3CPUState *cs = opaque;
+
+    return cs->num_list_regs != 0;
+}
+
+static const VMStateDescription vmstate_gicv3_cpu_virt = {
+    .name = "arm_gicv3_cpu/virt",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .needed = virt_state_needed,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT64_2DARRAY(ich_apr, GICv3CPUState, 3, 4),
+        VMSTATE_UINT64(ich_hcr_el2, GICv3CPUState),
+        VMSTATE_UINT64_ARRAY(ich_lr_el2, GICv3CPUState, GICV3_LR_MAX),
+        VMSTATE_UINT64(ich_vmcr_el2, GICv3CPUState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
 static const VMStateDescription vmstate_gicv3_cpu = {
     .name = "arm_gicv3_cpu",
     .version_id = 1,
@@ -75,6 +96,10 @@ static const VMStateDescription vmstate_gicv3_cpu = {
         VMSTATE_UINT64_ARRAY(icc_igrpen, GICv3CPUState, 3),
         VMSTATE_UINT64(icc_ctlr_el3, GICv3CPUState),
         VMSTATE_END_OF_LIST()
+    },
+    .subsections = (const VMStateDescription * []) {
+        &vmstate_gicv3_cpu_virt,
+        NULL
     }
 };
 
diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
index 35e8eb3..d2f859c 100644
--- a/hw/intc/arm_gicv3_cpuif.c
+++ b/hw/intc/arm_gicv3_cpuif.c
@@ -36,6 +36,12 @@ static bool gicv3_use_ns_bank(CPUARMState *env)
     return !arm_is_secure_below_el3(env);
 }
 
+/* The minimum BPR for the virtual interface is a configurable property */
+static inline int icv_min_vbpr(GICv3CPUState *cs)
+{
+    return 7 - cs->vprebits;
+}
+
 static int icc_highest_active_prio(GICv3CPUState *cs)
 {
     /* Calculate the current running priority based on the set bits
@@ -1081,6 +1087,13 @@ static void icc_reset(CPUARMState *env, const ARMCPRegInfo *ri)
     cs->icc_ctlr_el3 = ICC_CTLR_EL3_NDS | ICC_CTLR_EL3_A3V |
         (1 << ICC_CTLR_EL3_IDBITS_SHIFT) |
         (7 << ICC_CTLR_EL3_PRIBITS_SHIFT);
+
+    memset(cs->ich_apr, 0, sizeof(cs->ich_apr));
+    cs->ich_hcr_el2 = 0;
+    memset(cs->ich_lr_el2, 0, sizeof(cs->ich_lr_el2));
+    cs->ich_vmcr_el2 = ICH_VMCR_EL2_VFIQEN |
+        (icv_min_vbpr(cs) << ICH_VMCR_EL2_VBPR1_SHIFT) |
+        (icv_min_vbpr(cs) << ICH_VMCR_EL2_VBPR0_SHIFT);
 }
 
 static const ARMCPRegInfo gicv3_cpuif_reginfo[] = {
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Qemu-devel] [PATCH v2 08/18] hw/intc/arm_gicv3: Add accessors for ICH_ system registers
  2017-01-09 16:05 [Qemu-devel] [PATCH v2 00/18] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs Peter Maydell
                   ` (6 preceding siblings ...)
  2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 07/18] hw/intc/gicv3: Add data fields for virtualization support Peter Maydell
@ 2017-01-09 16:05 ` Peter Maydell
  2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 09/18] hw/intc/arm_gicv3: Implement ICV_ registers which are just accessors Peter Maydell
                   ` (10 subsequent siblings)
  18 siblings, 0 replies; 37+ messages in thread
From: Peter Maydell @ 2017-01-09 16:05 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: patches, Andrew Jones, Christoffer Dall, Edgar E . Iglesias,
	Alistair Francis

The GICv3 virtualization interface includes system registers
accessible only to the hypervisor which form the control
interface for interrupt virtualization. Implement these
registers.

The function gicv3_cpuif_virt_update() which determines
whether it needs to signal vIRQ, vFIQ or a maintenance
interrupt is introduced here as a stub function -- its
implementation will be added in a subsequent commit.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/intc/arm_gicv3_cpuif.c | 477 ++++++++++++++++++++++++++++++++++++++++++++++
 hw/intc/trace-events      |  16 ++
 2 files changed, 493 insertions(+)

diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
index d2f859c..585c91c 100644
--- a/hw/intc/arm_gicv3_cpuif.c
+++ b/hw/intc/arm_gicv3_cpuif.c
@@ -42,6 +42,132 @@ static inline int icv_min_vbpr(GICv3CPUState *cs)
     return 7 - cs->vprebits;
 }
 
+/* Simple accessor functions for LR fields */
+static int ich_lr_state(uint64_t lr)
+{
+    return extract64(lr, ICH_LR_EL2_STATE_SHIFT, ICH_LR_EL2_STATE_LENGTH);
+}
+
+static int read_vbpr(GICv3CPUState *cs, int grp)
+{
+    /* Read VBPR value out of the VMCR field (caller must handle
+     * VCBPR effects if required)
+     */
+    if (grp == GICV3_G0) {
+        return extract64(cs->ich_vmcr_el2, ICH_VMCR_EL2_VBPR0_SHIFT,
+                     ICH_VMCR_EL2_VBPR0_LENGTH);
+    } else {
+        return extract64(cs->ich_vmcr_el2, ICH_VMCR_EL2_VBPR1_SHIFT,
+                         ICH_VMCR_EL2_VBPR1_LENGTH);
+    }
+}
+
+static void write_vbpr(GICv3CPUState *cs, int grp, int value)
+{
+    /* Write new VBPR1 value, handling the "writing a value less than
+     * the minimum sets it to the minimum" semantics.
+     */
+    int min = icv_min_vbpr(cs);
+
+    if (grp != GICV3_G0) {
+        min++;
+    }
+
+    value = MAX(value, min);
+
+    if (grp == GICV3_G0) {
+        cs->ich_vmcr_el2 = deposit64(cs->ich_vmcr_el2, ICH_VMCR_EL2_VBPR0_SHIFT,
+                                     ICH_VMCR_EL2_VBPR0_LENGTH, value);
+    } else {
+        cs->ich_vmcr_el2 = deposit64(cs->ich_vmcr_el2, ICH_VMCR_EL2_VBPR1_SHIFT,
+                                     ICH_VMCR_EL2_VBPR1_LENGTH, value);
+    }
+}
+
+static uint32_t eoi_maintenance_interrupt_state(GICv3CPUState *cs,
+                                                uint32_t *misr)
+{
+    /* Return a set of bits indicating the EOI maintenance interrupt status
+     * for each list register. The EOI maintenance interrupt status is
+     * 1 if LR.State == 0 && LR.HW == 0 && LR.EOI == 1
+     * (see the GICv3 spec for the ICH_EISR_EL2 register).
+     * If misr is not NULL then we should also collect the information
+     * about the MISR.EOI, MISR.NP and MISR.U bits.
+     */
+    uint32_t value = 0;
+    int validcount = 0;
+    bool seenpending = false;
+    int i;
+
+    for (i = 0; i < cs->num_list_regs; i++) {
+        uint64_t lr = cs->ich_lr_el2[i];
+
+        if ((lr & (ICH_LR_EL2_STATE_MASK | ICH_LR_EL2_HW | ICH_LR_EL2_EOI))
+            == ICH_LR_EL2_EOI) {
+            value |= (1 << i);
+        }
+        if ((lr & ICH_LR_EL2_STATE_MASK)) {
+            validcount++;
+        }
+        if (ich_lr_state(lr) == ICH_LR_EL2_STATE_PENDING) {
+            seenpending = true;
+        }
+    }
+
+    if (misr) {
+        if (validcount < 2 && (cs->ich_hcr_el2 & ICH_HCR_EL2_UIE)) {
+            *misr |= ICH_MISR_EL2_U;
+        }
+        if (!seenpending && (cs->ich_hcr_el2 & ICH_HCR_EL2_NPIE)) {
+            *misr |= ICH_MISR_EL2_NP;
+        }
+        if (value) {
+            *misr |= ICH_MISR_EL2_EOI;
+        }
+    }
+    return value;
+}
+
+static uint32_t maintenance_interrupt_state(GICv3CPUState *cs)
+{
+    /* Return a set of bits indicating the maintenance interrupt status
+     * (as seen in the ICH_MISR_EL2 register).
+     */
+    uint32_t value = 0;
+
+    /* Scan list registers and fill in the U, NP and EOI bits */
+    eoi_maintenance_interrupt_state(cs, &value);
+
+    if (cs->ich_hcr_el2 & (ICH_HCR_EL2_LRENPIE | ICH_HCR_EL2_EOICOUNT_MASK)) {
+        value |= ICH_MISR_EL2_LRENP;
+    }
+
+    if ((cs->ich_hcr_el2 & ICH_HCR_EL2_VGRP0EIE) &&
+        (cs->ich_vmcr_el2 & ICH_VMCR_EL2_VENG0)) {
+        value |= ICH_MISR_EL2_VGRP0E;
+    }
+
+    if ((cs->ich_hcr_el2 & ICH_HCR_EL2_VGRP0DIE) &&
+        !(cs->ich_vmcr_el2 & ICH_VMCR_EL2_VENG1)) {
+        value |= ICH_MISR_EL2_VGRP0D;
+    }
+    if ((cs->ich_hcr_el2 & ICH_HCR_EL2_VGRP1EIE) &&
+        (cs->ich_vmcr_el2 & ICH_VMCR_EL2_VENG1)) {
+        value |= ICH_MISR_EL2_VGRP1E;
+    }
+
+    if ((cs->ich_hcr_el2 & ICH_HCR_EL2_VGRP1DIE) &&
+        !(cs->ich_vmcr_el2 & ICH_VMCR_EL2_VENG1)) {
+        value |= ICH_MISR_EL2_VGRP1D;
+    }
+
+    return value;
+}
+
+static void gicv3_cpuif_virt_update(GICv3CPUState *cs)
+{
+}
+
 static int icc_highest_active_prio(GICv3CPUState *cs)
 {
     /* Calculate the current running priority based on the set bits
@@ -1334,6 +1460,306 @@ static const ARMCPRegInfo gicv3_cpuif_reginfo[] = {
     REGINFO_SENTINEL
 };
 
+static uint64_t ich_ap_read(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+    GICv3CPUState *cs = icc_cs_from_env(env);
+    int regno = ri->opc2 & 3;
+    int grp = ri->crm & 1 ? GICV3_G0 : GICV3_G1NS;
+    uint64_t value;
+
+    value = cs->ich_apr[grp][regno];
+    trace_gicv3_ich_ap_read(ri->crm & 1, regno, gicv3_redist_affid(cs), value);
+    return value;
+}
+
+static void ich_ap_write(CPUARMState *env, const ARMCPRegInfo *ri,
+                         uint64_t value)
+{
+    GICv3CPUState *cs = icc_cs_from_env(env);
+    int regno = ri->opc2 & 3;
+    int grp = ri->crm & 1 ? GICV3_G0 : GICV3_G1NS;
+
+    trace_gicv3_ich_ap_write(ri->crm & 1, regno, gicv3_redist_affid(cs), value);
+
+    cs->ich_apr[grp][regno] = value & 0xFFFFFFFFU;
+    gicv3_cpuif_virt_update(cs);
+}
+
+static uint64_t ich_hcr_read(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+    GICv3CPUState *cs = icc_cs_from_env(env);
+    uint64_t value = cs->ich_hcr_el2;
+
+    trace_gicv3_ich_hcr_read(gicv3_redist_affid(cs), value);
+    return value;
+}
+
+static void ich_hcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
+                          uint64_t value)
+{
+    GICv3CPUState *cs = icc_cs_from_env(env);
+
+    trace_gicv3_ich_hcr_write(gicv3_redist_affid(cs), value);
+
+    value &= ICH_HCR_EL2_EN | ICH_HCR_EL2_UIE | ICH_HCR_EL2_LRENPIE |
+        ICH_HCR_EL2_NPIE | ICH_HCR_EL2_VGRP0EIE | ICH_HCR_EL2_VGRP0DIE |
+        ICH_HCR_EL2_VGRP1EIE | ICH_HCR_EL2_VGRP1DIE | ICH_HCR_EL2_TC |
+        ICH_HCR_EL2_TALL0 | ICH_HCR_EL2_TALL1 | ICH_HCR_EL2_TSEI |
+        ICH_HCR_EL2_TDIR | ICH_HCR_EL2_EOICOUNT_MASK;
+
+    cs->ich_hcr_el2 = value;
+    gicv3_cpuif_virt_update(cs);
+}
+
+static uint64_t ich_vmcr_read(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+    GICv3CPUState *cs = icc_cs_from_env(env);
+    uint64_t value = cs->ich_vmcr_el2;
+
+    trace_gicv3_ich_vmcr_read(gicv3_redist_affid(cs), value);
+    return value;
+}
+
+static void ich_vmcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
+                         uint64_t value)
+{
+    GICv3CPUState *cs = icc_cs_from_env(env);
+
+    trace_gicv3_ich_vmcr_write(gicv3_redist_affid(cs), value);
+
+    value &= ICH_VMCR_EL2_VENG0 | ICH_VMCR_EL2_VENG1 | ICH_VMCR_EL2_VCBPR |
+        ICH_VMCR_EL2_VEOIM | ICH_VMCR_EL2_VBPR1_MASK |
+        ICH_VMCR_EL2_VBPR0_MASK | ICH_VMCR_EL2_VPMR_MASK;
+    value |= ICH_VMCR_EL2_VFIQEN;
+
+    cs->ich_vmcr_el2 = value;
+    /* Enforce "writing BPRs to less than minimum sets them to the minimum"
+     * by reading and writing back the fields.
+     */
+    write_vbpr(cs, GICV3_G1, read_vbpr(cs, GICV3_G0));
+    write_vbpr(cs, GICV3_G1, read_vbpr(cs, GICV3_G1));
+
+    gicv3_cpuif_virt_update(cs);
+}
+
+static uint64_t ich_lr_read(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+    GICv3CPUState *cs = icc_cs_from_env(env);
+    int regno = ri->opc2 | ((ri->crm & 1) << 3);
+    uint64_t value;
+
+    /* This read function handles all of:
+     * 64-bit reads of the whole LR
+     * 32-bit reads of the low half of the LR
+     * 32-bit reads of the high half of the LR
+     */
+    if (ri->state == ARM_CP_STATE_AA32) {
+        if (ri->crm >= 14) {
+            value = extract64(cs->ich_lr_el2[regno], 32, 32);
+            trace_gicv3_ich_lrc_read(regno, gicv3_redist_affid(cs), value);
+        } else {
+            value = extract64(cs->ich_lr_el2[regno], 0, 32);
+            trace_gicv3_ich_lr32_read(regno, gicv3_redist_affid(cs), value);
+        }
+    } else {
+        value = cs->ich_lr_el2[regno];
+        trace_gicv3_ich_lr_read(regno, gicv3_redist_affid(cs), value);
+    }
+
+    return value;
+}
+
+static void ich_lr_write(CPUARMState *env, const ARMCPRegInfo *ri,
+                         uint64_t value)
+{
+    GICv3CPUState *cs = icc_cs_from_env(env);
+    int regno = ri->opc2 | ((ri->crm & 1) << 3);
+
+    /* This write function handles all of:
+     * 64-bit writes to the whole LR
+     * 32-bit writes to the low half of the LR
+     * 32-bit writes to the high half of the LR
+     */
+    if (ri->state == ARM_CP_STATE_AA32) {
+        if (ri->crm >= 14) {
+            trace_gicv3_ich_lrc_write(regno, gicv3_redist_affid(cs), value);
+            value = deposit64(cs->ich_lr_el2[regno], 32, 32, value);
+        } else {
+            trace_gicv3_ich_lr32_write(regno, gicv3_redist_affid(cs), value);
+            value = deposit64(cs->ich_lr_el2[regno], 0, 32, value);
+        }
+    } else {
+        trace_gicv3_ich_lr_write(regno, gicv3_redist_affid(cs), value);
+    }
+
+    /* Enforce RES0 bits in priority field */
+    if (cs->vpribits < 8) {
+        value = deposit64(value, ICH_LR_EL2_PRIORITY_SHIFT,
+                          8 - cs->vpribits, 0);
+    }
+
+    cs->ich_lr_el2[regno] = value;
+    gicv3_cpuif_virt_update(cs);
+}
+
+static uint64_t ich_vtr_read(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+    GICv3CPUState *cs = icc_cs_from_env(env);
+    uint64_t value;
+
+    value = ((cs->num_list_regs - 1) << ICH_VTR_EL2_LISTREGS_SHIFT)
+        | ICH_VTR_EL2_TDS | ICH_VTR_EL2_NV4 | ICH_VTR_EL2_A3V
+        | (1 << ICH_VTR_EL2_IDBITS_SHIFT)
+        | ((cs->vprebits - 1) << ICH_VTR_EL2_PREBITS_SHIFT)
+        | ((cs->vpribits - 1) << ICH_VTR_EL2_PRIBITS_SHIFT);
+
+    trace_gicv3_ich_vtr_read(gicv3_redist_affid(cs), value);
+    return value;
+}
+
+static uint64_t ich_misr_read(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+    GICv3CPUState *cs = icc_cs_from_env(env);
+    uint64_t value = maintenance_interrupt_state(cs);
+
+    trace_gicv3_ich_misr_read(gicv3_redist_affid(cs), value);
+    return value;
+}
+
+static uint64_t ich_eisr_read(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+    GICv3CPUState *cs = icc_cs_from_env(env);
+    uint64_t value = eoi_maintenance_interrupt_state(cs, NULL);
+
+    trace_gicv3_ich_eisr_read(gicv3_redist_affid(cs), value);
+    return value;
+}
+
+static uint64_t ich_elrsr_read(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+    GICv3CPUState *cs = icc_cs_from_env(env);
+    uint64_t value = 0;
+    int i;
+
+    for (i = 0; i < cs->num_list_regs; i++) {
+        uint64_t lr = cs->ich_lr_el2[i];
+
+        if ((lr & ICH_LR_EL2_STATE_MASK) == 0 &&
+            ((lr & ICH_LR_EL2_HW) == 1 || (lr & ICH_LR_EL2_EOI) == 0)) {
+            value |= (1 << i);
+        }
+    }
+
+    trace_gicv3_ich_elrsr_read(gicv3_redist_affid(cs), value);
+    return value;
+}
+
+static const ARMCPRegInfo gicv3_cpuif_hcr_reginfo[] = {
+    { .name = "ICH_AP0R0_EL2", .state = ARM_CP_STATE_BOTH,
+      .opc0 = 3, .opc1 = 4, .crn = 12, .crm = 8, .opc2 = 0,
+      .type = ARM_CP_IO | ARM_CP_NO_RAW,
+      .access = PL2_RW,
+      .readfn = ich_ap_read,
+      .writefn = ich_ap_write,
+    },
+    { .name = "ICH_AP1R0_EL2", .state = ARM_CP_STATE_BOTH,
+      .opc0 = 3, .opc1 = 4, .crn = 12, .crm = 9, .opc2 = 0,
+      .type = ARM_CP_IO | ARM_CP_NO_RAW,
+      .access = PL2_RW,
+      .readfn = ich_ap_read,
+      .writefn = ich_ap_write,
+    },
+    { .name = "ICH_HCR_EL2", .state = ARM_CP_STATE_BOTH,
+      .opc0 = 3, .opc1 = 4, .crn = 12, .crm = 11, .opc2 = 0,
+      .type = ARM_CP_IO | ARM_CP_NO_RAW,
+      .access = PL2_RW,
+      .readfn = ich_hcr_read,
+      .writefn = ich_hcr_write,
+    },
+    { .name = "ICH_VTR_EL2", .state = ARM_CP_STATE_BOTH,
+      .opc0 = 3, .opc1 = 4, .crn = 12, .crm = 11, .opc2 = 1,
+      .type = ARM_CP_IO | ARM_CP_NO_RAW,
+      .access = PL2_R,
+      .readfn = ich_vtr_read,
+    },
+    { .name = "ICH_MISR_EL2", .state = ARM_CP_STATE_BOTH,
+      .opc0 = 3, .opc1 = 4, .crn = 12, .crm = 11, .opc2 = 2,
+      .type = ARM_CP_IO | ARM_CP_NO_RAW,
+      .access = PL2_R,
+      .readfn = ich_misr_read,
+    },
+    { .name = "ICH_EISR_EL2", .state = ARM_CP_STATE_BOTH,
+      .opc0 = 3, .opc1 = 4, .crn = 12, .crm = 11, .opc2 = 3,
+      .type = ARM_CP_IO | ARM_CP_NO_RAW,
+      .access = PL2_R,
+      .readfn = ich_eisr_read,
+    },
+    { .name = "ICH_ELRSR_EL2", .state = ARM_CP_STATE_BOTH,
+      .opc0 = 3, .opc1 = 4, .crn = 12, .crm = 11, .opc2 = 5,
+      .type = ARM_CP_IO | ARM_CP_NO_RAW,
+      .access = PL2_R,
+      .readfn = ich_elrsr_read,
+    },
+    { .name = "ICH_VMCR_EL2", .state = ARM_CP_STATE_BOTH,
+      .opc0 = 3, .opc1 = 4, .crn = 12, .crm = 11, .opc2 = 7,
+      .type = ARM_CP_IO | ARM_CP_NO_RAW,
+      .access = PL2_RW,
+      .readfn = ich_vmcr_read,
+      .writefn = ich_vmcr_write,
+    },
+    REGINFO_SENTINEL
+};
+
+static const ARMCPRegInfo gicv3_cpuif_ich_apxr1_reginfo[] = {
+    { .name = "ICH_AP0R1_EL2", .state = ARM_CP_STATE_BOTH,
+      .opc0 = 3, .opc1 = 4, .crn = 12, .crm = 8, .opc2 = 1,
+      .type = ARM_CP_IO | ARM_CP_NO_RAW,
+      .access = PL2_RW,
+      .readfn = ich_ap_read,
+      .writefn = ich_ap_write,
+    },
+    { .name = "ICH_AP1R1_EL2", .state = ARM_CP_STATE_BOTH,
+      .opc0 = 3, .opc1 = 4, .crn = 12, .crm = 9, .opc2 = 1,
+      .type = ARM_CP_IO | ARM_CP_NO_RAW,
+      .access = PL2_RW,
+      .readfn = ich_ap_read,
+      .writefn = ich_ap_write,
+    },
+    REGINFO_SENTINEL
+};
+
+static const ARMCPRegInfo gicv3_cpuif_ich_apxr23_reginfo[] = {
+    { .name = "ICH_AP0R2_EL2", .state = ARM_CP_STATE_BOTH,
+      .opc0 = 3, .opc1 = 4, .crn = 12, .crm = 8, .opc2 = 2,
+      .type = ARM_CP_IO | ARM_CP_NO_RAW,
+      .access = PL2_RW,
+      .readfn = ich_ap_read,
+      .writefn = ich_ap_write,
+    },
+    { .name = "ICH_AP0R3_EL2", .state = ARM_CP_STATE_BOTH,
+      .opc0 = 3, .opc1 = 4, .crn = 12, .crm = 8, .opc2 = 3,
+      .type = ARM_CP_IO | ARM_CP_NO_RAW,
+      .access = PL2_RW,
+      .readfn = ich_ap_read,
+      .writefn = ich_ap_write,
+    },
+    { .name = "ICH_AP1R2_EL2", .state = ARM_CP_STATE_BOTH,
+      .opc0 = 3, .opc1 = 4, .crn = 12, .crm = 9, .opc2 = 2,
+      .type = ARM_CP_IO | ARM_CP_NO_RAW,
+      .access = PL2_RW,
+      .readfn = ich_ap_read,
+      .writefn = ich_ap_write,
+    },
+    { .name = "ICH_AP1R3_EL2", .state = ARM_CP_STATE_BOTH,
+      .opc0 = 3, .opc1 = 4, .crn = 12, .crm = 9, .opc2 = 3,
+      .type = ARM_CP_IO | ARM_CP_NO_RAW,
+      .access = PL2_RW,
+      .readfn = ich_ap_read,
+      .writefn = ich_ap_write,
+    },
+    REGINFO_SENTINEL
+};
+
 static void gicv3_cpuif_el_change_hook(ARMCPU *cpu, void *opaque)
 {
     GICv3CPUState *cs = opaque;
@@ -1362,6 +1788,57 @@ void gicv3_init_cpuif(GICv3State *s)
          * to need to register anyway.
          */
         define_arm_cp_regs(cpu, gicv3_cpuif_reginfo);
+        if (arm_feature(&cpu->env, ARM_FEATURE_EL2)
+            && cpu->gic_num_lrs) {
+            int j;
+
+            cs->num_list_regs = cpu->gic_num_lrs;
+            cs->vpribits = cpu->gic_vpribits;
+            cs->vprebits = cpu->gic_vprebits;
+
+            /* Check against architectural constraints: getting these
+             * wrong would be a bug in the CPU code defining these,
+             * and the implementation relies on them holding.
+             */
+            g_assert(cs->vprebits <= cs->vpribits);
+            g_assert(cs->vprebits >= 5 && cs->vprebits <= 7);
+            g_assert(cs->vpribits >= 5 && cs->vpribits <= 8);
+
+            define_arm_cp_regs(cpu, gicv3_cpuif_hcr_reginfo);
+
+            for (j = 0; j < cs->num_list_regs; j++) {
+                /* Note that the AArch64 LRs are 64-bit; the AArch32 LRs
+                 * are split into two cp15 regs, LR (the low part, with the
+                 * same encoding as the AArch64 LR) and LRC (the high part).
+                 */
+                ARMCPRegInfo lr_regset[] = {
+                    { .name = "ICH_LRn_EL2", .state = ARM_CP_STATE_BOTH,
+                      .opc0 = 3, .opc1 = 4, .crn = 12,
+                      .crm = 12 + (j >> 3), .opc2 = j & 7,
+                      .type = ARM_CP_IO | ARM_CP_NO_RAW,
+                      .access = PL2_RW,
+                      .readfn = ich_lr_read,
+                      .writefn = ich_lr_write,
+                    },
+                    { .name = "ICH_LRCn_EL2", .state = ARM_CP_STATE_AA32,
+                      .cp = 15, .opc1 = 4, .crn = 12,
+                      .crm = 14 + (j >> 3), .opc2 = j & 7,
+                      .type = ARM_CP_IO | ARM_CP_NO_RAW,
+                      .access = PL2_RW,
+                      .readfn = ich_lr_read,
+                      .writefn = ich_lr_write,
+                    },
+                    REGINFO_SENTINEL
+                };
+                define_arm_cp_regs(cpu, lr_regset);
+            }
+            if (cs->vprebits >= 6) {
+                define_arm_cp_regs(cpu, gicv3_cpuif_ich_apxr1_reginfo);
+            }
+            if (cs->vprebits == 7) {
+                define_arm_cp_regs(cpu, gicv3_cpuif_ich_apxr23_reginfo);
+            }
+        }
         arm_register_el_change_hook(cpu, gicv3_cpuif_el_change_hook, cs);
     }
 }
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
index 340f617..4ac1ea2 100644
--- a/hw/intc/trace-events
+++ b/hw/intc/trace-events
@@ -107,6 +107,22 @@ gicv3_icc_hppir0_read(uint32_t cpu, uint64_t val) "GICv3 ICC_HPPIR0 read cpu %x
 gicv3_icc_hppir1_read(uint32_t cpu, uint64_t val) "GICv3 ICC_HPPIR1 read cpu %x value 0x%" PRIx64
 gicv3_icc_dir_write(uint32_t cpu, uint64_t val) "GICv3 ICC_DIR write cpu %x value 0x%" PRIx64
 gicv3_icc_rpr_read(uint32_t cpu, uint64_t val) "GICv3 ICC_RPR read cpu %x value 0x%" PRIx64
+gicv3_ich_ap_read(int grp, int regno, uint32_t cpu, uint64_t val) "GICv3 ICH_AP%dR%d read cpu %x value 0x%" PRIx64
+gicv3_ich_ap_write(int grp, int regno, uint32_t cpu, uint64_t val) "GICv3 ICH_AP%dR%d write cpu %x value 0x%" PRIx64
+gicv3_ich_hcr_read(uint32_t cpu, uint64_t val) "GICv3 ICH_HCR_EL2 read cpu %x value 0x%" PRIx64
+gicv3_ich_hcr_write(uint32_t cpu, uint64_t val) "GICv3 ICH_HCR_EL2 write cpu %x value 0x%" PRIx64
+gicv3_ich_vmcr_read(uint32_t cpu, uint64_t val) "GICv3 ICH_VMCR_EL2 read cpu %x value 0x%" PRIx64
+gicv3_ich_vmcr_write(uint32_t cpu, uint64_t val) "GICv3 ICH_VMCR_EL2 write cpu %x value 0x%" PRIx64
+gicv3_ich_lr_read(int regno, uint32_t cpu, uint64_t val) "GICv3 ICH_LR%d_EL2 read cpu %x value 0x%" PRIx64
+gicv3_ich_lr32_read(int regno, uint32_t cpu, uint32_t val) "GICv3 ICH_LR%d read cpu %x value 0x%" PRIx32
+gicv3_ich_lrc_read(int regno, uint32_t cpu, uint32_t val) "GICv3 ICH_LRC%d read cpu %x value 0x%" PRIx32
+gicv3_ich_lr_write(int regno, uint32_t cpu, uint64_t val) "GICv3 ICH_LR%d_EL2 write cpu %x value 0x%" PRIx64
+gicv3_ich_lr32_write(int regno, uint32_t cpu, uint32_t val) "GICv3 ICH_LR%d write cpu %x value 0x%" PRIx32
+gicv3_ich_lrc_write(int regno, uint32_t cpu, uint32_t val) "GICv3 ICH_LRC%d write cpu %x value 0x%" PRIx32
+gicv3_ich_vtr_read(uint32_t cpu, uint64_t val) "GICv3 ICH_VTR read cpu %x value 0x%" PRIx64
+gicv3_ich_misr_read(uint32_t cpu, uint64_t val) "GICv3 ICH_MISR read cpu %x value 0x%" PRIx64
+gicv3_ich_eisr_read(uint32_t cpu, uint64_t val) "GICv3 ICH_EISR read cpu %x value 0x%" PRIx64
+gicv3_ich_elrsr_read(uint32_t cpu, uint64_t val) "GICv3 ICH_ELRSR read cpu %x value 0x%" PRIx64
 
 # hw/intc/arm_gicv3_dist.c
 gicv3_dist_read(uint64_t offset, uint64_t data, unsigned size, bool secure) "GICv3 distributor read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u secure %d"
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Qemu-devel] [PATCH v2 09/18] hw/intc/arm_gicv3: Implement ICV_ registers which are just accessors
  2017-01-09 16:05 [Qemu-devel] [PATCH v2 00/18] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs Peter Maydell
                   ` (7 preceding siblings ...)
  2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 08/18] hw/intc/arm_gicv3: Add accessors for ICH_ system registers Peter Maydell
@ 2017-01-09 16:05 ` Peter Maydell
  2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 10/18] hw/intc/arm_gicv3: Implement ICV_ HPPIR, DIR and RPR registers Peter Maydell
                   ` (9 subsequent siblings)
  18 siblings, 0 replies; 37+ messages in thread
From: Peter Maydell @ 2017-01-09 16:05 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: patches, Andrew Jones, Christoffer Dall, Edgar E . Iglesias,
	Alistair Francis

If the HCR_EL2.IMO or FMO bits are set, accesses to ICC_
system registers are redirected to be accesses to ICV_
registers (the guest-visible interface to the virtual
interrupt controller). Implement this behaviour for the
ICV_ registers which are simple accessors to the underlying
register state.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/intc/arm_gicv3_cpuif.c | 239 ++++++++++++++++++++++++++++++++++++++++++++++
 hw/intc/trace-events      |  10 ++
 2 files changed, 249 insertions(+)

diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
index 585c91c..40a52ce 100644
--- a/hw/intc/arm_gicv3_cpuif.c
+++ b/hw/intc/arm_gicv3_cpuif.c
@@ -13,6 +13,7 @@
  */
 
 #include "qemu/osdep.h"
+#include "qemu/bitops.h"
 #include "trace.h"
 #include "gicv3_internal.h"
 #include "cpu.h"
@@ -48,6 +49,26 @@ static int ich_lr_state(uint64_t lr)
     return extract64(lr, ICH_LR_EL2_STATE_SHIFT, ICH_LR_EL2_STATE_LENGTH);
 }
 
+static bool icv_access(CPUARMState *env, int hcr_flags)
+{
+    /* Return true if this ICC_ register access should really be
+     * directed to an ICV_ access. hcr_flags is a mask of
+     * HCR_EL2 bits to check: we treat this as an ICV_ access
+     * if we are in NS EL1 and at least one of the specified
+     * HCR_EL2 bits is set.
+     *
+     * ICV registers fall into four categories:
+     *  * access if NS EL1 and HCR_EL2.FMO == 1:
+     *    all ICV regs with '0' in their name
+     *  * access if NS EL1 and HCR_EL2.IMO == 1:
+     *    all ICV regs with '1' in their name
+     *  * access if NS EL1 and either IMO or FMO == 1:
+     *    CTLR, DIR, PMR, RPR
+     */
+    return (env->cp15.hcr_el2 & hcr_flags) && arm_current_el(env) == 1
+        && !arm_is_secure_below_el3(env);
+}
+
 static int read_vbpr(GICv3CPUState *cs, int grp)
 {
     /* Read VBPR value out of the VMCR field (caller must handle
@@ -84,6 +105,16 @@ static void write_vbpr(GICv3CPUState *cs, int grp, int value)
     }
 }
 
+static uint32_t icv_fullprio_mask(GICv3CPUState *cs)
+{
+    /* Return a mask word which clears the unimplemented priority bits
+     * from a priority value for a virtual interrupt. (Not to be confused
+     * with the group priority, whose mask depends on the value of VBPR
+     * for the interrupt group.)
+     */
+    return ~0U << (8 - cs->vpribits);
+}
+
 static uint32_t eoi_maintenance_interrupt_state(GICv3CPUState *cs,
                                                 uint32_t *misr)
 {
@@ -168,6 +199,170 @@ static void gicv3_cpuif_virt_update(GICv3CPUState *cs)
 {
 }
 
+static uint64_t icv_ap_read(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+    GICv3CPUState *cs = icc_cs_from_env(env);
+    int regno = ri->opc2 & 3;
+    int grp = ri->crm & 1 ? GICV3_G0 : GICV3_G1NS;
+    uint64_t value = cs->ich_apr[grp][regno];
+
+    trace_gicv3_icv_ap_read(ri->crm & 1, regno, gicv3_redist_affid(cs), value);
+    return value;
+}
+
+static void icv_ap_write(CPUARMState *env, const ARMCPRegInfo *ri,
+                         uint64_t value)
+{
+    GICv3CPUState *cs = icc_cs_from_env(env);
+    int regno = ri->opc2 & 3;
+    int grp = ri->crm & 1 ? GICV3_G0 : GICV3_G1NS;
+
+    trace_gicv3_icv_ap_write(ri->crm & 1, regno, gicv3_redist_affid(cs), value);
+
+    cs->ich_apr[grp][regno] = value & 0xFFFFFFFFU;
+
+    gicv3_cpuif_virt_update(cs);
+    return;
+}
+
+static uint64_t icv_bpr_read(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+    GICv3CPUState *cs = icc_cs_from_env(env);
+    int grp = (ri->crm == 8) ? GICV3_G0 : GICV3_G1NS;
+    uint64_t bpr;
+    bool satinc = false;
+
+    if (grp == GICV3_G1NS && (cs->ich_vmcr_el2 & ICH_VMCR_EL2_VCBPR)) {
+        /* reads return bpr0 + 1 saturated to 7, writes ignored */
+        grp = GICV3_G0;
+        satinc = true;
+    }
+
+    bpr = read_vbpr(cs, grp);
+
+    if (satinc) {
+        bpr++;
+        bpr = MIN(bpr, 7);
+    }
+
+    trace_gicv3_icv_bpr_read(ri->crm == 8 ? 0 : 1, gicv3_redist_affid(cs), bpr);
+
+    return bpr;
+}
+
+static void icv_bpr_write(CPUARMState *env, const ARMCPRegInfo *ri,
+                          uint64_t value)
+{
+    GICv3CPUState *cs = icc_cs_from_env(env);
+    int grp = (ri->crm == 8) ? GICV3_G0 : GICV3_G1NS;
+
+    trace_gicv3_icv_bpr_write(ri->crm == 8 ? 0 : 1,
+                              gicv3_redist_affid(cs), value);
+
+    if (grp == GICV3_G1NS && (cs->ich_vmcr_el2 & ICH_VMCR_EL2_VCBPR)) {
+        /* reads return bpr0 + 1 saturated to 7, writes ignored */
+        return;
+    }
+
+    write_vbpr(cs, grp, value);
+
+    gicv3_cpuif_virt_update(cs);
+}
+
+static uint64_t icv_pmr_read(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+    GICv3CPUState *cs = icc_cs_from_env(env);
+    uint64_t value;
+
+    value = extract64(cs->ich_vmcr_el2, ICH_VMCR_EL2_VPMR_SHIFT,
+                      ICH_VMCR_EL2_VPMR_LENGTH);
+
+    trace_gicv3_icv_pmr_read(gicv3_redist_affid(cs), value);
+    return value;
+}
+
+static void icv_pmr_write(CPUARMState *env, const ARMCPRegInfo *ri,
+                          uint64_t value)
+{
+    GICv3CPUState *cs = icc_cs_from_env(env);
+
+    trace_gicv3_icv_pmr_write(gicv3_redist_affid(cs), value);
+
+    value &= icv_fullprio_mask(cs);
+
+    cs->ich_vmcr_el2 = deposit64(cs->ich_vmcr_el2, ICH_VMCR_EL2_VPMR_SHIFT,
+                                 ICH_VMCR_EL2_VPMR_LENGTH, value);
+
+    gicv3_cpuif_virt_update(cs);
+}
+
+static uint64_t icv_igrpen_read(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+    GICv3CPUState *cs = icc_cs_from_env(env);
+    int enbit;
+    uint64_t value;
+
+    enbit = ri->opc2 & 1 ? ICH_VMCR_EL2_VENG1_SHIFT : ICH_VMCR_EL2_VENG0_SHIFT;
+    value = extract64(cs->ich_vmcr_el2, enbit, 1);
+
+    trace_gicv3_icv_igrpen_read(ri->opc2 & 1 ? 1 : 0,
+                                gicv3_redist_affid(cs), value);
+    return value;
+}
+
+static void icv_igrpen_write(CPUARMState *env, const ARMCPRegInfo *ri,
+                             uint64_t value)
+{
+    GICv3CPUState *cs = icc_cs_from_env(env);
+    int enbit;
+
+    trace_gicv3_icv_igrpen_write(ri->opc2 & 1 ? 1 : 0,
+                                 gicv3_redist_affid(cs), value);
+
+    enbit = ri->opc2 & 1 ? ICH_VMCR_EL2_VENG1_SHIFT : ICH_VMCR_EL2_VENG0_SHIFT;
+
+    cs->ich_vmcr_el2 = deposit64(cs->ich_vmcr_el2, enbit, 1, value);
+    gicv3_cpuif_virt_update(cs);
+}
+
+static uint64_t icv_ctlr_read(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+    GICv3CPUState *cs = icc_cs_from_env(env);
+    uint64_t value;
+
+    /* Note that the fixed fields here (A3V, SEIS, IDbits, PRIbits)
+     * should match the ones reported in ich_vtr_read().
+     */
+    value = ICC_CTLR_EL1_A3V | (1 << ICC_CTLR_EL1_IDBITS_SHIFT) |
+        (7 << ICC_CTLR_EL1_PRIBITS_SHIFT);
+
+    if (cs->ich_vmcr_el2 & ICH_VMCR_EL2_VEOIM) {
+        value |= ICC_CTLR_EL1_EOIMODE;
+    }
+
+    if (cs->ich_vmcr_el2 & ICH_VMCR_EL2_VCBPR) {
+        value |= ICC_CTLR_EL1_CBPR;
+    }
+
+    trace_gicv3_icv_ctlr_read(gicv3_redist_affid(cs), value);
+    return value;
+}
+
+static void icv_ctlr_write(CPUARMState *env, const ARMCPRegInfo *ri,
+                               uint64_t value)
+{
+    GICv3CPUState *cs = icc_cs_from_env(env);
+
+    trace_gicv3_icv_ctlr_write(gicv3_redist_affid(cs), value);
+
+    cs->ich_vmcr_el2 = deposit64(cs->ich_vmcr_el2, ICH_VMCR_EL2_VCBPR_SHIFT,
+                                 1, value & ICC_CTLR_EL1_CBPR ? 1 : 0);
+    cs->ich_vmcr_el2 = deposit64(cs->ich_vmcr_el2, ICH_VMCR_EL2_VEOIM_SHIFT,
+                                 1, value & ICC_CTLR_EL1_EOIMODE ? 1 : 0);
+
+    gicv3_cpuif_virt_update(cs);
+}
+
 static int icc_highest_active_prio(GICv3CPUState *cs)
 {
     /* Calculate the current running priority based on the set bits
@@ -309,6 +504,10 @@ static uint64_t icc_pmr_read(CPUARMState *env, const ARMCPRegInfo *ri)
     GICv3CPUState *cs = icc_cs_from_env(env);
     uint32_t value = cs->icc_pmr_el1;
 
+    if (icv_access(env, HCR_FMO | HCR_IMO)) {
+        return icv_pmr_read(env, ri);
+    }
+
     if (arm_feature(env, ARM_FEATURE_EL3) && !arm_is_secure(env) &&
         (env->cp15.scr_el3 & SCR_FIQ)) {
         /* NS access and Group 0 is inaccessible to NS: return the
@@ -332,6 +531,10 @@ static void icc_pmr_write(CPUARMState *env, const ARMCPRegInfo *ri,
 {
     GICv3CPUState *cs = icc_cs_from_env(env);
 
+    if (icv_access(env, HCR_FMO | HCR_IMO)) {
+        return icv_pmr_write(env, ri, value);
+    }
+
     trace_gicv3_icc_pmr_write(gicv3_redist_affid(cs), value);
 
     value &= 0xff;
@@ -650,6 +853,10 @@ static uint64_t icc_bpr_read(CPUARMState *env, const ARMCPRegInfo *ri)
     bool satinc = false;
     uint64_t bpr;
 
+    if (icv_access(env, grp == GICV3_G0 ? HCR_FMO : HCR_IMO)) {
+        return icv_bpr_read(env, ri);
+    }
+
     if (grp == GICV3_G1 && gicv3_use_ns_bank(env)) {
         grp = GICV3_G1NS;
     }
@@ -686,6 +893,11 @@ static void icc_bpr_write(CPUARMState *env, const ARMCPRegInfo *ri,
     GICv3CPUState *cs = icc_cs_from_env(env);
     int grp = (ri->crm == 8) ? GICV3_G0 : GICV3_G1;
 
+    if (icv_access(env, grp == GICV3_G0 ? HCR_FMO : HCR_IMO)) {
+        icv_bpr_write(env, ri, value);
+        return;
+    }
+
     trace_gicv3_icc_bpr_write(ri->crm == 8 ? 0 : 1,
                               gicv3_redist_affid(cs), value);
 
@@ -719,6 +931,10 @@ static uint64_t icc_ap_read(CPUARMState *env, const ARMCPRegInfo *ri)
     int regno = ri->opc2 & 3;
     int grp = ri->crm & 1 ? GICV3_G0 : GICV3_G1;
 
+    if (icv_access(env, grp == GICV3_G0 ? HCR_FMO : HCR_IMO)) {
+        return icv_ap_read(env, ri);
+    }
+
     if (grp == GICV3_G1 && gicv3_use_ns_bank(env)) {
         grp = GICV3_G1NS;
     }
@@ -737,6 +953,11 @@ static void icc_ap_write(CPUARMState *env, const ARMCPRegInfo *ri,
     int regno = ri->opc2 & 3;
     int grp = ri->crm & 1 ? GICV3_G0 : GICV3_G1;
 
+    if (icv_access(env, grp == GICV3_G0 ? HCR_FMO : HCR_IMO)) {
+        icv_ap_write(env, ri, value);
+        return;
+    }
+
     trace_gicv3_icc_ap_write(ri->crm & 1, regno, gicv3_redist_affid(cs), value);
 
     if (grp == GICV3_G1 && gicv3_use_ns_bank(env)) {
@@ -949,6 +1170,10 @@ static uint64_t icc_igrpen_read(CPUARMState *env, const ARMCPRegInfo *ri)
     int grp = ri->opc2 & 1 ? GICV3_G1 : GICV3_G0;
     uint64_t value;
 
+    if (icv_access(env, grp == GICV3_G0 ? HCR_FMO : HCR_IMO)) {
+        return icv_igrpen_read(env, ri);
+    }
+
     if (grp == GICV3_G1 && gicv3_use_ns_bank(env)) {
         grp = GICV3_G1NS;
     }
@@ -965,6 +1190,11 @@ static void icc_igrpen_write(CPUARMState *env, const ARMCPRegInfo *ri,
     GICv3CPUState *cs = icc_cs_from_env(env);
     int grp = ri->opc2 & 1 ? GICV3_G1 : GICV3_G0;
 
+    if (icv_access(env, grp == GICV3_G0 ? HCR_FMO : HCR_IMO)) {
+        icv_igrpen_write(env, ri, value);
+        return;
+    }
+
     trace_gicv3_icc_igrpen_write(ri->opc2 & 1 ? 1 : 0,
                                  gicv3_redist_affid(cs), value);
 
@@ -1006,6 +1236,10 @@ static uint64_t icc_ctlr_el1_read(CPUARMState *env, const ARMCPRegInfo *ri)
     int bank = gicv3_use_ns_bank(env) ? GICV3_NS : GICV3_S;
     uint64_t value;
 
+    if (icv_access(env, HCR_FMO | HCR_IMO)) {
+        return icv_ctlr_read(env, ri);
+    }
+
     value = cs->icc_ctlr_el1[bank];
     trace_gicv3_icc_ctlr_read(gicv3_redist_affid(cs), value);
     return value;
@@ -1018,6 +1252,11 @@ static void icc_ctlr_el1_write(CPUARMState *env, const ARMCPRegInfo *ri,
     int bank = gicv3_use_ns_bank(env) ? GICV3_NS : GICV3_S;
     uint64_t mask;
 
+    if (icv_access(env, HCR_FMO | HCR_IMO)) {
+        icv_ctlr_write(env, ri, value);
+        return;
+    }
+
     trace_gicv3_icc_ctlr_write(gicv3_redist_affid(cs), value);
 
     /* Only CBPR and EOIMODE can be RW;
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
index 4ac1ea2..19fe1d5 100644
--- a/hw/intc/trace-events
+++ b/hw/intc/trace-events
@@ -123,6 +123,16 @@ gicv3_ich_vtr_read(uint32_t cpu, uint64_t val) "GICv3 ICH_VTR read cpu %x value
 gicv3_ich_misr_read(uint32_t cpu, uint64_t val) "GICv3 ICH_MISR read cpu %x value 0x%" PRIx64
 gicv3_ich_eisr_read(uint32_t cpu, uint64_t val) "GICv3 ICH_EISR read cpu %x value 0x%" PRIx64
 gicv3_ich_elrsr_read(uint32_t cpu, uint64_t val) "GICv3 ICH_ELRSR read cpu %x value 0x%" PRIx64
+gicv3_icv_ap_read(int grp, int regno, uint32_t cpu, uint64_t val) "GICv3 ICV_AP%dR%d read cpu %x value 0x%" PRIx64
+gicv3_icv_ap_write(int grp, int regno, uint32_t cpu, uint64_t val) "GICv3 ICV_AP%dR%d write cpu %x value 0x%" PRIx64
+gicv3_icv_bpr_read(int grp, uint32_t cpu, uint64_t val) "GICv3 ICV_BPR%d read cpu %x value 0x%" PRIx64
+gicv3_icv_bpr_write(int grp, uint32_t cpu, uint64_t val) "GICv3 ICV_BPR%d write cpu %x value 0x%" PRIx64
+gicv3_icv_pmr_read(uint32_t cpu, uint64_t val) "GICv3 ICV_PMR read cpu %x value 0x%" PRIx64
+gicv3_icv_pmr_write(uint32_t cpu, uint64_t val) "GICv3 ICV_PMR write cpu %x value 0x%" PRIx64
+gicv3_icv_igrpen_read(int grp, uint32_t cpu, uint64_t val) "GICv3 ICV_IGRPEN%d read cpu %x value 0x%" PRIx64
+gicv3_icv_igrpen_write(int grp, uint32_t cpu, uint64_t val) "GICv3 ICV_IGRPEN%d write cpu %x value 0x%" PRIx64
+gicv3_icv_ctlr_read(uint32_t cpu, uint64_t val) "GICv3 ICV_CTLR read cpu %x value 0x%" PRIx64
+gicv3_icv_ctlr_write(uint32_t cpu, uint64_t val) "GICv3 ICV_CTLR write cpu %x value 0x%" PRIx64
 
 # hw/intc/arm_gicv3_dist.c
 gicv3_dist_read(uint64_t offset, uint64_t data, unsigned size, bool secure) "GICv3 distributor read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u secure %d"
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Qemu-devel] [PATCH v2 10/18] hw/intc/arm_gicv3: Implement ICV_ HPPIR, DIR and RPR registers
  2017-01-09 16:05 [Qemu-devel] [PATCH v2 00/18] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs Peter Maydell
                   ` (8 preceding siblings ...)
  2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 09/18] hw/intc/arm_gicv3: Implement ICV_ registers which are just accessors Peter Maydell
@ 2017-01-09 16:05 ` Peter Maydell
  2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 11/18] hw/intc/arm_gicv3: Implement ICV_ registers EOIR and IAR Peter Maydell
                   ` (8 subsequent siblings)
  18 siblings, 0 replies; 37+ messages in thread
From: Peter Maydell @ 2017-01-09 16:05 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: patches, Andrew Jones, Christoffer Dall, Edgar E . Iglesias,
	Alistair Francis

Implement the the ICV_ registers HPPIR, DIR and RPR.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/intc/arm_gicv3_cpuif.c | 235 +++++++++++++++++++++++++++++++++++++++++++++-
 hw/intc/trace-events      |   3 +
 2 files changed, 235 insertions(+), 3 deletions(-)

diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
index 40a52ce..e069082 100644
--- a/hw/intc/arm_gicv3_cpuif.c
+++ b/hw/intc/arm_gicv3_cpuif.c
@@ -44,6 +44,21 @@ static inline int icv_min_vbpr(GICv3CPUState *cs)
 }
 
 /* Simple accessor functions for LR fields */
+static uint32_t ich_lr_vintid(uint64_t lr)
+{
+    return extract64(lr, ICH_LR_EL2_VINTID_SHIFT, ICH_LR_EL2_VINTID_LENGTH);
+}
+
+static uint32_t ich_lr_pintid(uint64_t lr)
+{
+    return extract64(lr, ICH_LR_EL2_PINTID_SHIFT, ICH_LR_EL2_PINTID_LENGTH);
+}
+
+static uint32_t ich_lr_prio(uint64_t lr)
+{
+    return extract64(lr, ICH_LR_EL2_PRIORITY_SHIFT, ICH_LR_EL2_PRIORITY_LENGTH);
+}
+
 static int ich_lr_state(uint64_t lr)
 {
     return extract64(lr, ICH_LR_EL2_STATE_SHIFT, ICH_LR_EL2_STATE_LENGTH);
@@ -115,6 +130,79 @@ static uint32_t icv_fullprio_mask(GICv3CPUState *cs)
     return ~0U << (8 - cs->vpribits);
 }
 
+static int ich_highest_active_virt_prio(GICv3CPUState *cs)
+{
+    /* Calculate the current running priority based on the set bits
+     * in the ICH Active Priority Registers.
+     */
+    int i;
+    int aprmax = 1 << (cs->vprebits - 5);
+
+    assert(aprmax <= ARRAY_SIZE(cs->ich_apr[0]));
+
+    for (i = 0; i < aprmax; i++) {
+        uint32_t apr = cs->ich_apr[GICV3_G0][i] |
+            cs->ich_apr[GICV3_G1NS][i];
+
+        if (!apr) {
+            continue;
+        }
+        return (i * 32 + ctz32(apr)) << (icv_min_vbpr(cs) + 1);
+    }
+    /* No current active interrupts: return idle priority */
+    return 0xff;
+}
+
+static int hppvi_index(GICv3CPUState *cs)
+{
+    /* Return the list register index of the highest priority pending
+     * virtual interrupt, as per the HighestPriorityVirtualInterrupt
+     * pseudocode. If no pending virtual interrupts, return -1.
+     */
+    int idx = -1;
+    int i;
+    /* Note that a list register entry with a priority of 0xff will
+     * never be reported by this function; this is the architecturally
+     * correct behaviour.
+     */
+    int prio = 0xff;
+
+    if (!(cs->ich_vmcr_el2 & (ICH_VMCR_EL2_VENG0 | ICH_VMCR_EL2_VENG1))) {
+        /* Both groups disabled, definitely nothing to do */
+        return idx;
+    }
+
+    for (i = 0; i < cs->num_list_regs; i++) {
+        uint64_t lr = cs->ich_lr_el2[i];
+        int thisprio;
+
+        if (ich_lr_state(lr) != ICH_LR_EL2_STATE_PENDING) {
+            /* Not Pending */
+            continue;
+        }
+
+        /* Ignore interrupts if relevant group enable not set */
+        if (lr & ICH_LR_EL2_GROUP) {
+            if (!(cs->ich_vmcr_el2 & ICH_VMCR_EL2_VENG1)) {
+                continue;
+            }
+        } else {
+            if (!(cs->ich_vmcr_el2 & ICH_VMCR_EL2_VENG0)) {
+                continue;
+            }
+        }
+
+        thisprio = ich_lr_prio(lr);
+
+        if (thisprio < prio) {
+            prio = thisprio;
+            idx = i;
+        }
+    }
+
+    return idx;
+}
+
 static uint32_t eoi_maintenance_interrupt_state(GICv3CPUState *cs,
                                                 uint32_t *misr)
 {
@@ -363,6 +451,35 @@ static void icv_ctlr_write(CPUARMState *env, const ARMCPRegInfo *ri,
     gicv3_cpuif_virt_update(cs);
 }
 
+static uint64_t icv_rpr_read(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+    GICv3CPUState *cs = icc_cs_from_env(env);
+    int prio = ich_highest_active_virt_prio(cs);
+
+    trace_gicv3_icv_rpr_read(gicv3_redist_affid(cs), prio);
+    return prio;
+}
+
+static uint64_t icv_hppir_read(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+    GICv3CPUState *cs = icc_cs_from_env(env);
+    int grp = ri->crm == 8 ? GICV3_G0 : GICV3_G1NS;
+    int idx = hppvi_index(cs);
+    uint64_t value = INTID_SPURIOUS;
+
+    if (idx >= 0) {
+        uint64_t lr = cs->ich_lr_el2[idx];
+        int thisgrp = (lr & ICH_LR_EL2_GROUP) ? GICV3_G1NS : GICV3_G0;
+
+        if (grp == thisgrp) {
+            value = ich_lr_vintid(lr);
+        }
+    }
+
+    trace_gicv3_icv_hppir_read(grp, gicv3_redist_affid(cs), value);
+    return value;
+}
+
 static int icc_highest_active_prio(GICv3CPUState *cs)
 {
     /* Calculate the current running priority based on the set bits
@@ -781,6 +898,97 @@ static void icc_deactivate_irq(GICv3CPUState *cs, int irq)
     }
 }
 
+static bool icv_eoi_split(CPUARMState *env, GICv3CPUState *cs)
+{
+    /* Return true if we should split priority drop and interrupt
+     * deactivation, ie whether the virtual EOIMode bit is set.
+     */
+    return cs->ich_vmcr_el2 & ICH_VMCR_EL2_VEOIM;
+}
+
+static int icv_find_active(GICv3CPUState *cs, int irq)
+{
+    /* Given an interrupt number for an active interrupt, return the index
+     * of the corresponding list register, or -1 if there is no match.
+     * Corresponds to FindActiveVirtualInterrupt pseudocode.
+     */
+    int i;
+
+    for (i = 0; i < cs->num_list_regs; i++) {
+        uint64_t lr = cs->ich_lr_el2[i];
+
+        if ((lr & ICH_LR_EL2_STATE_ACTIVE_BIT) && ich_lr_vintid(lr) == irq) {
+            return i;
+        }
+    }
+
+    return -1;
+}
+
+static void icv_deactivate_irq(GICv3CPUState *cs, int idx)
+{
+    /* Deactivate the interrupt in the specified list register index */
+    uint64_t lr = cs->ich_lr_el2[idx];
+
+    if (lr & ICH_LR_EL2_HW) {
+        /* Deactivate the associated physical interrupt */
+        int pirq = ich_lr_pintid(lr);
+
+        if (pirq < INTID_SECURE) {
+            icc_deactivate_irq(cs, pirq);
+        }
+    }
+
+    /* Clear the 'active' part of the state, so ActivePending->Pending
+     * and Active->Invalid.
+     */
+    lr &= ~ICH_LR_EL2_STATE_ACTIVE_BIT;
+    cs->ich_lr_el2[idx] = lr;
+}
+
+static void icv_increment_eoicount(GICv3CPUState *cs)
+{
+    /* Increment the EOICOUNT field in ICH_HCR_EL2 */
+    int eoicount = extract64(cs->ich_hcr_el2, ICH_HCR_EL2_EOICOUNT_SHIFT,
+                             ICH_HCR_EL2_EOICOUNT_LENGTH);
+
+    cs->ich_hcr_el2 = deposit64(cs->ich_hcr_el2, ICH_HCR_EL2_EOICOUNT_SHIFT,
+                                ICH_HCR_EL2_EOICOUNT_LENGTH, eoicount + 1);
+}
+
+static void icv_dir_write(CPUARMState *env, const ARMCPRegInfo *ri,
+                          uint64_t value)
+{
+    /* Deactivate interrupt */
+    GICv3CPUState *cs = icc_cs_from_env(env);
+    int idx;
+    int irq = value & 0xffffff;
+
+    trace_gicv3_icv_dir_write(gicv3_redist_affid(cs), value);
+
+    if (irq >= cs->gic->num_irq) {
+        /* Also catches special interrupt numbers and LPIs */
+        return;
+    }
+
+    if (!icv_eoi_split(env, cs)) {
+        return;
+    }
+
+    idx = icv_find_active(cs, irq);
+
+    if (idx < 0) {
+        /* No list register matching this, so increment the EOI count
+         * (might trigger a maintenance interrupt)
+         */
+        icv_increment_eoicount(cs);
+    } else {
+        icv_deactivate_irq(cs, idx);
+    }
+
+    gicv3_cpuif_virt_update(cs);
+}
+
 static void icc_eoir_write(CPUARMState *env, const ARMCPRegInfo *ri,
                            uint64_t value)
 {
@@ -831,8 +1039,13 @@ static void icc_eoir_write(CPUARMState *env, const ARMCPRegInfo *ri,
 static uint64_t icc_hppir0_read(CPUARMState *env, const ARMCPRegInfo *ri)
 {
     GICv3CPUState *cs = icc_cs_from_env(env);
-    uint64_t value = icc_hppir0_value(cs, env);
+    uint64_t value;
+
+    if (icv_access(env, HCR_FMO)) {
+        return icv_hppir_read(env, ri);
+    }
 
+    value = icc_hppir0_value(cs, env);
     trace_gicv3_icc_hppir0_read(gicv3_redist_affid(cs), value);
     return value;
 }
@@ -840,8 +1053,13 @@ static uint64_t icc_hppir0_read(CPUARMState *env, const ARMCPRegInfo *ri)
 static uint64_t icc_hppir1_read(CPUARMState *env, const ARMCPRegInfo *ri)
 {
     GICv3CPUState *cs = icc_cs_from_env(env);
-    uint64_t value = icc_hppir1_value(cs, env);
+    uint64_t value;
+
+    if (icv_access(env, HCR_IMO)) {
+        return icv_hppir_read(env, ri);
+    }
 
+    value = icc_hppir1_value(cs, env);
     trace_gicv3_icc_hppir1_read(gicv3_redist_affid(cs), value);
     return value;
 }
@@ -986,6 +1204,11 @@ static void icc_dir_write(CPUARMState *env, const ARMCPRegInfo *ri,
     bool irq_is_secure, single_sec_state, irq_is_grp0;
     bool route_fiq_to_el3, route_irq_to_el3, route_fiq_to_el2, route_irq_to_el2;
 
+    if (icv_access(env, HCR_FMO | HCR_IMO)) {
+        icv_dir_write(env, ri, value);
+        return;
+    }
+
     trace_gicv3_icc_dir_write(gicv3_redist_affid(cs), value);
 
     if (irq >= cs->gic->num_irq) {
@@ -1057,7 +1280,13 @@ static void icc_dir_write(CPUARMState *env, const ARMCPRegInfo *ri,
 static uint64_t icc_rpr_read(CPUARMState *env, const ARMCPRegInfo *ri)
 {
     GICv3CPUState *cs = icc_cs_from_env(env);
-    int prio = icc_highest_active_prio(cs);
+    int prio;
+
+    if (icv_access(env, HCR_FMO | HCR_IMO)) {
+        return icv_rpr_read(env, ri);
+    }
+
+    prio = icc_highest_active_prio(cs);
 
     if (arm_feature(env, ARM_FEATURE_EL3) &&
         !arm_is_secure(env) && (env->cp15.scr_el3 & SCR_FIQ)) {
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
index 19fe1d5..fc9ec57 100644
--- a/hw/intc/trace-events
+++ b/hw/intc/trace-events
@@ -133,6 +133,9 @@ gicv3_icv_igrpen_read(int grp, uint32_t cpu, uint64_t val) "GICv3 ICV_IGRPEN%d r
 gicv3_icv_igrpen_write(int grp, uint32_t cpu, uint64_t val) "GICv3 ICV_IGRPEN%d write cpu %x value 0x%" PRIx64
 gicv3_icv_ctlr_read(uint32_t cpu, uint64_t val) "GICv3 ICV_CTLR read cpu %x value 0x%" PRIx64
 gicv3_icv_ctlr_write(uint32_t cpu, uint64_t val) "GICv3 ICV_CTLR write cpu %x value 0x%" PRIx64
+gicv3_icv_rpr_read(uint32_t cpu, uint64_t val) "GICv3 ICV_RPR read cpu %x value 0x%" PRIx64
+gicv3_icv_hppir_read(int grp, uint32_t cpu, uint64_t val) "GICv3 ICV_HPPIR%d read cpu %x value 0x%" PRIx64
+gicv3_icv_dir_write(uint32_t cpu, uint64_t val) "GICv3 ICV_DIR write cpu %x value 0x%" PRIx64
 
 # hw/intc/arm_gicv3_dist.c
 gicv3_dist_read(uint64_t offset, uint64_t data, unsigned size, bool secure) "GICv3 distributor read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u secure %d"
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Qemu-devel] [PATCH v2 11/18] hw/intc/arm_gicv3: Implement ICV_ registers EOIR and IAR
  2017-01-09 16:05 [Qemu-devel] [PATCH v2 00/18] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs Peter Maydell
                   ` (9 preceding siblings ...)
  2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 10/18] hw/intc/arm_gicv3: Implement ICV_ HPPIR, DIR and RPR registers Peter Maydell
@ 2017-01-09 16:05 ` Peter Maydell
  2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 12/18] hw/intc/arm_gicv3: Implement gicv3_cpuif_virt_update() Peter Maydell
                   ` (7 subsequent siblings)
  18 siblings, 0 replies; 37+ messages in thread
From: Peter Maydell @ 2017-01-09 16:05 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: patches, Andrew Jones, Christoffer Dall, Edgar E . Iglesias,
	Alistair Francis

Implement the two remaining ICV_ registers: EOIR and IAR.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/intc/arm_gicv3_cpuif.c | 220 ++++++++++++++++++++++++++++++++++++++++++++++
 hw/intc/trace-events      |   2 +
 2 files changed, 222 insertions(+)

diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
index e069082..f3845a6 100644
--- a/hw/intc/arm_gicv3_cpuif.c
+++ b/hw/intc/arm_gicv3_cpuif.c
@@ -203,6 +203,73 @@ static int hppvi_index(GICv3CPUState *cs)
     return idx;
 }
 
+static uint32_t icv_gprio_mask(GICv3CPUState *cs, int group)
+{
+    /* Return a mask word which clears the subpriority bits from
+     * a priority value for a virtual interrupt in the specified group.
+     * This depends on the VBPR value:
+     *  a BPR of 0 means the group priority bits are [7:1];
+     *  a BPR of 1 means they are [7:2], and so on down to
+     *  a BPR of 7 meaning no group priority bits at all.
+     * Which BPR to use depends on the group of the interrupt and
+     * the current ICH_VMCR_EL2.VCBPR settings.
+     */
+    if (group == GICV3_G1NS && cs->ich_vmcr_el2 & ICH_VMCR_EL2_VCBPR) {
+        group = GICV3_G0;
+    }
+
+    return ~0U << (read_vbpr(cs, group) + 1);
+}
+
+static bool icv_hppi_can_preempt(GICv3CPUState *cs, uint64_t lr)
+{
+    /* Return true if we can signal this virtual interrupt defined by
+     * the given list register value; see the pseudocode functions
+     * CanSignalVirtualInterrupt and CanSignalVirtualInt.
+     * Compare also icc_hppi_can_preempt() which is the non-virtual
+     * equivalent of these checks.
+     */
+    int grp;
+    uint32_t mask, prio, rprio, vpmr;
+
+    if (!(cs->ich_hcr_el2 & ICH_HCR_EL2_EN)) {
+        /* Virtual interface disabled */
+        return false;
+    }
+
+    /* We don't need to check that this LR is in Pending state because
+     * that has already been done in hppvi_index().
+     */
+
+    prio = ich_lr_prio(lr);
+    vpmr = extract64(cs->ich_vmcr_el2, ICH_VMCR_EL2_VPMR_SHIFT,
+                     ICH_VMCR_EL2_VPMR_LENGTH);
+
+    if (prio >= vpmr) {
+        /* Priority mask masks this interrupt */
+        return false;
+    }
+
+    rprio = ich_highest_active_virt_prio(cs);
+    if (rprio == 0xff) {
+        /* No running interrupt so we can preempt */
+        return true;
+    }
+
+    grp = (lr & ICH_LR_EL2_GROUP) ? GICV3_G1NS : GICV3_G0;
+
+    mask = icv_gprio_mask(cs, grp);
+
+    /* We only preempt a running interrupt if the pending interrupt's
+     * group priority is sufficient (the subpriorities are not considered).
+     */
+    if ((prio & mask) < (rprio & mask)) {
+        return true;
+    }
+
+    return false;
+}
+
 static uint32_t eoi_maintenance_interrupt_state(GICv3CPUState *cs,
                                                 uint32_t *misr)
 {
@@ -480,6 +547,53 @@ static uint64_t icv_hppir_read(CPUARMState *env, const ARMCPRegInfo *ri)
     return value;
 }
 
+static void icv_activate_irq(GICv3CPUState *cs, int idx, int grp)
+{
+    /* Activate the interrupt in the specified list register
+     * by moving it from Pending to Active state, and update the
+     * Active Priority Registers.
+     */
+    uint32_t mask = icv_gprio_mask(cs, grp);
+    int prio = ich_lr_prio(cs->ich_lr_el2[idx]) & mask;
+    int aprbit = prio >> (8 - cs->vprebits);
+    int regno = aprbit / 32;
+    int regbit = aprbit % 32;
+
+    cs->ich_lr_el2[idx] &= ~ICH_LR_EL2_STATE_PENDING_BIT;
+    cs->ich_lr_el2[idx] |= ICH_LR_EL2_STATE_ACTIVE_BIT;
+    cs->ich_apr[grp][regno] |= (1 << regbit);
+}
+
+static uint64_t icv_iar_read(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+    GICv3CPUState *cs = icc_cs_from_env(env);
+    int grp = ri->crm == 8 ? GICV3_G0 : GICV3_G1NS;
+    int idx = hppvi_index(cs);
+    uint64_t intid = INTID_SPURIOUS;
+
+    if (idx >= 0) {
+        uint64_t lr = cs->ich_lr_el2[idx];
+        int thisgrp = (lr & ICH_LR_EL2_GROUP) ? GICV3_G1NS : GICV3_G0;
+
+        if (thisgrp == grp && icv_hppi_can_preempt(cs, lr)) {
+            intid = ich_lr_vintid(lr);
+            if (intid < INTID_SECURE) {
+                icv_activate_irq(cs, idx, grp);
+            } else {
+                /* Interrupt goes from Pending to Invalid */
+                cs->ich_lr_el2[idx] &= ~ICH_LR_EL2_STATE_PENDING_BIT;
+                /* We will now return the (bogus) ID from the list register,
+                 * as per the pseudocode.
+                 */
+            }
+        }
+    }
+
+    trace_gicv3_icv_iar_read(ri->crm == 8 ? 0 : 1,
+                             gicv3_redist_affid(cs), intid);
+    return intid;
+}
+
 static int icc_highest_active_prio(GICv3CPUState *cs)
 {
     /* Calculate the current running priority based on the set bits
@@ -773,6 +887,10 @@ static uint64_t icc_iar0_read(CPUARMState *env, const ARMCPRegInfo *ri)
     GICv3CPUState *cs = icc_cs_from_env(env);
     uint64_t intid;
 
+    if (icv_access(env, HCR_FMO)) {
+        return icv_iar_read(env, ri);
+    }
+
     if (!icc_hppi_can_preempt(cs)) {
         intid = INTID_SPURIOUS;
     } else {
@@ -792,6 +910,10 @@ static uint64_t icc_iar1_read(CPUARMState *env, const ARMCPRegInfo *ri)
     GICv3CPUState *cs = icc_cs_from_env(env);
     uint64_t intid;
 
+    if (icv_access(env, HCR_IMO)) {
+        return icv_iar_read(env, ri);
+    }
+
     if (!icc_hppi_can_preempt(cs)) {
         intid = INTID_SPURIOUS;
     } else {
@@ -956,6 +1078,48 @@ static void icv_increment_eoicount(GICv3CPUState *cs)
                                 ICH_HCR_EL2_EOICOUNT_LENGTH, eoicount + 1);
 }
 
+static int icv_drop_prio(GICv3CPUState *cs)
+{
+    /* Drop the priority of the currently active virtual interrupt
+     * (favouring group 0 if there is a set active bit at
+     * the same priority for both group 0 and group 1).
+     * Return the priority value for the bit we just cleared,
+     * or 0xff if no bits were set in the AP registers at all.
+     * Note that though the ich_apr[] are uint64_t only the low
+     * 32 bits are actually relevant.
+     */
+    int i;
+    int aprmax = 1 << (cs->vprebits - 5);
+
+    assert(aprmax <= ARRAY_SIZE(cs->ich_apr[0]));
+
+    for (i = 0; i < aprmax; i++) {
+        uint64_t *papr0 = &cs->ich_apr[GICV3_G0][i];
+        uint64_t *papr1 = &cs->ich_apr[GICV3_G1NS][i];
+        int apr0count, apr1count;
+
+        if (!*papr0 && !*papr1) {
+            continue;
+        }
+
+        /* We can't just use the bit-twiddling hack icc_drop_prio() does
+         * because we need to return the bit number we cleared so
+         * it can be compared against the list register's priority field.
+         */
+        apr0count = ctz32(*papr0);
+        apr1count = ctz32(*papr1);
+
+        if (apr0count <= apr1count) {
+            *papr0 &= *papr0 - 1;
+            return (apr0count + i * 32) << (icv_min_vbpr(cs) + 1);
+        } else {
+            *papr1 &= *papr1 - 1;
+            return (apr1count + i * 32) << (icv_min_vbpr(cs) + 1);
+        }
+    }
+    return 0xff;
+}
+
 static void icv_dir_write(CPUARMState *env, const ARMCPRegInfo *ri,
                           uint64_t value)
 {
@@ -989,6 +1153,57 @@ static void icv_dir_write(CPUARMState *env, const ARMCPRegInfo *ri,
     gicv3_cpuif_virt_update(cs);
 }
 
+static void icv_eoir_write(CPUARMState *env, const ARMCPRegInfo *ri,
+                           uint64_t value)
+{
+    /* End of Interrupt */
+    GICv3CPUState *cs = icc_cs_from_env(env);
+    int irq = value & 0xffffff;
+    int grp = ri->crm == 8 ? GICV3_G0 : GICV3_G1NS;
+    int idx, dropprio;
+
+    trace_gicv3_icv_eoir_write(ri->crm == 8 ? 0 : 1,
+                               gicv3_redist_affid(cs), value);
+
+    if (irq >= cs->gic->num_irq) {
+        /* Also catches special interrupt numbers and LPIs */
+        return;
+    }
+
+    /* We implement the IMPDEF choice of "drop priority before doing
+     * error checks" (because that lets us avoid scanning the AP
+     * registers twice).
+     */
+    dropprio = icv_drop_prio(cs);
+    if (dropprio == 0xff) {
+        /* No active interrupt. It is CONSTRAINED UNPREDICTABLE
+         * whether the list registers are checked in this
+         * situation; we choose not to.
+         */
+        return;
+    }
+
+    idx = icv_find_active(cs, irq);
+
+    if (idx < 0) {
+        /* No valid list register corresponding to EOI ID */
+        icv_increment_eoicount(cs);
+    } else {
+        uint64_t lr = cs->ich_lr_el2[idx];
+        int thisgrp = (lr & ICH_LR_EL2_GROUP) ? GICV3_G1NS : GICV3_G0;
+        int lr_gprio = ich_lr_prio(lr) & icv_gprio_mask(cs, grp);
+
+        if (thisgrp == grp && lr_gprio == dropprio) {
+            if (!icv_eoi_split(env, cs)) {
+                /* Priority drop and deactivate not split: deactivate irq now */
+                icv_deactivate_irq(cs, idx);
+            }
+        }
+    }
+
+    gicv3_cpuif_virt_update(cs);
+}
+
 static void icc_eoir_write(CPUARMState *env, const ARMCPRegInfo *ri,
                            uint64_t value)
 {
@@ -997,6 +1212,11 @@ static void icc_eoir_write(CPUARMState *env, const ARMCPRegInfo *ri,
     int irq = value & 0xffffff;
     int grp;
 
+    if (icv_access(env, ri->crm == 8 ? HCR_FMO : HCR_IMO)) {
+        icv_eoir_write(env, ri, value);
+        return;
+    }
+
     trace_gicv3_icc_eoir_write(ri->crm == 8 ? 0 : 1,
                                gicv3_redist_affid(cs), value);
 
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
index fc9ec57..1dcc830 100644
--- a/hw/intc/trace-events
+++ b/hw/intc/trace-events
@@ -136,6 +136,8 @@ gicv3_icv_ctlr_write(uint32_t cpu, uint64_t val) "GICv3 ICV_CTLR write cpu %x va
 gicv3_icv_rpr_read(uint32_t cpu, uint64_t val) "GICv3 ICV_RPR read cpu %x value 0x%" PRIx64
 gicv3_icv_hppir_read(int grp, uint32_t cpu, uint64_t val) "GICv3 ICV_HPPIR%d read cpu %x value 0x%" PRIx64
 gicv3_icv_dir_write(uint32_t cpu, uint64_t val) "GICv3 ICV_DIR write cpu %x value 0x%" PRIx64
+gicv3_icv_iar_read(int grp, uint32_t cpu, uint64_t val) "GICv3 ICV_IAR%d read cpu %x value 0x%" PRIx64
+gicv3_icv_eoir_write(int grp, uint32_t cpu, uint64_t val) "GICv3 ICV_EOIR%d write cpu %x value 0x%" PRIx64
 
 # hw/intc/arm_gicv3_dist.c
 gicv3_dist_read(uint64_t offset, uint64_t data, unsigned size, bool secure) "GICv3 distributor read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u secure %d"
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Qemu-devel] [PATCH v2 12/18] hw/intc/arm_gicv3: Implement gicv3_cpuif_virt_update()
  2017-01-09 16:05 [Qemu-devel] [PATCH v2 00/18] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs Peter Maydell
                   ` (10 preceding siblings ...)
  2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 11/18] hw/intc/arm_gicv3: Implement ICV_ registers EOIR and IAR Peter Maydell
@ 2017-01-09 16:05 ` Peter Maydell
  2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 13/18] hw/intc/arm_gicv3: Implement EL2 traps for CPU i/f regs Peter Maydell
                   ` (6 subsequent siblings)
  18 siblings, 0 replies; 37+ messages in thread
From: Peter Maydell @ 2017-01-09 16:05 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: patches, Andrew Jones, Christoffer Dall, Edgar E . Iglesias,
	Alistair Francis

Implement the function which signals virtual interrupts to the
CPU as appropriate following CPU interface state changes.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 include/hw/intc/arm_gicv3_common.h |  1 +
 hw/intc/arm_gicv3_cpuif.c          | 49 ++++++++++++++++++++++++++++++++++++++
 hw/intc/trace-events               |  2 ++
 3 files changed, 52 insertions(+)

diff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h
index 665d3f8..4156051 100644
--- a/include/hw/intc/arm_gicv3_common.h
+++ b/include/hw/intc/arm_gicv3_common.h
@@ -150,6 +150,7 @@ struct GICv3CPUState {
     qemu_irq parent_fiq;
     qemu_irq parent_virq;
     qemu_irq parent_vfiq;
+    qemu_irq maintenance_irq;
 
     /* Redistributor */
     uint32_t level;                  /* Current IRQ level */
diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
index f3845a6..e05f6b3 100644
--- a/hw/intc/arm_gicv3_cpuif.c
+++ b/hw/intc/arm_gicv3_cpuif.c
@@ -352,6 +352,53 @@ static uint32_t maintenance_interrupt_state(GICv3CPUState *cs)
 
 static void gicv3_cpuif_virt_update(GICv3CPUState *cs)
 {
+    /* Tell the CPU about any pending virtual interrupts or
+     * maintenance interrupts, following a change to the state
+     * of the CPU interface relevant to virtual interrupts.
+     *
+     * CAUTION: this function will call qemu_set_irq() on the
+     * CPU maintenance IRQ line, which is typically wired up
+     * to the GIC as a per-CPU interrupt. This means that it
+     * will recursively call back into the GIC code via
+     * gicv3_redist_set_irq() and thus into the CPU interface code's
+     * gicv3_cpuif_update(). It is therefore important that this
+     * function is only called as the final action of a CPU interface
+     * register write implementation, after all the GIC state
+     * fields have been updated. gicv3_cpuif_update() also must
+     * not cause this function to be called, but that happens
+     * naturally as a result of there being no architectural
+     * linkage between the physical and virtual GIC logic.
+     */
+    int idx;
+    int irqlevel = 0;
+    int fiqlevel = 0;
+    int maintlevel = 0;
+
+    idx = hppvi_index(cs);
+    trace_gicv3_cpuif_virt_update(gicv3_redist_affid(cs), idx);
+    if (idx >= 0) {
+        uint64_t lr = cs->ich_lr_el2[idx];
+
+        if (icv_hppi_can_preempt(cs, lr)) {
+            /* Virtual interrupts are simple: G0 are always FIQ, and G1 IRQ */
+            if (lr & ICH_LR_EL2_GROUP) {
+                irqlevel = 1;
+            } else {
+                fiqlevel = 1;
+            }
+        }
+    }
+
+    if (cs->ich_hcr_el2 & ICH_HCR_EL2_EN) {
+        maintlevel = maintenance_interrupt_state(cs);
+    }
+
+    trace_gicv3_cpuif_virt_set_irqs(gicv3_redist_affid(cs), fiqlevel,
+                                    irqlevel, maintlevel);
+
+    qemu_set_irq(cs->parent_vfiq, fiqlevel);
+    qemu_set_irq(cs->parent_virq, irqlevel);
+    qemu_set_irq(cs->maintenance_irq, maintlevel);
 }
 
 static uint64_t icv_ap_read(CPUARMState *env, const ARMCPRegInfo *ri)
@@ -2480,6 +2527,8 @@ void gicv3_init_cpuif(GICv3State *s)
             && cpu->gic_num_lrs) {
             int j;
 
+            cs->maintenance_irq = cpu->gicv3_maintenance_interrupt;
+
             cs->num_list_regs = cpu->gic_num_lrs;
             cs->vpribits = cpu->gic_vpribits;
             cs->vprebits = cpu->gic_vprebits;
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
index 1dcc830..6116df5 100644
--- a/hw/intc/trace-events
+++ b/hw/intc/trace-events
@@ -138,6 +138,8 @@ gicv3_icv_hppir_read(int grp, uint32_t cpu, uint64_t val) "GICv3 ICV_HPPIR%d rea
 gicv3_icv_dir_write(uint32_t cpu, uint64_t val) "GICv3 ICV_DIR write cpu %x value 0x%" PRIx64
 gicv3_icv_iar_read(int grp, uint32_t cpu, uint64_t val) "GICv3 ICV_IAR%d read cpu %x value 0x%" PRIx64
 gicv3_icv_eoir_write(int grp, uint32_t cpu, uint64_t val) "GICv3 ICV_EOIR%d write cpu %x value 0x%" PRIx64
+gicv3_cpuif_virt_update(uint32_t cpuid, int idx) "GICv3 CPU i/f %x virt HPPI update LR index %d"
+gicv3_cpuif_virt_set_irqs(uint32_t cpuid, int fiqlevel, int irqlevel, int maintlevel) "GICv3 CPU i/f %x virt HPPI update: setting FIQ %d IRQ %d maintenance-irq %d"
 
 # hw/intc/arm_gicv3_dist.c
 gicv3_dist_read(uint64_t offset, uint64_t data, unsigned size, bool secure) "GICv3 distributor read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u secure %d"
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Qemu-devel] [PATCH v2 13/18] hw/intc/arm_gicv3: Implement EL2 traps for CPU i/f regs
  2017-01-09 16:05 [Qemu-devel] [PATCH v2 00/18] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs Peter Maydell
                   ` (11 preceding siblings ...)
  2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 12/18] hw/intc/arm_gicv3: Implement gicv3_cpuif_virt_update() Peter Maydell
@ 2017-01-09 16:05 ` Peter Maydell
  2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 14/18] hw/arm/virt: Support using SMC for PSCI Peter Maydell
                   ` (5 subsequent siblings)
  18 siblings, 0 replies; 37+ messages in thread
From: Peter Maydell @ 2017-01-09 16:05 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: patches, Andrew Jones, Christoffer Dall, Edgar E . Iglesias,
	Alistair Francis

Implement the architecturally required traps from NS EL1
to EL2 for the CPU interface registers. These fall into
several different groups:
 * group-0-only registers all trap if ICH_HRC_EL2.TALL0 is set
   (exactly the registers covered by gicv3_fiq_access())
 * group-1-only registers all trap if ICH_HRC_EL2.TALL1 is set
   (exactly the registers covered by gicv3_irq_access())
 * DIR traps if ICH_HCR_EL2.TC or ICH_HCR_EL2.TDIR are set
 * PMR, RPR, CTLR trap if ICH_HCR_EL2.TC is set
 * SGI0R, SGI1R, ASGI1R trap if ICH_HCR_EL2.TC is set or
   if HCR_EL2.IMO or HCR_EL2.FMO are set

We split DIR and the SGI registers out into their own access
functions, leaving the existing gicv3_irqfiq_access() just
handling PMR, RPR and CTLR.

This commit doesn't implement support for trapping on
HSTR_EL2.T12 for the 32-bit registers, as we don't implement
any of those per-coprocessor trap bits currently and
probably will want to do those in some more centralized way.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/intc/arm_gicv3_cpuif.c | 70 ++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 60 insertions(+), 10 deletions(-)

diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
index e05f6b3..a9ee7fd 100644
--- a/hw/intc/arm_gicv3_cpuif.c
+++ b/hw/intc/arm_gicv3_cpuif.c
@@ -1833,9 +1833,17 @@ static CPAccessResult gicv3_irqfiq_access(CPUARMState *env,
                                           const ARMCPRegInfo *ri, bool isread)
 {
     CPAccessResult r = CP_ACCESS_OK;
+    GICv3CPUState *cs = icc_cs_from_env(env);
+    int el = arm_current_el(env);
+
+    if ((cs->ich_hcr_el2 & ICH_HCR_EL2_TC) &&
+        el == 1 && !arm_is_secure_below_el3(env)) {
+        /* Takes priority over a possible EL3 trap */
+        return CP_ACCESS_TRAP_EL2;
+    }
 
     if ((env->cp15.scr_el3 & (SCR_FIQ | SCR_IRQ)) == (SCR_FIQ | SCR_IRQ)) {
-        switch (arm_current_el(env)) {
+        switch (el) {
         case 1:
             if (arm_is_secure_below_el3(env) ||
                 ((env->cp15.hcr_el2 & (HCR_IMO | HCR_FMO)) == 0)) {
@@ -1861,13 +1869,47 @@ static CPAccessResult gicv3_irqfiq_access(CPUARMState *env,
     return r;
 }
 
+static CPAccessResult gicv3_dir_access(CPUARMState *env,
+                                       const ARMCPRegInfo *ri, bool isread)
+{
+    GICv3CPUState *cs = icc_cs_from_env(env);
+
+    if ((cs->ich_hcr_el2 & ICH_HCR_EL2_TDIR) &&
+        arm_current_el(env) == 1 && !arm_is_secure_below_el3(env)) {
+        /* Takes priority over a possible EL3 trap */
+        return CP_ACCESS_TRAP_EL2;
+    }
+
+    return gicv3_irqfiq_access(env, ri, isread);
+}
+
+static CPAccessResult gicv3_sgi_access(CPUARMState *env,
+                                       const ARMCPRegInfo *ri, bool isread)
+{
+    if ((env->cp15.hcr_el2 & (HCR_IMO | HCR_FMO)) &&
+        arm_current_el(env) == 1 && !arm_is_secure_below_el3(env)) {
+        /* Takes priority over a possible EL3 trap */
+        return CP_ACCESS_TRAP_EL2;
+    }
+
+    return gicv3_irqfiq_access(env, ri, isread);
+}
+
 static CPAccessResult gicv3_fiq_access(CPUARMState *env,
                                        const ARMCPRegInfo *ri, bool isread)
 {
     CPAccessResult r = CP_ACCESS_OK;
+    GICv3CPUState *cs = icc_cs_from_env(env);
+    int el = arm_current_el(env);
+
+    if ((cs->ich_hcr_el2 & ICH_HCR_EL2_TALL0) &&
+        el == 1 && !arm_is_secure_below_el3(env)) {
+        /* Takes priority over a possible EL3 trap */
+        return CP_ACCESS_TRAP_EL2;
+    }
 
     if (env->cp15.scr_el3 & SCR_FIQ) {
-        switch (arm_current_el(env)) {
+        switch (el) {
         case 1:
             if (arm_is_secure_below_el3(env) ||
                 ((env->cp15.hcr_el2 & HCR_FMO) == 0)) {
@@ -1897,9 +1939,17 @@ static CPAccessResult gicv3_irq_access(CPUARMState *env,
                                        const ARMCPRegInfo *ri, bool isread)
 {
     CPAccessResult r = CP_ACCESS_OK;
+    GICv3CPUState *cs = icc_cs_from_env(env);
+    int el = arm_current_el(env);
+
+    if ((cs->ich_hcr_el2 & ICH_HCR_EL2_TALL1) &&
+        el == 1 && !arm_is_secure_below_el3(env)) {
+        /* Takes priority over a possible EL3 trap */
+        return CP_ACCESS_TRAP_EL2;
+    }
 
     if (env->cp15.scr_el3 & SCR_IRQ) {
-        switch (arm_current_el(env)) {
+        switch (el) {
         case 1:
             if (arm_is_secure_below_el3(env) ||
                 ((env->cp15.hcr_el2 & HCR_IMO) == 0)) {
@@ -2055,7 +2105,7 @@ static const ARMCPRegInfo gicv3_cpuif_reginfo[] = {
     { .name = "ICC_DIR_EL1", .state = ARM_CP_STATE_BOTH,
       .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 11, .opc2 = 1,
       .type = ARM_CP_IO | ARM_CP_NO_RAW,
-      .access = PL1_W, .accessfn = gicv3_irqfiq_access,
+      .access = PL1_W, .accessfn = gicv3_dir_access,
       .writefn = icc_dir_write,
     },
     { .name = "ICC_RPR_EL1", .state = ARM_CP_STATE_BOTH,
@@ -2067,37 +2117,37 @@ static const ARMCPRegInfo gicv3_cpuif_reginfo[] = {
     { .name = "ICC_SGI1R_EL1", .state = ARM_CP_STATE_AA64,
       .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 11, .opc2 = 5,
       .type = ARM_CP_IO | ARM_CP_NO_RAW,
-      .access = PL1_W, .accessfn = gicv3_irqfiq_access,
+      .access = PL1_W, .accessfn = gicv3_sgi_access,
       .writefn = icc_sgi1r_write,
     },
     { .name = "ICC_SGI1R",
       .cp = 15, .opc1 = 0, .crm = 12,
       .type = ARM_CP_64BIT | ARM_CP_IO | ARM_CP_NO_RAW,
-      .access = PL1_W, .accessfn = gicv3_irqfiq_access,
+      .access = PL1_W, .accessfn = gicv3_sgi_access,
       .writefn = icc_sgi1r_write,
     },
     { .name = "ICC_ASGI1R_EL1", .state = ARM_CP_STATE_AA64,
       .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 11, .opc2 = 6,
       .type = ARM_CP_IO | ARM_CP_NO_RAW,
-      .access = PL1_W, .accessfn = gicv3_irqfiq_access,
+      .access = PL1_W, .accessfn = gicv3_sgi_access,
       .writefn = icc_asgi1r_write,
     },
     { .name = "ICC_ASGI1R",
       .cp = 15, .opc1 = 1, .crm = 12,
       .type = ARM_CP_64BIT | ARM_CP_IO | ARM_CP_NO_RAW,
-      .access = PL1_W, .accessfn = gicv3_irqfiq_access,
+      .access = PL1_W, .accessfn = gicv3_sgi_access,
       .writefn = icc_asgi1r_write,
     },
     { .name = "ICC_SGI0R_EL1", .state = ARM_CP_STATE_AA64,
       .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 11, .opc2 = 7,
       .type = ARM_CP_IO | ARM_CP_NO_RAW,
-      .access = PL1_W, .accessfn = gicv3_irqfiq_access,
+      .access = PL1_W, .accessfn = gicv3_sgi_access,
       .writefn = icc_sgi0r_write,
     },
     { .name = "ICC_SGI0R",
       .cp = 15, .opc1 = 2, .crm = 12,
       .type = ARM_CP_64BIT | ARM_CP_IO | ARM_CP_NO_RAW,
-      .access = PL1_W, .accessfn = gicv3_irqfiq_access,
+      .access = PL1_W, .accessfn = gicv3_sgi_access,
       .writefn = icc_sgi0r_write,
     },
     { .name = "ICC_IAR1_EL1", .state = ARM_CP_STATE_BOTH,
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Qemu-devel] [PATCH v2 14/18] hw/arm/virt: Support using SMC for PSCI
  2017-01-09 16:05 [Qemu-devel] [PATCH v2 00/18] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs Peter Maydell
                   ` (12 preceding siblings ...)
  2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 13/18] hw/intc/arm_gicv3: Implement EL2 traps for CPU i/f regs Peter Maydell
@ 2017-01-09 16:05 ` Peter Maydell
  2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 15/18] hw/arm/virt-acpi-build: use SMC if booting in EL2 Peter Maydell
                   ` (4 subsequent siblings)
  18 siblings, 0 replies; 37+ messages in thread
From: Peter Maydell @ 2017-01-09 16:05 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: patches, Andrew Jones, Christoffer Dall, Edgar E . Iglesias,
	Alistair Francis

If we are giving the guest a CPU with EL2, it is likely to
want to use the HVC instruction itself, for instance for
providing PSCI to inner guest VMs. This makes using HVC
as the PSCI conduit for the outer QEMU a bad idea. We will
want to use SMC instead is this case: this makes sense
because QEMU's PSCI implementation is effectively an
emulation of functionality provided by EL3 firmware.

Add code to support selecting the PSCI conduit to use,
rather than hardcoding use of HVC.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Reviewed-by: Andrew Jones <drjones@redhat.com>
---
 include/hw/arm/virt.h |  2 +-
 hw/arm/virt.c         | 27 +++++++++++++++++++++------
 2 files changed, 22 insertions(+), 7 deletions(-)

diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
index b8a19ec..53507e6 100644
--- a/include/hw/arm/virt.h
+++ b/include/hw/arm/virt.h
@@ -103,7 +103,7 @@ typedef struct {
     uint32_t clock_phandle;
     uint32_t gic_phandle;
     uint32_t msi_phandle;
-    bool using_psci;
+    int psci_conduit;
 } VirtMachineState;
 
 #define TYPE_VIRT_MACHINE   MACHINE_TYPE_NAME("virt")
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index b31d302..1fdc791 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -230,9 +230,19 @@ static void fdt_add_psci_node(const VirtMachineState *vms)
     uint32_t migrate_fn;
     void *fdt = vms->fdt;
     ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(0));
+    const char *psci_method;
 
-    if (!vms->using_psci) {
+    switch (vms->psci_conduit) {
+    case QEMU_PSCI_CONDUIT_DISABLED:
         return;
+    case QEMU_PSCI_CONDUIT_HVC:
+        psci_method = "hvc";
+        break;
+    case QEMU_PSCI_CONDUIT_SMC:
+        psci_method = "smc";
+        break;
+    default:
+        g_assert_not_reached();
     }
 
     qemu_fdt_add_subnode(fdt, "/psci");
@@ -264,7 +274,7 @@ static void fdt_add_psci_node(const VirtMachineState *vms)
      * However, the device tree binding uses 'method' instead, so that is
      * what we should use here.
      */
-    qemu_fdt_setprop_string(fdt, "/psci", "method", "hvc");
+    qemu_fdt_setprop_string(fdt, "/psci", "method", psci_method);
 
     qemu_fdt_setprop_cell(fdt, "/psci", "cpu_suspend", cpu_suspend_fn);
     qemu_fdt_setprop_cell(fdt, "/psci", "cpu_off", cpu_off_fn);
@@ -366,7 +376,8 @@ static void fdt_add_cpu_nodes(const VirtMachineState *vms)
         qemu_fdt_setprop_string(vms->fdt, nodename, "compatible",
                                     armcpu->dtb_compatible);
 
-        if (vms->using_psci && vms->smp_cpus > 1) {
+        if (vms->psci_conduit != QEMU_PSCI_CONDUIT_DISABLED
+            && vms->smp_cpus > 1) {
             qemu_fdt_setprop_string(vms->fdt, nodename,
                                         "enable-method", "psci");
         }
@@ -1231,7 +1242,11 @@ static void machvirt_init(MachineState *machine)
      * let the boot ROM sort them out.
      * The usual case is that we do use QEMU's PSCI implementation.
      */
-    vms->using_psci = !(vms->secure && firmware_loaded);
+    if (vms->secure && firmware_loaded) {
+        vms->psci_conduit = QEMU_PSCI_CONDUIT_DISABLED;
+    } else {
+        vms->psci_conduit = QEMU_PSCI_CONDUIT_HVC;
+    }
 
     /* The maximum number of CPUs depends on the GIC version, or on how
      * many redistributors we can fit into the memory map.
@@ -1314,8 +1329,8 @@ static void machvirt_init(MachineState *machine)
             object_property_set_bool(cpuobj, false, "has_el3", NULL);
         }
 
-        if (vms->using_psci) {
-            object_property_set_int(cpuobj, QEMU_PSCI_CONDUIT_HVC,
+        if (vms->psci_conduit != QEMU_PSCI_CONDUIT_DISABLED) {
+            object_property_set_int(cpuobj, vms->psci_conduit,
                                     "psci-conduit", NULL);
 
             /* Secondary CPUs start in PSCI powered-down state */
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Qemu-devel] [PATCH v2 15/18] hw/arm/virt-acpi-build: use SMC if booting in EL2
  2017-01-09 16:05 [Qemu-devel] [PATCH v2 00/18] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs Peter Maydell
                   ` (13 preceding siblings ...)
  2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 14/18] hw/arm/virt: Support using SMC for PSCI Peter Maydell
@ 2017-01-09 16:05 ` Peter Maydell
  2017-01-17 22:14   ` Alistair Francis
  2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 16/18] target/arm/psci.c: If EL2 implemented, start CPUs " Peter Maydell
                   ` (3 subsequent siblings)
  18 siblings, 1 reply; 37+ messages in thread
From: Peter Maydell @ 2017-01-09 16:05 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: patches, Andrew Jones, Christoffer Dall, Edgar E . Iglesias,
	Alistair Francis

From: Andrew Jones <drjones@redhat.com>

Signed-off-by: Andrew Jones <drjones@redhat.com>
[PMM: look at vms->psci_conduit rather than vms->virt
 to decide whether to use HVC or SMC, and report no
 PSCI support at all for the 'PSCI disabled' case]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/arm/virt-acpi-build.c | 26 ++++++++++++++++++++------
 1 file changed, 20 insertions(+), 6 deletions(-)

diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index 085a611..ec7f83b 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -643,16 +643,30 @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
 }
 
 /* FADT */
-static void
-build_fadt(GArray *table_data, BIOSLinker *linker, unsigned dsdt_tbl_offset)
+static void build_fadt(GArray *table_data, BIOSLinker *linker,
+                       VirtMachineState *vms, unsigned dsdt_tbl_offset)
 {
     AcpiFadtDescriptorRev5_1 *fadt = acpi_data_push(table_data, sizeof(*fadt));
     unsigned dsdt_entry_offset = (char *)&fadt->dsdt - table_data->data;
+    uint16_t bootflags;
+
+    switch (vms->psci_conduit) {
+    case QEMU_PSCI_CONDUIT_DISABLED:
+        bootflags = 0;
+        break;
+    case QEMU_PSCI_CONDUIT_HVC:
+        bootflags = ACPI_FADT_ARM_PSCI_COMPLIANT | ACPI_FADT_ARM_PSCI_USE_HVC;
+        break;
+    case QEMU_PSCI_CONDUIT_SMC:
+        bootflags = ACPI_FADT_ARM_PSCI_COMPLIANT;
+        break;
+    default:
+        g_assert_not_reached();
+    }
 
-    /* Hardware Reduced = 1 and use PSCI 0.2+ and with HVC */
+    /* Hardware Reduced = 1 and use PSCI 0.2+ */
     fadt->flags = cpu_to_le32(1 << ACPI_FADT_F_HW_REDUCED_ACPI);
-    fadt->arm_boot_flags = cpu_to_le16(ACPI_FADT_ARM_PSCI_COMPLIANT |
-                                       ACPI_FADT_ARM_PSCI_USE_HVC);
+    fadt->arm_boot_flags = cpu_to_le16(bootflags);
 
     /* ACPI v5.1 (fadt->revision.fadt->minor_revision) */
     fadt->minor_revision = 0x1;
@@ -738,7 +752,7 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables)
 
     /* FADT MADT GTDT MCFG SPCR pointed to by RSDT */
     acpi_add_table(table_offsets, tables_blob);
-    build_fadt(tables_blob, tables->linker, dsdt);
+    build_fadt(tables_blob, tables->linker, vms, dsdt);
 
     acpi_add_table(table_offsets, tables_blob);
     build_madt(tables_blob, tables->linker, vms);
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Qemu-devel] [PATCH v2 16/18] target/arm/psci.c: If EL2 implemented, start CPUs in EL2
  2017-01-09 16:05 [Qemu-devel] [PATCH v2 00/18] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs Peter Maydell
                   ` (14 preceding siblings ...)
  2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 15/18] hw/arm/virt-acpi-build: use SMC if booting in EL2 Peter Maydell
@ 2017-01-09 16:05 ` Peter Maydell
  2017-01-10 16:36   ` Edgar E. Iglesias
  2017-01-17 14:47   ` Andrew Jones
  2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 17/18] target-arm: Enable EL2 feature bit on A53 and A57 Peter Maydell
                   ` (2 subsequent siblings)
  18 siblings, 2 replies; 37+ messages in thread
From: Peter Maydell @ 2017-01-09 16:05 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: patches, Andrew Jones, Christoffer Dall, Edgar E . Iglesias,
	Alistair Francis

The PSCI spec states that a CPU_ON call should cause the new
CPU to be started in the highest implemented Non-secure
exception level. We were incorrectly starting it at the
exception level of the caller, which happens to be correct
if EL2 is not implemented. Implement the correct logic
as described in the PSCI 1.0 spec section 6.4:
 * if EL2 exists and SCR_EL3.HCE is set: start in EL2
 * otherwise start in EL1

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target/arm/psci.c | 25 ++++++++++++++++++-------
 1 file changed, 18 insertions(+), 7 deletions(-)

diff --git a/target/arm/psci.c b/target/arm/psci.c
index 14316eb..64bf82e 100644
--- a/target/arm/psci.c
+++ b/target/arm/psci.c
@@ -148,17 +148,28 @@ void arm_handle_psci_call(ARMCPU *cpu)
     case QEMU_PSCI_0_1_FN_CPU_ON:
     case QEMU_PSCI_0_2_FN_CPU_ON:
     case QEMU_PSCI_0_2_FN64_CPU_ON:
+    {
+        /* The PSCI spec mandates that newly brought up CPUs start
+         * in the highest exception level which exists and is enabled
+         * on the calling CPU. Since the QEMU PSCI implementation is
+         * acting as a "fake EL3" or "fake EL2" firmware, this for us
+         * means that we want to start at the highest NS exception level
+         * that we are providing to the guest.
+         * The execution mode should be that which is currently in use
+         * by the same exception level on the calling CPU.
+         * The CPU should be started with the context_id value
+         * in x0 (if AArch64) or r0 (if AArch32).
+         */
+        int target_el = arm_feature(env, ARM_FEATURE_EL2) ? 2 : 1;
+        bool target_aarch64 = arm_el_is_aa64(env, target_el);
+
         mpidr = param[1];
         entry = param[2];
         context_id = param[3];
-        /*
-         * The PSCI spec mandates that newly brought up CPUs enter the
-         * exception level of the caller in the same execution mode as
-         * the caller, with context_id in x0/r0, respectively.
-         */
-        ret = arm_set_cpu_on(mpidr, entry, context_id, arm_current_el(env),
-                             is_a64(env));
+        ret = arm_set_cpu_on(mpidr, entry, context_id,
+                             target_el, target_aarch64);
         break;
+    }
     case QEMU_PSCI_0_1_FN_CPU_OFF:
     case QEMU_PSCI_0_2_FN_CPU_OFF:
         goto cpu_off;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Qemu-devel] [PATCH v2 17/18] target-arm: Enable EL2 feature bit on A53 and A57
  2017-01-09 16:05 [Qemu-devel] [PATCH v2 00/18] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs Peter Maydell
                   ` (15 preceding siblings ...)
  2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 16/18] target/arm/psci.c: If EL2 implemented, start CPUs " Peter Maydell
@ 2017-01-09 16:05 ` Peter Maydell
  2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 18/18] hw/arm/virt: Add board property to enable EL2 Peter Maydell
  2017-01-17 14:07 ` [Qemu-devel] [Qemu-arm] [PATCH v2 00/18] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs Peter Maydell
  18 siblings, 0 replies; 37+ messages in thread
From: Peter Maydell @ 2017-01-09 16:05 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: patches, Andrew Jones, Christoffer Dall, Edgar E . Iglesias,
	Alistair Francis

Enable the ARM_FEATURE_EL2 bit on Cortex-A52 and
Cortex-A57, since this is all now sufficiently implemented
to work with the GICv3. We provide the usual CPU property
to disable it for backwards compatibility with the older
virt boards.

In this commit, we disable the EL2 feature on the
virt and ZynpMP boards, so there is no overall effect.
Another commit will expose a board-level property to
allow the user to enable EL2.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Andrew Jones <drjones@redhat.com>
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
---
 target/arm/cpu.h     |  2 ++
 hw/arm/virt.c        |  4 ++++
 hw/arm/xlnx-zynqmp.c |  2 ++
 target/arm/cpu.c     | 12 ++++++++++++
 target/arm/cpu64.c   |  2 ++
 5 files changed, 22 insertions(+)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 28c5d8f..c5b835f 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -574,6 +574,8 @@ struct ARMCPU {
     bool start_powered_off;
     /* CPU currently in PSCI powered-off state */
     bool powered_off;
+    /* CPU has virtualization extension */
+    bool has_el2;
     /* CPU has security extension */
     bool has_el3;
     /* CPU has PMU (Performance Monitor Unit) */
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 1fdc791..46f19cd 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -1329,6 +1329,10 @@ static void machvirt_init(MachineState *machine)
             object_property_set_bool(cpuobj, false, "has_el3", NULL);
         }
 
+        if (object_property_find(cpuobj, "has_el2", NULL)) {
+            object_property_set_bool(cpuobj, false, "has_el2", NULL);
+        }
+
         if (vms->psci_conduit != QEMU_PSCI_CONDUIT_DISABLED) {
             object_property_set_int(cpuobj, vms->psci_conduit,
                                     "psci-conduit", NULL);
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
index 0d86ba3..bc4e66b 100644
--- a/hw/arm/xlnx-zynqmp.c
+++ b/hw/arm/xlnx-zynqmp.c
@@ -258,6 +258,8 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
 
         object_property_set_bool(OBJECT(&s->apu_cpu[i]),
                                  s->secure, "has_el3", NULL);
+        object_property_set_bool(OBJECT(&s->apu_cpu[i]),
+                                 false, "has_el2", NULL);
         object_property_set_int(OBJECT(&s->apu_cpu[i]), GIC_BASE_ADDR,
                                 "reset-cbar", &error_abort);
         object_property_set_bool(OBJECT(&s->apu_cpu[i]), true, "realized",
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 8932086..2c9073d 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -497,6 +497,9 @@ static Property arm_cpu_reset_hivecs_property =
 static Property arm_cpu_rvbar_property =
             DEFINE_PROP_UINT64("rvbar", ARMCPU, rvbar, 0);
 
+static Property arm_cpu_has_el2_property =
+            DEFINE_PROP_BOOL("has_el2", ARMCPU, has_el2, true);
+
 static Property arm_cpu_has_el3_property =
             DEFINE_PROP_BOOL("has_el3", ARMCPU, has_el3, true);
 
@@ -547,6 +550,11 @@ static void arm_cpu_post_init(Object *obj)
 #endif
     }
 
+    if (arm_feature(&cpu->env, ARM_FEATURE_EL2)) {
+        qdev_property_add_static(DEVICE(obj), &arm_cpu_has_el2_property,
+                                 &error_abort);
+    }
+
     if (arm_feature(&cpu->env, ARM_FEATURE_PMU)) {
         qdev_property_add_static(DEVICE(obj), &arm_cpu_has_pmu_property,
                                  &error_abort);
@@ -695,6 +703,10 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
         cpu->id_aa64pfr0 &= ~0xf000;
     }
 
+    if (!cpu->has_el2) {
+        unset_feature(env, ARM_FEATURE_EL2);
+    }
+
     if (!cpu->has_pmu || !kvm_enabled()) {
         cpu->has_pmu = false;
         unset_feature(env, ARM_FEATURE_PMU);
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index 73c7f31..670c07a 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -110,6 +110,7 @@ static void aarch64_a57_initfn(Object *obj)
     set_feature(&cpu->env, ARM_FEATURE_V8_SHA256);
     set_feature(&cpu->env, ARM_FEATURE_V8_PMULL);
     set_feature(&cpu->env, ARM_FEATURE_CRC);
+    set_feature(&cpu->env, ARM_FEATURE_EL2);
     set_feature(&cpu->env, ARM_FEATURE_EL3);
     set_feature(&cpu->env, ARM_FEATURE_PMU);
     cpu->kvm_target = QEMU_KVM_ARM_TARGET_CORTEX_A57;
@@ -169,6 +170,7 @@ static void aarch64_a53_initfn(Object *obj)
     set_feature(&cpu->env, ARM_FEATURE_V8_SHA256);
     set_feature(&cpu->env, ARM_FEATURE_V8_PMULL);
     set_feature(&cpu->env, ARM_FEATURE_CRC);
+    set_feature(&cpu->env, ARM_FEATURE_EL2);
     set_feature(&cpu->env, ARM_FEATURE_EL3);
     set_feature(&cpu->env, ARM_FEATURE_PMU);
     cpu->kvm_target = QEMU_KVM_ARM_TARGET_CORTEX_A53;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Qemu-devel] [PATCH v2 18/18] hw/arm/virt: Add board property to enable EL2
  2017-01-09 16:05 [Qemu-devel] [PATCH v2 00/18] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs Peter Maydell
                   ` (16 preceding siblings ...)
  2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 17/18] target-arm: Enable EL2 feature bit on A53 and A57 Peter Maydell
@ 2017-01-09 16:05 ` Peter Maydell
  2017-01-10 16:45   ` Edgar E. Iglesias
  2017-01-17 14:07 ` [Qemu-devel] [Qemu-arm] [PATCH v2 00/18] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs Peter Maydell
  18 siblings, 1 reply; 37+ messages in thread
From: Peter Maydell @ 2017-01-09 16:05 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: patches, Andrew Jones, Christoffer Dall, Edgar E . Iglesias,
	Alistair Francis

Add a board level property to the virt board which will
enable EL2 on the CPU if the user asks for it. The
default is not to provide EL2. If EL2 is enabled then
we will use SMC as our PSCI conduit, and report the
virtualization support in the GICv3 device tree node
and the ACPI tables.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Andrew Jones <drjones@redhat.com>
---
 include/hw/arm/virt.h    |  1 +
 hw/arm/virt-acpi-build.c |  3 +++
 hw/arm/virt.c            | 44 ++++++++++++++++++++++++++++++++++++++++++--
 3 files changed, 46 insertions(+), 2 deletions(-)

diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
index 53507e6..58ce74e 100644
--- a/include/hw/arm/virt.h
+++ b/include/hw/arm/virt.h
@@ -93,6 +93,7 @@ typedef struct {
     FWCfgState *fw_cfg;
     bool secure;
     bool highmem;
+    bool virt;
     int32_t gic_version;
     struct arm_boot_info bootinfo;
     const MemMapEntry *memmap;
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index ec7f83b..32b660d 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -607,6 +607,9 @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
         if (arm_feature(&armcpu->env, ARM_FEATURE_PMU)) {
             gicc->performance_interrupt = cpu_to_le32(PPI(VIRTUAL_PMU_IRQ));
         }
+        if (vms->virt && vms->gic_version == 3) {
+            gicc->vgic_interrupt = cpu_to_le32(PPI(ARCH_GICV3_MAINT_IRQ));
+        }
     }
 
     if (vms->gic_version == 3) {
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 46f19cd..709da40 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -444,6 +444,11 @@ static void fdt_add_gic_node(VirtMachineState *vms)
                                      2, vms->memmap[VIRT_GIC_DIST].size,
                                      2, vms->memmap[VIRT_GIC_REDIST].base,
                                      2, vms->memmap[VIRT_GIC_REDIST].size);
+        if (vms->virt) {
+            qemu_fdt_setprop_cells(vms->fdt, "/intc", "interrupts",
+                                   GIC_FDT_IRQ_TYPE_PPI, ARCH_GICV3_MAINT_IRQ,
+                                   GIC_FDT_IRQ_FLAGS_LEVEL_HI);
+        }
     } else {
         /* 'cortex-a15-gic' means 'GIC v2' */
         qemu_fdt_setprop_string(vms->fdt, "/intc", "compatible",
@@ -1240,10 +1245,15 @@ static void machvirt_init(MachineState *machine)
      * so it doesn't get in the way. Instead of starting secondary
      * CPUs in PSCI powerdown state we will start them all running and
      * let the boot ROM sort them out.
-     * The usual case is that we do use QEMU's PSCI implementation.
+     * The usual case is that we do use QEMU's PSCI implementation;
+     * if the guest has EL2 then we will use SMC as the conduit,
+     * and otherwise we will use HVC (for backwards compatibility and
+     * because if we're using KVM then we must use HVC).
      */
     if (vms->secure && firmware_loaded) {
         vms->psci_conduit = QEMU_PSCI_CONDUIT_DISABLED;
+    } else if (vms->virt) {
+        vms->psci_conduit = QEMU_PSCI_CONDUIT_SMC;
     } else {
         vms->psci_conduit = QEMU_PSCI_CONDUIT_HVC;
     }
@@ -1273,6 +1283,12 @@ static void machvirt_init(MachineState *machine)
         exit(1);
     }
 
+    if (vms->virt && kvm_enabled()) {
+        error_report("mach-virt: KVM does not support providing "
+                     "Virtualization extensions to the guest CPU");
+        exit(1);
+    }
+
     if (vms->secure) {
         if (kvm_enabled()) {
             error_report("mach-virt: KVM does not support Security extensions");
@@ -1329,7 +1345,7 @@ static void machvirt_init(MachineState *machine)
             object_property_set_bool(cpuobj, false, "has_el3", NULL);
         }
 
-        if (object_property_find(cpuobj, "has_el2", NULL)) {
+        if (!vms->virt && object_property_find(cpuobj, "has_el2", NULL)) {
             object_property_set_bool(cpuobj, false, "has_el2", NULL);
         }
 
@@ -1435,6 +1451,20 @@ static void virt_set_secure(Object *obj, bool value, Error **errp)
     vms->secure = value;
 }
 
+static bool virt_get_virt(Object *obj, Error **errp)
+{
+    VirtMachineState *vms = VIRT_MACHINE(obj);
+
+    return vms->virt;
+}
+
+static void virt_set_virt(Object *obj, bool value, Error **errp)
+{
+    VirtMachineState *vms = VIRT_MACHINE(obj);
+
+    vms->virt = value;
+}
+
 static bool virt_get_highmem(Object *obj, Error **errp)
 {
     VirtMachineState *vms = VIRT_MACHINE(obj);
@@ -1522,6 +1552,16 @@ static void virt_2_9_instance_init(Object *obj)
                                     "Security Extensions (TrustZone)",
                                     NULL);
 
+    /* EL2 is also disabled by default, for similar reasons */
+    vms->virt = false;
+    object_property_add_bool(obj, "virtualization", virt_get_virt,
+                             virt_set_virt, NULL);
+    object_property_set_description(obj, "virtualization",
+                                    "Set on/off to enable/disable emulating a "
+                                    "guest CPU which implements the ARM "
+                                    "Virtualization Extensions",
+                                    NULL);
+
     /* High memory is enabled by default */
     vms->highmem = true;
     object_property_add_bool(obj, "highmem", virt_get_highmem,
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* Re: [Qemu-devel] [PATCH v2 16/18] target/arm/psci.c: If EL2 implemented, start CPUs in EL2
  2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 16/18] target/arm/psci.c: If EL2 implemented, start CPUs " Peter Maydell
@ 2017-01-10 16:36   ` Edgar E. Iglesias
  2017-01-17 14:47   ` Andrew Jones
  1 sibling, 0 replies; 37+ messages in thread
From: Edgar E. Iglesias @ 2017-01-10 16:36 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-arm, qemu-devel, patches, Andrew Jones, Christoffer Dall,
	Alistair Francis

On Mon, Jan 09, 2017 at 04:05:22PM +0000, Peter Maydell wrote:
> The PSCI spec states that a CPU_ON call should cause the new
> CPU to be started in the highest implemented Non-secure
> exception level. We were incorrectly starting it at the
> exception level of the caller, which happens to be correct
> if EL2 is not implemented. Implement the correct logic
> as described in the PSCI 1.0 spec section 6.4:
>  * if EL2 exists and SCR_EL3.HCE is set: start in EL2
>  * otherwise start in EL1
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>


Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>


> ---
>  target/arm/psci.c | 25 ++++++++++++++++++-------
>  1 file changed, 18 insertions(+), 7 deletions(-)
> 
> diff --git a/target/arm/psci.c b/target/arm/psci.c
> index 14316eb..64bf82e 100644
> --- a/target/arm/psci.c
> +++ b/target/arm/psci.c
> @@ -148,17 +148,28 @@ void arm_handle_psci_call(ARMCPU *cpu)
>      case QEMU_PSCI_0_1_FN_CPU_ON:
>      case QEMU_PSCI_0_2_FN_CPU_ON:
>      case QEMU_PSCI_0_2_FN64_CPU_ON:
> +    {
> +        /* The PSCI spec mandates that newly brought up CPUs start
> +         * in the highest exception level which exists and is enabled
> +         * on the calling CPU. Since the QEMU PSCI implementation is
> +         * acting as a "fake EL3" or "fake EL2" firmware, this for us
> +         * means that we want to start at the highest NS exception level
> +         * that we are providing to the guest.
> +         * The execution mode should be that which is currently in use
> +         * by the same exception level on the calling CPU.
> +         * The CPU should be started with the context_id value
> +         * in x0 (if AArch64) or r0 (if AArch32).
> +         */
> +        int target_el = arm_feature(env, ARM_FEATURE_EL2) ? 2 : 1;
> +        bool target_aarch64 = arm_el_is_aa64(env, target_el);
> +
>          mpidr = param[1];
>          entry = param[2];
>          context_id = param[3];
> -        /*
> -         * The PSCI spec mandates that newly brought up CPUs enter the
> -         * exception level of the caller in the same execution mode as
> -         * the caller, with context_id in x0/r0, respectively.
> -         */
> -        ret = arm_set_cpu_on(mpidr, entry, context_id, arm_current_el(env),
> -                             is_a64(env));
> +        ret = arm_set_cpu_on(mpidr, entry, context_id,
> +                             target_el, target_aarch64);
>          break;
> +    }
>      case QEMU_PSCI_0_1_FN_CPU_OFF:
>      case QEMU_PSCI_0_2_FN_CPU_OFF:
>          goto cpu_off;
> -- 
> 2.7.4
> 

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Qemu-devel] [PATCH v2 04/18] hw/arm/virt: Wire VIRQ, VFIQ, maintenance irq lines from GIC to CPU
  2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 04/18] hw/arm/virt: Wire VIRQ, VFIQ, maintenance irq lines from GIC to CPU Peter Maydell
@ 2017-01-10 16:42   ` Edgar E. Iglesias
  2017-01-10 17:17     ` Peter Maydell
  0 siblings, 1 reply; 37+ messages in thread
From: Edgar E. Iglesias @ 2017-01-10 16:42 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-arm, qemu-devel, patches, Andrew Jones, Christoffer Dall,
	Alistair Francis

On Mon, Jan 09, 2017 at 04:05:10PM +0000, Peter Maydell wrote:
> Wire the new VIRQ, VFIQ and maintenance interrupt lines from the
> GIC to each CPU.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  include/hw/arm/virt.h |  2 ++
>  hw/arm/virt.c         | 14 +++++++++++---
>  2 files changed, 13 insertions(+), 3 deletions(-)
> 
> diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
> index eb1c63d..b8a19ec 100644
> --- a/include/hw/arm/virt.h
> +++ b/include/hw/arm/virt.h
> @@ -39,6 +39,8 @@
>  #define NUM_GICV2M_SPIS       64
>  #define NUM_VIRTIO_TRANSPORTS 32
>  
> +#define ARCH_GICV3_MAINT_IRQ  9
> +
>  #define ARCH_TIMER_VIRT_IRQ   11
>  #define ARCH_TIMER_S_EL1_IRQ  13
>  #define ARCH_TIMER_NS_EL1_IRQ 14
> diff --git a/hw/arm/virt.c b/hw/arm/virt.c
> index 7a03f84..b31d302 100644
> --- a/hw/arm/virt.c
> +++ b/hw/arm/virt.c
> @@ -547,9 +547,9 @@ static void create_gic(VirtMachineState *vms, qemu_irq *pic)
>          sysbus_mmio_map(gicbusdev, 1, vms->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
> -     * the CPU's IRQ input.
> +    /* Wire the outputs from each CPU's generic timer and the GICv3
> +     * maintenance interrupt signal to the appropriate GIC PPI inputs,
> +     * and the GIC's IRQ/FIQ/VIRQ/VFIQ interrupt outputs to the CPU's inputs.
>       */
>      for (i = 0; i < smp_cpus; i++) {
>          DeviceState *cpudev = DEVICE(qemu_get_cpu(i));
> @@ -571,9 +571,17 @@ static void create_gic(VirtMachineState *vms, qemu_irq *pic)
>                                                     ppibase + timer_irq[irq]));
>          }
>  
> +        qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt", 0,
> +                                    qdev_get_gpio_in(gicdev, ppibase
> +                                                     + ARCH_GICV3_MAINT_IRQ));
> +
>          sysbus_connect_irq(gicbusdev, i, qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
>          sysbus_connect_irq(gicbusdev, i + smp_cpus,
>                             qdev_get_gpio_in(cpudev, ARM_CPU_FIQ));
> +        sysbus_connect_irq(gicbusdev, i + 2 * smp_cpus,
> +                           qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ));
> +        sysbus_connect_irq(gicbusdev, i + 3 * smp_cpus,

I thought there was an error here first (i.e i * smp_cpus + 3).
The code is correct but could have perhaps been more readable with named irqs.

Anyway, it looks correct:

Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>



> +                           qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ));
>      }
>  
>      for (i = 0; i < NUM_IRQS; i++) {
> -- 
> 2.7.4
> 

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Qemu-devel] [PATCH v2 18/18] hw/arm/virt: Add board property to enable EL2
  2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 18/18] hw/arm/virt: Add board property to enable EL2 Peter Maydell
@ 2017-01-10 16:45   ` Edgar E. Iglesias
  0 siblings, 0 replies; 37+ messages in thread
From: Edgar E. Iglesias @ 2017-01-10 16:45 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-arm, qemu-devel, patches, Andrew Jones, Christoffer Dall,
	Alistair Francis

On Mon, Jan 09, 2017 at 04:05:24PM +0000, Peter Maydell wrote:
> Add a board level property to the virt board which will
> enable EL2 on the CPU if the user asks for it. The
> default is not to provide EL2. If EL2 is enabled then
> we will use SMC as our PSCI conduit, and report the
> virtualization support in the GICv3 device tree node
> and the ACPI tables.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> Reviewed-by: Andrew Jones <drjones@redhat.com>

Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>


> ---
>  include/hw/arm/virt.h    |  1 +
>  hw/arm/virt-acpi-build.c |  3 +++
>  hw/arm/virt.c            | 44 ++++++++++++++++++++++++++++++++++++++++++--
>  3 files changed, 46 insertions(+), 2 deletions(-)
> 
> diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
> index 53507e6..58ce74e 100644
> --- a/include/hw/arm/virt.h
> +++ b/include/hw/arm/virt.h
> @@ -93,6 +93,7 @@ typedef struct {
>      FWCfgState *fw_cfg;
>      bool secure;
>      bool highmem;
> +    bool virt;
>      int32_t gic_version;
>      struct arm_boot_info bootinfo;
>      const MemMapEntry *memmap;
> diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
> index ec7f83b..32b660d 100644
> --- a/hw/arm/virt-acpi-build.c
> +++ b/hw/arm/virt-acpi-build.c
> @@ -607,6 +607,9 @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
>          if (arm_feature(&armcpu->env, ARM_FEATURE_PMU)) {
>              gicc->performance_interrupt = cpu_to_le32(PPI(VIRTUAL_PMU_IRQ));
>          }
> +        if (vms->virt && vms->gic_version == 3) {
> +            gicc->vgic_interrupt = cpu_to_le32(PPI(ARCH_GICV3_MAINT_IRQ));
> +        }
>      }
>  
>      if (vms->gic_version == 3) {
> diff --git a/hw/arm/virt.c b/hw/arm/virt.c
> index 46f19cd..709da40 100644
> --- a/hw/arm/virt.c
> +++ b/hw/arm/virt.c
> @@ -444,6 +444,11 @@ static void fdt_add_gic_node(VirtMachineState *vms)
>                                       2, vms->memmap[VIRT_GIC_DIST].size,
>                                       2, vms->memmap[VIRT_GIC_REDIST].base,
>                                       2, vms->memmap[VIRT_GIC_REDIST].size);
> +        if (vms->virt) {
> +            qemu_fdt_setprop_cells(vms->fdt, "/intc", "interrupts",
> +                                   GIC_FDT_IRQ_TYPE_PPI, ARCH_GICV3_MAINT_IRQ,
> +                                   GIC_FDT_IRQ_FLAGS_LEVEL_HI);
> +        }
>      } else {
>          /* 'cortex-a15-gic' means 'GIC v2' */
>          qemu_fdt_setprop_string(vms->fdt, "/intc", "compatible",
> @@ -1240,10 +1245,15 @@ static void machvirt_init(MachineState *machine)
>       * so it doesn't get in the way. Instead of starting secondary
>       * CPUs in PSCI powerdown state we will start them all running and
>       * let the boot ROM sort them out.
> -     * The usual case is that we do use QEMU's PSCI implementation.
> +     * The usual case is that we do use QEMU's PSCI implementation;
> +     * if the guest has EL2 then we will use SMC as the conduit,
> +     * and otherwise we will use HVC (for backwards compatibility and
> +     * because if we're using KVM then we must use HVC).
>       */
>      if (vms->secure && firmware_loaded) {
>          vms->psci_conduit = QEMU_PSCI_CONDUIT_DISABLED;
> +    } else if (vms->virt) {
> +        vms->psci_conduit = QEMU_PSCI_CONDUIT_SMC;
>      } else {
>          vms->psci_conduit = QEMU_PSCI_CONDUIT_HVC;
>      }
> @@ -1273,6 +1283,12 @@ static void machvirt_init(MachineState *machine)
>          exit(1);
>      }
>  
> +    if (vms->virt && kvm_enabled()) {
> +        error_report("mach-virt: KVM does not support providing "
> +                     "Virtualization extensions to the guest CPU");
> +        exit(1);
> +    }
> +
>      if (vms->secure) {
>          if (kvm_enabled()) {
>              error_report("mach-virt: KVM does not support Security extensions");
> @@ -1329,7 +1345,7 @@ static void machvirt_init(MachineState *machine)
>              object_property_set_bool(cpuobj, false, "has_el3", NULL);
>          }
>  
> -        if (object_property_find(cpuobj, "has_el2", NULL)) {
> +        if (!vms->virt && object_property_find(cpuobj, "has_el2", NULL)) {
>              object_property_set_bool(cpuobj, false, "has_el2", NULL);
>          }
>  
> @@ -1435,6 +1451,20 @@ static void virt_set_secure(Object *obj, bool value, Error **errp)
>      vms->secure = value;
>  }
>  
> +static bool virt_get_virt(Object *obj, Error **errp)
> +{
> +    VirtMachineState *vms = VIRT_MACHINE(obj);
> +
> +    return vms->virt;
> +}
> +
> +static void virt_set_virt(Object *obj, bool value, Error **errp)
> +{
> +    VirtMachineState *vms = VIRT_MACHINE(obj);
> +
> +    vms->virt = value;
> +}
> +
>  static bool virt_get_highmem(Object *obj, Error **errp)
>  {
>      VirtMachineState *vms = VIRT_MACHINE(obj);
> @@ -1522,6 +1552,16 @@ static void virt_2_9_instance_init(Object *obj)
>                                      "Security Extensions (TrustZone)",
>                                      NULL);
>  
> +    /* EL2 is also disabled by default, for similar reasons */
> +    vms->virt = false;
> +    object_property_add_bool(obj, "virtualization", virt_get_virt,
> +                             virt_set_virt, NULL);
> +    object_property_set_description(obj, "virtualization",
> +                                    "Set on/off to enable/disable emulating a "
> +                                    "guest CPU which implements the ARM "
> +                                    "Virtualization Extensions",
> +                                    NULL);
> +
>      /* High memory is enabled by default */
>      vms->highmem = true;
>      object_property_add_bool(obj, "highmem", virt_get_highmem,
> -- 
> 2.7.4
> 

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Qemu-devel] [PATCH v2 02/18] hw/intc/arm_gic: Add external IRQ lines for VIRQ and VFIQ
  2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 02/18] hw/intc/arm_gic: " Peter Maydell
@ 2017-01-10 16:49   ` Edgar E. Iglesias
  0 siblings, 0 replies; 37+ messages in thread
From: Edgar E. Iglesias @ 2017-01-10 16:49 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-arm, qemu-devel, patches, Andrew Jones, Christoffer Dall,
	Alistair Francis

On Mon, Jan 09, 2017 at 04:05:08PM +0000, Peter Maydell wrote:
> Augment the GIC's QOM device interface by adding two
> new sets of sysbus IRQ lines, to signal VIRQ and VFIQ to
> each CPU.
> 
> We never use these, but it's helpful to keep the v2-and-earlier
> GIC's external interface in line with that of the GICv3 to
> avoid board code having to add extra code conditional on which
> version of the GIC is in use.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>

Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>


> ---
>  include/hw/intc/arm_gic_common.h | 2 ++
>  hw/intc/arm_gic_common.c         | 6 ++++++
>  2 files changed, 8 insertions(+)
> 
> diff --git a/include/hw/intc/arm_gic_common.h b/include/hw/intc/arm_gic_common.h
> index f4c349a..af3ca18 100644
> --- a/include/hw/intc/arm_gic_common.h
> +++ b/include/hw/intc/arm_gic_common.h
> @@ -55,6 +55,8 @@ typedef struct GICState {
>  
>      qemu_irq parent_irq[GIC_NCPU];
>      qemu_irq parent_fiq[GIC_NCPU];
> +    qemu_irq parent_virq[GIC_NCPU];
> +    qemu_irq parent_vfiq[GIC_NCPU];
>      /* GICD_CTLR; for a GIC with the security extensions the NS banked version
>       * of this register is just an alias of bit 1 of the S banked version.
>       */
> diff --git a/hw/intc/arm_gic_common.c b/hw/intc/arm_gic_common.c
> index 0a1f56a..4a8df44 100644
> --- a/hw/intc/arm_gic_common.c
> +++ b/hw/intc/arm_gic_common.c
> @@ -110,6 +110,12 @@ void gic_init_irqs_and_mmio(GICState *s, qemu_irq_handler handler,
>      for (i = 0; i < s->num_cpu; i++) {
>          sysbus_init_irq(sbd, &s->parent_fiq[i]);
>      }
> +    for (i = 0; i < s->num_cpu; i++) {
> +        sysbus_init_irq(sbd, &s->parent_virq[i]);
> +    }
> +    for (i = 0; i < s->num_cpu; i++) {
> +        sysbus_init_irq(sbd, &s->parent_vfiq[i]);
> +    }
>  
>      /* Distributor */
>      memory_region_init_io(&s->iomem, OBJECT(s), ops, s, "gic_dist", 0x1000);
> -- 
> 2.7.4
> 

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Qemu-devel] [PATCH v2 04/18] hw/arm/virt: Wire VIRQ, VFIQ, maintenance irq lines from GIC to CPU
  2017-01-10 16:42   ` Edgar E. Iglesias
@ 2017-01-10 17:17     ` Peter Maydell
  0 siblings, 0 replies; 37+ messages in thread
From: Peter Maydell @ 2017-01-10 17:17 UTC (permalink / raw)
  To: Edgar E. Iglesias
  Cc: qemu-arm, QEMU Developers, patches, Andrew Jones,
	Christoffer Dall, Alistair Francis

On 10 January 2017 at 16:42, Edgar E. Iglesias
<edgar.iglesias@xilinx.com> wrote:
> On Mon, Jan 09, 2017 at 04:05:10PM +0000, Peter Maydell wrote:
>> @@ -571,9 +571,17 @@ static void create_gic(VirtMachineState *vms, qemu_irq *pic)
>>                                                     ppibase + timer_irq[irq]));
>>          }
>>
>> +        qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt", 0,
>> +                                    qdev_get_gpio_in(gicdev, ppibase
>> +                                                     + ARCH_GICV3_MAINT_IRQ));
>> +
>>          sysbus_connect_irq(gicbusdev, i, qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
>>          sysbus_connect_irq(gicbusdev, i + smp_cpus,
>>                             qdev_get_gpio_in(cpudev, ARM_CPU_FIQ));
>> +        sysbus_connect_irq(gicbusdev, i + 2 * smp_cpus,
>> +                           qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ));
>> +        sysbus_connect_irq(gicbusdev, i + 3 * smp_cpus,
>
> I thought there was an error here first (i.e i * smp_cpus + 3).
> The code is correct but could have perhaps been more readable with named irqs.

Yeah, all the GIC interfacing predates named IRQs and we haven't
got round to trying to convert it (it would be a fairly tedious
job given all the boards that wire up GICs these days).

thanks
-- PMM

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Qemu-devel] [Qemu-arm] [PATCH v2 00/18] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs
  2017-01-09 16:05 [Qemu-devel] [PATCH v2 00/18] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs Peter Maydell
                   ` (17 preceding siblings ...)
  2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 18/18] hw/arm/virt: Add board property to enable EL2 Peter Maydell
@ 2017-01-17 14:07 ` Peter Maydell
  2017-01-17 14:49   ` Andrew Jones
  2017-01-18  9:17   ` Edgar E. Iglesias
  18 siblings, 2 replies; 37+ messages in thread
From: Peter Maydell @ 2017-01-17 14:07 UTC (permalink / raw)
  To: qemu-arm, QEMU Developers
  Cc: Edgar E . Iglesias, Andrew Jones, Alistair Francis,
	Christoffer Dall, patches

On 9 January 2017 at 16:05, Peter Maydell <peter.maydell@linaro.org> wrote:
> This patchset adds support for the Virtualization extensions to QEMU's
> GICv3 emulation. This was the last missing piece that was stopping
> us from turning on the EL2 support in the CPU model, so the patchset
> also adds support for enabling it all on the virt board via the
> '-machine virtualization=on' option.

> Patches 1, 4-13, 15, 16 still need review.

So is anybody interested in reviewing the complicated
bits in the middle of this patchset (5-13) or shall I
just throw it into target-arm.next? :-)

thanks
-- PMM

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Qemu-devel] [PATCH v2 16/18] target/arm/psci.c: If EL2 implemented, start CPUs in EL2
  2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 16/18] target/arm/psci.c: If EL2 implemented, start CPUs " Peter Maydell
  2017-01-10 16:36   ` Edgar E. Iglesias
@ 2017-01-17 14:47   ` Andrew Jones
  1 sibling, 0 replies; 37+ messages in thread
From: Andrew Jones @ 2017-01-17 14:47 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-arm, qemu-devel, Edgar E . Iglesias, Alistair Francis,
	Christoffer Dall, patches

On Mon, Jan 09, 2017 at 04:05:22PM +0000, Peter Maydell wrote:
> The PSCI spec states that a CPU_ON call should cause the new
> CPU to be started in the highest implemented Non-secure
> exception level. We were incorrectly starting it at the
> exception level of the caller, which happens to be correct
> if EL2 is not implemented. Implement the correct logic
> as described in the PSCI 1.0 spec section 6.4:
>  * if EL2 exists and SCR_EL3.HCE is set: start in EL2
>  * otherwise start in EL1
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  target/arm/psci.c | 25 ++++++++++++++++++-------
>  1 file changed, 18 insertions(+), 7 deletions(-)

Reviewed-by: Andrew Jones <drjones@redhat.com>
Tested-by: Andrew Jones <drjones@redhat.com>

> 
> diff --git a/target/arm/psci.c b/target/arm/psci.c
> index 14316eb..64bf82e 100644
> --- a/target/arm/psci.c
> +++ b/target/arm/psci.c
> @@ -148,17 +148,28 @@ void arm_handle_psci_call(ARMCPU *cpu)
>      case QEMU_PSCI_0_1_FN_CPU_ON:
>      case QEMU_PSCI_0_2_FN_CPU_ON:
>      case QEMU_PSCI_0_2_FN64_CPU_ON:
> +    {
> +        /* The PSCI spec mandates that newly brought up CPUs start
> +         * in the highest exception level which exists and is enabled
> +         * on the calling CPU. Since the QEMU PSCI implementation is
> +         * acting as a "fake EL3" or "fake EL2" firmware, this for us
> +         * means that we want to start at the highest NS exception level
> +         * that we are providing to the guest.
> +         * The execution mode should be that which is currently in use
> +         * by the same exception level on the calling CPU.
> +         * The CPU should be started with the context_id value
> +         * in x0 (if AArch64) or r0 (if AArch32).
> +         */
> +        int target_el = arm_feature(env, ARM_FEATURE_EL2) ? 2 : 1;
> +        bool target_aarch64 = arm_el_is_aa64(env, target_el);
> +
>          mpidr = param[1];
>          entry = param[2];
>          context_id = param[3];
> -        /*
> -         * The PSCI spec mandates that newly brought up CPUs enter the
> -         * exception level of the caller in the same execution mode as
> -         * the caller, with context_id in x0/r0, respectively.
> -         */
> -        ret = arm_set_cpu_on(mpidr, entry, context_id, arm_current_el(env),
> -                             is_a64(env));
> +        ret = arm_set_cpu_on(mpidr, entry, context_id,
> +                             target_el, target_aarch64);
>          break;
> +    }
>      case QEMU_PSCI_0_1_FN_CPU_OFF:
>      case QEMU_PSCI_0_2_FN_CPU_OFF:
>          goto cpu_off;
> -- 
> 2.7.4
> 
> 

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Qemu-devel] [Qemu-arm] [PATCH v2 00/18] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs
  2017-01-17 14:07 ` [Qemu-devel] [Qemu-arm] [PATCH v2 00/18] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs Peter Maydell
@ 2017-01-17 14:49   ` Andrew Jones
  2017-01-17 22:16     ` Alistair Francis
  2017-01-18  9:17   ` Edgar E. Iglesias
  1 sibling, 1 reply; 37+ messages in thread
From: Andrew Jones @ 2017-01-17 14:49 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-arm, QEMU Developers, Edgar E . Iglesias, patches,
	Christoffer Dall, Alistair Francis

On Tue, Jan 17, 2017 at 02:07:31PM +0000, Peter Maydell wrote:
> On 9 January 2017 at 16:05, Peter Maydell <peter.maydell@linaro.org> wrote:
> > This patchset adds support for the Virtualization extensions to QEMU's
> > GICv3 emulation. This was the last missing piece that was stopping
> > us from turning on the EL2 support in the CPU model, so the patchset
> > also adds support for enabling it all on the virt board via the
> > '-machine virtualization=on' option.
> 
> > Patches 1, 4-13, 15, 16 still need review.
> 
> So is anybody interested in reviewing the complicated
> bits in the middle of this patchset (5-13) or shall I
> just throw it into target-arm.next? :-)

Unfortunately I don't have time right now to give them the justice
they deserve. FWIW, I've done light testing and light reviewing and
I don't have any complaints.

Thanks,
drew

> 
> thanks
> -- PMM
> 

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Qemu-devel] [PATCH v2 01/18] hw/intc/arm_gicv3: Add external IRQ lines for VIRQ and VFIQ
  2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 01/18] hw/intc/arm_gicv3: Add external IRQ lines for VIRQ and VFIQ Peter Maydell
@ 2017-01-17 21:49   ` Alistair Francis
  0 siblings, 0 replies; 37+ messages in thread
From: Alistair Francis @ 2017-01-17 21:49 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-arm, qemu-devel@nongnu.org Developers, Edgar E . Iglesias,
	Andrew Jones, Alistair Francis, Christoffer Dall, Patch Tracking

On Mon, Jan 9, 2017 at 8:05 AM, Peter Maydell <peter.maydell@linaro.org> wrote:
> Augment the GICv3's QOM device interface by adding two
> new sets of sysbus IRQ lines, to signal VIRQ and VFIQ to
> each CPU.
>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>

Thanks,

Alistair

> ---
>  include/hw/intc/arm_gicv3_common.h | 2 ++
>  hw/intc/arm_gicv3_common.c         | 6 ++++++
>  2 files changed, 8 insertions(+)
>
> diff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h
> index 341a311..beb2c77 100644
> --- a/include/hw/intc/arm_gicv3_common.h
> +++ b/include/hw/intc/arm_gicv3_common.h
> @@ -145,6 +145,8 @@ struct GICv3CPUState {
>      CPUState *cpu;
>      qemu_irq parent_irq;
>      qemu_irq parent_fiq;
> +    qemu_irq parent_virq;
> +    qemu_irq parent_vfiq;
>
>      /* Redistributor */
>      uint32_t level;                  /* Current IRQ level */
> diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
> index 0aa9b9c..0ee67a4 100644
> --- a/hw/intc/arm_gicv3_common.c
> +++ b/hw/intc/arm_gicv3_common.c
> @@ -126,6 +126,12 @@ void gicv3_init_irqs_and_mmio(GICv3State *s, qemu_irq_handler handler,
>      for (i = 0; i < s->num_cpu; i++) {
>          sysbus_init_irq(sbd, &s->cpu[i].parent_fiq);
>      }
> +    for (i = 0; i < s->num_cpu; i++) {
> +        sysbus_init_irq(sbd, &s->cpu[i].parent_virq);
> +    }
> +    for (i = 0; i < s->num_cpu; i++) {
> +        sysbus_init_irq(sbd, &s->cpu[i].parent_vfiq);
> +    }
>
>      memory_region_init_io(&s->iomem_dist, OBJECT(s), ops, s,
>                            "gicv3_dist", 0x10000);
> --
> 2.7.4
>
>

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Qemu-devel] [PATCH v2 03/18] target-arm: Expose output GPIO line for VCPU maintenance interrupt
  2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 03/18] target-arm: Expose output GPIO line for VCPU maintenance interrupt Peter Maydell
@ 2017-01-17 21:50   ` Alistair Francis
  0 siblings, 0 replies; 37+ messages in thread
From: Alistair Francis @ 2017-01-17 21:50 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-arm, qemu-devel@nongnu.org Developers, Edgar E . Iglesias,
	Andrew Jones, Alistair Francis, Christoffer Dall, Patch Tracking

On Mon, Jan 9, 2017 at 8:05 AM, Peter Maydell <peter.maydell@linaro.org> wrote:
> The GICv3 support for virtualization includes an outbound
> maintenance interrupt signal which is asserted when the
> CPU interface wants to signal to the hypervisor that it
> needs attention. Expose this as an outbound GPIO line from
> the CPU object which can be wired up as a physical interrupt
> line by the board code (as we do already for the CPU timers).
>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>

Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>

Thanks,

Alistair

> ---
>  target/arm/cpu.h | 2 ++
>  target/arm/cpu.c | 3 +++
>  2 files changed, 5 insertions(+)
>
> diff --git a/target/arm/cpu.h b/target/arm/cpu.h
> index ab119e6..764b511 100644
> --- a/target/arm/cpu.h
> +++ b/target/arm/cpu.h
> @@ -555,6 +555,8 @@ struct ARMCPU {
>      QEMUTimer *gt_timer[NUM_GTIMERS];
>      /* GPIO outputs for generic timer */
>      qemu_irq gt_timer_outputs[NUM_GTIMERS];
> +    /* GPIO output for GICv3 maintenance interrupt signal */
> +    qemu_irq gicv3_maintenance_interrupt;
>
>      /* MemoryRegion to use for secure physical accesses */
>      MemoryRegion *secure_memory;
> diff --git a/target/arm/cpu.c b/target/arm/cpu.c
> index f5cb30a..8932086 100644
> --- a/target/arm/cpu.c
> +++ b/target/arm/cpu.c
> @@ -466,6 +466,9 @@ static void arm_cpu_initfn(Object *obj)
>                                                  arm_gt_stimer_cb, cpu);
>      qdev_init_gpio_out(DEVICE(cpu), cpu->gt_timer_outputs,
>                         ARRAY_SIZE(cpu->gt_timer_outputs));
> +
> +    qdev_init_gpio_out_named(DEVICE(cpu), &cpu->gicv3_maintenance_interrupt,
> +                             "gicv3-maintenance-interrupt", 1);
>  #endif
>
>      /* DTB consumers generally don't in fact care what the 'compatible'
> --
> 2.7.4
>
>

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Qemu-devel] [PATCH v2 05/18] target-arm: Add ARMCPU fields for GIC CPU i/f config
  2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 05/18] target-arm: Add ARMCPU fields for GIC CPU i/f config Peter Maydell
@ 2017-01-17 22:12   ` Alistair Francis
  0 siblings, 0 replies; 37+ messages in thread
From: Alistair Francis @ 2017-01-17 22:12 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-arm, qemu-devel@nongnu.org Developers, Edgar E . Iglesias,
	Andrew Jones, Alistair Francis, Christoffer Dall, Patch Tracking

On Mon, Jan 9, 2017 at 8:05 AM, Peter Maydell <peter.maydell@linaro.org> wrote:
> Add fields to the ARMCPU structure to allow CPU classes to
> specify the configurable aspects of their GIC CPU interface.
> In particular, the virtualization support allows different
> values for number of list registers, priority bits and
> preemption bits.
>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Acked-by: Alistair Francis <alistair.francis@xilinx.com>

Thanks,

Alistair

> ---
>  target/arm/cpu.h   | 5 +++++
>  target/arm/cpu64.c | 6 ++++++
>  2 files changed, 11 insertions(+)
>
> diff --git a/target/arm/cpu.h b/target/arm/cpu.h
> index 764b511..28c5d8f 100644
> --- a/target/arm/cpu.h
> +++ b/target/arm/cpu.h
> @@ -659,6 +659,11 @@ struct ARMCPU {
>      uint32_t dcz_blocksize;
>      uint64_t rvbar;
>
> +    /* Configurable aspects of GIC cpu interface (which is part of the CPU) */
> +    int gic_num_lrs; /* number of list registers */
> +    int gic_vpribits; /* number of virtual priority bits */
> +    int gic_vprebits; /* number of virtual preemption bits */
> +
>      ARMELChangeHook *el_change_hook;
>      void *el_change_hook_opaque;
>  };
> diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
> index 549cb1e..73c7f31 100644
> --- a/target/arm/cpu64.c
> +++ b/target/arm/cpu64.c
> @@ -147,6 +147,9 @@ static void aarch64_a57_initfn(Object *obj)
>      cpu->ccsidr[1] = 0x201fe012; /* 48KB L1 icache */
>      cpu->ccsidr[2] = 0x70ffe07a; /* 2048KB L2 cache */
>      cpu->dcz_blocksize = 4; /* 64 bytes */
> +    cpu->gic_num_lrs = 4;
> +    cpu->gic_vpribits = 5;
> +    cpu->gic_vprebits = 5;
>      define_arm_cp_regs(cpu, cortex_a57_a53_cp_reginfo);
>  }
>
> @@ -201,6 +204,9 @@ static void aarch64_a53_initfn(Object *obj)
>      cpu->ccsidr[1] = 0x201fe00a; /* 32KB L1 icache */
>      cpu->ccsidr[2] = 0x707fe07a; /* 1024KB L2 cache */
>      cpu->dcz_blocksize = 4; /* 64 bytes */
> +    cpu->gic_num_lrs = 4;
> +    cpu->gic_vpribits = 5;
> +    cpu->gic_vprebits = 5;
>      define_arm_cp_regs(cpu, cortex_a57_a53_cp_reginfo);
>  }
>
> --
> 2.7.4
>
>

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Qemu-devel] [PATCH v2 07/18] hw/intc/gicv3: Add data fields for virtualization support
  2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 07/18] hw/intc/gicv3: Add data fields for virtualization support Peter Maydell
@ 2017-01-17 22:13   ` Alistair Francis
  0 siblings, 0 replies; 37+ messages in thread
From: Alistair Francis @ 2017-01-17 22:13 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-arm, qemu-devel@nongnu.org Developers, Edgar E . Iglesias,
	Andrew Jones, Alistair Francis, Christoffer Dall, Patch Tracking

On Mon, Jan 9, 2017 at 8:05 AM, Peter Maydell <peter.maydell@linaro.org> wrote:
> As the first step in adding support for the virtualization
> extensions to the GICv3 emulation:
>  * add the necessary data fields to the state structures
>  * add the fields to the migration state, as a subsection
>    which is only present if virtualization is enabled
>
> The use of a subsection means we retain migration
> compatibility as EL2 is not enabled on any CPUs currently.
>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Acked-by: Alistair Francis <alistair.francis@xilinx.com>

Thanks,

Alistair

> ---
>  include/hw/intc/arm_gicv3_common.h | 18 ++++++++++++++++++
>  hw/intc/arm_gicv3_common.c         | 25 +++++++++++++++++++++++++
>  hw/intc/arm_gicv3_cpuif.c          | 13 +++++++++++++
>  3 files changed, 56 insertions(+)
>
> diff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h
> index beb2c77..665d3f8 100644
> --- a/include/hw/intc/arm_gicv3_common.h
> +++ b/include/hw/intc/arm_gicv3_common.h
> @@ -38,6 +38,9 @@
>  /* Number of SGI target-list bits */
>  #define GICV3_TARGETLIST_BITS 16
>
> +/* Maximum number of list registers (architectural limit) */
> +#define GICV3_LR_MAX 16
> +
>  /* Minimum BPR for Secure, or when security not enabled */
>  #define GIC_MIN_BPR 0
>  /* Minimum BPR for Nonsecure when security is enabled */
> @@ -175,6 +178,21 @@ struct GICv3CPUState {
>      uint64_t icc_igrpen[3];
>      uint64_t icc_ctlr_el3;
>
> +    /* Virtualization control interface */
> +    uint64_t ich_apr[3][4]; /* ich_apr[GICV3_G1][x] never used */
> +    uint64_t ich_hcr_el2;
> +    uint64_t ich_lr_el2[GICV3_LR_MAX];
> +    uint64_t ich_vmcr_el2;
> +
> +    /* Properties of the CPU interface. These are initialized from
> +     * the settings in the CPU proper.
> +     * If the number of implemented list registers is 0 then the
> +     * virtualization support is not implemented.
> +     */
> +    int num_list_regs;
> +    int vpribits; /* number of virtual priority bits */
> +    int vprebits; /* number of virtual preemption bits */
> +
>      /* Current highest priority pending interrupt for this CPU.
>       * This is cached information that can be recalculated from the
>       * real state above; it doesn't need to be migrated.
> diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
> index 0ee67a4..16b9b0f 100644
> --- a/hw/intc/arm_gicv3_common.c
> +++ b/hw/intc/arm_gicv3_common.c
> @@ -49,6 +49,27 @@ static int gicv3_post_load(void *opaque, int version_id)
>      return 0;
>  }
>
> +static bool virt_state_needed(void *opaque)
> +{
> +    GICv3CPUState *cs = opaque;
> +
> +    return cs->num_list_regs != 0;
> +}
> +
> +static const VMStateDescription vmstate_gicv3_cpu_virt = {
> +    .name = "arm_gicv3_cpu/virt",
> +    .version_id = 1,
> +    .minimum_version_id = 1,
> +    .needed = virt_state_needed,
> +    .fields = (VMStateField[]) {
> +        VMSTATE_UINT64_2DARRAY(ich_apr, GICv3CPUState, 3, 4),
> +        VMSTATE_UINT64(ich_hcr_el2, GICv3CPUState),
> +        VMSTATE_UINT64_ARRAY(ich_lr_el2, GICv3CPUState, GICV3_LR_MAX),
> +        VMSTATE_UINT64(ich_vmcr_el2, GICv3CPUState),
> +        VMSTATE_END_OF_LIST()
> +    }
> +};
> +
>  static const VMStateDescription vmstate_gicv3_cpu = {
>      .name = "arm_gicv3_cpu",
>      .version_id = 1,
> @@ -75,6 +96,10 @@ static const VMStateDescription vmstate_gicv3_cpu = {
>          VMSTATE_UINT64_ARRAY(icc_igrpen, GICv3CPUState, 3),
>          VMSTATE_UINT64(icc_ctlr_el3, GICv3CPUState),
>          VMSTATE_END_OF_LIST()
> +    },
> +    .subsections = (const VMStateDescription * []) {
> +        &vmstate_gicv3_cpu_virt,
> +        NULL
>      }
>  };
>
> diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
> index 35e8eb3..d2f859c 100644
> --- a/hw/intc/arm_gicv3_cpuif.c
> +++ b/hw/intc/arm_gicv3_cpuif.c
> @@ -36,6 +36,12 @@ static bool gicv3_use_ns_bank(CPUARMState *env)
>      return !arm_is_secure_below_el3(env);
>  }
>
> +/* The minimum BPR for the virtual interface is a configurable property */
> +static inline int icv_min_vbpr(GICv3CPUState *cs)
> +{
> +    return 7 - cs->vprebits;
> +}
> +
>  static int icc_highest_active_prio(GICv3CPUState *cs)
>  {
>      /* Calculate the current running priority based on the set bits
> @@ -1081,6 +1087,13 @@ static void icc_reset(CPUARMState *env, const ARMCPRegInfo *ri)
>      cs->icc_ctlr_el3 = ICC_CTLR_EL3_NDS | ICC_CTLR_EL3_A3V |
>          (1 << ICC_CTLR_EL3_IDBITS_SHIFT) |
>          (7 << ICC_CTLR_EL3_PRIBITS_SHIFT);
> +
> +    memset(cs->ich_apr, 0, sizeof(cs->ich_apr));
> +    cs->ich_hcr_el2 = 0;
> +    memset(cs->ich_lr_el2, 0, sizeof(cs->ich_lr_el2));
> +    cs->ich_vmcr_el2 = ICH_VMCR_EL2_VFIQEN |
> +        (icv_min_vbpr(cs) << ICH_VMCR_EL2_VBPR1_SHIFT) |
> +        (icv_min_vbpr(cs) << ICH_VMCR_EL2_VBPR0_SHIFT);
>  }
>
>  static const ARMCPRegInfo gicv3_cpuif_reginfo[] = {
> --
> 2.7.4
>
>

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Qemu-devel] [PATCH v2 15/18] hw/arm/virt-acpi-build: use SMC if booting in EL2
  2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 15/18] hw/arm/virt-acpi-build: use SMC if booting in EL2 Peter Maydell
@ 2017-01-17 22:14   ` Alistair Francis
  0 siblings, 0 replies; 37+ messages in thread
From: Alistair Francis @ 2017-01-17 22:14 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-arm, qemu-devel@nongnu.org Developers, Edgar E . Iglesias,
	Andrew Jones, Alistair Francis, Christoffer Dall, Patch Tracking

On Mon, Jan 9, 2017 at 8:05 AM, Peter Maydell <peter.maydell@linaro.org> wrote:
> From: Andrew Jones <drjones@redhat.com>
>
> Signed-off-by: Andrew Jones <drjones@redhat.com>
> [PMM: look at vms->psci_conduit rather than vms->virt
>  to decide whether to use HVC or SMC, and report no
>  PSCI support at all for the 'PSCI disabled' case]
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Acked-by: Alistair Francis <alistair.francis@xilinx.com>

Thanks,

Alistair

> ---
>  hw/arm/virt-acpi-build.c | 26 ++++++++++++++++++++------
>  1 file changed, 20 insertions(+), 6 deletions(-)
>
> diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
> index 085a611..ec7f83b 100644
> --- a/hw/arm/virt-acpi-build.c
> +++ b/hw/arm/virt-acpi-build.c
> @@ -643,16 +643,30 @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
>  }
>
>  /* FADT */
> -static void
> -build_fadt(GArray *table_data, BIOSLinker *linker, unsigned dsdt_tbl_offset)
> +static void build_fadt(GArray *table_data, BIOSLinker *linker,
> +                       VirtMachineState *vms, unsigned dsdt_tbl_offset)
>  {
>      AcpiFadtDescriptorRev5_1 *fadt = acpi_data_push(table_data, sizeof(*fadt));
>      unsigned dsdt_entry_offset = (char *)&fadt->dsdt - table_data->data;
> +    uint16_t bootflags;
> +
> +    switch (vms->psci_conduit) {
> +    case QEMU_PSCI_CONDUIT_DISABLED:
> +        bootflags = 0;
> +        break;
> +    case QEMU_PSCI_CONDUIT_HVC:
> +        bootflags = ACPI_FADT_ARM_PSCI_COMPLIANT | ACPI_FADT_ARM_PSCI_USE_HVC;
> +        break;
> +    case QEMU_PSCI_CONDUIT_SMC:
> +        bootflags = ACPI_FADT_ARM_PSCI_COMPLIANT;
> +        break;
> +    default:
> +        g_assert_not_reached();
> +    }
>
> -    /* Hardware Reduced = 1 and use PSCI 0.2+ and with HVC */
> +    /* Hardware Reduced = 1 and use PSCI 0.2+ */
>      fadt->flags = cpu_to_le32(1 << ACPI_FADT_F_HW_REDUCED_ACPI);
> -    fadt->arm_boot_flags = cpu_to_le16(ACPI_FADT_ARM_PSCI_COMPLIANT |
> -                                       ACPI_FADT_ARM_PSCI_USE_HVC);
> +    fadt->arm_boot_flags = cpu_to_le16(bootflags);
>
>      /* ACPI v5.1 (fadt->revision.fadt->minor_revision) */
>      fadt->minor_revision = 0x1;
> @@ -738,7 +752,7 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables)
>
>      /* FADT MADT GTDT MCFG SPCR pointed to by RSDT */
>      acpi_add_table(table_offsets, tables_blob);
> -    build_fadt(tables_blob, tables->linker, dsdt);
> +    build_fadt(tables_blob, tables->linker, vms, dsdt);
>
>      acpi_add_table(table_offsets, tables_blob);
>      build_madt(tables_blob, tables->linker, vms);
> --
> 2.7.4
>
>

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Qemu-devel] [Qemu-arm] [PATCH v2 00/18] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs
  2017-01-17 14:49   ` Andrew Jones
@ 2017-01-17 22:16     ` Alistair Francis
  0 siblings, 0 replies; 37+ messages in thread
From: Alistair Francis @ 2017-01-17 22:16 UTC (permalink / raw)
  To: Andrew Jones
  Cc: Peter Maydell, Edgar E . Iglesias, patches, QEMU Developers,
	Alistair Francis, qemu-arm, Christoffer Dall

On Tue, Jan 17, 2017 at 6:49 AM, Andrew Jones <drjones@redhat.com> wrote:
> On Tue, Jan 17, 2017 at 02:07:31PM +0000, Peter Maydell wrote:
>> On 9 January 2017 at 16:05, Peter Maydell <peter.maydell@linaro.org> wrote:
>> > This patchset adds support for the Virtualization extensions to QEMU's
>> > GICv3 emulation. This was the last missing piece that was stopping
>> > us from turning on the EL2 support in the CPU model, so the patchset
>> > also adds support for enabling it all on the virt board via the
>> > '-machine virtualization=on' option.
>>
>> > Patches 1, 4-13, 15, 16 still need review.
>>
>> So is anybody interested in reviewing the complicated
>> bits in the middle of this patchset (5-13) or shall I
>> just throw it into target-arm.next? :-)

I have Acked and Reviewed what I can. I don't know much about GICv3 so
I can't really judge those patches. Overall they look good to me
though.

Thanks,

Alistair

>
> Unfortunately I don't have time right now to give them the justice
> they deserve. FWIW, I've done light testing and light reviewing and
> I don't have any complaints.
>
> Thanks,
> drew
>
>>
>> thanks
>> -- PMM
>>
>

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Qemu-devel] [Qemu-arm] [PATCH v2 00/18] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs
  2017-01-17 14:07 ` [Qemu-devel] [Qemu-arm] [PATCH v2 00/18] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs Peter Maydell
  2017-01-17 14:49   ` Andrew Jones
@ 2017-01-18  9:17   ` Edgar E. Iglesias
  2017-01-19 12:59     ` Peter Maydell
  1 sibling, 1 reply; 37+ messages in thread
From: Edgar E. Iglesias @ 2017-01-18  9:17 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-devel, qemu-arm, Alistair Francis, patches,
	Christoffer Dall, Andrew Jones

Hi Peter,  I'm on holidays and won't have time to review for a couple of
weeks at least...

Cheers,
Edgar

---
Sent from my phone

On 17 Jan 2017 14:08, "Peter Maydell" <peter.maydell@linaro.org> wrote:

> On 9 January 2017 at 16:05, Peter Maydell <peter.maydell@linaro.org>
> wrote:
> > This patchset adds support for the Virtualization extensions to QEMU's
> > GICv3 emulation. This was the last missing piece that was stopping
> > us from turning on the EL2 support in the CPU model, so the patchset
> > also adds support for enabling it all on the virt board via the
> > '-machine virtualization=on' option.
>
> > Patches 1, 4-13, 15, 16 still need review.
>
> So is anybody interested in reviewing the complicated
> bits in the middle of this patchset (5-13) or shall I
> just throw it into target-arm.next? :-)
>
> thanks
> -- PMM
>
>

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Qemu-devel] [Qemu-arm] [PATCH v2 00/18] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs
  2017-01-18  9:17   ` Edgar E. Iglesias
@ 2017-01-19 12:59     ` Peter Maydell
  2017-01-19 13:02       ` Edgar E. Iglesias
  0 siblings, 1 reply; 37+ messages in thread
From: Peter Maydell @ 2017-01-19 12:59 UTC (permalink / raw)
  To: Edgar E. Iglesias
  Cc: qemu-devel, qemu-arm, Alistair Francis, patches,
	Christoffer Dall, Andrew Jones

On 18 January 2017 at 09:17, Edgar E. Iglesias <edgar.iglesias@gmail.com> wrote:
> Hi Peter,  I'm on holidays and won't have time to review for a couple of
> weeks at least...

Do you want me to hold off on committing the GICv3 patches
until you get back and have had a chance to review?

thanks
-- PMM

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Qemu-devel] [Qemu-arm] [PATCH v2 00/18] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs
  2017-01-19 12:59     ` Peter Maydell
@ 2017-01-19 13:02       ` Edgar E. Iglesias
  2017-01-19 13:31         ` Peter Maydell
  0 siblings, 1 reply; 37+ messages in thread
From: Edgar E. Iglesias @ 2017-01-19 13:02 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-arm, Patch Tracking, Alistair Francis, Christoffer Dall,
	qemu-devel, Andrew Jones

Nah, if I find something we can always fix it with follow up patches...

Cheers,
Edgar

On Jan 19, 2017 1:59 PM, "Peter Maydell" <peter.maydell@linaro.org> wrote:

> On 18 January 2017 at 09:17, Edgar E. Iglesias <edgar.iglesias@gmail.com>
> wrote:
> > Hi Peter,  I'm on holidays and won't have time to review for a couple of
> > weeks at least...
>
> Do you want me to hold off on committing the GICv3 patches
> until you get back and have had a chance to review?
>
> thanks
> -- PMM
>

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Qemu-devel] [Qemu-arm] [PATCH v2 00/18] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs
  2017-01-19 13:02       ` Edgar E. Iglesias
@ 2017-01-19 13:31         ` Peter Maydell
  0 siblings, 0 replies; 37+ messages in thread
From: Peter Maydell @ 2017-01-19 13:31 UTC (permalink / raw)
  To: Edgar E. Iglesias
  Cc: qemu-arm, Patch Tracking, Alistair Francis, Christoffer Dall,
	qemu-devel, Andrew Jones

On 19 January 2017 at 13:02, Edgar E. Iglesias <edgar.iglesias@gmail.com> wrote:
> Nah, if I find something we can always fix it with follow up patches...

Cool. I've applied this series to target-arm.next.

thanks
-- PMM

^ permalink raw reply	[flat|nested] 37+ messages in thread

end of thread, other threads:[~2017-01-19 13:31 UTC | newest]

Thread overview: 37+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-01-09 16:05 [Qemu-devel] [PATCH v2 00/18] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs Peter Maydell
2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 01/18] hw/intc/arm_gicv3: Add external IRQ lines for VIRQ and VFIQ Peter Maydell
2017-01-17 21:49   ` Alistair Francis
2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 02/18] hw/intc/arm_gic: " Peter Maydell
2017-01-10 16:49   ` Edgar E. Iglesias
2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 03/18] target-arm: Expose output GPIO line for VCPU maintenance interrupt Peter Maydell
2017-01-17 21:50   ` Alistair Francis
2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 04/18] hw/arm/virt: Wire VIRQ, VFIQ, maintenance irq lines from GIC to CPU Peter Maydell
2017-01-10 16:42   ` Edgar E. Iglesias
2017-01-10 17:17     ` Peter Maydell
2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 05/18] target-arm: Add ARMCPU fields for GIC CPU i/f config Peter Maydell
2017-01-17 22:12   ` Alistair Francis
2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 06/18] hw/intc/gicv3: Add defines for ICH system register fields Peter Maydell
2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 07/18] hw/intc/gicv3: Add data fields for virtualization support Peter Maydell
2017-01-17 22:13   ` Alistair Francis
2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 08/18] hw/intc/arm_gicv3: Add accessors for ICH_ system registers Peter Maydell
2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 09/18] hw/intc/arm_gicv3: Implement ICV_ registers which are just accessors Peter Maydell
2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 10/18] hw/intc/arm_gicv3: Implement ICV_ HPPIR, DIR and RPR registers Peter Maydell
2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 11/18] hw/intc/arm_gicv3: Implement ICV_ registers EOIR and IAR Peter Maydell
2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 12/18] hw/intc/arm_gicv3: Implement gicv3_cpuif_virt_update() Peter Maydell
2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 13/18] hw/intc/arm_gicv3: Implement EL2 traps for CPU i/f regs Peter Maydell
2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 14/18] hw/arm/virt: Support using SMC for PSCI Peter Maydell
2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 15/18] hw/arm/virt-acpi-build: use SMC if booting in EL2 Peter Maydell
2017-01-17 22:14   ` Alistair Francis
2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 16/18] target/arm/psci.c: If EL2 implemented, start CPUs " Peter Maydell
2017-01-10 16:36   ` Edgar E. Iglesias
2017-01-17 14:47   ` Andrew Jones
2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 17/18] target-arm: Enable EL2 feature bit on A53 and A57 Peter Maydell
2017-01-09 16:05 ` [Qemu-devel] [PATCH v2 18/18] hw/arm/virt: Add board property to enable EL2 Peter Maydell
2017-01-10 16:45   ` Edgar E. Iglesias
2017-01-17 14:07 ` [Qemu-devel] [Qemu-arm] [PATCH v2 00/18] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs Peter Maydell
2017-01-17 14:49   ` Andrew Jones
2017-01-17 22:16     ` Alistair Francis
2017-01-18  9:17   ` Edgar E. Iglesias
2017-01-19 12:59     ` Peter Maydell
2017-01-19 13:02       ` Edgar E. Iglesias
2017-01-19 13:31         ` Peter Maydell

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.