All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 00/23] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs
@ 2016-12-13 10:36 Peter Maydell
  2016-12-13 10:36 ` [Qemu-devel] [PATCH 01/23] target-arm: Log AArch64 exception returns Peter Maydell
                   ` (25 more replies)
  0 siblings, 26 replies; 45+ messages in thread
From: Peter Maydell @ 2016-12-13 10:36 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: patches, Edgar E. Iglesias, Christoffer Dall, Andrew Jones

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.

Patches 1-7 have already appeared on list, and 1-5 + 7 have been
reviewed. The rest are new.

As per mailing list discussion, there is a new CPU property
for enabling EL2 which defaults to 'true' (named 'has_el2' to
parallel the existing 'has_el3'). There is also a board property
on 'virt' which defaults to 'false' (named 'virtualization' to
parallel the existing 'secure'). The only other 64-bit board
is the ZynqMP -- this patchset makes it always set has_el2 to false,
so no change in behaviour. (I imagine the Xilinx folk will want to
enable it at some point.)

There is no property on the GIC device object to enable virtualization,
because this only affects the CPU interface, which in real hardware
is part of the CPU itself and which in QEMU we enable and configure
via a close coupling between the cpuif code and the CPU code.

These patches include changes to the reported device tree info
to (a) report the GICv3 maintenance IRQ binding and (b) report
use of SMC as the PSCI conduit. I haven't tried to make the
equivalent changes to the ACPI tables because Drew said on
Monday that he had a cleanup to make in that area, which would
change all that code anyway. I'm guessing there'll be a v2 of
this series, so we can fix that dependency up properly then.

The new state in the GICv3 for the virtualization should not
cause a migration compat break because we put it in a subsection
which is only sent if virtualization is enabled.

Unfortunately to enable EL2 on the 32-bit CPU models we need
to do this all over again for the GICv2 emulation :-)

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


thanks
-- PMM

Peter Maydell (23):
  target-arm: Log AArch64 exception returns
  hw/intc/arm_gicv3: Remove incorrect usage of fieldoffset
  hw/intc/arm_gicv3: Don't signal Pending+Active interrupts to CPU
  hw/arm/virt: add 2.9 machine type
  hw/arm/virt: Merge VirtBoardInfo and VirtMachineState
  hw/arm/virt: Rename 'vbi' variables to 'vms'
  hw/arm/virt: Don't incorrectly claim architectural timer to be
    edge-triggered
  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: 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              |    2 +
 include/hw/compat.h                |    3 +
 include/hw/intc/arm_gic_common.h   |    2 +
 include/hw/intc/arm_gicv3_common.h |   21 +
 target-arm/cpu.h                   |    9 +
 hw/arm/virt.c                      |  696 +++++++++++--------
 hw/arm/xlnx-zynqmp.c               |    2 +
 hw/intc/arm_gic_common.c           |    6 +
 hw/intc/arm_gicv3.c                |    5 +
 hw/intc/arm_gicv3_common.c         |   31 +
 hw/intc/arm_gicv3_cpuif.c          | 1336 +++++++++++++++++++++++++++++++++++-
 target-arm/cpu.c                   |   15 +
 target-arm/cpu64.c                 |    8 +
 target-arm/op_helper.c             |    9 +
 hw/intc/trace-events               |   33 +
 16 files changed, 1925 insertions(+), 332 deletions(-)

-- 
2.7.4

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

* [Qemu-devel] [PATCH 01/23] target-arm: Log AArch64 exception returns
  2016-12-13 10:36 [Qemu-devel] [PATCH 00/23] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs Peter Maydell
@ 2016-12-13 10:36 ` Peter Maydell
  2016-12-19 21:51   ` Alistair Francis
  2016-12-20 15:31   ` Andrew Jones
  2016-12-13 10:36 ` [Qemu-devel] [PATCH 02/23] hw/intc/arm_gicv3: Remove incorrect usage of fieldoffset Peter Maydell
                   ` (24 subsequent siblings)
  25 siblings, 2 replies; 45+ messages in thread
From: Peter Maydell @ 2016-12-13 10:36 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: patches, Edgar E. Iglesias, Christoffer Dall, Andrew Jones

We already log exception entry; add logging of the AArch64 exception
return path as well.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
---
 target-arm/op_helper.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
index cd94216..ba796d8 100644
--- a/target-arm/op_helper.c
+++ b/target-arm/op_helper.c
@@ -17,6 +17,7 @@
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 #include "qemu/osdep.h"
+#include "qemu/log.h"
 #include "cpu.h"
 #include "exec/helper-proto.h"
 #include "internals.h"
@@ -972,6 +973,9 @@ void HELPER(exception_return)(CPUARMState *env)
         } else {
             env->regs[15] = env->elr_el[cur_el] & ~0x3;
         }
+        qemu_log_mask(CPU_LOG_INT, "Exception return from AArch64 EL%d to "
+                      "AArch32 EL%d PC 0x%" PRIx32 "\n",
+                      cur_el, new_el, env->regs[15]);
     } else {
         env->aarch64 = 1;
         pstate_write(env, spsr);
@@ -980,6 +984,9 @@ void HELPER(exception_return)(CPUARMState *env)
         }
         aarch64_restore_sp(env, new_el);
         env->pc = env->elr_el[cur_el];
+        qemu_log_mask(CPU_LOG_INT, "Exception return from AArch64 EL%d to "
+                      "AArch64 EL%d PC 0x%" PRIx64 "\n",
+                      cur_el, new_el, env->pc);
     }
 
     arm_call_el_change_hook(arm_env_get_cpu(env));
@@ -1002,6 +1009,8 @@ illegal_return:
     if (!arm_singlestep_active(env)) {
         env->pstate &= ~PSTATE_SS;
     }
+    qemu_log_mask(LOG_GUEST_ERROR, "Illegal exception return at EL%d: "
+                  "resuming execution at 0x%" PRIx64 "\n", cur_el, env->pc);
 }
 
 /* Return true if the linked breakpoint entry lbn passes its checks */
-- 
2.7.4

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

* [Qemu-devel] [PATCH 02/23] hw/intc/arm_gicv3: Remove incorrect usage of fieldoffset
  2016-12-13 10:36 [Qemu-devel] [PATCH 00/23] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs Peter Maydell
  2016-12-13 10:36 ` [Qemu-devel] [PATCH 01/23] target-arm: Log AArch64 exception returns Peter Maydell
@ 2016-12-13 10:36 ` Peter Maydell
  2016-12-13 10:36 ` [Qemu-devel] [PATCH 03/23] hw/intc/arm_gicv3: Don't signal Pending+Active interrupts to CPU Peter Maydell
                   ` (23 subsequent siblings)
  25 siblings, 0 replies; 45+ messages in thread
From: Peter Maydell @ 2016-12-13 10:36 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: patches, Edgar E. Iglesias, Christoffer Dall, Andrew Jones

In the ARMCPRegInfo definitions for the GICv3 CPU interface
registers, we were trying to use .fieldoffset to specify
the locations of data fields within the GICv3CPUState struct.
This is completely broken, because .fieldoffset is for offsets
into the CPUARMState struct. We didn't notice because we
were only using this for reads to BPR0, AP0R<n>, IGRPEN0
and CTLR_EL3, and Linux doesn't use these registers.

Replace the .fieldoffset uses with explicit read functions.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
---
 hw/intc/arm_gicv3_cpuif.c | 13 ++++++-------
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
index bca30c4..35e8eb3 100644
--- a/hw/intc/arm_gicv3_cpuif.c
+++ b/hw/intc/arm_gicv3_cpuif.c
@@ -1118,35 +1118,35 @@ static const ARMCPRegInfo gicv3_cpuif_reginfo[] = {
       .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 8, .opc2 = 3,
       .type = ARM_CP_IO | ARM_CP_NO_RAW,
       .access = PL1_RW, .accessfn = gicv3_fiq_access,
-      .fieldoffset = offsetof(GICv3CPUState, icc_bpr[GICV3_G0]),
+      .readfn = icc_bpr_read,
       .writefn = icc_bpr_write,
     },
     { .name = "ICC_AP0R0_EL1", .state = ARM_CP_STATE_BOTH,
       .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 8, .opc2 = 4,
       .type = ARM_CP_IO | ARM_CP_NO_RAW,
       .access = PL1_RW, .accessfn = gicv3_fiq_access,
-      .fieldoffset = offsetof(GICv3CPUState, icc_apr[GICV3_G0][0]),
+      .readfn = icc_ap_read,
       .writefn = icc_ap_write,
     },
     { .name = "ICC_AP0R1_EL1", .state = ARM_CP_STATE_BOTH,
       .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 8, .opc2 = 5,
       .type = ARM_CP_IO | ARM_CP_NO_RAW,
       .access = PL1_RW, .accessfn = gicv3_fiq_access,
-      .fieldoffset = offsetof(GICv3CPUState, icc_apr[GICV3_G0][1]),
+      .readfn = icc_ap_read,
       .writefn = icc_ap_write,
     },
     { .name = "ICC_AP0R2_EL1", .state = ARM_CP_STATE_BOTH,
       .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 8, .opc2 = 6,
       .type = ARM_CP_IO | ARM_CP_NO_RAW,
       .access = PL1_RW, .accessfn = gicv3_fiq_access,
-      .fieldoffset = offsetof(GICv3CPUState, icc_apr[GICV3_G0][2]),
+      .readfn = icc_ap_read,
       .writefn = icc_ap_write,
     },
     { .name = "ICC_AP0R3_EL1", .state = ARM_CP_STATE_BOTH,
       .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 8, .opc2 = 7,
       .type = ARM_CP_IO | ARM_CP_NO_RAW,
       .access = PL1_RW, .accessfn = gicv3_fiq_access,
-      .fieldoffset = offsetof(GICv3CPUState, icc_apr[GICV3_G0][3]),
+      .readfn = icc_ap_read,
       .writefn = icc_ap_write,
     },
     /* All the ICC_AP1R*_EL1 registers are banked */
@@ -1275,7 +1275,7 @@ static const ARMCPRegInfo gicv3_cpuif_reginfo[] = {
       .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 12, .opc2 = 6,
       .type = ARM_CP_IO | ARM_CP_NO_RAW,
       .access = PL1_RW, .accessfn = gicv3_fiq_access,
-      .fieldoffset = offsetof(GICv3CPUState, icc_igrpen[GICV3_G0]),
+      .readfn = icc_igrpen_read,
       .writefn = icc_igrpen_write,
     },
     /* This register is banked */
@@ -1299,7 +1299,6 @@ static const ARMCPRegInfo gicv3_cpuif_reginfo[] = {
       .opc0 = 3, .opc1 = 6, .crn = 12, .crm = 12, .opc2 = 4,
       .type = ARM_CP_IO | ARM_CP_NO_RAW,
       .access = PL3_RW,
-      .fieldoffset = offsetof(GICv3CPUState, icc_ctlr_el3),
       .readfn = icc_ctlr_el3_read,
       .writefn = icc_ctlr_el3_write,
     },
-- 
2.7.4

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

* [Qemu-devel] [PATCH 03/23] hw/intc/arm_gicv3: Don't signal Pending+Active interrupts to CPU
  2016-12-13 10:36 [Qemu-devel] [PATCH 00/23] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs Peter Maydell
  2016-12-13 10:36 ` [Qemu-devel] [PATCH 01/23] target-arm: Log AArch64 exception returns Peter Maydell
  2016-12-13 10:36 ` [Qemu-devel] [PATCH 02/23] hw/intc/arm_gicv3: Remove incorrect usage of fieldoffset Peter Maydell
@ 2016-12-13 10:36 ` Peter Maydell
  2016-12-13 10:36 ` [Qemu-devel] [PATCH 04/23] hw/arm/virt: add 2.9 machine type Peter Maydell
                   ` (22 subsequent siblings)
  25 siblings, 0 replies; 45+ messages in thread
From: Peter Maydell @ 2016-12-13 10:36 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: patches, Edgar E. Iglesias, Christoffer Dall, Andrew Jones

The GICv3 requires that we only signal Pending interrupts to
the CPU. This category does not include Pending+Active interrupts,
which means we need to check whether the interrupt is Active in
the gicr_int_pending() and gicd_int_pending() functions.

Interrupts are rarely in the Active+Pending state, but KVM
uses this as part of its handling of the virtual timer, so
this bug was causing KVM to go into an infinite loop of
taking the vtimer interrupt when the guest first triggered it.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
---
 hw/intc/arm_gicv3.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/hw/intc/arm_gicv3.c b/hw/intc/arm_gicv3.c
index 8a6c647..f0c967b 100644
--- a/hw/intc/arm_gicv3.c
+++ b/hw/intc/arm_gicv3.c
@@ -54,6 +54,7 @@ static uint32_t gicd_int_pending(GICv3State *s, int irq)
      *  + the PENDING latch is set OR it is level triggered and the input is 1
      *  + its ENABLE bit is set
      *  + the GICD enable bit for its group is set
+     *  + its ACTIVE bit is not set (otherwise it would be Active+Pending)
      * Conveniently we can bulk-calculate this with bitwise operations.
      */
     uint32_t pend, grpmask;
@@ -63,9 +64,11 @@ static uint32_t gicd_int_pending(GICv3State *s, int irq)
     uint32_t group = *gic_bmp_ptr32(s->group, irq);
     uint32_t grpmod = *gic_bmp_ptr32(s->grpmod, irq);
     uint32_t enable = *gic_bmp_ptr32(s->enabled, irq);
+    uint32_t active = *gic_bmp_ptr32(s->active, irq);
 
     pend = pending | (~edge_trigger & level);
     pend &= enable;
+    pend &= ~active;
 
     if (s->gicd_ctlr & GICD_CTLR_DS) {
         grpmod = 0;
@@ -96,12 +99,14 @@ static uint32_t gicr_int_pending(GICv3CPUState *cs)
      *  + the PENDING latch is set OR it is level triggered and the input is 1
      *  + its ENABLE bit is set
      *  + the GICD enable bit for its group is set
+     *  + its ACTIVE bit is not set (otherwise it would be Active+Pending)
      * Conveniently we can bulk-calculate this with bitwise operations.
      */
     uint32_t pend, grpmask, grpmod;
 
     pend = cs->gicr_ipendr0 | (~cs->edge_trigger & cs->level);
     pend &= cs->gicr_ienabler0;
+    pend &= ~cs->gicr_iactiver0;
 
     if (cs->gic->gicd_ctlr & GICD_CTLR_DS) {
         grpmod = 0;
-- 
2.7.4

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

* [Qemu-devel] [PATCH 04/23] hw/arm/virt: add 2.9 machine type
  2016-12-13 10:36 [Qemu-devel] [PATCH 00/23] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs Peter Maydell
                   ` (2 preceding siblings ...)
  2016-12-13 10:36 ` [Qemu-devel] [PATCH 03/23] hw/intc/arm_gicv3: Don't signal Pending+Active interrupts to CPU Peter Maydell
@ 2016-12-13 10:36 ` Peter Maydell
  2016-12-13 10:36 ` [Qemu-devel] [PATCH 05/23] hw/arm/virt: Merge VirtBoardInfo and VirtMachineState Peter Maydell
                   ` (21 subsequent siblings)
  25 siblings, 0 replies; 45+ messages in thread
From: Peter Maydell @ 2016-12-13 10:36 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: patches, Edgar E. Iglesias, Christoffer Dall, Andrew Jones

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

diff --git a/include/hw/compat.h b/include/hw/compat.h
index 0f06e11..f8b8354 100644
--- a/include/hw/compat.h
+++ b/include/hw/compat.h
@@ -1,6 +1,9 @@
 #ifndef HW_COMPAT_H
 #define HW_COMPAT_H
 
+#define HW_COMPAT_2_8 \
+    /* empty */
+
 #define HW_COMPAT_2_7 \
     {\
         .driver   = "virtio-pci",\
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index d04e4ac..11c53a5 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -1525,7 +1525,7 @@ static void machvirt_machine_init(void)
 }
 type_init(machvirt_machine_init);
 
-static void virt_2_8_instance_init(Object *obj)
+static void virt_2_9_instance_init(Object *obj)
 {
     VirtMachineState *vms = VIRT_MACHINE(obj);
 
@@ -1558,10 +1558,25 @@ static void virt_2_8_instance_init(Object *obj)
                                     "Valid values are 2, 3 and host", NULL);
 }
 
+static void virt_machine_2_9_options(MachineClass *mc)
+{
+}
+DEFINE_VIRT_MACHINE_AS_LATEST(2, 9)
+
+#define VIRT_COMPAT_2_8 \
+    HW_COMPAT_2_8
+
+static void virt_2_8_instance_init(Object *obj)
+{
+    virt_2_9_instance_init(obj);
+}
+
 static void virt_machine_2_8_options(MachineClass *mc)
 {
+    virt_machine_2_9_options(mc);
+    SET_MACHINE_COMPAT(mc, VIRT_COMPAT_2_8);
 }
-DEFINE_VIRT_MACHINE_AS_LATEST(2, 8)
+DEFINE_VIRT_MACHINE(2, 8)
 
 #define VIRT_COMPAT_2_7 \
     HW_COMPAT_2_7
-- 
2.7.4

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

* [Qemu-devel] [PATCH 05/23] hw/arm/virt: Merge VirtBoardInfo and VirtMachineState
  2016-12-13 10:36 [Qemu-devel] [PATCH 00/23] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs Peter Maydell
                   ` (3 preceding siblings ...)
  2016-12-13 10:36 ` [Qemu-devel] [PATCH 04/23] hw/arm/virt: add 2.9 machine type Peter Maydell
@ 2016-12-13 10:36 ` Peter Maydell
  2016-12-13 10:36 ` [Qemu-devel] [PATCH 06/23] hw/arm/virt: Rename 'vbi' variables to 'vms' Peter Maydell
                   ` (20 subsequent siblings)
  25 siblings, 0 replies; 45+ messages in thread
From: Peter Maydell @ 2016-12-13 10:36 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: patches, Edgar E. Iglesias, Christoffer Dall, Andrew Jones

One of the purposes of VirtBoardInfo was to hold various
bits of state about the board. Now we have MachineState
and the subclass VirtMachineState to do this. Fold the
VirtBoardInfo into VirtMachineState rather than having
some flags in one struct and some in another with no
useful way to get between them.

In the process we drop the code for looking up the
memory map and irq map from the CPU model, because
in practice we always use the same maps in all cases.

For easier code review, this change removes the
VirtBoardInfo type but leaves all the variables which
used to be VirtBoardInfo* and are now VirtMachineState*
with their now-confusing 'vbi' names.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Andrew Jones <drjones@redhat.com>
---
 hw/arm/virt.c | 118 +++++++++++++++++++++++++---------------------------------
 1 file changed, 51 insertions(+), 67 deletions(-)

diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 11c53a5..fd4eed9 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -66,23 +66,8 @@
 
 static ARMPlatformBusSystemParams platform_bus_params;
 
-typedef struct VirtBoardInfo {
-    struct arm_boot_info bootinfo;
-    const char *cpu_model;
-    const MemMapEntry *memmap;
-    const int *irqmap;
-    int smp_cpus;
-    void *fdt;
-    int fdt_size;
-    uint32_t clock_phandle;
-    uint32_t gic_phandle;
-    uint32_t msi_phandle;
-    bool using_psci;
-} VirtBoardInfo;
-
 typedef struct {
     MachineClass parent;
-    VirtBoardInfo *daughterboard;
     bool disallow_affinity_adjustment;
     bool no_its;
     bool no_pmu;
@@ -93,6 +78,16 @@ typedef struct {
     bool secure;
     bool highmem;
     int32_t gic_version;
+    struct arm_boot_info bootinfo;
+    const MemMapEntry *memmap;
+    const int *irqmap;
+    int smp_cpus;
+    void *fdt;
+    int fdt_size;
+    uint32_t clock_phandle;
+    uint32_t gic_phandle;
+    uint32_t msi_phandle;
+    bool using_psci;
 } VirtMachineState;
 
 #define TYPE_VIRT_MACHINE   MACHINE_TYPE_NAME("virt")
@@ -202,42 +197,27 @@ static const int a15irqmap[] = {
     [VIRT_PLATFORM_BUS] = 112, /* ...to 112 + PLATFORM_BUS_NUM_IRQS -1 */
 };
 
-static VirtBoardInfo machines[] = {
-    {
-        .cpu_model = "cortex-a15",
-        .memmap = a15memmap,
-        .irqmap = a15irqmap,
-    },
-    {
-        .cpu_model = "cortex-a53",
-        .memmap = a15memmap,
-        .irqmap = a15irqmap,
-    },
-    {
-        .cpu_model = "cortex-a57",
-        .memmap = a15memmap,
-        .irqmap = a15irqmap,
-    },
-    {
-        .cpu_model = "host",
-        .memmap = a15memmap,
-        .irqmap = a15irqmap,
-    },
+static const char *valid_cpus[] = {
+    "cortex-a15",
+    "cortex-a53",
+    "cortex-a57",
+    "host",
+    NULL
 };
 
-static VirtBoardInfo *find_machine_info(const char *cpu)
+static bool cpuname_valid(const char *cpu)
 {
     int i;
 
-    for (i = 0; i < ARRAY_SIZE(machines); i++) {
-        if (strcmp(cpu, machines[i].cpu_model) == 0) {
-            return &machines[i];
+    for (i = 0; i < ARRAY_SIZE(valid_cpus); i++) {
+        if (strcmp(cpu, valid_cpus[i]) == 0) {
+            return true;
         }
     }
-    return NULL;
+    return false;
 }
 
-static void create_fdt(VirtBoardInfo *vbi)
+static void create_fdt(VirtMachineState *vbi)
 {
     void *fdt = create_device_tree(&vbi->fdt_size);
 
@@ -277,7 +257,7 @@ static void create_fdt(VirtBoardInfo *vbi)
 
 }
 
-static void fdt_add_psci_node(const VirtBoardInfo *vbi)
+static void fdt_add_psci_node(const VirtMachineState *vbi)
 {
     uint32_t cpu_suspend_fn;
     uint32_t cpu_off_fn;
@@ -327,7 +307,7 @@ static void fdt_add_psci_node(const VirtBoardInfo *vbi)
     qemu_fdt_setprop_cell(fdt, "/psci", "migrate", migrate_fn);
 }
 
-static void fdt_add_timer_nodes(const VirtBoardInfo *vbi, int gictype)
+static void fdt_add_timer_nodes(const VirtMachineState *vbi, int gictype)
 {
     /* Note that on A15 h/w these interrupts are level-triggered,
      * but for the GIC implementation provided by both QEMU and KVM
@@ -361,7 +341,7 @@ static void fdt_add_timer_nodes(const VirtBoardInfo *vbi, int gictype)
                        GIC_FDT_IRQ_TYPE_PPI, ARCH_TIMER_NS_EL2_IRQ, irqflags);
 }
 
-static void fdt_add_cpu_nodes(const VirtBoardInfo *vbi)
+static void fdt_add_cpu_nodes(const VirtMachineState *vbi)
 {
     int cpu;
     int addr_cells = 1;
@@ -424,7 +404,7 @@ static void fdt_add_cpu_nodes(const VirtBoardInfo *vbi)
     }
 }
 
-static void fdt_add_its_gic_node(VirtBoardInfo *vbi)
+static void fdt_add_its_gic_node(VirtMachineState *vbi)
 {
     vbi->msi_phandle = qemu_fdt_alloc_phandle(vbi->fdt);
     qemu_fdt_add_subnode(vbi->fdt, "/intc/its");
@@ -437,7 +417,7 @@ static void fdt_add_its_gic_node(VirtBoardInfo *vbi)
     qemu_fdt_setprop_cell(vbi->fdt, "/intc/its", "phandle", vbi->msi_phandle);
 }
 
-static void fdt_add_v2m_gic_node(VirtBoardInfo *vbi)
+static void fdt_add_v2m_gic_node(VirtMachineState *vbi)
 {
     vbi->msi_phandle = qemu_fdt_alloc_phandle(vbi->fdt);
     qemu_fdt_add_subnode(vbi->fdt, "/intc/v2m");
@@ -450,7 +430,7 @@ static void fdt_add_v2m_gic_node(VirtBoardInfo *vbi)
     qemu_fdt_setprop_cell(vbi->fdt, "/intc/v2m", "phandle", vbi->msi_phandle);
 }
 
-static void fdt_add_gic_node(VirtBoardInfo *vbi, int type)
+static void fdt_add_gic_node(VirtMachineState *vbi, int type)
 {
     vbi->gic_phandle = qemu_fdt_alloc_phandle(vbi->fdt);
     qemu_fdt_setprop_cell(vbi->fdt, "/", "interrupt-parent", vbi->gic_phandle);
@@ -483,7 +463,7 @@ static void fdt_add_gic_node(VirtBoardInfo *vbi, int type)
     qemu_fdt_setprop_cell(vbi->fdt, "/intc", "phandle", vbi->gic_phandle);
 }
 
-static void fdt_add_pmu_nodes(const VirtBoardInfo *vbi, int gictype)
+static void fdt_add_pmu_nodes(const VirtMachineState *vbi, int gictype)
 {
     CPUState *cpu;
     ARMCPU *armcpu;
@@ -514,7 +494,7 @@ static void fdt_add_pmu_nodes(const VirtBoardInfo *vbi, int gictype)
     }
 }
 
-static void create_its(VirtBoardInfo *vbi, DeviceState *gicdev)
+static void create_its(VirtMachineState *vbi, DeviceState *gicdev)
 {
     const char *itsclass = its_class_name();
     DeviceState *dev;
@@ -534,7 +514,7 @@ static void create_its(VirtBoardInfo *vbi, DeviceState *gicdev)
     fdt_add_its_gic_node(vbi);
 }
 
-static void create_v2m(VirtBoardInfo *vbi, qemu_irq *pic)
+static void create_v2m(VirtMachineState *vbi, qemu_irq *pic)
 {
     int i;
     int irq = vbi->irqmap[VIRT_GIC_V2M];
@@ -553,7 +533,7 @@ static void create_v2m(VirtBoardInfo *vbi, qemu_irq *pic)
     fdt_add_v2m_gic_node(vbi);
 }
 
-static void create_gic(VirtBoardInfo *vbi, qemu_irq *pic, int type,
+static void create_gic(VirtMachineState *vbi, qemu_irq *pic, int type,
                        bool secure, bool no_its)
 {
     /* We create a standalone GIC */
@@ -625,7 +605,7 @@ static void create_gic(VirtBoardInfo *vbi, qemu_irq *pic, int type,
     }
 }
 
-static void create_uart(const VirtBoardInfo *vbi, qemu_irq *pic, int uart,
+static void create_uart(const VirtMachineState *vbi, qemu_irq *pic, int uart,
                         MemoryRegion *mem, CharDriverState *chr)
 {
     char *nodename;
@@ -669,7 +649,7 @@ static void create_uart(const VirtBoardInfo *vbi, qemu_irq *pic, int uart,
     g_free(nodename);
 }
 
-static void create_rtc(const VirtBoardInfo *vbi, qemu_irq *pic)
+static void create_rtc(const VirtMachineState *vbi, qemu_irq *pic)
 {
     char *nodename;
     hwaddr base = vbi->memmap[VIRT_RTC].base;
@@ -703,7 +683,7 @@ static Notifier virt_system_powerdown_notifier = {
     .notify = virt_powerdown_req
 };
 
-static void create_gpio(const VirtBoardInfo *vbi, qemu_irq *pic)
+static void create_gpio(const VirtMachineState *vbi, qemu_irq *pic)
 {
     char *nodename;
     DeviceState *pl061_dev;
@@ -750,7 +730,7 @@ static void create_gpio(const VirtBoardInfo *vbi, qemu_irq *pic)
     g_free(nodename);
 }
 
-static void create_virtio_devices(const VirtBoardInfo *vbi, qemu_irq *pic)
+static void create_virtio_devices(const VirtMachineState *vbi, qemu_irq *pic)
 {
     int i;
     hwaddr size = vbi->memmap[VIRT_MMIO].size;
@@ -870,7 +850,7 @@ static void create_one_flash(const char *name, hwaddr flashbase,
     }
 }
 
-static void create_flash(const VirtBoardInfo *vbi,
+static void create_flash(const VirtMachineState *vbi,
                          MemoryRegion *sysmem,
                          MemoryRegion *secure_sysmem)
 {
@@ -925,7 +905,7 @@ static void create_flash(const VirtBoardInfo *vbi,
     }
 }
 
-static void create_fw_cfg(const VirtBoardInfo *vbi, AddressSpace *as)
+static void create_fw_cfg(const VirtMachineState *vbi, AddressSpace *as)
 {
     hwaddr base = vbi->memmap[VIRT_FW_CFG].base;
     hwaddr size = vbi->memmap[VIRT_FW_CFG].size;
@@ -944,7 +924,8 @@ static void create_fw_cfg(const VirtBoardInfo *vbi, AddressSpace *as)
     g_free(nodename);
 }
 
-static void create_pcie_irq_map(const VirtBoardInfo *vbi, uint32_t gic_phandle,
+static void create_pcie_irq_map(const VirtMachineState *vbi,
+                                uint32_t gic_phandle,
                                 int first_irq, const char *nodename)
 {
     int devfn, pin;
@@ -979,7 +960,7 @@ static void create_pcie_irq_map(const VirtBoardInfo *vbi, uint32_t gic_phandle,
                            0x7           /* PCI irq */);
 }
 
-static void create_pcie(const VirtBoardInfo *vbi, qemu_irq *pic,
+static void create_pcie(const VirtMachineState *vbi, qemu_irq *pic,
                         bool use_highmem)
 {
     hwaddr base_mmio = vbi->memmap[VIRT_PCIE_MMIO].base;
@@ -1095,7 +1076,7 @@ static void create_pcie(const VirtBoardInfo *vbi, qemu_irq *pic,
     g_free(nodename);
 }
 
-static void create_platform_bus(VirtBoardInfo *vbi, qemu_irq *pic)
+static void create_platform_bus(VirtMachineState *vbi, qemu_irq *pic)
 {
     DeviceState *dev;
     SysBusDevice *s;
@@ -1136,7 +1117,8 @@ static void create_platform_bus(VirtBoardInfo *vbi, qemu_irq *pic)
                                 sysbus_mmio_get_region(s, 0));
 }
 
-static void create_secure_ram(VirtBoardInfo *vbi, MemoryRegion *secure_sysmem)
+static void create_secure_ram(VirtMachineState *vbi,
+                              MemoryRegion *secure_sysmem)
 {
     MemoryRegion *secram = g_new(MemoryRegion, 1);
     char *nodename;
@@ -1159,7 +1141,8 @@ static void create_secure_ram(VirtBoardInfo *vbi, MemoryRegion *secure_sysmem)
 
 static void *machvirt_dtb(const struct arm_boot_info *binfo, int *fdt_size)
 {
-    const VirtBoardInfo *board = (const VirtBoardInfo *)binfo;
+    const VirtMachineState *board = container_of(binfo, VirtMachineState,
+                                                 bootinfo);
 
     *fdt_size = board->fdt_size;
     return board->fdt;
@@ -1214,7 +1197,7 @@ static void machvirt_init(MachineState *machine)
     int n, virt_max_cpus;
     MemoryRegion *ram = g_new(MemoryRegion, 1);
     const char *cpu_model = machine->cpu_model;
-    VirtBoardInfo *vbi;
+    VirtMachineState *vbi = vms;
     VirtGuestInfoState *guest_info_state = g_malloc0(sizeof *guest_info_state);
     VirtGuestInfo *guest_info = &guest_info_state->info;
     char **cpustr;
@@ -1248,9 +1231,7 @@ static void machvirt_init(MachineState *machine)
     /* Separate the actual CPU model name from any appended features */
     cpustr = g_strsplit(cpu_model, ",", 2);
 
-    vbi = find_machine_info(cpustr[0]);
-
-    if (!vbi) {
+    if (!cpuname_valid(cpustr[0])) {
         error_report("mach-virt: CPU %s not supported", cpustr[0]);
         exit(1);
     }
@@ -1556,6 +1537,9 @@ static void virt_2_9_instance_init(Object *obj)
     object_property_set_description(obj, "gic-version",
                                     "Set GIC version. "
                                     "Valid values are 2, 3 and host", NULL);
+
+    vms->memmap = a15memmap;
+    vms->irqmap = a15irqmap;
 }
 
 static void virt_machine_2_9_options(MachineClass *mc)
-- 
2.7.4

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

* [Qemu-devel] [PATCH 06/23] hw/arm/virt: Rename 'vbi' variables to 'vms'
  2016-12-13 10:36 [Qemu-devel] [PATCH 00/23] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs Peter Maydell
                   ` (4 preceding siblings ...)
  2016-12-13 10:36 ` [Qemu-devel] [PATCH 05/23] hw/arm/virt: Merge VirtBoardInfo and VirtMachineState Peter Maydell
@ 2016-12-13 10:36 ` Peter Maydell
  2016-12-20 15:46   ` Andrew Jones
  2016-12-13 10:36 ` [Qemu-devel] [PATCH 07/23] hw/arm/virt: Don't incorrectly claim architectural timer to be edge-triggered Peter Maydell
                   ` (19 subsequent siblings)
  25 siblings, 1 reply; 45+ messages in thread
From: Peter Maydell @ 2016-12-13 10:36 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: patches, Edgar E. Iglesias, Christoffer Dall, Andrew Jones

Rename all the variables which used to be VirtBoardInfo*
and are now VirtMachineState* so their names are in line
with the type being used.

Apart from the removal of the line 'VirtMachineState *vbi = vms;'
this commit is purely a search-and-replace of 'vbi' with 'vms'.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/arm/virt.c | 489 +++++++++++++++++++++++++++++-----------------------------
 1 file changed, 244 insertions(+), 245 deletions(-)

diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index fd4eed9..54498ea 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -217,16 +217,16 @@ static bool cpuname_valid(const char *cpu)
     return false;
 }
 
-static void create_fdt(VirtMachineState *vbi)
+static void create_fdt(VirtMachineState *vms)
 {
-    void *fdt = create_device_tree(&vbi->fdt_size);
+    void *fdt = create_device_tree(&vms->fdt_size);
 
     if (!fdt) {
         error_report("create_device_tree() failed");
         exit(1);
     }
 
-    vbi->fdt = fdt;
+    vms->fdt = fdt;
 
     /* Header */
     qemu_fdt_setprop_string(fdt, "/", "compatible", "linux,dummy-virt");
@@ -246,27 +246,27 @@ static void create_fdt(VirtMachineState *vbi)
      * optional but in practice if you omit them the kernel refuses to
      * probe for the device.
      */
-    vbi->clock_phandle = qemu_fdt_alloc_phandle(fdt);
+    vms->clock_phandle = qemu_fdt_alloc_phandle(fdt);
     qemu_fdt_add_subnode(fdt, "/apb-pclk");
     qemu_fdt_setprop_string(fdt, "/apb-pclk", "compatible", "fixed-clock");
     qemu_fdt_setprop_cell(fdt, "/apb-pclk", "#clock-cells", 0x0);
     qemu_fdt_setprop_cell(fdt, "/apb-pclk", "clock-frequency", 24000000);
     qemu_fdt_setprop_string(fdt, "/apb-pclk", "clock-output-names",
                                 "clk24mhz");
-    qemu_fdt_setprop_cell(fdt, "/apb-pclk", "phandle", vbi->clock_phandle);
+    qemu_fdt_setprop_cell(fdt, "/apb-pclk", "phandle", vms->clock_phandle);
 
 }
 
-static void fdt_add_psci_node(const VirtMachineState *vbi)
+static void fdt_add_psci_node(const VirtMachineState *vms)
 {
     uint32_t cpu_suspend_fn;
     uint32_t cpu_off_fn;
     uint32_t cpu_on_fn;
     uint32_t migrate_fn;
-    void *fdt = vbi->fdt;
+    void *fdt = vms->fdt;
     ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(0));
 
-    if (!vbi->using_psci) {
+    if (!vms->using_psci) {
         return;
     }
 
@@ -307,7 +307,7 @@ static void fdt_add_psci_node(const VirtMachineState *vbi)
     qemu_fdt_setprop_cell(fdt, "/psci", "migrate", migrate_fn);
 }
 
-static void fdt_add_timer_nodes(const VirtMachineState *vbi, int gictype)
+static void fdt_add_timer_nodes(const VirtMachineState *vms, int gictype)
 {
     /* Note that on A15 h/w these interrupts are level-triggered,
      * but for the GIC implementation provided by both QEMU and KVM
@@ -319,29 +319,29 @@ static void fdt_add_timer_nodes(const VirtMachineState *vbi, int gictype)
     if (gictype == 2) {
         irqflags = deposit32(irqflags, GIC_FDT_IRQ_PPI_CPU_START,
                              GIC_FDT_IRQ_PPI_CPU_WIDTH,
-                             (1 << vbi->smp_cpus) - 1);
+                             (1 << vms->smp_cpus) - 1);
     }
 
-    qemu_fdt_add_subnode(vbi->fdt, "/timer");
+    qemu_fdt_add_subnode(vms->fdt, "/timer");
 
     armcpu = ARM_CPU(qemu_get_cpu(0));
     if (arm_feature(&armcpu->env, ARM_FEATURE_V8)) {
         const char compat[] = "arm,armv8-timer\0arm,armv7-timer";
-        qemu_fdt_setprop(vbi->fdt, "/timer", "compatible",
+        qemu_fdt_setprop(vms->fdt, "/timer", "compatible",
                          compat, sizeof(compat));
     } else {
-        qemu_fdt_setprop_string(vbi->fdt, "/timer", "compatible",
+        qemu_fdt_setprop_string(vms->fdt, "/timer", "compatible",
                                 "arm,armv7-timer");
     }
-    qemu_fdt_setprop(vbi->fdt, "/timer", "always-on", NULL, 0);
-    qemu_fdt_setprop_cells(vbi->fdt, "/timer", "interrupts",
+    qemu_fdt_setprop(vms->fdt, "/timer", "always-on", NULL, 0);
+    qemu_fdt_setprop_cells(vms->fdt, "/timer", "interrupts",
                        GIC_FDT_IRQ_TYPE_PPI, ARCH_TIMER_S_EL1_IRQ, irqflags,
                        GIC_FDT_IRQ_TYPE_PPI, ARCH_TIMER_NS_EL1_IRQ, irqflags,
                        GIC_FDT_IRQ_TYPE_PPI, ARCH_TIMER_VIRT_IRQ, irqflags,
                        GIC_FDT_IRQ_TYPE_PPI, ARCH_TIMER_NS_EL2_IRQ, irqflags);
 }
 
-static void fdt_add_cpu_nodes(const VirtMachineState *vbi)
+static void fdt_add_cpu_nodes(const VirtMachineState *vms)
 {
     int cpu;
     int addr_cells = 1;
@@ -360,7 +360,7 @@ static void fdt_add_cpu_nodes(const VirtMachineState *vbi)
      *  The simplest way to go is to examine affinity IDs of all our CPUs. If
      *  at least one of them has Aff3 populated, we set #address-cells to 2.
      */
-    for (cpu = 0; cpu < vbi->smp_cpus; cpu++) {
+    for (cpu = 0; cpu < vms->smp_cpus; cpu++) {
         ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(cpu));
 
         if (armcpu->mp_affinity & ARM_AFF3_MASK) {
@@ -369,101 +369,101 @@ static void fdt_add_cpu_nodes(const VirtMachineState *vbi)
         }
     }
 
-    qemu_fdt_add_subnode(vbi->fdt, "/cpus");
-    qemu_fdt_setprop_cell(vbi->fdt, "/cpus", "#address-cells", addr_cells);
-    qemu_fdt_setprop_cell(vbi->fdt, "/cpus", "#size-cells", 0x0);
+    qemu_fdt_add_subnode(vms->fdt, "/cpus");
+    qemu_fdt_setprop_cell(vms->fdt, "/cpus", "#address-cells", addr_cells);
+    qemu_fdt_setprop_cell(vms->fdt, "/cpus", "#size-cells", 0x0);
 
-    for (cpu = vbi->smp_cpus - 1; cpu >= 0; cpu--) {
+    for (cpu = vms->smp_cpus - 1; cpu >= 0; cpu--) {
         char *nodename = g_strdup_printf("/cpus/cpu@%d", cpu);
         ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(cpu));
 
-        qemu_fdt_add_subnode(vbi->fdt, nodename);
-        qemu_fdt_setprop_string(vbi->fdt, nodename, "device_type", "cpu");
-        qemu_fdt_setprop_string(vbi->fdt, nodename, "compatible",
+        qemu_fdt_add_subnode(vms->fdt, nodename);
+        qemu_fdt_setprop_string(vms->fdt, nodename, "device_type", "cpu");
+        qemu_fdt_setprop_string(vms->fdt, nodename, "compatible",
                                     armcpu->dtb_compatible);
 
-        if (vbi->using_psci && vbi->smp_cpus > 1) {
-            qemu_fdt_setprop_string(vbi->fdt, nodename,
+        if (vms->using_psci && vms->smp_cpus > 1) {
+            qemu_fdt_setprop_string(vms->fdt, nodename,
                                         "enable-method", "psci");
         }
 
         if (addr_cells == 2) {
-            qemu_fdt_setprop_u64(vbi->fdt, nodename, "reg",
+            qemu_fdt_setprop_u64(vms->fdt, nodename, "reg",
                                  armcpu->mp_affinity);
         } else {
-            qemu_fdt_setprop_cell(vbi->fdt, nodename, "reg",
+            qemu_fdt_setprop_cell(vms->fdt, nodename, "reg",
                                   armcpu->mp_affinity);
         }
 
         i = numa_get_node_for_cpu(cpu);
         if (i < nb_numa_nodes) {
-            qemu_fdt_setprop_cell(vbi->fdt, nodename, "numa-node-id", i);
+            qemu_fdt_setprop_cell(vms->fdt, nodename, "numa-node-id", i);
         }
 
         g_free(nodename);
     }
 }
 
-static void fdt_add_its_gic_node(VirtMachineState *vbi)
+static void fdt_add_its_gic_node(VirtMachineState *vms)
 {
-    vbi->msi_phandle = qemu_fdt_alloc_phandle(vbi->fdt);
-    qemu_fdt_add_subnode(vbi->fdt, "/intc/its");
-    qemu_fdt_setprop_string(vbi->fdt, "/intc/its", "compatible",
+    vms->msi_phandle = qemu_fdt_alloc_phandle(vms->fdt);
+    qemu_fdt_add_subnode(vms->fdt, "/intc/its");
+    qemu_fdt_setprop_string(vms->fdt, "/intc/its", "compatible",
                             "arm,gic-v3-its");
-    qemu_fdt_setprop(vbi->fdt, "/intc/its", "msi-controller", NULL, 0);
-    qemu_fdt_setprop_sized_cells(vbi->fdt, "/intc/its", "reg",
-                                 2, vbi->memmap[VIRT_GIC_ITS].base,
-                                 2, vbi->memmap[VIRT_GIC_ITS].size);
-    qemu_fdt_setprop_cell(vbi->fdt, "/intc/its", "phandle", vbi->msi_phandle);
+    qemu_fdt_setprop(vms->fdt, "/intc/its", "msi-controller", NULL, 0);
+    qemu_fdt_setprop_sized_cells(vms->fdt, "/intc/its", "reg",
+                                 2, vms->memmap[VIRT_GIC_ITS].base,
+                                 2, vms->memmap[VIRT_GIC_ITS].size);
+    qemu_fdt_setprop_cell(vms->fdt, "/intc/its", "phandle", vms->msi_phandle);
 }
 
-static void fdt_add_v2m_gic_node(VirtMachineState *vbi)
+static void fdt_add_v2m_gic_node(VirtMachineState *vms)
 {
-    vbi->msi_phandle = qemu_fdt_alloc_phandle(vbi->fdt);
-    qemu_fdt_add_subnode(vbi->fdt, "/intc/v2m");
-    qemu_fdt_setprop_string(vbi->fdt, "/intc/v2m", "compatible",
+    vms->msi_phandle = qemu_fdt_alloc_phandle(vms->fdt);
+    qemu_fdt_add_subnode(vms->fdt, "/intc/v2m");
+    qemu_fdt_setprop_string(vms->fdt, "/intc/v2m", "compatible",
                             "arm,gic-v2m-frame");
-    qemu_fdt_setprop(vbi->fdt, "/intc/v2m", "msi-controller", NULL, 0);
-    qemu_fdt_setprop_sized_cells(vbi->fdt, "/intc/v2m", "reg",
-                                 2, vbi->memmap[VIRT_GIC_V2M].base,
-                                 2, vbi->memmap[VIRT_GIC_V2M].size);
-    qemu_fdt_setprop_cell(vbi->fdt, "/intc/v2m", "phandle", vbi->msi_phandle);
+    qemu_fdt_setprop(vms->fdt, "/intc/v2m", "msi-controller", NULL, 0);
+    qemu_fdt_setprop_sized_cells(vms->fdt, "/intc/v2m", "reg",
+                                 2, vms->memmap[VIRT_GIC_V2M].base,
+                                 2, vms->memmap[VIRT_GIC_V2M].size);
+    qemu_fdt_setprop_cell(vms->fdt, "/intc/v2m", "phandle", vms->msi_phandle);
 }
 
-static void fdt_add_gic_node(VirtMachineState *vbi, int type)
+static void fdt_add_gic_node(VirtMachineState *vms, int type)
 {
-    vbi->gic_phandle = qemu_fdt_alloc_phandle(vbi->fdt);
-    qemu_fdt_setprop_cell(vbi->fdt, "/", "interrupt-parent", vbi->gic_phandle);
-
-    qemu_fdt_add_subnode(vbi->fdt, "/intc");
-    qemu_fdt_setprop_cell(vbi->fdt, "/intc", "#interrupt-cells", 3);
-    qemu_fdt_setprop(vbi->fdt, "/intc", "interrupt-controller", NULL, 0);
-    qemu_fdt_setprop_cell(vbi->fdt, "/intc", "#address-cells", 0x2);
-    qemu_fdt_setprop_cell(vbi->fdt, "/intc", "#size-cells", 0x2);
-    qemu_fdt_setprop(vbi->fdt, "/intc", "ranges", NULL, 0);
+    vms->gic_phandle = qemu_fdt_alloc_phandle(vms->fdt);
+    qemu_fdt_setprop_cell(vms->fdt, "/", "interrupt-parent", vms->gic_phandle);
+
+    qemu_fdt_add_subnode(vms->fdt, "/intc");
+    qemu_fdt_setprop_cell(vms->fdt, "/intc", "#interrupt-cells", 3);
+    qemu_fdt_setprop(vms->fdt, "/intc", "interrupt-controller", NULL, 0);
+    qemu_fdt_setprop_cell(vms->fdt, "/intc", "#address-cells", 0x2);
+    qemu_fdt_setprop_cell(vms->fdt, "/intc", "#size-cells", 0x2);
+    qemu_fdt_setprop(vms->fdt, "/intc", "ranges", NULL, 0);
     if (type == 3) {
-        qemu_fdt_setprop_string(vbi->fdt, "/intc", "compatible",
+        qemu_fdt_setprop_string(vms->fdt, "/intc", "compatible",
                                 "arm,gic-v3");
-        qemu_fdt_setprop_sized_cells(vbi->fdt, "/intc", "reg",
-                                     2, vbi->memmap[VIRT_GIC_DIST].base,
-                                     2, vbi->memmap[VIRT_GIC_DIST].size,
-                                     2, vbi->memmap[VIRT_GIC_REDIST].base,
-                                     2, vbi->memmap[VIRT_GIC_REDIST].size);
+        qemu_fdt_setprop_sized_cells(vms->fdt, "/intc", "reg",
+                                     2, vms->memmap[VIRT_GIC_DIST].base,
+                                     2, vms->memmap[VIRT_GIC_DIST].size,
+                                     2, vms->memmap[VIRT_GIC_REDIST].base,
+                                     2, vms->memmap[VIRT_GIC_REDIST].size);
     } else {
         /* 'cortex-a15-gic' means 'GIC v2' */
-        qemu_fdt_setprop_string(vbi->fdt, "/intc", "compatible",
+        qemu_fdt_setprop_string(vms->fdt, "/intc", "compatible",
                                 "arm,cortex-a15-gic");
-        qemu_fdt_setprop_sized_cells(vbi->fdt, "/intc", "reg",
-                                      2, vbi->memmap[VIRT_GIC_DIST].base,
-                                      2, vbi->memmap[VIRT_GIC_DIST].size,
-                                      2, vbi->memmap[VIRT_GIC_CPU].base,
-                                      2, vbi->memmap[VIRT_GIC_CPU].size);
+        qemu_fdt_setprop_sized_cells(vms->fdt, "/intc", "reg",
+                                      2, vms->memmap[VIRT_GIC_DIST].base,
+                                      2, vms->memmap[VIRT_GIC_DIST].size,
+                                      2, vms->memmap[VIRT_GIC_CPU].base,
+                                      2, vms->memmap[VIRT_GIC_CPU].size);
     }
 
-    qemu_fdt_setprop_cell(vbi->fdt, "/intc", "phandle", vbi->gic_phandle);
+    qemu_fdt_setprop_cell(vms->fdt, "/intc", "phandle", vms->gic_phandle);
 }
 
-static void fdt_add_pmu_nodes(const VirtMachineState *vbi, int gictype)
+static void fdt_add_pmu_nodes(const VirtMachineState *vms, int gictype)
 {
     CPUState *cpu;
     ARMCPU *armcpu;
@@ -480,21 +480,21 @@ static void fdt_add_pmu_nodes(const VirtMachineState *vbi, int gictype)
     if (gictype == 2) {
         irqflags = deposit32(irqflags, GIC_FDT_IRQ_PPI_CPU_START,
                              GIC_FDT_IRQ_PPI_CPU_WIDTH,
-                             (1 << vbi->smp_cpus) - 1);
+                             (1 << vms->smp_cpus) - 1);
     }
 
     armcpu = ARM_CPU(qemu_get_cpu(0));
-    qemu_fdt_add_subnode(vbi->fdt, "/pmu");
+    qemu_fdt_add_subnode(vms->fdt, "/pmu");
     if (arm_feature(&armcpu->env, ARM_FEATURE_V8)) {
         const char compat[] = "arm,armv8-pmuv3";
-        qemu_fdt_setprop(vbi->fdt, "/pmu", "compatible",
+        qemu_fdt_setprop(vms->fdt, "/pmu", "compatible",
                          compat, sizeof(compat));
-        qemu_fdt_setprop_cells(vbi->fdt, "/pmu", "interrupts",
+        qemu_fdt_setprop_cells(vms->fdt, "/pmu", "interrupts",
                                GIC_FDT_IRQ_TYPE_PPI, VIRTUAL_PMU_IRQ, irqflags);
     }
 }
 
-static void create_its(VirtMachineState *vbi, DeviceState *gicdev)
+static void create_its(VirtMachineState *vms, DeviceState *gicdev)
 {
     const char *itsclass = its_class_name();
     DeviceState *dev;
@@ -509,19 +509,19 @@ static void create_its(VirtMachineState *vbi, DeviceState *gicdev)
     object_property_set_link(OBJECT(dev), OBJECT(gicdev), "parent-gicv3",
                              &error_abort);
     qdev_init_nofail(dev);
-    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, vbi->memmap[VIRT_GIC_ITS].base);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, vms->memmap[VIRT_GIC_ITS].base);
 
-    fdt_add_its_gic_node(vbi);
+    fdt_add_its_gic_node(vms);
 }
 
-static void create_v2m(VirtMachineState *vbi, qemu_irq *pic)
+static void create_v2m(VirtMachineState *vms, qemu_irq *pic)
 {
     int i;
-    int irq = vbi->irqmap[VIRT_GIC_V2M];
+    int irq = vms->irqmap[VIRT_GIC_V2M];
     DeviceState *dev;
 
     dev = qdev_create(NULL, "arm-gicv2m");
-    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, vbi->memmap[VIRT_GIC_V2M].base);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, vms->memmap[VIRT_GIC_V2M].base);
     qdev_prop_set_uint32(dev, "base-spi", irq);
     qdev_prop_set_uint32(dev, "num-spi", NUM_GICV2M_SPIS);
     qdev_init_nofail(dev);
@@ -530,10 +530,10 @@ static void create_v2m(VirtMachineState *vbi, qemu_irq *pic)
         sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, pic[irq + i]);
     }
 
-    fdt_add_v2m_gic_node(vbi);
+    fdt_add_v2m_gic_node(vms);
 }
 
-static void create_gic(VirtMachineState *vbi, qemu_irq *pic, int type,
+static void create_gic(VirtMachineState *vms, qemu_irq *pic, int type,
                        bool secure, bool no_its)
 {
     /* We create a standalone GIC */
@@ -556,11 +556,11 @@ static void create_gic(VirtMachineState *vbi, qemu_irq *pic, int type,
     }
     qdev_init_nofail(gicdev);
     gicbusdev = SYS_BUS_DEVICE(gicdev);
-    sysbus_mmio_map(gicbusdev, 0, vbi->memmap[VIRT_GIC_DIST].base);
+    sysbus_mmio_map(gicbusdev, 0, vms->memmap[VIRT_GIC_DIST].base);
     if (type == 3) {
-        sysbus_mmio_map(gicbusdev, 1, vbi->memmap[VIRT_GIC_REDIST].base);
+        sysbus_mmio_map(gicbusdev, 1, vms->memmap[VIRT_GIC_REDIST].base);
     } else {
-        sysbus_mmio_map(gicbusdev, 1, vbi->memmap[VIRT_GIC_CPU].base);
+        sysbus_mmio_map(gicbusdev, 1, vms->memmap[VIRT_GIC_CPU].base);
     }
 
     /* Wire the outputs from each CPU's generic timer to the
@@ -596,22 +596,22 @@ static void create_gic(VirtMachineState *vbi, qemu_irq *pic, int type,
         pic[i] = qdev_get_gpio_in(gicdev, i);
     }
 
-    fdt_add_gic_node(vbi, type);
+    fdt_add_gic_node(vms, type);
 
     if (type == 3 && !no_its) {
-        create_its(vbi, gicdev);
+        create_its(vms, gicdev);
     } else if (type == 2) {
-        create_v2m(vbi, pic);
+        create_v2m(vms, pic);
     }
 }
 
-static void create_uart(const VirtMachineState *vbi, qemu_irq *pic, int uart,
+static void create_uart(const VirtMachineState *vms, qemu_irq *pic, int uart,
                         MemoryRegion *mem, CharDriverState *chr)
 {
     char *nodename;
-    hwaddr base = vbi->memmap[uart].base;
-    hwaddr size = vbi->memmap[uart].size;
-    int irq = vbi->irqmap[uart];
+    hwaddr base = vms->memmap[uart].base;
+    hwaddr size = vms->memmap[uart].size;
+    int irq = vms->irqmap[uart];
     const char compat[] = "arm,pl011\0arm,primecell";
     const char clocknames[] = "uartclk\0apb_pclk";
     DeviceState *dev = qdev_create(NULL, "pl011");
@@ -624,51 +624,51 @@ static void create_uart(const VirtMachineState *vbi, qemu_irq *pic, int uart,
     sysbus_connect_irq(s, 0, pic[irq]);
 
     nodename = g_strdup_printf("/pl011@%" PRIx64, base);
-    qemu_fdt_add_subnode(vbi->fdt, nodename);
+    qemu_fdt_add_subnode(vms->fdt, nodename);
     /* Note that we can't use setprop_string because of the embedded NUL */
-    qemu_fdt_setprop(vbi->fdt, nodename, "compatible",
+    qemu_fdt_setprop(vms->fdt, nodename, "compatible",
                          compat, sizeof(compat));
-    qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "reg",
+    qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg",
                                      2, base, 2, size);
-    qemu_fdt_setprop_cells(vbi->fdt, nodename, "interrupts",
+    qemu_fdt_setprop_cells(vms->fdt, nodename, "interrupts",
                                GIC_FDT_IRQ_TYPE_SPI, irq,
                                GIC_FDT_IRQ_FLAGS_LEVEL_HI);
-    qemu_fdt_setprop_cells(vbi->fdt, nodename, "clocks",
-                               vbi->clock_phandle, vbi->clock_phandle);
-    qemu_fdt_setprop(vbi->fdt, nodename, "clock-names",
+    qemu_fdt_setprop_cells(vms->fdt, nodename, "clocks",
+                               vms->clock_phandle, vms->clock_phandle);
+    qemu_fdt_setprop(vms->fdt, nodename, "clock-names",
                          clocknames, sizeof(clocknames));
 
     if (uart == VIRT_UART) {
-        qemu_fdt_setprop_string(vbi->fdt, "/chosen", "stdout-path", nodename);
+        qemu_fdt_setprop_string(vms->fdt, "/chosen", "stdout-path", nodename);
     } else {
         /* Mark as not usable by the normal world */
-        qemu_fdt_setprop_string(vbi->fdt, nodename, "status", "disabled");
-        qemu_fdt_setprop_string(vbi->fdt, nodename, "secure-status", "okay");
+        qemu_fdt_setprop_string(vms->fdt, nodename, "status", "disabled");
+        qemu_fdt_setprop_string(vms->fdt, nodename, "secure-status", "okay");
     }
 
     g_free(nodename);
 }
 
-static void create_rtc(const VirtMachineState *vbi, qemu_irq *pic)
+static void create_rtc(const VirtMachineState *vms, qemu_irq *pic)
 {
     char *nodename;
-    hwaddr base = vbi->memmap[VIRT_RTC].base;
-    hwaddr size = vbi->memmap[VIRT_RTC].size;
-    int irq = vbi->irqmap[VIRT_RTC];
+    hwaddr base = vms->memmap[VIRT_RTC].base;
+    hwaddr size = vms->memmap[VIRT_RTC].size;
+    int irq = vms->irqmap[VIRT_RTC];
     const char compat[] = "arm,pl031\0arm,primecell";
 
     sysbus_create_simple("pl031", base, pic[irq]);
 
     nodename = g_strdup_printf("/pl031@%" PRIx64, base);
-    qemu_fdt_add_subnode(vbi->fdt, nodename);
-    qemu_fdt_setprop(vbi->fdt, nodename, "compatible", compat, sizeof(compat));
-    qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "reg",
+    qemu_fdt_add_subnode(vms->fdt, nodename);
+    qemu_fdt_setprop(vms->fdt, nodename, "compatible", compat, sizeof(compat));
+    qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg",
                                  2, base, 2, size);
-    qemu_fdt_setprop_cells(vbi->fdt, nodename, "interrupts",
+    qemu_fdt_setprop_cells(vms->fdt, nodename, "interrupts",
                            GIC_FDT_IRQ_TYPE_SPI, irq,
                            GIC_FDT_IRQ_FLAGS_LEVEL_HI);
-    qemu_fdt_setprop_cell(vbi->fdt, nodename, "clocks", vbi->clock_phandle);
-    qemu_fdt_setprop_string(vbi->fdt, nodename, "clock-names", "apb_pclk");
+    qemu_fdt_setprop_cell(vms->fdt, nodename, "clocks", vms->clock_phandle);
+    qemu_fdt_setprop_string(vms->fdt, nodename, "clock-names", "apb_pclk");
     g_free(nodename);
 }
 
@@ -683,45 +683,45 @@ static Notifier virt_system_powerdown_notifier = {
     .notify = virt_powerdown_req
 };
 
-static void create_gpio(const VirtMachineState *vbi, qemu_irq *pic)
+static void create_gpio(const VirtMachineState *vms, qemu_irq *pic)
 {
     char *nodename;
     DeviceState *pl061_dev;
-    hwaddr base = vbi->memmap[VIRT_GPIO].base;
-    hwaddr size = vbi->memmap[VIRT_GPIO].size;
-    int irq = vbi->irqmap[VIRT_GPIO];
+    hwaddr base = vms->memmap[VIRT_GPIO].base;
+    hwaddr size = vms->memmap[VIRT_GPIO].size;
+    int irq = vms->irqmap[VIRT_GPIO];
     const char compat[] = "arm,pl061\0arm,primecell";
 
     pl061_dev = sysbus_create_simple("pl061", base, pic[irq]);
 
-    uint32_t phandle = qemu_fdt_alloc_phandle(vbi->fdt);
+    uint32_t phandle = qemu_fdt_alloc_phandle(vms->fdt);
     nodename = g_strdup_printf("/pl061@%" PRIx64, base);
-    qemu_fdt_add_subnode(vbi->fdt, nodename);
-    qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "reg",
+    qemu_fdt_add_subnode(vms->fdt, nodename);
+    qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg",
                                  2, base, 2, size);
-    qemu_fdt_setprop(vbi->fdt, nodename, "compatible", compat, sizeof(compat));
-    qemu_fdt_setprop_cell(vbi->fdt, nodename, "#gpio-cells", 2);
-    qemu_fdt_setprop(vbi->fdt, nodename, "gpio-controller", NULL, 0);
-    qemu_fdt_setprop_cells(vbi->fdt, nodename, "interrupts",
+    qemu_fdt_setprop(vms->fdt, nodename, "compatible", compat, sizeof(compat));
+    qemu_fdt_setprop_cell(vms->fdt, nodename, "#gpio-cells", 2);
+    qemu_fdt_setprop(vms->fdt, nodename, "gpio-controller", NULL, 0);
+    qemu_fdt_setprop_cells(vms->fdt, nodename, "interrupts",
                            GIC_FDT_IRQ_TYPE_SPI, irq,
                            GIC_FDT_IRQ_FLAGS_LEVEL_HI);
-    qemu_fdt_setprop_cell(vbi->fdt, nodename, "clocks", vbi->clock_phandle);
-    qemu_fdt_setprop_string(vbi->fdt, nodename, "clock-names", "apb_pclk");
-    qemu_fdt_setprop_cell(vbi->fdt, nodename, "phandle", phandle);
+    qemu_fdt_setprop_cell(vms->fdt, nodename, "clocks", vms->clock_phandle);
+    qemu_fdt_setprop_string(vms->fdt, nodename, "clock-names", "apb_pclk");
+    qemu_fdt_setprop_cell(vms->fdt, nodename, "phandle", phandle);
 
     gpio_key_dev = sysbus_create_simple("gpio-key", -1,
                                         qdev_get_gpio_in(pl061_dev, 3));
-    qemu_fdt_add_subnode(vbi->fdt, "/gpio-keys");
-    qemu_fdt_setprop_string(vbi->fdt, "/gpio-keys", "compatible", "gpio-keys");
-    qemu_fdt_setprop_cell(vbi->fdt, "/gpio-keys", "#size-cells", 0);
-    qemu_fdt_setprop_cell(vbi->fdt, "/gpio-keys", "#address-cells", 1);
+    qemu_fdt_add_subnode(vms->fdt, "/gpio-keys");
+    qemu_fdt_setprop_string(vms->fdt, "/gpio-keys", "compatible", "gpio-keys");
+    qemu_fdt_setprop_cell(vms->fdt, "/gpio-keys", "#size-cells", 0);
+    qemu_fdt_setprop_cell(vms->fdt, "/gpio-keys", "#address-cells", 1);
 
-    qemu_fdt_add_subnode(vbi->fdt, "/gpio-keys/poweroff");
-    qemu_fdt_setprop_string(vbi->fdt, "/gpio-keys/poweroff",
+    qemu_fdt_add_subnode(vms->fdt, "/gpio-keys/poweroff");
+    qemu_fdt_setprop_string(vms->fdt, "/gpio-keys/poweroff",
                             "label", "GPIO Key Poweroff");
-    qemu_fdt_setprop_cell(vbi->fdt, "/gpio-keys/poweroff", "linux,code",
+    qemu_fdt_setprop_cell(vms->fdt, "/gpio-keys/poweroff", "linux,code",
                           KEY_POWER);
-    qemu_fdt_setprop_cells(vbi->fdt, "/gpio-keys/poweroff",
+    qemu_fdt_setprop_cells(vms->fdt, "/gpio-keys/poweroff",
                            "gpios", phandle, 3, 0);
 
     /* connect powerdown request */
@@ -730,10 +730,10 @@ static void create_gpio(const VirtMachineState *vbi, qemu_irq *pic)
     g_free(nodename);
 }
 
-static void create_virtio_devices(const VirtMachineState *vbi, qemu_irq *pic)
+static void create_virtio_devices(const VirtMachineState *vms, qemu_irq *pic)
 {
     int i;
-    hwaddr size = vbi->memmap[VIRT_MMIO].size;
+    hwaddr size = vms->memmap[VIRT_MMIO].size;
 
     /* We create the transports in forwards order. Since qbus_realize()
      * prepends (not appends) new child buses, the incrementing loop below will
@@ -763,8 +763,8 @@ static void create_virtio_devices(const VirtMachineState *vbi, qemu_irq *pic)
      * of disks users must use UUIDs or similar mechanisms.
      */
     for (i = 0; i < NUM_VIRTIO_TRANSPORTS; i++) {
-        int irq = vbi->irqmap[VIRT_MMIO] + i;
-        hwaddr base = vbi->memmap[VIRT_MMIO].base + i * size;
+        int irq = vms->irqmap[VIRT_MMIO] + i;
+        hwaddr base = vms->memmap[VIRT_MMIO].base + i * size;
 
         sysbus_create_simple("virtio-mmio", base, pic[irq]);
     }
@@ -778,16 +778,16 @@ static void create_virtio_devices(const VirtMachineState *vbi, qemu_irq *pic)
      */
     for (i = NUM_VIRTIO_TRANSPORTS - 1; i >= 0; i--) {
         char *nodename;
-        int irq = vbi->irqmap[VIRT_MMIO] + i;
-        hwaddr base = vbi->memmap[VIRT_MMIO].base + i * size;
+        int irq = vms->irqmap[VIRT_MMIO] + i;
+        hwaddr base = vms->memmap[VIRT_MMIO].base + i * size;
 
         nodename = g_strdup_printf("/virtio_mmio@%" PRIx64, base);
-        qemu_fdt_add_subnode(vbi->fdt, nodename);
-        qemu_fdt_setprop_string(vbi->fdt, nodename,
+        qemu_fdt_add_subnode(vms->fdt, nodename);
+        qemu_fdt_setprop_string(vms->fdt, nodename,
                                 "compatible", "virtio,mmio");
-        qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "reg",
+        qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg",
                                      2, base, 2, size);
-        qemu_fdt_setprop_cells(vbi->fdt, nodename, "interrupts",
+        qemu_fdt_setprop_cells(vms->fdt, nodename, "interrupts",
                                GIC_FDT_IRQ_TYPE_SPI, irq,
                                GIC_FDT_IRQ_FLAGS_EDGE_LO_HI);
         g_free(nodename);
@@ -850,7 +850,7 @@ static void create_one_flash(const char *name, hwaddr flashbase,
     }
 }
 
-static void create_flash(const VirtMachineState *vbi,
+static void create_flash(const VirtMachineState *vms,
                          MemoryRegion *sysmem,
                          MemoryRegion *secure_sysmem)
 {
@@ -862,8 +862,8 @@ static void create_flash(const VirtMachineState *vbi,
      * If sysmem == secure_sysmem this means there is no separate Secure
      * address space and both flash devices are generally visible.
      */
-    hwaddr flashsize = vbi->memmap[VIRT_FLASH].size / 2;
-    hwaddr flashbase = vbi->memmap[VIRT_FLASH].base;
+    hwaddr flashsize = vms->memmap[VIRT_FLASH].size / 2;
+    hwaddr flashbase = vms->memmap[VIRT_FLASH].base;
     char *nodename;
 
     create_one_flash("virt.flash0", flashbase, flashsize,
@@ -874,41 +874,41 @@ static void create_flash(const VirtMachineState *vbi,
     if (sysmem == secure_sysmem) {
         /* Report both flash devices as a single node in the DT */
         nodename = g_strdup_printf("/flash@%" PRIx64, flashbase);
-        qemu_fdt_add_subnode(vbi->fdt, nodename);
-        qemu_fdt_setprop_string(vbi->fdt, nodename, "compatible", "cfi-flash");
-        qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "reg",
+        qemu_fdt_add_subnode(vms->fdt, nodename);
+        qemu_fdt_setprop_string(vms->fdt, nodename, "compatible", "cfi-flash");
+        qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg",
                                      2, flashbase, 2, flashsize,
                                      2, flashbase + flashsize, 2, flashsize);
-        qemu_fdt_setprop_cell(vbi->fdt, nodename, "bank-width", 4);
+        qemu_fdt_setprop_cell(vms->fdt, nodename, "bank-width", 4);
         g_free(nodename);
     } else {
         /* Report the devices as separate nodes so we can mark one as
          * only visible to the secure world.
          */
         nodename = g_strdup_printf("/secflash@%" PRIx64, flashbase);
-        qemu_fdt_add_subnode(vbi->fdt, nodename);
-        qemu_fdt_setprop_string(vbi->fdt, nodename, "compatible", "cfi-flash");
-        qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "reg",
+        qemu_fdt_add_subnode(vms->fdt, nodename);
+        qemu_fdt_setprop_string(vms->fdt, nodename, "compatible", "cfi-flash");
+        qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg",
                                      2, flashbase, 2, flashsize);
-        qemu_fdt_setprop_cell(vbi->fdt, nodename, "bank-width", 4);
-        qemu_fdt_setprop_string(vbi->fdt, nodename, "status", "disabled");
-        qemu_fdt_setprop_string(vbi->fdt, nodename, "secure-status", "okay");
+        qemu_fdt_setprop_cell(vms->fdt, nodename, "bank-width", 4);
+        qemu_fdt_setprop_string(vms->fdt, nodename, "status", "disabled");
+        qemu_fdt_setprop_string(vms->fdt, nodename, "secure-status", "okay");
         g_free(nodename);
 
         nodename = g_strdup_printf("/flash@%" PRIx64, flashbase);
-        qemu_fdt_add_subnode(vbi->fdt, nodename);
-        qemu_fdt_setprop_string(vbi->fdt, nodename, "compatible", "cfi-flash");
-        qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "reg",
+        qemu_fdt_add_subnode(vms->fdt, nodename);
+        qemu_fdt_setprop_string(vms->fdt, nodename, "compatible", "cfi-flash");
+        qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg",
                                      2, flashbase + flashsize, 2, flashsize);
-        qemu_fdt_setprop_cell(vbi->fdt, nodename, "bank-width", 4);
+        qemu_fdt_setprop_cell(vms->fdt, nodename, "bank-width", 4);
         g_free(nodename);
     }
 }
 
-static void create_fw_cfg(const VirtMachineState *vbi, AddressSpace *as)
+static void create_fw_cfg(const VirtMachineState *vms, AddressSpace *as)
 {
-    hwaddr base = vbi->memmap[VIRT_FW_CFG].base;
-    hwaddr size = vbi->memmap[VIRT_FW_CFG].size;
+    hwaddr base = vms->memmap[VIRT_FW_CFG].base;
+    hwaddr size = vms->memmap[VIRT_FW_CFG].size;
     FWCfgState *fw_cfg;
     char *nodename;
 
@@ -916,15 +916,15 @@ static void create_fw_cfg(const VirtMachineState *vbi, AddressSpace *as)
     fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, (uint16_t)smp_cpus);
 
     nodename = g_strdup_printf("/fw-cfg@%" PRIx64, base);
-    qemu_fdt_add_subnode(vbi->fdt, nodename);
-    qemu_fdt_setprop_string(vbi->fdt, nodename,
+    qemu_fdt_add_subnode(vms->fdt, nodename);
+    qemu_fdt_setprop_string(vms->fdt, nodename,
                             "compatible", "qemu,fw-cfg-mmio");
-    qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "reg",
+    qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg",
                                  2, base, 2, size);
     g_free(nodename);
 }
 
-static void create_pcie_irq_map(const VirtMachineState *vbi,
+static void create_pcie_irq_map(const VirtMachineState *vms,
                                 uint32_t gic_phandle,
                                 int first_irq, const char *nodename)
 {
@@ -952,28 +952,28 @@ static void create_pcie_irq_map(const VirtMachineState *vbi,
         }
     }
 
-    qemu_fdt_setprop(vbi->fdt, nodename, "interrupt-map",
+    qemu_fdt_setprop(vms->fdt, nodename, "interrupt-map",
                      full_irq_map, sizeof(full_irq_map));
 
-    qemu_fdt_setprop_cells(vbi->fdt, nodename, "interrupt-map-mask",
+    qemu_fdt_setprop_cells(vms->fdt, nodename, "interrupt-map-mask",
                            0x1800, 0, 0, /* devfn (PCI_SLOT(3)) */
                            0x7           /* PCI irq */);
 }
 
-static void create_pcie(const VirtMachineState *vbi, qemu_irq *pic,
+static void create_pcie(const VirtMachineState *vms, qemu_irq *pic,
                         bool use_highmem)
 {
-    hwaddr base_mmio = vbi->memmap[VIRT_PCIE_MMIO].base;
-    hwaddr size_mmio = vbi->memmap[VIRT_PCIE_MMIO].size;
-    hwaddr base_mmio_high = vbi->memmap[VIRT_PCIE_MMIO_HIGH].base;
-    hwaddr size_mmio_high = vbi->memmap[VIRT_PCIE_MMIO_HIGH].size;
-    hwaddr base_pio = vbi->memmap[VIRT_PCIE_PIO].base;
-    hwaddr size_pio = vbi->memmap[VIRT_PCIE_PIO].size;
-    hwaddr base_ecam = vbi->memmap[VIRT_PCIE_ECAM].base;
-    hwaddr size_ecam = vbi->memmap[VIRT_PCIE_ECAM].size;
+    hwaddr base_mmio = vms->memmap[VIRT_PCIE_MMIO].base;
+    hwaddr size_mmio = vms->memmap[VIRT_PCIE_MMIO].size;
+    hwaddr base_mmio_high = vms->memmap[VIRT_PCIE_MMIO_HIGH].base;
+    hwaddr size_mmio_high = vms->memmap[VIRT_PCIE_MMIO_HIGH].size;
+    hwaddr base_pio = vms->memmap[VIRT_PCIE_PIO].base;
+    hwaddr size_pio = vms->memmap[VIRT_PCIE_PIO].size;
+    hwaddr base_ecam = vms->memmap[VIRT_PCIE_ECAM].base;
+    hwaddr size_ecam = vms->memmap[VIRT_PCIE_ECAM].size;
     hwaddr base = base_mmio;
     int nr_pcie_buses = size_ecam / PCIE_MMCFG_SIZE_MIN;
-    int irq = vbi->irqmap[VIRT_PCIE];
+    int irq = vms->irqmap[VIRT_PCIE];
     MemoryRegion *mmio_alias;
     MemoryRegion *mmio_reg;
     MemoryRegion *ecam_alias;
@@ -1035,26 +1035,26 @@ static void create_pcie(const VirtMachineState *vbi, qemu_irq *pic,
     }
 
     nodename = g_strdup_printf("/pcie@%" PRIx64, base);
-    qemu_fdt_add_subnode(vbi->fdt, nodename);
-    qemu_fdt_setprop_string(vbi->fdt, nodename,
+    qemu_fdt_add_subnode(vms->fdt, nodename);
+    qemu_fdt_setprop_string(vms->fdt, nodename,
                             "compatible", "pci-host-ecam-generic");
-    qemu_fdt_setprop_string(vbi->fdt, nodename, "device_type", "pci");
-    qemu_fdt_setprop_cell(vbi->fdt, nodename, "#address-cells", 3);
-    qemu_fdt_setprop_cell(vbi->fdt, nodename, "#size-cells", 2);
-    qemu_fdt_setprop_cells(vbi->fdt, nodename, "bus-range", 0,
+    qemu_fdt_setprop_string(vms->fdt, nodename, "device_type", "pci");
+    qemu_fdt_setprop_cell(vms->fdt, nodename, "#address-cells", 3);
+    qemu_fdt_setprop_cell(vms->fdt, nodename, "#size-cells", 2);
+    qemu_fdt_setprop_cells(vms->fdt, nodename, "bus-range", 0,
                            nr_pcie_buses - 1);
-    qemu_fdt_setprop(vbi->fdt, nodename, "dma-coherent", NULL, 0);
+    qemu_fdt_setprop(vms->fdt, nodename, "dma-coherent", NULL, 0);
 
-    if (vbi->msi_phandle) {
-        qemu_fdt_setprop_cells(vbi->fdt, nodename, "msi-parent",
-                               vbi->msi_phandle);
+    if (vms->msi_phandle) {
+        qemu_fdt_setprop_cells(vms->fdt, nodename, "msi-parent",
+                               vms->msi_phandle);
     }
 
-    qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "reg",
+    qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg",
                                  2, base_ecam, 2, size_ecam);
 
     if (use_highmem) {
-        qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "ranges",
+        qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "ranges",
                                      1, FDT_PCI_RANGE_IOPORT, 2, 0,
                                      2, base_pio, 2, size_pio,
                                      1, FDT_PCI_RANGE_MMIO, 2, base_mmio,
@@ -1063,20 +1063,20 @@ static void create_pcie(const VirtMachineState *vbi, qemu_irq *pic,
                                      2, base_mmio_high,
                                      2, base_mmio_high, 2, size_mmio_high);
     } else {
-        qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "ranges",
+        qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "ranges",
                                      1, FDT_PCI_RANGE_IOPORT, 2, 0,
                                      2, base_pio, 2, size_pio,
                                      1, FDT_PCI_RANGE_MMIO, 2, base_mmio,
                                      2, base_mmio, 2, size_mmio);
     }
 
-    qemu_fdt_setprop_cell(vbi->fdt, nodename, "#interrupt-cells", 1);
-    create_pcie_irq_map(vbi, vbi->gic_phandle, irq, nodename);
+    qemu_fdt_setprop_cell(vms->fdt, nodename, "#interrupt-cells", 1);
+    create_pcie_irq_map(vms, vms->gic_phandle, irq, nodename);
 
     g_free(nodename);
 }
 
-static void create_platform_bus(VirtMachineState *vbi, qemu_irq *pic)
+static void create_platform_bus(VirtMachineState *vms, qemu_irq *pic)
 {
     DeviceState *dev;
     SysBusDevice *s;
@@ -1084,13 +1084,13 @@ static void create_platform_bus(VirtMachineState *vbi, qemu_irq *pic)
     ARMPlatformBusFDTParams *fdt_params = g_new(ARMPlatformBusFDTParams, 1);
     MemoryRegion *sysmem = get_system_memory();
 
-    platform_bus_params.platform_bus_base = vbi->memmap[VIRT_PLATFORM_BUS].base;
-    platform_bus_params.platform_bus_size = vbi->memmap[VIRT_PLATFORM_BUS].size;
-    platform_bus_params.platform_bus_first_irq = vbi->irqmap[VIRT_PLATFORM_BUS];
+    platform_bus_params.platform_bus_base = vms->memmap[VIRT_PLATFORM_BUS].base;
+    platform_bus_params.platform_bus_size = vms->memmap[VIRT_PLATFORM_BUS].size;
+    platform_bus_params.platform_bus_first_irq = vms->irqmap[VIRT_PLATFORM_BUS];
     platform_bus_params.platform_bus_num_irqs = PLATFORM_BUS_NUM_IRQS;
 
     fdt_params->system_params = &platform_bus_params;
-    fdt_params->binfo = &vbi->bootinfo;
+    fdt_params->binfo = &vms->bootinfo;
     fdt_params->intc = "/intc";
     /*
      * register a machine init done notifier that creates the device tree
@@ -1117,24 +1117,24 @@ static void create_platform_bus(VirtMachineState *vbi, qemu_irq *pic)
                                 sysbus_mmio_get_region(s, 0));
 }
 
-static void create_secure_ram(VirtMachineState *vbi,
+static void create_secure_ram(VirtMachineState *vms,
                               MemoryRegion *secure_sysmem)
 {
     MemoryRegion *secram = g_new(MemoryRegion, 1);
     char *nodename;
-    hwaddr base = vbi->memmap[VIRT_SECURE_MEM].base;
-    hwaddr size = vbi->memmap[VIRT_SECURE_MEM].size;
+    hwaddr base = vms->memmap[VIRT_SECURE_MEM].base;
+    hwaddr size = vms->memmap[VIRT_SECURE_MEM].size;
 
     memory_region_init_ram(secram, NULL, "virt.secure-ram", size, &error_fatal);
     vmstate_register_ram_global(secram);
     memory_region_add_subregion(secure_sysmem, base, secram);
 
     nodename = g_strdup_printf("/secram@%" PRIx64, base);
-    qemu_fdt_add_subnode(vbi->fdt, nodename);
-    qemu_fdt_setprop_string(vbi->fdt, nodename, "device_type", "memory");
-    qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "reg", 2, base, 2, size);
-    qemu_fdt_setprop_string(vbi->fdt, nodename, "status", "disabled");
-    qemu_fdt_setprop_string(vbi->fdt, nodename, "secure-status", "okay");
+    qemu_fdt_add_subnode(vms->fdt, nodename);
+    qemu_fdt_setprop_string(vms->fdt, nodename, "device_type", "memory");
+    qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg", 2, base, 2, size);
+    qemu_fdt_setprop_string(vms->fdt, nodename, "status", "disabled");
+    qemu_fdt_setprop_string(vms->fdt, nodename, "secure-status", "okay");
 
     g_free(nodename);
 }
@@ -1197,7 +1197,6 @@ static void machvirt_init(MachineState *machine)
     int n, virt_max_cpus;
     MemoryRegion *ram = g_new(MemoryRegion, 1);
     const char *cpu_model = machine->cpu_model;
-    VirtMachineState *vbi = vms;
     VirtGuestInfoState *guest_info_state = g_malloc0(sizeof *guest_info_state);
     VirtGuestInfo *guest_info = &guest_info_state->info;
     char **cpustr;
@@ -1243,13 +1242,13 @@ 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.
      */
-    vbi->using_psci = !(vms->secure && firmware_loaded);
+    vms->using_psci = !(vms->secure && firmware_loaded);
 
     /* The maximum number of CPUs depends on the GIC version, or on how
      * many redistributors we can fit into the memory map.
      */
     if (gic_version == 3) {
-        virt_max_cpus = vbi->memmap[VIRT_GIC_REDIST].size / 0x20000;
+        virt_max_cpus = vms->memmap[VIRT_GIC_REDIST].size / 0x20000;
         clustersz = GICV3_TARGETLIST_BITS;
     } else {
         virt_max_cpus = GIC_NCPU;
@@ -1263,9 +1262,9 @@ static void machvirt_init(MachineState *machine)
         exit(1);
     }
 
-    vbi->smp_cpus = smp_cpus;
+    vms->smp_cpus = smp_cpus;
 
-    if (machine->ram_size > vbi->memmap[VIRT_MEM].size) {
+    if (machine->ram_size > vms->memmap[VIRT_MEM].size) {
         error_report("mach-virt: cannot model more than %dGB RAM", RAMLIMIT_GB);
         exit(1);
     }
@@ -1287,7 +1286,7 @@ static void machvirt_init(MachineState *machine)
         memory_region_add_subregion_overlap(secure_sysmem, 0, sysmem, -1);
     }
 
-    create_fdt(vbi);
+    create_fdt(vms);
 
     oc = cpu_class_by_name(TYPE_ARM_CPU, cpustr[0]);
     if (!oc) {
@@ -1326,7 +1325,7 @@ static void machvirt_init(MachineState *machine)
             object_property_set_bool(cpuobj, false, "has_el3", NULL);
         }
 
-        if (vbi->using_psci) {
+        if (vms->using_psci) {
             object_property_set_int(cpuobj, QEMU_PSCI_CONDUIT_HVC,
                                     "psci-conduit", NULL);
 
@@ -1342,7 +1341,7 @@ static void machvirt_init(MachineState *machine)
         }
 
         if (object_property_find(cpuobj, "reset-cbar", NULL)) {
-            object_property_set_int(cpuobj, vbi->memmap[VIRT_CPUPERIPHS].base,
+            object_property_set_int(cpuobj, vms->memmap[VIRT_CPUPERIPHS].base,
                                     "reset-cbar", &error_abort);
         }
 
@@ -1355,62 +1354,62 @@ static void machvirt_init(MachineState *machine)
 
         object_property_set_bool(cpuobj, true, "realized", NULL);
     }
-    fdt_add_timer_nodes(vbi, gic_version);
-    fdt_add_cpu_nodes(vbi);
-    fdt_add_psci_node(vbi);
+    fdt_add_timer_nodes(vms, gic_version);
+    fdt_add_cpu_nodes(vms);
+    fdt_add_psci_node(vms);
 
     memory_region_allocate_system_memory(ram, NULL, "mach-virt.ram",
                                          machine->ram_size);
-    memory_region_add_subregion(sysmem, vbi->memmap[VIRT_MEM].base, ram);
+    memory_region_add_subregion(sysmem, vms->memmap[VIRT_MEM].base, ram);
 
-    create_flash(vbi, sysmem, secure_sysmem ? secure_sysmem : sysmem);
+    create_flash(vms, sysmem, secure_sysmem ? secure_sysmem : sysmem);
 
-    create_gic(vbi, pic, gic_version, vms->secure, vmc->no_its);
+    create_gic(vms, pic, gic_version, vms->secure, vmc->no_its);
 
-    fdt_add_pmu_nodes(vbi, gic_version);
+    fdt_add_pmu_nodes(vms, gic_version);
 
-    create_uart(vbi, pic, VIRT_UART, sysmem, serial_hds[0]);
+    create_uart(vms, pic, VIRT_UART, sysmem, serial_hds[0]);
 
     if (vms->secure) {
-        create_secure_ram(vbi, secure_sysmem);
-        create_uart(vbi, pic, VIRT_SECURE_UART, secure_sysmem, serial_hds[1]);
+        create_secure_ram(vms, secure_sysmem);
+        create_uart(vms, pic, VIRT_SECURE_UART, secure_sysmem, serial_hds[1]);
     }
 
-    create_rtc(vbi, pic);
+    create_rtc(vms, pic);
 
-    create_pcie(vbi, pic, vms->highmem);
+    create_pcie(vms, pic, vms->highmem);
 
-    create_gpio(vbi, pic);
+    create_gpio(vms, pic);
 
     /* Create mmio transports, so the user can create virtio backends
      * (which will be automatically plugged in to the transports). If
      * no backend is created the transport will just sit harmlessly idle.
      */
-    create_virtio_devices(vbi, pic);
+    create_virtio_devices(vms, pic);
 
-    create_fw_cfg(vbi, &address_space_memory);
+    create_fw_cfg(vms, &address_space_memory);
     rom_set_fw(fw_cfg_find());
 
     guest_info->smp_cpus = smp_cpus;
     guest_info->fw_cfg = fw_cfg_find();
-    guest_info->memmap = vbi->memmap;
-    guest_info->irqmap = vbi->irqmap;
+    guest_info->memmap = vms->memmap;
+    guest_info->irqmap = vms->irqmap;
     guest_info->use_highmem = vms->highmem;
     guest_info->gic_version = gic_version;
     guest_info->no_its = vmc->no_its;
     guest_info_state->machine_done.notify = virt_guest_info_machine_done;
     qemu_add_machine_init_done_notifier(&guest_info_state->machine_done);
 
-    vbi->bootinfo.ram_size = machine->ram_size;
-    vbi->bootinfo.kernel_filename = machine->kernel_filename;
-    vbi->bootinfo.kernel_cmdline = machine->kernel_cmdline;
-    vbi->bootinfo.initrd_filename = machine->initrd_filename;
-    vbi->bootinfo.nb_cpus = smp_cpus;
-    vbi->bootinfo.board_id = -1;
-    vbi->bootinfo.loader_start = vbi->memmap[VIRT_MEM].base;
-    vbi->bootinfo.get_dtb = machvirt_dtb;
-    vbi->bootinfo.firmware_loaded = firmware_loaded;
-    arm_load_kernel(ARM_CPU(first_cpu), &vbi->bootinfo);
+    vms->bootinfo.ram_size = machine->ram_size;
+    vms->bootinfo.kernel_filename = machine->kernel_filename;
+    vms->bootinfo.kernel_cmdline = machine->kernel_cmdline;
+    vms->bootinfo.initrd_filename = machine->initrd_filename;
+    vms->bootinfo.nb_cpus = smp_cpus;
+    vms->bootinfo.board_id = -1;
+    vms->bootinfo.loader_start = vms->memmap[VIRT_MEM].base;
+    vms->bootinfo.get_dtb = machvirt_dtb;
+    vms->bootinfo.firmware_loaded = firmware_loaded;
+    arm_load_kernel(ARM_CPU(first_cpu), &vms->bootinfo);
 
     /*
      * arm_load_kernel machine init done notifier registration must
@@ -1418,7 +1417,7 @@ static void machvirt_init(MachineState *machine)
      * another notifier is registered which adds platform bus nodes.
      * Notifiers are executed in registration reverse order.
      */
-    create_platform_bus(vbi, pic);
+    create_platform_bus(vms, pic);
 }
 
 static bool virt_get_secure(Object *obj, Error **errp)
-- 
2.7.4

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

* [Qemu-devel] [PATCH 07/23] hw/arm/virt: Don't incorrectly claim architectural timer to be edge-triggered
  2016-12-13 10:36 [Qemu-devel] [PATCH 00/23] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs Peter Maydell
                   ` (5 preceding siblings ...)
  2016-12-13 10:36 ` [Qemu-devel] [PATCH 06/23] hw/arm/virt: Rename 'vbi' variables to 'vms' Peter Maydell
@ 2016-12-13 10:36 ` Peter Maydell
  2016-12-13 10:36 ` [Qemu-devel] [PATCH 08/23] hw/intc/arm_gicv3: Add external IRQ lines for VIRQ and VFIQ Peter Maydell
                   ` (18 subsequent siblings)
  25 siblings, 0 replies; 45+ messages in thread
From: Peter Maydell @ 2016-12-13 10:36 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: patches, Edgar E. Iglesias, Christoffer Dall, Andrew Jones

The architectural timers in ARM CPUs all have level triggered interrupts
(unless you're using KVM on a host kernel before 4.4, which misimplemented
them as edge-triggered).

We were incorrectly describing them in the device tree as edge triggered.
This can cause problems for guest kernels in 4.8 before rc6:
 * pre-4.8 kernels ignore the values in the DT
 * 4.8 before rc6 write the DT values to the GIC config registers
 * newer than rc6 ignore the DT and insist that the timer interrupts
   are level triggered regardless

Fix the DT so we're describing reality. For backwards-compatibility
purposes, only do this for the virt-2.9 machine onward.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Andrew Jones <drjones@redhat.com>
---
 hw/arm/virt.c | 34 ++++++++++++++++++++++++++++++----
 1 file changed, 30 insertions(+), 4 deletions(-)

diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 54498ea..2ca9527 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -71,6 +71,7 @@ typedef struct {
     bool disallow_affinity_adjustment;
     bool no_its;
     bool no_pmu;
+    bool claim_edge_triggered_timers;
 } VirtMachineClass;
 
 typedef struct {
@@ -309,12 +310,31 @@ static void fdt_add_psci_node(const VirtMachineState *vms)
 
 static void fdt_add_timer_nodes(const VirtMachineState *vms, int gictype)
 {
-    /* Note that on A15 h/w these interrupts are level-triggered,
-     * but for the GIC implementation provided by both QEMU and KVM
-     * they are edge-triggered.
+    /* On real hardware these interrupts are level-triggered.
+     * On KVM they were edge-triggered before host kernel version 4.4,
+     * and level-triggered afterwards.
+     * On emulated QEMU they are level-triggered.
+     *
+     * Getting the DTB info about them wrong is awkward for some
+     * guest kernels:
+     *  pre-4.8 ignore the DT and leave the interrupt configured
+     *   with whatever the GIC reset value (or the bootloader) left it at
+     *  4.8 before rc6 honour the incorrect data by programming it back
+     *   into the GIC, causing problems
+     *  4.8rc6 and later ignore the DT and always write "level triggered"
+     *   into the GIC
+     *
+     * For backwards-compatibility, virt-2.8 and earlier will continue
+     * to say these are edge-triggered, but later machines will report
+     * the correct information.
      */
     ARMCPU *armcpu;
-    uint32_t irqflags = GIC_FDT_IRQ_FLAGS_EDGE_LO_HI;
+    VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
+    uint32_t irqflags = GIC_FDT_IRQ_FLAGS_LEVEL_HI;
+
+    if (vmc->claim_edge_triggered_timers) {
+        irqflags = GIC_FDT_IRQ_FLAGS_EDGE_LO_HI;
+    }
 
     if (gictype == 2) {
         irqflags = deposit32(irqflags, GIC_FDT_IRQ_PPI_CPU_START,
@@ -1556,8 +1576,14 @@ static void virt_2_8_instance_init(Object *obj)
 
 static void virt_machine_2_8_options(MachineClass *mc)
 {
+    VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc));
+
     virt_machine_2_9_options(mc);
     SET_MACHINE_COMPAT(mc, VIRT_COMPAT_2_8);
+    /* For 2.8 and earlier we falsely claimed in the DT that
+     * our timers were edge-triggered, not level-triggered.
+     */
+    vmc->claim_edge_triggered_timers = true;
 }
 DEFINE_VIRT_MACHINE(2, 8)
 
-- 
2.7.4

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

* [Qemu-devel] [PATCH 08/23] hw/intc/arm_gicv3: Add external IRQ lines for VIRQ and VFIQ
  2016-12-13 10:36 [Qemu-devel] [PATCH 00/23] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs Peter Maydell
                   ` (6 preceding siblings ...)
  2016-12-13 10:36 ` [Qemu-devel] [PATCH 07/23] hw/arm/virt: Don't incorrectly claim architectural timer to be edge-triggered Peter Maydell
@ 2016-12-13 10:36 ` Peter Maydell
  2016-12-13 10:36 ` [Qemu-devel] [PATCH 09/23] hw/intc/arm_gic: " Peter Maydell
                   ` (17 subsequent siblings)
  25 siblings, 0 replies; 45+ messages in thread
From: Peter Maydell @ 2016-12-13 10:36 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: patches, Edgar E. Iglesias, Christoffer Dall, Andrew Jones

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 0f8c4b8..9bb8d01 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] 45+ messages in thread

* [Qemu-devel] [PATCH 09/23] hw/intc/arm_gic: Add external IRQ lines for VIRQ and VFIQ
  2016-12-13 10:36 [Qemu-devel] [PATCH 00/23] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs Peter Maydell
                   ` (7 preceding siblings ...)
  2016-12-13 10:36 ` [Qemu-devel] [PATCH 08/23] hw/intc/arm_gicv3: Add external IRQ lines for VIRQ and VFIQ Peter Maydell
@ 2016-12-13 10:36 ` Peter Maydell
  2016-12-19 21:54   ` Alistair Francis
  2016-12-13 10:36 ` [Qemu-devel] [PATCH 10/23] target-arm: Expose output GPIO line for VCPU maintenance interrupt Peter Maydell
                   ` (16 subsequent siblings)
  25 siblings, 1 reply; 45+ messages in thread
From: Peter Maydell @ 2016-12-13 10:36 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: patches, Edgar E. Iglesias, Christoffer Dall, Andrew Jones

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>
---
 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] 45+ messages in thread

* [Qemu-devel] [PATCH 10/23] target-arm: Expose output GPIO line for VCPU maintenance interrupt
  2016-12-13 10:36 [Qemu-devel] [PATCH 00/23] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs Peter Maydell
                   ` (8 preceding siblings ...)
  2016-12-13 10:36 ` [Qemu-devel] [PATCH 09/23] hw/intc/arm_gic: " Peter Maydell
@ 2016-12-13 10:36 ` Peter Maydell
  2016-12-13 12:37   ` Edgar E. Iglesias
  2016-12-13 10:36 ` [Qemu-devel] [PATCH 11/23] hw/arm/virt: Wire VIRQ, VFIQ, maintenance irq lines from GIC to CPU Peter Maydell
                   ` (15 subsequent siblings)
  25 siblings, 1 reply; 45+ messages in thread
From: Peter Maydell @ 2016-12-13 10:36 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: patches, Edgar E. Iglesias, Christoffer Dall, Andrew Jones

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>
---
 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 ca5c849..c38488a 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 99f0dbe..5e0d21d 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] 45+ messages in thread

* [Qemu-devel] [PATCH 11/23] hw/arm/virt: Wire VIRQ, VFIQ, maintenance irq lines from GIC to CPU
  2016-12-13 10:36 [Qemu-devel] [PATCH 00/23] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs Peter Maydell
                   ` (9 preceding siblings ...)
  2016-12-13 10:36 ` [Qemu-devel] [PATCH 10/23] target-arm: Expose output GPIO line for VCPU maintenance interrupt Peter Maydell
@ 2016-12-13 10:36 ` Peter Maydell
  2016-12-13 10:36 ` [Qemu-devel] [PATCH 12/23] target-arm: Add ARMCPU fields for GIC CPU i/f config Peter Maydell
                   ` (14 subsequent siblings)
  25 siblings, 0 replies; 45+ messages in thread
From: Peter Maydell @ 2016-12-13 10:36 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: patches, Edgar E. Iglesias, Christoffer Dall, Andrew Jones

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 9650193..b805b76 100644
--- a/include/hw/arm/virt.h
+++ b/include/hw/arm/virt.h
@@ -36,6 +36,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 2ca9527..7adb58b 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -583,9 +583,9 @@ static void create_gic(VirtMachineState *vms, qemu_irq *pic, int type,
         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));
@@ -607,9 +607,17 @@ static void create_gic(VirtMachineState *vms, qemu_irq *pic, int type,
                                                    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] 45+ messages in thread

* [Qemu-devel] [PATCH 12/23] target-arm: Add ARMCPU fields for GIC CPU i/f config
  2016-12-13 10:36 [Qemu-devel] [PATCH 00/23] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs Peter Maydell
                   ` (10 preceding siblings ...)
  2016-12-13 10:36 ` [Qemu-devel] [PATCH 11/23] hw/arm/virt: Wire VIRQ, VFIQ, maintenance irq lines from GIC to CPU Peter Maydell
@ 2016-12-13 10:36 ` Peter Maydell
  2016-12-13 10:36 ` [Qemu-devel] [PATCH 13/23] hw/intc/gicv3: Add defines for ICH system register fields Peter Maydell
                   ` (13 subsequent siblings)
  25 siblings, 0 replies; 45+ messages in thread
From: Peter Maydell @ 2016-12-13 10:36 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: patches, Edgar E. Iglesias, Christoffer Dall, Andrew Jones

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 c38488a..be42ffb 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] 45+ messages in thread

* [Qemu-devel] [PATCH 13/23] hw/intc/gicv3: Add defines for ICH system register fields
  2016-12-13 10:36 [Qemu-devel] [PATCH 00/23] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs Peter Maydell
                   ` (11 preceding siblings ...)
  2016-12-13 10:36 ` [Qemu-devel] [PATCH 12/23] target-arm: Add ARMCPU fields for GIC CPU i/f config Peter Maydell
@ 2016-12-13 10:36 ` Peter Maydell
  2016-12-13 10:36 ` [Qemu-devel] [PATCH 14/23] hw/intc/gicv3: Add data fields for virtualization support Peter Maydell
                   ` (12 subsequent siblings)
  25 siblings, 0 replies; 45+ messages in thread
From: Peter Maydell @ 2016-12-13 10:36 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: patches, Edgar E. Iglesias, Christoffer Dall, Andrew Jones

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] 45+ messages in thread

* [Qemu-devel] [PATCH 14/23] hw/intc/gicv3: Add data fields for virtualization support
  2016-12-13 10:36 [Qemu-devel] [PATCH 00/23] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs Peter Maydell
                   ` (12 preceding siblings ...)
  2016-12-13 10:36 ` [Qemu-devel] [PATCH 13/23] hw/intc/gicv3: Add defines for ICH system register fields Peter Maydell
@ 2016-12-13 10:36 ` Peter Maydell
  2016-12-13 10:36 ` [Qemu-devel] [PATCH 15/23] hw/intc/arm_gicv3: Add accessors for ICH_ system registers Peter Maydell
                   ` (11 subsequent siblings)
  25 siblings, 0 replies; 45+ messages in thread
From: Peter Maydell @ 2016-12-13 10:36 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: patches, Edgar E. Iglesias, Christoffer Dall, Andrew Jones

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 9bb8d01..a14aa5a 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] 45+ messages in thread

* [Qemu-devel] [PATCH 15/23] hw/intc/arm_gicv3: Add accessors for ICH_ system registers
  2016-12-13 10:36 [Qemu-devel] [PATCH 00/23] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs Peter Maydell
                   ` (13 preceding siblings ...)
  2016-12-13 10:36 ` [Qemu-devel] [PATCH 14/23] hw/intc/gicv3: Add data fields for virtualization support Peter Maydell
@ 2016-12-13 10:36 ` Peter Maydell
  2016-12-13 10:36 ` [Qemu-devel] [PATCH 16/23] hw/intc/arm_gicv3: Implement ICV_ registers which are just accessors Peter Maydell
                   ` (10 subsequent siblings)
  25 siblings, 0 replies; 45+ messages in thread
From: Peter Maydell @ 2016-12-13 10:36 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: patches, Edgar E. Iglesias, Christoffer Dall, Andrew Jones

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] 45+ messages in thread

* [Qemu-devel] [PATCH 16/23] hw/intc/arm_gicv3: Implement ICV_ registers which are just accessors
  2016-12-13 10:36 [Qemu-devel] [PATCH 00/23] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs Peter Maydell
                   ` (14 preceding siblings ...)
  2016-12-13 10:36 ` [Qemu-devel] [PATCH 15/23] hw/intc/arm_gicv3: Add accessors for ICH_ system registers Peter Maydell
@ 2016-12-13 10:36 ` Peter Maydell
  2016-12-13 10:36 ` [Qemu-devel] [PATCH 17/23] hw/intc/arm_gicv3: Implement ICV_ HPPIR, DIR and RPR registers Peter Maydell
                   ` (9 subsequent siblings)
  25 siblings, 0 replies; 45+ messages in thread
From: Peter Maydell @ 2016-12-13 10:36 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: patches, Edgar E. Iglesias, Christoffer Dall, Andrew Jones

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] 45+ messages in thread

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

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] 45+ messages in thread

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

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] 45+ messages in thread

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

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] 45+ messages in thread

* [Qemu-devel] [PATCH 20/23] hw/intc/arm_gicv3: Implement EL2 traps for CPU i/f regs
  2016-12-13 10:36 [Qemu-devel] [PATCH 00/23] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs Peter Maydell
                   ` (18 preceding siblings ...)
  2016-12-13 10:36 ` [Qemu-devel] [PATCH 19/23] hw/intc/arm_gicv3: Implement gicv3_cpuif_virt_update() Peter Maydell
@ 2016-12-13 10:36 ` Peter Maydell
  2016-12-13 10:36 ` [Qemu-devel] [PATCH 21/23] hw/arm/virt: Support using SMC for PSCI Peter Maydell
                   ` (5 subsequent siblings)
  25 siblings, 0 replies; 45+ messages in thread
From: Peter Maydell @ 2016-12-13 10:36 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: patches, Edgar E. Iglesias, Christoffer Dall, Andrew Jones

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] 45+ messages in thread

* [Qemu-devel] [PATCH 21/23] hw/arm/virt: Support using SMC for PSCI
  2016-12-13 10:36 [Qemu-devel] [PATCH 00/23] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs Peter Maydell
                   ` (19 preceding siblings ...)
  2016-12-13 10:36 ` [Qemu-devel] [PATCH 20/23] hw/intc/arm_gicv3: Implement EL2 traps for CPU i/f regs Peter Maydell
@ 2016-12-13 10:36 ` Peter Maydell
  2016-12-13 12:36   ` Edgar E. Iglesias
  2016-12-28 13:14   ` Andrew Jones
  2016-12-13 10:36 ` [Qemu-devel] [PATCH 22/23] target-arm: Enable EL2 feature bit on A53 and A57 Peter Maydell
                   ` (4 subsequent siblings)
  25 siblings, 2 replies; 45+ messages in thread
From: Peter Maydell @ 2016-12-13 10:36 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: patches, Edgar E. Iglesias, Christoffer Dall, Andrew Jones

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>
---
 hw/arm/virt.c | 29 ++++++++++++++++++++++-------
 1 file changed, 22 insertions(+), 7 deletions(-)

diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 7adb58b..cce8d2e 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -88,7 +88,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")
@@ -266,9 +266,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");
@@ -300,7 +310,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);
@@ -402,7 +412,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");
         }
@@ -1270,7 +1281,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.
@@ -1353,8 +1368,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] 45+ messages in thread

* [Qemu-devel] [PATCH 22/23] target-arm: Enable EL2 feature bit on A53 and A57
  2016-12-13 10:36 [Qemu-devel] [PATCH 00/23] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs Peter Maydell
                   ` (20 preceding siblings ...)
  2016-12-13 10:36 ` [Qemu-devel] [PATCH 21/23] hw/arm/virt: Support using SMC for PSCI Peter Maydell
@ 2016-12-13 10:36 ` Peter Maydell
  2016-12-13 16:11   ` Edgar E. Iglesias
  2016-12-28 13:14   ` Andrew Jones
  2016-12-13 10:36 ` [Qemu-devel] [PATCH 23/23] hw/arm/virt: Add board property to enable EL2 Peter Maydell
                   ` (3 subsequent siblings)
  25 siblings, 2 replies; 45+ messages in thread
From: Peter Maydell @ 2016-12-13 10:36 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: patches, Edgar E. Iglesias, Christoffer Dall, Andrew Jones

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>
---
 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 be42ffb..51165fa 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 cce8d2e..5bde68c 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -1368,6 +1368,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 5e0d21d..d721cd4 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);
@@ -690,6 +698,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] 45+ messages in thread

* [Qemu-devel] [PATCH 23/23] hw/arm/virt: Add board property to enable EL2
  2016-12-13 10:36 [Qemu-devel] [PATCH 00/23] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs Peter Maydell
                   ` (21 preceding siblings ...)
  2016-12-13 10:36 ` [Qemu-devel] [PATCH 22/23] target-arm: Enable EL2 feature bit on A53 and A57 Peter Maydell
@ 2016-12-13 10:36 ` Peter Maydell
  2016-12-28 13:14   ` Andrew Jones
  2016-12-13 21:16 ` [Qemu-devel] [PATCH 00/23] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs Andrew Jones
                   ` (2 subsequent siblings)
  25 siblings, 1 reply; 45+ messages in thread
From: Peter Maydell @ 2016-12-13 10:36 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: patches, Edgar E. Iglesias, Christoffer Dall, Andrew Jones

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.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/arm/virt.c | 45 +++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 43 insertions(+), 2 deletions(-)

diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 5bde68c..7eec50a 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -78,6 +78,7 @@ typedef struct {
     MachineState parent;
     bool secure;
     bool highmem;
+    bool virt;
     int32_t gic_version;
     struct arm_boot_info bootinfo;
     const MemMapEntry *memmap;
@@ -480,6 +481,11 @@ static void fdt_add_gic_node(VirtMachineState *vms, int type)
                                      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",
@@ -1279,10 +1285,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;
     }
@@ -1312,6 +1323,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");
@@ -1368,7 +1385,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);
         }
 
@@ -1481,6 +1498,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);
@@ -1568,6 +1599,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] 45+ messages in thread

* Re: [Qemu-devel] [PATCH 21/23] hw/arm/virt: Support using SMC for PSCI
  2016-12-13 10:36 ` [Qemu-devel] [PATCH 21/23] hw/arm/virt: Support using SMC for PSCI Peter Maydell
@ 2016-12-13 12:36   ` Edgar E. Iglesias
  2016-12-28 13:14   ` Andrew Jones
  1 sibling, 0 replies; 45+ messages in thread
From: Edgar E. Iglesias @ 2016-12-13 12:36 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-arm, qemu-devel, patches, Christoffer Dall, Andrew Jones

On Tue, Dec 13, 2016 at 10:36:22AM +0000, Peter Maydell wrote:
> 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>


> ---
>  hw/arm/virt.c | 29 ++++++++++++++++++++++-------
>  1 file changed, 22 insertions(+), 7 deletions(-)
> 
> diff --git a/hw/arm/virt.c b/hw/arm/virt.c
> index 7adb58b..cce8d2e 100644
> --- a/hw/arm/virt.c
> +++ b/hw/arm/virt.c
> @@ -88,7 +88,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")
> @@ -266,9 +266,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");
> @@ -300,7 +310,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);
> @@ -402,7 +412,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");
>          }
> @@ -1270,7 +1281,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.
> @@ -1353,8 +1368,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	[flat|nested] 45+ messages in thread

* Re: [Qemu-devel] [PATCH 10/23] target-arm: Expose output GPIO line for VCPU maintenance interrupt
  2016-12-13 10:36 ` [Qemu-devel] [PATCH 10/23] target-arm: Expose output GPIO line for VCPU maintenance interrupt Peter Maydell
@ 2016-12-13 12:37   ` Edgar E. Iglesias
  0 siblings, 0 replies; 45+ messages in thread
From: Edgar E. Iglesias @ 2016-12-13 12:37 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-arm, qemu-devel, patches, Christoffer Dall, Andrew Jones

On Tue, Dec 13, 2016 at 10:36:11AM +0000, Peter Maydell 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>



> ---
>  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 ca5c849..c38488a 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 99f0dbe..5e0d21d 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] 45+ messages in thread

* Re: [Qemu-devel] [PATCH 22/23] target-arm: Enable EL2 feature bit on A53 and A57
  2016-12-13 10:36 ` [Qemu-devel] [PATCH 22/23] target-arm: Enable EL2 feature bit on A53 and A57 Peter Maydell
@ 2016-12-13 16:11   ` Edgar E. Iglesias
  2016-12-19 22:04     ` Alistair Francis
  2016-12-28 13:14   ` Andrew Jones
  1 sibling, 1 reply; 45+ messages in thread
From: Edgar E. Iglesias @ 2016-12-13 16:11 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-arm, qemu-devel, patches, Christoffer Dall, Andrew Jones

On Tue, Dec 13, 2016 at 10:36:23AM +0000, Peter Maydell wrote:
> 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.

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


> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  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 be42ffb..51165fa 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 cce8d2e..5bde68c 100644
> --- a/hw/arm/virt.c
> +++ b/hw/arm/virt.c
> @@ -1368,6 +1368,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 5e0d21d..d721cd4 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);
> @@ -690,6 +698,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	[flat|nested] 45+ messages in thread

* Re: [Qemu-devel] [PATCH 00/23] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs
  2016-12-13 10:36 [Qemu-devel] [PATCH 00/23] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs Peter Maydell
                   ` (22 preceding siblings ...)
  2016-12-13 10:36 ` [Qemu-devel] [PATCH 23/23] hw/arm/virt: Add board property to enable EL2 Peter Maydell
@ 2016-12-13 21:16 ` Andrew Jones
  2016-12-14 10:18   ` Peter Maydell
  2017-01-09 15:08   ` Peter Maydell
  2016-12-16 21:42 ` Andrew Jones
  2016-12-19 22:20 ` Alistair Francis
  25 siblings, 2 replies; 45+ messages in thread
From: Andrew Jones @ 2016-12-13 21:16 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-arm, qemu-devel, Edgar E. Iglesias, Christoffer Dall, patches

On Tue, Dec 13, 2016 at 10:36:01AM +0000, Peter Maydell 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.
> 
> 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.
>

I've started some testing with this. When I boot an outer (L1) kernel
with more than one cpu allocated I get

[    3.441908] CPU: CPUs started in inconsistent modes
[    3.442787] ------------[ cut here ]------------
[    3.445434] WARNING: CPU: 0 PID: 1 at arch/arm64/kernel/smp.c:418 smp_cpus_done+0x80/0xa0
...

and KVM does not init. Booting with only one cpu I see we do start in EL2
and KVM does init. I'm booting the L1 kernel through UEFI (AAVMF). Also,
my L1 guest kernel is 4.9 based, but not pure upstream. I can try a more
pure 4.9 kernel with a defconfig later.

Thanks,
drew

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

* Re: [Qemu-devel] [PATCH 00/23] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs
  2016-12-13 21:16 ` [Qemu-devel] [PATCH 00/23] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs Andrew Jones
@ 2016-12-14 10:18   ` Peter Maydell
  2017-01-09 15:08   ` Peter Maydell
  1 sibling, 0 replies; 45+ messages in thread
From: Peter Maydell @ 2016-12-14 10:18 UTC (permalink / raw)
  To: Andrew Jones
  Cc: qemu-arm, QEMU Developers, Edgar E. Iglesias, Christoffer Dall, patches

On 13 December 2016 at 21:16, Andrew Jones <drjones@redhat.com> wrote:
> On Tue, Dec 13, 2016 at 10:36:01AM +0000, Peter Maydell 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.
>>
>> 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.
>>
>
> I've started some testing with this. When I boot an outer (L1) kernel
> with more than one cpu allocated I get
>
> [    3.441908] CPU: CPUs started in inconsistent modes
> [    3.442787] ------------[ cut here ]------------
> [    3.445434] WARNING: CPU: 0 PID: 1 at arch/arm64/kernel/smp.c:418 smp_cpus_done+0x80/0xa0
> ...
>
> and KVM does not init. Booting with only one cpu I see we do start in EL2
> and KVM does init. I'm booting the L1 kernel through UEFI (AAVMF). Also,
> my L1 guest kernel is 4.9 based, but not pure upstream. I can try a more
> pure 4.9 kernel with a defconfig later.

Yeah, I don't think I ever tried an SMP config in outer QEMU.
This seems like it would be a problem with the boot.c code rather than
the new GIC features, though... I'll have a look.

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH 00/23] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs
  2016-12-13 10:36 [Qemu-devel] [PATCH 00/23] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs Peter Maydell
                   ` (23 preceding siblings ...)
  2016-12-13 21:16 ` [Qemu-devel] [PATCH 00/23] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs Andrew Jones
@ 2016-12-16 21:42 ` Andrew Jones
  2016-12-19 22:20 ` Alistair Francis
  25 siblings, 0 replies; 45+ messages in thread
From: Andrew Jones @ 2016-12-16 21:42 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-arm, qemu-devel, patches, Edgar E. Iglesias, Christoffer Dall

On Tue, Dec 13, 2016 at 10:36:01AM +0000, Peter Maydell 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.
> 
> 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.

After seeing that multiple cpus didn't work with Linux, I modified
my EL2 supporting kvm-unit-tests branch to also output what level
each cpu starts in. I see the same issue - only cpu0 starts in El2.
Here's the new kvm-unit-tests branch

 https://github.com/rhdrjones/kvm-unit-tests/commits/arm64/hyp-test

 $ ./configure --arch=arm64 --cross-prefix=aarch64-linux-gnu-
 $ make

 $ arm/run arm/hyp-mode.flat -smp 4 -machine virtualization=on
 INFO: cpu1 did not start in HYP
 INFO: cpu2 did not start in HYP
 INFO: cpu3 did not start in HYP
 INFO: cpu0 started in HYP
 FAIL: HYP start

Thanks,
drew

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

* Re: [Qemu-devel] [PATCH 01/23] target-arm: Log AArch64 exception returns
  2016-12-13 10:36 ` [Qemu-devel] [PATCH 01/23] target-arm: Log AArch64 exception returns Peter Maydell
@ 2016-12-19 21:51   ` Alistair Francis
  2016-12-20 15:31   ` Andrew Jones
  1 sibling, 0 replies; 45+ messages in thread
From: Alistair Francis @ 2016-12-19 21:51 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-arm, qemu-devel@nongnu.org Developers, Edgar E. Iglesias,
	Andrew Jones, Christoffer Dall, Patch Tracking

On Tue, Dec 13, 2016 at 2:36 AM, Peter Maydell <peter.maydell@linaro.org> wrote:
> We already log exception entry; add logging of the AArch64 exception
> return path as well.
>
> 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/op_helper.c | 9 +++++++++
>  1 file changed, 9 insertions(+)
>
> diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
> index cd94216..ba796d8 100644
> --- a/target-arm/op_helper.c
> +++ b/target-arm/op_helper.c
> @@ -17,6 +17,7 @@
>   * License along with this library; if not, see <http://www.gnu.org/licenses/>.
>   */
>  #include "qemu/osdep.h"
> +#include "qemu/log.h"
>  #include "cpu.h"
>  #include "exec/helper-proto.h"
>  #include "internals.h"
> @@ -972,6 +973,9 @@ void HELPER(exception_return)(CPUARMState *env)
>          } else {
>              env->regs[15] = env->elr_el[cur_el] & ~0x3;
>          }
> +        qemu_log_mask(CPU_LOG_INT, "Exception return from AArch64 EL%d to "
> +                      "AArch32 EL%d PC 0x%" PRIx32 "\n",
> +                      cur_el, new_el, env->regs[15]);
>      } else {
>          env->aarch64 = 1;
>          pstate_write(env, spsr);
> @@ -980,6 +984,9 @@ void HELPER(exception_return)(CPUARMState *env)
>          }
>          aarch64_restore_sp(env, new_el);
>          env->pc = env->elr_el[cur_el];
> +        qemu_log_mask(CPU_LOG_INT, "Exception return from AArch64 EL%d to "
> +                      "AArch64 EL%d PC 0x%" PRIx64 "\n",
> +                      cur_el, new_el, env->pc);
>      }
>
>      arm_call_el_change_hook(arm_env_get_cpu(env));
> @@ -1002,6 +1009,8 @@ illegal_return:
>      if (!arm_singlestep_active(env)) {
>          env->pstate &= ~PSTATE_SS;
>      }
> +    qemu_log_mask(LOG_GUEST_ERROR, "Illegal exception return at EL%d: "
> +                  "resuming execution at 0x%" PRIx64 "\n", cur_el, env->pc);
>  }
>
>  /* Return true if the linked breakpoint entry lbn passes its checks */
> --
> 2.7.4
>
>

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

* Re: [Qemu-devel] [PATCH 09/23] hw/intc/arm_gic: Add external IRQ lines for VIRQ and VFIQ
  2016-12-13 10:36 ` [Qemu-devel] [PATCH 09/23] hw/intc/arm_gic: " Peter Maydell
@ 2016-12-19 21:54   ` Alistair Francis
  0 siblings, 0 replies; 45+ messages in thread
From: Alistair Francis @ 2016-12-19 21:54 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-arm, qemu-devel@nongnu.org Developers, Edgar E. Iglesias,
	Andrew Jones, Christoffer Dall, Patch Tracking

On Tue, Dec 13, 2016 at 2:36 AM, Peter Maydell <peter.maydell@linaro.org> 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>

Thanks,

Alistair

> ---
>  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] 45+ messages in thread

* Re: [Qemu-devel] [PATCH 22/23] target-arm: Enable EL2 feature bit on A53 and A57
  2016-12-13 16:11   ` Edgar E. Iglesias
@ 2016-12-19 22:04     ` Alistair Francis
  2016-12-20 13:32       ` Peter Maydell
  0 siblings, 1 reply; 45+ messages in thread
From: Alistair Francis @ 2016-12-19 22:04 UTC (permalink / raw)
  To: Edgar E. Iglesias
  Cc: Peter Maydell, Andrew Jones, qemu-arm,
	qemu-devel@nongnu.org Developers, Christoffer Dall,
	Patch Tracking

On Tue, Dec 13, 2016 at 8:11 AM, Edgar E. Iglesias
<edgar.iglesias@gmail.com> wrote:
> On Tue, Dec 13, 2016 at 10:36:23AM +0000, Peter Maydell wrote:
>> 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.
>
> Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>

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

>
>
>>
>> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
>> ---
>>  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 be42ffb..51165fa 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 cce8d2e..5bde68c 100644
>> --- a/hw/arm/virt.c
>> +++ b/hw/arm/virt.c
>> @@ -1368,6 +1368,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);

Hey Peter,

We would like this to be settable. I think just copying the s->secure
(same as EL3) should be fine here.

Let me know what is easier for you, if you want to just add an extra
patch to enable it or if you want me to send a patch doing it?

Thanks,

Alistair

>>          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 5e0d21d..d721cd4 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);
>> @@ -690,6 +698,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	[flat|nested] 45+ messages in thread

* Re: [Qemu-devel] [PATCH 00/23] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs
  2016-12-13 10:36 [Qemu-devel] [PATCH 00/23] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs Peter Maydell
                   ` (24 preceding siblings ...)
  2016-12-16 21:42 ` Andrew Jones
@ 2016-12-19 22:20 ` Alistair Francis
  2017-01-09 15:57   ` Peter Maydell
  25 siblings, 1 reply; 45+ messages in thread
From: Alistair Francis @ 2016-12-19 22:20 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-arm, qemu-devel@nongnu.org Developers, Edgar E. Iglesias,
	Andrew Jones, Christoffer Dall, Patch Tracking

On Tue, Dec 13, 2016 at 2:36 AM, 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.
>
> 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.
>
> Patches 1-7 have already appeared on list, and 1-5 + 7 have been
> reviewed. The rest are new.
>
> As per mailing list discussion, there is a new CPU property
> for enabling EL2 which defaults to 'true' (named 'has_el2' to
> parallel the existing 'has_el3'). There is also a board property
> on 'virt' which defaults to 'false' (named 'virtualization' to
> parallel the existing 'secure'). The only other 64-bit board
> is the ZynqMP -- this patchset makes it always set has_el2 to false,
> so no change in behaviour. (I imagine the Xilinx folk will want to
> enable it at some point.)
>
> There is no property on the GIC device object to enable virtualization,
> because this only affects the CPU interface, which in real hardware
> is part of the CPU itself and which in QEMU we enable and configure
> via a close coupling between the cpuif code and the CPU code.
>
> These patches include changes to the reported device tree info
> to (a) report the GICv3 maintenance IRQ binding and (b) report
> use of SMC as the PSCI conduit. I haven't tried to make the
> equivalent changes to the ACPI tables because Drew said on
> Monday that he had a cleanup to make in that area, which would
> change all that code anyway. I'm guessing there'll be a v2 of
> this series, so we can fix that dependency up properly then.
>
> The new state in the GICv3 for the virtualization should not
> cause a migration compat break because we put it in a subsection
> which is only sent if virtualization is enabled.
>
> Unfortunately to enable EL2 on the 32-bit CPU models we need
> to do this all over again for the GICv2 emulation :-)
>
> Git branch for this:
>  https://git.linaro.org/people/peter.maydell/qemu-arm.git gicv3-virt

Hey Peter,

If I manually enable EL2 and EL3 for the Xilinx EP108 board I can
replicate a full hardware flow from ATF -> u-boot -> Linux.

Unfortunately Linux doesn't get too far as I get the error below. This
is further then it was getting before though, so I'm still including
this:

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

[       24547.770] Detected VIPT I-cache on CPU1
[       24667.370] CPU features: SANITY CHECK: Unexpected variation in
SYS_CNTFRQ_EL0. Boot CPU: 0x00000005f5e100, CPU1: 0x00000003b9aca0
[       24769.210] Unsupported CPU feature variation.
[       25004.700] ------------[ cut here ]------------
[       25016.880] WARNING: at
/proj/petalinux/petalinux-v2016.2_0609_2/petalinux-v2016.2-final/components/linux-kernel/xlnx-4.4/arch/arm64/kernel/cpufeature.c:578
[       25052.590] Modules linked in:
[       25069.260]
[       25167.520] CPU: 1 PID: 0 Comm: swapper/1 Not tainted 4.4.0 #2
[       25178.040] Hardware name: ZynqMP EP108 (DT)
[       25230.380] task: ffffffc0328c2280 ti: ffffffc0328c8000
task.ti: ffffffc0328c8000
[       25259.620] PC is at update_cpu_features+0x3a4/0x3b4
[       25273.900] LR is at update_cpu_features+0x3a4/0x3b4
[       25283.850] pc : [<ffffffc00008c500>] lr : [<ffffffc00008c500>]
pstate: 600003c5
[       25289.440] sp : ffffffc0328cbf80
[       25319.600] x29: ffffffc0328cbf80 x28: 0000000000000000
[       25332.960] x27: ffffffc000081050 x26: 0000000001c7b000
[       25344.260] x25: 0000000001c78000 x24: 0000000000000000
[       25355.700] x23: 0000000000000000 x22: ffffffc001c21190
[       25367.180] x21: ffffffc037fa44d0 x20: 0000000000000001
[       25378.440] x19: ffffffc001c1d000 x18: 00000000410fd034
[       25389.660] x17: 0000000003010066 x16: 0000000002101110
[       25400.920] x15: 0000000013112111 x14: 203a55504320746f
[       25412.180] x13: 6f42202e304c455f x12: 515246544e435f53
[       25423.440] x11: ffffffc001bb2000 x10: ffffffc001c23000
[       25444.920] x9 : 0000000000000000 x8 : ffffffc001c252a0
[       25456.710] x7 : 0000000000000000 x6 : 0000000000000015
[       25467.920] x5 : 000000000008bc0e x4 : 0000000000000000
[       25479.060] x3 : 0000000000000000 x2 : 0000000000000077
[       25490.010] x1 : 00000000000003c0 x0 : 0000000000000022
[       25495.030]
[       26235.260] ---[ end trace 21587db8a41df80a ]---
[       26314.660] Call trace:
[       26339.500] [<ffffffc00008c500>] update_cpu_features+0x3a4/0x3b4
[       26398.300] [<ffffffc00008bc20>] cpuinfo_store_cpu+0x44/0x4c
[       26408.860] [<ffffffc00008cf78>] secondary_start_kernel+0xc8/0x140
[       26487.690] [<000000000008103c>] 0x8103c
[       27185.930] CPU1: Booted secondary processor [410fd034]


Thanks,

Alistair


>
>
> thanks
> -- PMM
>
> Peter Maydell (23):
>   target-arm: Log AArch64 exception returns
>   hw/intc/arm_gicv3: Remove incorrect usage of fieldoffset
>   hw/intc/arm_gicv3: Don't signal Pending+Active interrupts to CPU
>   hw/arm/virt: add 2.9 machine type
>   hw/arm/virt: Merge VirtBoardInfo and VirtMachineState
>   hw/arm/virt: Rename 'vbi' variables to 'vms'
>   hw/arm/virt: Don't incorrectly claim architectural timer to be
>     edge-triggered
>   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: 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              |    2 +
>  include/hw/compat.h                |    3 +
>  include/hw/intc/arm_gic_common.h   |    2 +
>  include/hw/intc/arm_gicv3_common.h |   21 +
>  target-arm/cpu.h                   |    9 +
>  hw/arm/virt.c                      |  696 +++++++++++--------
>  hw/arm/xlnx-zynqmp.c               |    2 +
>  hw/intc/arm_gic_common.c           |    6 +
>  hw/intc/arm_gicv3.c                |    5 +
>  hw/intc/arm_gicv3_common.c         |   31 +
>  hw/intc/arm_gicv3_cpuif.c          | 1336 +++++++++++++++++++++++++++++++++++-
>  target-arm/cpu.c                   |   15 +
>  target-arm/cpu64.c                 |    8 +
>  target-arm/op_helper.c             |    9 +
>  hw/intc/trace-events               |   33 +
>  16 files changed, 1925 insertions(+), 332 deletions(-)
>
> --
> 2.7.4
>
>

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

* Re: [Qemu-devel] [PATCH 22/23] target-arm: Enable EL2 feature bit on A53 and A57
  2016-12-19 22:04     ` Alistair Francis
@ 2016-12-20 13:32       ` Peter Maydell
  2016-12-20 17:46         ` Alistair Francis
  0 siblings, 1 reply; 45+ messages in thread
From: Peter Maydell @ 2016-12-20 13:32 UTC (permalink / raw)
  To: Alistair Francis
  Cc: Edgar E. Iglesias, Andrew Jones, qemu-arm,
	qemu-devel@nongnu.org Developers, Christoffer Dall,
	Patch Tracking

On 19 December 2016 at 22:04, Alistair Francis <alistair23@gmail.com> wrote:
> On Tue, Dec 13, 2016 at 8:11 AM, Edgar E. Iglesias
> <edgar.iglesias@gmail.com> wrote:
>> On Tue, Dec 13, 2016 at 10:36:23AM +0000, Peter Maydell wrote:
>>> 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.

>>> 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);
>
> Hey Peter,
>
> We would like this to be settable. I think just copying the s->secure
> (same as EL3) should be fine here.
>
> Let me know what is easier for you, if you want to just add an extra
> patch to enable it or if you want me to send a patch doing it?

I'm not really set up to test the xilinx boards, so I'd rather
let you test and send the extra patch to enable it for them.

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH 01/23] target-arm: Log AArch64 exception returns
  2016-12-13 10:36 ` [Qemu-devel] [PATCH 01/23] target-arm: Log AArch64 exception returns Peter Maydell
  2016-12-19 21:51   ` Alistair Francis
@ 2016-12-20 15:31   ` Andrew Jones
  2016-12-27 15:13     ` Peter Maydell
  1 sibling, 1 reply; 45+ messages in thread
From: Andrew Jones @ 2016-12-20 15:31 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-arm, qemu-devel, Edgar E. Iglesias, Christoffer Dall, patches

On Tue, Dec 13, 2016 at 10:36:02AM +0000, Peter Maydell wrote:
> We already log exception entry; add logging of the AArch64 exception
> return path as well.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
> ---
>  target-arm/op_helper.c | 9 +++++++++
>  1 file changed, 9 insertions(+)
> 
> diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
> index cd94216..ba796d8 100644
> --- a/target-arm/op_helper.c
> +++ b/target-arm/op_helper.c
> @@ -17,6 +17,7 @@
>   * License along with this library; if not, see <http://www.gnu.org/licenses/>.
>   */
>  #include "qemu/osdep.h"
> +#include "qemu/log.h"
>  #include "cpu.h"
>  #include "exec/helper-proto.h"
>  #include "internals.h"
> @@ -972,6 +973,9 @@ void HELPER(exception_return)(CPUARMState *env)
>          } else {
>              env->regs[15] = env->elr_el[cur_el] & ~0x3;
>          }
> +        qemu_log_mask(CPU_LOG_INT, "Exception return from AArch64 EL%d to "
> +                      "AArch32 EL%d PC 0x%" PRIx32 "\n",
> +                      cur_el, new_el, env->regs[15]);
>      } else {
>          env->aarch64 = 1;
>          pstate_write(env, spsr);
> @@ -980,6 +984,9 @@ void HELPER(exception_return)(CPUARMState *env)
>          }
>          aarch64_restore_sp(env, new_el);
>          env->pc = env->elr_el[cur_el];
> +        qemu_log_mask(CPU_LOG_INT, "Exception return from AArch64 EL%d to "
> +                      "AArch64 EL%d PC 0x%" PRIx64 "\n",
> +                      cur_el, new_el, env->pc);
>      }
>  
>      arm_call_el_change_hook(arm_env_get_cpu(env));
> @@ -1002,6 +1009,8 @@ illegal_return:
>      if (!arm_singlestep_active(env)) {
>          env->pstate &= ~PSTATE_SS;
>      }
> +    qemu_log_mask(LOG_GUEST_ERROR, "Illegal exception return at EL%d: "
> +                  "resuming execution at 0x%" PRIx64 "\n", cur_el, env->pc);
>  }
>  
>  /* Return true if the linked breakpoint entry lbn passes its checks */
> -- 
> 2.7.4
> 
>

Should we output both the destination PC (ELR) and the source PC (where
the eret was)? Otherwise if there are many erets to the same entry point,
then the logs won't fully enlighten us.

Thanks,
drew

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

* Re: [Qemu-devel] [PATCH 06/23] hw/arm/virt: Rename 'vbi' variables to 'vms'
  2016-12-13 10:36 ` [Qemu-devel] [PATCH 06/23] hw/arm/virt: Rename 'vbi' variables to 'vms' Peter Maydell
@ 2016-12-20 15:46   ` Andrew Jones
  0 siblings, 0 replies; 45+ messages in thread
From: Andrew Jones @ 2016-12-20 15:46 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-arm, qemu-devel, Edgar E. Iglesias, Christoffer Dall, patches

On Tue, Dec 13, 2016 at 10:36:07AM +0000, Peter Maydell wrote:
> Rename all the variables which used to be VirtBoardInfo*
> and are now VirtMachineState* so their names are in line
> with the type being used.
> 
> Apart from the removal of the line 'VirtMachineState *vbi = vms;'
> this commit is purely a search-and-replace of 'vbi' with 'vms'.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  hw/arm/virt.c | 489 +++++++++++++++++++++++++++++-----------------------------
>  1 file changed, 244 insertions(+), 245 deletions(-)
>

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

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

* Re: [Qemu-devel] [PATCH 22/23] target-arm: Enable EL2 feature bit on A53 and A57
  2016-12-20 13:32       ` Peter Maydell
@ 2016-12-20 17:46         ` Alistair Francis
  0 siblings, 0 replies; 45+ messages in thread
From: Alistair Francis @ 2016-12-20 17:46 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Edgar E. Iglesias, Andrew Jones, qemu-arm,
	qemu-devel@nongnu.org Developers, Christoffer Dall,
	Patch Tracking

On Tue, Dec 20, 2016 at 5:32 AM, Peter Maydell <peter.maydell@linaro.org> wrote:
> On 19 December 2016 at 22:04, Alistair Francis <alistair23@gmail.com> wrote:
>> On Tue, Dec 13, 2016 at 8:11 AM, Edgar E. Iglesias
>> <edgar.iglesias@gmail.com> wrote:
>>> On Tue, Dec 13, 2016 at 10:36:23AM +0000, Peter Maydell wrote:
>>>> 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.
>
>>>> 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);
>>
>> Hey Peter,
>>
>> We would like this to be settable. I think just copying the s->secure
>> (same as EL3) should be fine here.
>>
>> Let me know what is easier for you, if you want to just add an extra
>> patch to enable it or if you want me to send a patch doing it?
>
> I'm not really set up to test the xilinx boards, so I'd rather
> let you test and send the extra patch to enable it for them.

Yeah, no worries. I'll sent a patch out to apply on top of this series.

Thanks,

Alistair

>
> thanks
> -- PMM

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

* Re: [Qemu-devel] [PATCH 01/23] target-arm: Log AArch64 exception returns
  2016-12-20 15:31   ` Andrew Jones
@ 2016-12-27 15:13     ` Peter Maydell
  0 siblings, 0 replies; 45+ messages in thread
From: Peter Maydell @ 2016-12-27 15:13 UTC (permalink / raw)
  To: Andrew Jones
  Cc: qemu-arm, QEMU Developers, Edgar E. Iglesias, Christoffer Dall, patches

On 20 December 2016 at 15:31, Andrew Jones <drjones@redhat.com> wrote:
> Should we output both the destination PC (ELR) and the source PC (where
> the eret was)? Otherwise if there are many erets to the same entry point,
> then the logs won't fully enlighten us.

We don't really conveniently have the source PC, because it isn't
written out to env->pc at the point when this helper function
is called (the calling code in translate-a64.c doesn't call
gen_a64_set_pc(), because it knows the helper doesn't need to
care about the PC value).

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH 21/23] hw/arm/virt: Support using SMC for PSCI
  2016-12-13 10:36 ` [Qemu-devel] [PATCH 21/23] hw/arm/virt: Support using SMC for PSCI Peter Maydell
  2016-12-13 12:36   ` Edgar E. Iglesias
@ 2016-12-28 13:14   ` Andrew Jones
  1 sibling, 0 replies; 45+ messages in thread
From: Andrew Jones @ 2016-12-28 13:14 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-arm, qemu-devel, Edgar E. Iglesias, Christoffer Dall, patches

On Tue, Dec 13, 2016 at 10:36:22AM +0000, Peter Maydell wrote:
> 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>
> ---
>  hw/arm/virt.c | 29 ++++++++++++++++++++++-------
>  1 file changed, 22 insertions(+), 7 deletions(-)
>

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

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

* Re: [Qemu-devel] [PATCH 22/23] target-arm: Enable EL2 feature bit on A53 and A57
  2016-12-13 10:36 ` [Qemu-devel] [PATCH 22/23] target-arm: Enable EL2 feature bit on A53 and A57 Peter Maydell
  2016-12-13 16:11   ` Edgar E. Iglesias
@ 2016-12-28 13:14   ` Andrew Jones
  1 sibling, 0 replies; 45+ messages in thread
From: Andrew Jones @ 2016-12-28 13:14 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-arm, qemu-devel, Edgar E. Iglesias, Christoffer Dall, patches

On Tue, Dec 13, 2016 at 10:36:23AM +0000, Peter Maydell wrote:
> 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>
> ---
>  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(+)
>

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

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

* Re: [Qemu-devel] [PATCH 23/23] hw/arm/virt: Add board property to enable EL2
  2016-12-13 10:36 ` [Qemu-devel] [PATCH 23/23] hw/arm/virt: Add board property to enable EL2 Peter Maydell
@ 2016-12-28 13:14   ` Andrew Jones
  2017-01-17 22:15     ` Alistair Francis
  0 siblings, 1 reply; 45+ messages in thread
From: Andrew Jones @ 2016-12-28 13:14 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-arm, qemu-devel, Edgar E. Iglesias, Christoffer Dall, patches

On Tue, Dec 13, 2016 at 10:36:24AM +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.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  hw/arm/virt.c | 45 +++++++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 43 insertions(+), 2 deletions(-)
>

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

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

* Re: [Qemu-devel] [PATCH 00/23] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs
  2016-12-13 21:16 ` [Qemu-devel] [PATCH 00/23] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs Andrew Jones
  2016-12-14 10:18   ` Peter Maydell
@ 2017-01-09 15:08   ` Peter Maydell
  1 sibling, 0 replies; 45+ messages in thread
From: Peter Maydell @ 2017-01-09 15:08 UTC (permalink / raw)
  To: Andrew Jones
  Cc: qemu-arm, QEMU Developers, Edgar E. Iglesias, Christoffer Dall, patches

On 13 December 2016 at 21:16, Andrew Jones <drjones@redhat.com> wrote:
> On Tue, Dec 13, 2016 at 10:36:01AM +0000, Peter Maydell wrote:
>> This patchset adds support for the Virtualization extensions to QEMU's
>> GICv3 emulation.

> I've started some testing with this. When I boot an outer (L1) kernel
> with more than one cpu allocated I get
>
> [    3.441908] CPU: CPUs started in inconsistent modes
> [    3.442787] ------------[ cut here ]------------
> [    3.445434] WARNING: CPU: 0 PID: 1 at arch/arm64/kernel/smp.c:418 smp_cpus_done+0x80/0xa0
> ...
>
> and KVM does not init. Booting with only one cpu I see we do start in EL2
> and KVM does init.

This turns out to be a bug in QEMU's builtin PSCI implementation:
the CPU_ON call is supposed to start the new CPU in the highest
implemented-and-enabled NS exception level, but we were always
starting it in the exception level of the calling CPU. Since
Linux does its CPU_ON calls from EL1, this meant the new CPU got
started at EL1 rather than EL2.

I have a fix which I will put into v2 of the patchset (which I
will send mostly as an encouragement to further code review
since I don't think I've seen any other comments for things
I need to fix...)

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH 00/23] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs
  2016-12-19 22:20 ` Alistair Francis
@ 2017-01-09 15:57   ` Peter Maydell
  0 siblings, 0 replies; 45+ messages in thread
From: Peter Maydell @ 2017-01-09 15:57 UTC (permalink / raw)
  To: Alistair Francis
  Cc: qemu-arm, qemu-devel@nongnu.org Developers, Edgar E. Iglesias,
	Andrew Jones, Christoffer Dall, Patch Tracking

On 19 December 2016 at 22:20, Alistair Francis <alistair23@gmail.com> wrote:
> If I manually enable EL2 and EL3 for the Xilinx EP108 board I can
> replicate a full hardware flow from ATF -> u-boot -> Linux.
>
> Unfortunately Linux doesn't get too far as I get the error below. This
> is further then it was getting before though, so I'm still including
> this:
>
> Tested-by: Alistair Francis <alistair.francis@xilinx.com>
>
> [       24547.770] Detected VIPT I-cache on CPU1
> [       24667.370] CPU features: SANITY CHECK: Unexpected variation in
> SYS_CNTFRQ_EL0. Boot CPU: 0x00000005f5e100, CPU1: 0x00000003b9aca0
> [       24769.210] Unsupported CPU feature variation.

I'm not sure what's going on here -- in a full-EL3 setup then
we should be using the ATF PSCI implementation and it's the
firmware's job to ensure that SYS_CNTFRQ_EL0 is the same on
the booted up CPU (by pulling it out of the memory mapped system
timer, usually). On reset the CPUs will all have the same
CNTFRQ_EL0 value so unless EL3 firmware is writing dodgy values
to it they shouldn't end up out of sync. Might also be worth
checking we're not accidentally trying to use QEMU's PSCI
implementation.

I suspect this will be easier for you to investigate than me --
is this related to the system timer implementation you sent
patches for?

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH 23/23] hw/arm/virt: Add board property to enable EL2
  2016-12-28 13:14   ` Andrew Jones
@ 2017-01-17 22:15     ` Alistair Francis
  0 siblings, 0 replies; 45+ messages in thread
From: Alistair Francis @ 2017-01-17 22:15 UTC (permalink / raw)
  To: Andrew Jones
  Cc: Peter Maydell, Edgar E. Iglesias, qemu-arm,
	qemu-devel@nongnu.org Developers, Christoffer Dall,
	Patch Tracking

On Wed, Dec 28, 2016 at 5:14 AM, Andrew Jones <drjones@redhat.com> wrote:
> On Tue, Dec 13, 2016 at 10:36:24AM +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.
>>
>> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

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

Thanks,

Alistair

>> ---
>>  hw/arm/virt.c | 45 +++++++++++++++++++++++++++++++++++++++++++--
>>  1 file changed, 43 insertions(+), 2 deletions(-)
>>
>
> Reviewed-by: Andrew Jones <drjones@redhat.com>
>

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

end of thread, other threads:[~2017-01-17 22:16 UTC | newest]

Thread overview: 45+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-12-13 10:36 [Qemu-devel] [PATCH 00/23] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs Peter Maydell
2016-12-13 10:36 ` [Qemu-devel] [PATCH 01/23] target-arm: Log AArch64 exception returns Peter Maydell
2016-12-19 21:51   ` Alistair Francis
2016-12-20 15:31   ` Andrew Jones
2016-12-27 15:13     ` Peter Maydell
2016-12-13 10:36 ` [Qemu-devel] [PATCH 02/23] hw/intc/arm_gicv3: Remove incorrect usage of fieldoffset Peter Maydell
2016-12-13 10:36 ` [Qemu-devel] [PATCH 03/23] hw/intc/arm_gicv3: Don't signal Pending+Active interrupts to CPU Peter Maydell
2016-12-13 10:36 ` [Qemu-devel] [PATCH 04/23] hw/arm/virt: add 2.9 machine type Peter Maydell
2016-12-13 10:36 ` [Qemu-devel] [PATCH 05/23] hw/arm/virt: Merge VirtBoardInfo and VirtMachineState Peter Maydell
2016-12-13 10:36 ` [Qemu-devel] [PATCH 06/23] hw/arm/virt: Rename 'vbi' variables to 'vms' Peter Maydell
2016-12-20 15:46   ` Andrew Jones
2016-12-13 10:36 ` [Qemu-devel] [PATCH 07/23] hw/arm/virt: Don't incorrectly claim architectural timer to be edge-triggered Peter Maydell
2016-12-13 10:36 ` [Qemu-devel] [PATCH 08/23] hw/intc/arm_gicv3: Add external IRQ lines for VIRQ and VFIQ Peter Maydell
2016-12-13 10:36 ` [Qemu-devel] [PATCH 09/23] hw/intc/arm_gic: " Peter Maydell
2016-12-19 21:54   ` Alistair Francis
2016-12-13 10:36 ` [Qemu-devel] [PATCH 10/23] target-arm: Expose output GPIO line for VCPU maintenance interrupt Peter Maydell
2016-12-13 12:37   ` Edgar E. Iglesias
2016-12-13 10:36 ` [Qemu-devel] [PATCH 11/23] hw/arm/virt: Wire VIRQ, VFIQ, maintenance irq lines from GIC to CPU Peter Maydell
2016-12-13 10:36 ` [Qemu-devel] [PATCH 12/23] target-arm: Add ARMCPU fields for GIC CPU i/f config Peter Maydell
2016-12-13 10:36 ` [Qemu-devel] [PATCH 13/23] hw/intc/gicv3: Add defines for ICH system register fields Peter Maydell
2016-12-13 10:36 ` [Qemu-devel] [PATCH 14/23] hw/intc/gicv3: Add data fields for virtualization support Peter Maydell
2016-12-13 10:36 ` [Qemu-devel] [PATCH 15/23] hw/intc/arm_gicv3: Add accessors for ICH_ system registers Peter Maydell
2016-12-13 10:36 ` [Qemu-devel] [PATCH 16/23] hw/intc/arm_gicv3: Implement ICV_ registers which are just accessors Peter Maydell
2016-12-13 10:36 ` [Qemu-devel] [PATCH 17/23] hw/intc/arm_gicv3: Implement ICV_ HPPIR, DIR and RPR registers Peter Maydell
2016-12-13 10:36 ` [Qemu-devel] [PATCH 18/23] hw/intc/arm_gicv3: Implement ICV_ registers EOIR and IAR Peter Maydell
2016-12-13 10:36 ` [Qemu-devel] [PATCH 19/23] hw/intc/arm_gicv3: Implement gicv3_cpuif_virt_update() Peter Maydell
2016-12-13 10:36 ` [Qemu-devel] [PATCH 20/23] hw/intc/arm_gicv3: Implement EL2 traps for CPU i/f regs Peter Maydell
2016-12-13 10:36 ` [Qemu-devel] [PATCH 21/23] hw/arm/virt: Support using SMC for PSCI Peter Maydell
2016-12-13 12:36   ` Edgar E. Iglesias
2016-12-28 13:14   ` Andrew Jones
2016-12-13 10:36 ` [Qemu-devel] [PATCH 22/23] target-arm: Enable EL2 feature bit on A53 and A57 Peter Maydell
2016-12-13 16:11   ` Edgar E. Iglesias
2016-12-19 22:04     ` Alistair Francis
2016-12-20 13:32       ` Peter Maydell
2016-12-20 17:46         ` Alistair Francis
2016-12-28 13:14   ` Andrew Jones
2016-12-13 10:36 ` [Qemu-devel] [PATCH 23/23] hw/arm/virt: Add board property to enable EL2 Peter Maydell
2016-12-28 13:14   ` Andrew Jones
2017-01-17 22:15     ` Alistair Francis
2016-12-13 21:16 ` [Qemu-devel] [PATCH 00/23] arm: Add virtualization to GICv3, and enable EL2 on 64-bit CPUs Andrew Jones
2016-12-14 10:18   ` Peter Maydell
2017-01-09 15:08   ` Peter Maydell
2016-12-16 21:42 ` Andrew Jones
2016-12-19 22:20 ` Alistair Francis
2017-01-09 15:57   ` 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.