qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v4 00/10] target-arm: Parts of the AArch64 EL2/3 exception model
@ 2014-08-05  8:49 Edgar E. Iglesias
  2014-08-05  8:49 ` [Qemu-devel] [PATCH v4 01/10] target-arm: Add HCR_EL2 Edgar E. Iglesias
                   ` (9 more replies)
  0 siblings, 10 replies; 11+ messages in thread
From: Edgar E. Iglesias @ 2014-08-05  8:49 UTC (permalink / raw)
  To: qemu-devel, peter.maydell
  Cc: rob.herring, peter.crosthwaite, aggelerf, agraf, blauwirbel,
	greg.bellows, pbonzini, alex.bennee, christoffer.dall, rth

From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>

Hi,

This is a second round of AArch64 EL2/3 patches working on the exception
model. Among other things adding HVC/SMC, interrupt routing to EL2/3 and
Virtual IRQs/FIQs. The VIRQ/VFIQ support only adds the external signal
delivery method.

Patch 8 fails checkpatch, seems like a bug in checkpatch, CC:d Blue.

This conflicts slightly with the PSCI emulation patches that Rob posted.
A rebase should be trivial, hooking in the PSCI emulation calls in the
HVC/SMC helpers.

Note that part of this series has already been applied, I'm only
posting the remaining patches.

Cheers,
Edgar

v3 -> v4:
* Coding style changes.
* Add access spec for v8_el3_no_el2_cp_reginfo.HCR_EL2.
* Move SCR to the el3 cpreg defs and add NO_MIGRATE to SCR_EL3.
* Correct HCR.HCD and HCR.TSC RES0 behaviour.
* Comment on hcr_write TLB flush.
* Use uint32_t with explicit masking for imm16 in syndrome generator.
* Add table lookup of interrupt masks in arm_cpu_set_irq.
* Move M profile irq handling comment from cpu-exec.c to cpu.h.
* Correct trap address for disabled HVC/SMD and for SMC routed to EL2.

v2 -> v3:
* Add more HCR bitfield macros
* Flush TLB on hcr_write change of HCR RW, DC and PTW.
* Fix hvc helper, HVC is undefined in secure mode.
* Remove uint16_t imm16 syndrome gen change.
* Replace c1_scr with scr_el3

v1 -> v2:
* Avoid imm16 mask in syndrome generation
* Use g_assert_not_reached() in arm_excp_unmasked()
* Avoid some logic duplication in arm_excp_target_el and arm_excp_unmasked.
* Put arm_excp_target_el in helper.c to start with.
* Fix SMC disable (SMD or SCD) for ARMv7 only applies if EL2 exists
* SCR_RES0_MASK -> SCR_MASK
* HCR_RES0_MASK -> HCR_MASK
* Fix SMC routing to EL2, only applies for NS EL1.
* Fix CPreg defs for ESR_EL2/3
* Fix SMC helper, SMC routing to EL2 and SCR.SMD for AArch32.

Edgar E. Iglesias (10):
  target-arm: Add HCR_EL2
  target-arm: Add SCR_EL3
  target-arm: A64: Refactor aarch64_cpu_do_interrupt
  target-arm: Break out exception masking to a separate func
  target-arm: Don't take interrupts targeting lower ELs
  target-arm: A64: Correct updates to FAR and ESR on exceptions
  target-arm: A64: Emulate the HVC insn
  target-arm: A64: Emulate the SMC insn
  target-arm: Add IRQ and FIQ routing to EL2 and 3
  target-arm: Add support for VIRQ and VFIQ

 cpu-exec.c                 |  17 +++++-
 target-arm/cpu.c           |  25 +++++----
 target-arm/cpu.h           | 127 ++++++++++++++++++++++++++++++++++++++++++-
 target-arm/helper-a64.c    |  31 ++++++-----
 target-arm/helper.c        | 133 ++++++++++++++++++++++++++++++++++++++++++++-
 target-arm/helper.h        |   2 +
 target-arm/internals.h     |  14 +++++
 target-arm/op_helper.c     |  66 ++++++++++++++++++++++
 target-arm/translate-a64.c |  31 +++++++++--
 9 files changed, 410 insertions(+), 36 deletions(-)

-- 
1.9.1

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

* [Qemu-devel] [PATCH v4 01/10] target-arm: Add HCR_EL2
  2014-08-05  8:49 [Qemu-devel] [PATCH v4 00/10] target-arm: Parts of the AArch64 EL2/3 exception model Edgar E. Iglesias
@ 2014-08-05  8:49 ` Edgar E. Iglesias
  2014-08-05  8:49 ` [Qemu-devel] [PATCH v4 02/10] target-arm: Add SCR_EL3 Edgar E. Iglesias
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Edgar E. Iglesias @ 2014-08-05  8:49 UTC (permalink / raw)
  To: qemu-devel, peter.maydell
  Cc: rob.herring, peter.crosthwaite, aggelerf, agraf, blauwirbel,
	greg.bellows, pbonzini, alex.bennee, christoffer.dall, rth

From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>

Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
---
 target-arm/cpu.h    | 36 ++++++++++++++++++++++++++++++++++++
 target-arm/helper.c | 34 ++++++++++++++++++++++++++++++++++
 2 files changed, 70 insertions(+)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 79205ba..8859b94 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -184,6 +184,7 @@ typedef struct CPUARMState {
                         MPU write buffer control.  */
         uint32_t pmsav5_data_ap; /* PMSAv5 MPU data access permissions */
         uint32_t pmsav5_insn_ap; /* PMSAv5 MPU insn access permissions */
+        uint64_t hcr_el2; /* Hypervisor configuration register */
         uint32_t ifsr_el2; /* Fault status registers.  */
         uint64_t esr_el[4];
         uint32_t c6_region[8]; /* MPU base/size registers.  */
@@ -542,6 +543,41 @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
     }
 }
 
+#define HCR_VM        (1ULL << 0)
+#define HCR_SWIO      (1ULL << 1)
+#define HCR_PTW       (1ULL << 2)
+#define HCR_FMO       (1ULL << 3)
+#define HCR_IMO       (1ULL << 4)
+#define HCR_AMO       (1ULL << 5)
+#define HCR_VF        (1ULL << 6)
+#define HCR_VI        (1ULL << 7)
+#define HCR_VSE       (1ULL << 8)
+#define HCR_FB        (1ULL << 9)
+#define HCR_BSU_MASK  (3ULL << 10)
+#define HCR_DC        (1ULL << 12)
+#define HCR_TWI       (1ULL << 13)
+#define HCR_TWE       (1ULL << 14)
+#define HCR_TID0      (1ULL << 15)
+#define HCR_TID1      (1ULL << 16)
+#define HCR_TID2      (1ULL << 17)
+#define HCR_TID3      (1ULL << 18)
+#define HCR_TSC       (1ULL << 19)
+#define HCR_TIDCP     (1ULL << 20)
+#define HCR_TACR      (1ULL << 21)
+#define HCR_TSW       (1ULL << 22)
+#define HCR_TPC       (1ULL << 23)
+#define HCR_TPU       (1ULL << 24)
+#define HCR_TTLB      (1ULL << 25)
+#define HCR_TVM       (1ULL << 26)
+#define HCR_TGE       (1ULL << 27)
+#define HCR_TDZ       (1ULL << 28)
+#define HCR_HCD       (1ULL << 29)
+#define HCR_TRVM      (1ULL << 30)
+#define HCR_RW        (1ULL << 31)
+#define HCR_CD        (1ULL << 32)
+#define HCR_ID        (1ULL << 33)
+#define HCR_MASK      ((1ULL << 34) - 1)
+
 /* Return the current FPSCR value.  */
 uint32_t vfp_get_fpscr(CPUARMState *env);
 void vfp_set_fpscr(CPUARMState *env, uint32_t val);
diff --git a/target-arm/helper.c b/target-arm/helper.c
index f630d96..1021812 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -2124,10 +2124,44 @@ static const ARMCPRegInfo v8_el3_no_el2_cp_reginfo[] = {
       .opc0 = 3, .opc1 = 4, .crn = 12, .crm = 0, .opc2 = 0,
       .access = PL2_RW,
       .readfn = arm_cp_read_zero, .writefn = arm_cp_write_ignore },
+    { .name = "HCR_EL2", .state = ARM_CP_STATE_AA64,
+      .type = ARM_CP_NO_MIGRATE,
+      .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 0,
+      .access = PL2_RW,
+      .readfn = arm_cp_read_zero, .writefn = arm_cp_write_ignore },
     REGINFO_SENTINEL
 };
 
+static void hcr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
+{
+    ARMCPU *cpu = arm_env_get_cpu(env);
+    uint64_t valid_mask = HCR_MASK;
+
+    if (arm_feature(env, ARM_FEATURE_EL3)) {
+        valid_mask &= ~HCR_HCD;
+    } else {
+        valid_mask &= ~HCR_TSC;
+    }
+
+    /* Clear RES0 bits.  */
+    value &= valid_mask;
+
+    /* These bits change the MMU setup:
+     * HCR_VM enables stage 2 translation
+     * HCR_PTW forbids certain page-table setups
+     * HCR_DC Disables stage1 and enables stage2 translation
+     */
+    if ((raw_read(env, ri) ^ value) & (HCR_VM | HCR_PTW | HCR_DC)) {
+        tlb_flush(CPU(cpu), 1);
+    }
+    raw_write(env, ri, value);
+}
+
 static const ARMCPRegInfo v8_el2_cp_reginfo[] = {
+    { .name = "HCR_EL2", .state = ARM_CP_STATE_AA64,
+      .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 0,
+      .access = PL2_RW, .fieldoffset = offsetof(CPUARMState, cp15.hcr_el2),
+      .writefn = hcr_write },
     { .name = "ELR_EL2", .state = ARM_CP_STATE_AA64,
       .type = ARM_CP_NO_MIGRATE,
       .opc0 = 3, .opc1 = 4, .crn = 4, .crm = 0, .opc2 = 1,
-- 
1.9.1

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

* [Qemu-devel] [PATCH v4 02/10] target-arm: Add SCR_EL3
  2014-08-05  8:49 [Qemu-devel] [PATCH v4 00/10] target-arm: Parts of the AArch64 EL2/3 exception model Edgar E. Iglesias
  2014-08-05  8:49 ` [Qemu-devel] [PATCH v4 01/10] target-arm: Add HCR_EL2 Edgar E. Iglesias
@ 2014-08-05  8:49 ` Edgar E. Iglesias
  2014-08-05  8:49 ` [Qemu-devel] [PATCH v4 03/10] target-arm: A64: Refactor aarch64_cpu_do_interrupt Edgar E. Iglesias
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Edgar E. Iglesias @ 2014-08-05  8:49 UTC (permalink / raw)
  To: qemu-devel, peter.maydell
  Cc: rob.herring, peter.crosthwaite, aggelerf, agraf, blauwirbel,
	greg.bellows, pbonzini, alex.bennee, christoffer.dall, rth

From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>

Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
---
 target-arm/cpu.h    | 16 +++++++++++++++-
 target-arm/helper.c | 36 +++++++++++++++++++++++++++++++++---
 2 files changed, 48 insertions(+), 4 deletions(-)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 8859b94..579570b 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -172,7 +172,6 @@ typedef struct CPUARMState {
         uint64_t c1_sys; /* System control register.  */
         uint64_t c1_coproc; /* Coprocessor access register.  */
         uint32_t c1_xscaleauxcr; /* XScale auxiliary control register.  */
-        uint32_t c1_scr; /* secure config register.  */
         uint64_t ttbr0_el1; /* MMU translation table base 0. */
         uint64_t ttbr1_el1; /* MMU translation table base 1. */
         uint64_t c2_control; /* MMU translation table base control.  */
@@ -185,6 +184,7 @@ typedef struct CPUARMState {
         uint32_t pmsav5_data_ap; /* PMSAv5 MPU data access permissions */
         uint32_t pmsav5_insn_ap; /* PMSAv5 MPU insn access permissions */
         uint64_t hcr_el2; /* Hypervisor configuration register */
+        uint32_t scr_el3; /* Secure configuration register.  */
         uint32_t ifsr_el2; /* Fault status registers.  */
         uint64_t esr_el[4];
         uint32_t c6_region[8]; /* MPU base/size registers.  */
@@ -578,6 +578,20 @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
 #define HCR_ID        (1ULL << 33)
 #define HCR_MASK      ((1ULL << 34) - 1)
 
+#define SCR_NS        (1U << 0)
+#define SCR_IRQ       (1U << 1)
+#define SCR_FIQ       (1U << 2)
+#define SCR_EA        (1U << 3)
+#define SCR_SMD       (1U << 7)
+#define SCR_HCE       (1U << 8)
+#define SCR_SIF       (1U << 9)
+#define SCR_RW        (1U << 10)
+#define SCR_ST        (1U << 11)
+#define SCR_TWI       (1U << 12)
+#define SCR_TWE       (1U << 13)
+#define SCR_RES1_MASK (3U << 4)
+#define SCR_MASK      (0x3fff & ~SCR_RES1_MASK)
+
 /* Return the current FPSCR value.  */
 uint32_t vfp_get_fpscr(CPUARMState *env);
 void vfp_set_fpscr(CPUARMState *env, uint32_t val);
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 1021812..a767380 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -792,9 +792,6 @@ static const ARMCPRegInfo v7_cp_reginfo[] = {
       .access = PL1_RW, .writefn = vbar_write,
       .fieldoffset = offsetof(CPUARMState, cp15.vbar_el[1]),
       .resetvalue = 0 },
-    { .name = "SCR", .cp = 15, .crn = 1, .crm = 1, .opc1 = 0, .opc2 = 0,
-      .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.c1_scr),
-      .resetvalue = 0, },
     { .name = "CCSIDR", .state = ARM_CP_STATE_BOTH,
       .opc0 = 3, .crn = 0, .crm = 0, .opc1 = 1, .opc2 = 0,
       .access = PL1_R, .readfn = ccsidr_read, .type = ARM_CP_NO_MIGRATE },
@@ -2186,6 +2183,31 @@ static const ARMCPRegInfo v8_el2_cp_reginfo[] = {
     REGINFO_SENTINEL
 };
 
+static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
+{
+    uint32_t valid_mask = SCR_MASK;
+
+    if (!arm_feature(env, ARM_FEATURE_EL2)) {
+        valid_mask &= ~SCR_HCE;
+
+        /* On ARMv7, SMD (or SCD as it is called in v7) is only
+         * supported if EL2 exists. The bit is UNK/SBZP when
+         * EL2 is unavailable. In QEMU ARMv7, we force it to always zero
+         * when EL2 is unavailable.
+         */
+        if (arm_feature(env, ARM_FEATURE_V7)) {
+            valid_mask &= ~SCR_SMD;
+        }
+    }
+
+    /* Set RES1 bits.  */
+    value |= SCR_RES1_MASK;
+
+    /* Clear RES0 bits.  */
+    value &= valid_mask;
+    raw_write(env, ri, value);
+}
+
 static const ARMCPRegInfo v8_el3_cp_reginfo[] = {
     { .name = "ELR_EL3", .state = ARM_CP_STATE_AA64,
       .type = ARM_CP_NO_MIGRATE,
@@ -2208,6 +2230,14 @@ static const ARMCPRegInfo v8_el3_cp_reginfo[] = {
       .access = PL3_RW, .writefn = vbar_write,
       .fieldoffset = offsetof(CPUARMState, cp15.vbar_el[3]),
       .resetvalue = 0 },
+    { .name = "SCR", .cp = 15, .crn = 1, .crm = 1, .opc1 = 0, .opc2 = 0,
+      .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.scr_el3),
+      .resetvalue = 0, },
+    { .name = "SCR_EL3", .state = ARM_CP_STATE_AA64,
+      .type = ARM_CP_NO_MIGRATE,
+      .opc0 = 3, .opc1 = 6, .crn = 1, .crm = 1, .opc2 = 0,
+      .access = PL3_RW, .fieldoffset = offsetof(CPUARMState, cp15.scr_el3),
+      .writefn = scr_write },
     REGINFO_SENTINEL
 };
 
-- 
1.9.1

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

* [Qemu-devel] [PATCH v4 03/10] target-arm: A64: Refactor aarch64_cpu_do_interrupt
  2014-08-05  8:49 [Qemu-devel] [PATCH v4 00/10] target-arm: Parts of the AArch64 EL2/3 exception model Edgar E. Iglesias
  2014-08-05  8:49 ` [Qemu-devel] [PATCH v4 01/10] target-arm: Add HCR_EL2 Edgar E. Iglesias
  2014-08-05  8:49 ` [Qemu-devel] [PATCH v4 02/10] target-arm: Add SCR_EL3 Edgar E. Iglesias
@ 2014-08-05  8:49 ` Edgar E. Iglesias
  2014-08-05  8:49 ` [Qemu-devel] [PATCH v4 04/10] target-arm: Break out exception masking to a separate func Edgar E. Iglesias
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Edgar E. Iglesias @ 2014-08-05  8:49 UTC (permalink / raw)
  To: qemu-devel, peter.maydell
  Cc: rob.herring, peter.crosthwaite, aggelerf, agraf, blauwirbel,
	greg.bellows, pbonzini, alex.bennee, christoffer.dall, rth

From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>

Introduce new_el and new_mode in preparation for future patches
that add support for taking exceptions to and from EL2 and 3.
No functional change.

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
---
 target-arm/cpu.h        |  7 +++++++
 target-arm/helper-a64.c | 24 +++++++++++++-----------
 target-arm/helper.c     | 13 +++++++++++++
 3 files changed, 33 insertions(+), 11 deletions(-)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 579570b..2fff2e7 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -476,6 +476,12 @@ int arm_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int rw,
 #define PSTATE_MODE_EL1t 4
 #define PSTATE_MODE_EL0t 0
 
+/* Map EL and handler into a PSTATE_MODE.  */
+static inline unsigned int aarch64_pstate_mode(unsigned int el, bool handler)
+{
+    return (el << 2) | handler;
+}
+
 /* Return the current PSTATE value. For the moment we don't support 32<->64 bit
  * interprocessing, so we don't attempt to sync with the cpsr state used by
  * the 32 bit decoder.
@@ -728,6 +734,7 @@ static inline bool arm_el_is_aa64(CPUARMState *env, int el)
 }
 
 void arm_cpu_list(FILE *f, fprintf_function cpu_fprintf);
+unsigned int arm_excp_target_el(CPUState *cs, unsigned int excp_idx);
 
 /* Interface between CPU and Interrupt controller.  */
 void armv7m_nvic_set_pending(void *opaque, int irq);
diff --git a/target-arm/helper-a64.c b/target-arm/helper-a64.c
index 2e9ef64..4be0784 100644
--- a/target-arm/helper-a64.c
+++ b/target-arm/helper-a64.c
@@ -443,10 +443,12 @@ void aarch64_cpu_do_interrupt(CPUState *cs)
 {
     ARMCPU *cpu = ARM_CPU(cs);
     CPUARMState *env = &cpu->env;
-    target_ulong addr = env->cp15.vbar_el[1];
+    unsigned int new_el = arm_excp_target_el(cs, cs->exception_index);
+    target_ulong addr = env->cp15.vbar_el[new_el];
+    unsigned int new_mode = aarch64_pstate_mode(new_el, true);
     int i;
 
-    if (arm_current_pl(env) == 0) {
+    if (arm_current_pl(env) < new_el) {
         if (env->aarch64) {
             addr += 0x400;
         } else {
@@ -464,14 +466,14 @@ void aarch64_cpu_do_interrupt(CPUState *cs)
                       env->exception.syndrome);
     }
 
-    env->cp15.esr_el[1] = env->exception.syndrome;
-    env->cp15.far_el[1] = env->exception.vaddress;
+    env->cp15.esr_el[new_el] = env->exception.syndrome;
+    env->cp15.far_el[new_el] = env->exception.vaddress;
 
     switch (cs->exception_index) {
     case EXCP_PREFETCH_ABORT:
     case EXCP_DATA_ABORT:
         qemu_log_mask(CPU_LOG_INT, "...with FAR 0x%" PRIx64 "\n",
-                      env->cp15.far_el[1]);
+                      env->cp15.far_el[new_el]);
         break;
     case EXCP_BKPT:
     case EXCP_UDEF:
@@ -488,15 +490,15 @@ void aarch64_cpu_do_interrupt(CPUState *cs)
     }
 
     if (is_a64(env)) {
-        env->banked_spsr[aarch64_banked_spsr_index(1)] = pstate_read(env);
+        env->banked_spsr[aarch64_banked_spsr_index(new_el)] = pstate_read(env);
         aarch64_save_sp(env, arm_current_pl(env));
-        env->elr_el[1] = env->pc;
+        env->elr_el[new_el] = env->pc;
     } else {
         env->banked_spsr[0] = cpsr_read(env);
         if (!env->thumb) {
-            env->cp15.esr_el[1] |= 1 << 25;
+            env->cp15.esr_el[new_el] |= 1 << 25;
         }
-        env->elr_el[1] = env->regs[15];
+        env->elr_el[new_el] = env->regs[15];
 
         for (i = 0; i < 15; i++) {
             env->xregs[i] = env->regs[i];
@@ -505,9 +507,9 @@ void aarch64_cpu_do_interrupt(CPUState *cs)
         env->condexec_bits = 0;
     }
 
-    pstate_write(env, PSTATE_DAIF | PSTATE_MODE_EL1h);
+    pstate_write(env, PSTATE_DAIF | new_mode);
     env->aarch64 = 1;
-    aarch64_restore_sp(env, 1);
+    aarch64_restore_sp(env, new_el);
 
     env->pc = addr;
     cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
diff --git a/target-arm/helper.c b/target-arm/helper.c
index a767380..5bbcb3e 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -3242,6 +3242,11 @@ uint32_t HELPER(get_r13_banked)(CPUARMState *env, uint32_t mode)
     return 0;
 }
 
+unsigned int arm_excp_target_el(CPUState *cs, unsigned int excp_idx)
+{
+    return 1;
+}
+
 #else
 
 /* Map CPU modes onto saved register banks.  */
@@ -3297,6 +3302,14 @@ void switch_mode(CPUARMState *env, int mode)
     env->spsr = env->banked_spsr[i];
 }
 
+/*
+ * Determine the target EL for a given exception type.
+ */
+unsigned int arm_excp_target_el(CPUState *cs, unsigned int excp_idx)
+{
+    return 1;
+}
+
 static void v7m_push(CPUARMState *env, uint32_t val)
 {
     CPUState *cs = CPU(arm_env_get_cpu(env));
-- 
1.9.1

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

* [Qemu-devel] [PATCH v4 04/10] target-arm: Break out exception masking to a separate func
  2014-08-05  8:49 [Qemu-devel] [PATCH v4 00/10] target-arm: Parts of the AArch64 EL2/3 exception model Edgar E. Iglesias
                   ` (2 preceding siblings ...)
  2014-08-05  8:49 ` [Qemu-devel] [PATCH v4 03/10] target-arm: A64: Refactor aarch64_cpu_do_interrupt Edgar E. Iglesias
@ 2014-08-05  8:49 ` Edgar E. Iglesias
  2014-08-05  8:49 ` [Qemu-devel] [PATCH v4 05/10] target-arm: Don't take interrupts targeting lower ELs Edgar E. Iglesias
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Edgar E. Iglesias @ 2014-08-05  8:49 UTC (permalink / raw)
  To: qemu-devel, peter.maydell
  Cc: rob.herring, peter.crosthwaite, aggelerf, agraf, blauwirbel,
	greg.bellows, pbonzini, alex.bennee, christoffer.dall, rth

From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>

Reviewed-by: Greg Bellows <greg.bellows@linaro.org>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
---
 cpu-exec.c       |  5 ++---
 target-arm/cpu.h | 15 +++++++++++++++
 2 files changed, 17 insertions(+), 3 deletions(-)

diff --git a/cpu-exec.c b/cpu-exec.c
index 38e5f02..a579ffc 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -478,7 +478,7 @@ int cpu_exec(CPUArchState *env)
                     }
 #elif defined(TARGET_ARM)
                     if (interrupt_request & CPU_INTERRUPT_FIQ
-                        && !(env->daif & PSTATE_F)) {
+                        && arm_excp_unmasked(cpu, EXCP_FIQ)) {
                         cpu->exception_index = EXCP_FIQ;
                         cc->do_interrupt(cpu);
                         next_tb = 0;
@@ -493,8 +493,7 @@ int cpu_exec(CPUArchState *env)
                        We avoid this by disabling interrupts when
                        pc contains a magic address.  */
                     if (interrupt_request & CPU_INTERRUPT_HARD
-                        && ((IS_M(env) && env->regs[15] < 0xfffffff0)
-                            || !(env->daif & PSTATE_I))) {
+                        && arm_excp_unmasked(cpu, EXCP_IRQ)) {
                         cpu->exception_index = EXCP_IRQ;
                         cc->do_interrupt(cpu);
                         next_tb = 0;
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 2fff2e7..63fdcbf 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -1145,6 +1145,21 @@ bool write_cpustate_to_list(ARMCPU *cpu);
 #  define TARGET_VIRT_ADDR_SPACE_BITS 32
 #endif
 
+static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx)
+{
+    CPUARMState *env = cs->env_ptr;
+
+    switch (excp_idx) {
+    case EXCP_FIQ:
+        return !(env->daif & PSTATE_F);
+    case EXCP_IRQ:
+        return ((IS_M(env) && env->regs[15] < 0xfffffff0)
+                            || !(env->daif & PSTATE_I));
+    default:
+        g_assert_not_reached();
+    }
+}
+
 static inline CPUARMState *cpu_init(const char *cpu_model)
 {
     ARMCPU *cpu = cpu_arm_init(cpu_model);
-- 
1.9.1

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

* [Qemu-devel] [PATCH v4 05/10] target-arm: Don't take interrupts targeting lower ELs
  2014-08-05  8:49 [Qemu-devel] [PATCH v4 00/10] target-arm: Parts of the AArch64 EL2/3 exception model Edgar E. Iglesias
                   ` (3 preceding siblings ...)
  2014-08-05  8:49 ` [Qemu-devel] [PATCH v4 04/10] target-arm: Break out exception masking to a separate func Edgar E. Iglesias
@ 2014-08-05  8:49 ` Edgar E. Iglesias
  2014-08-05  8:50 ` [Qemu-devel] [PATCH v4 06/10] target-arm: A64: Correct updates to FAR and ESR on exceptions Edgar E. Iglesias
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Edgar E. Iglesias @ 2014-08-05  8:49 UTC (permalink / raw)
  To: qemu-devel, peter.maydell
  Cc: rob.herring, peter.crosthwaite, aggelerf, agraf, blauwirbel,
	greg.bellows, pbonzini, alex.bennee, christoffer.dall, rth

From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Greg Bellows <greg.bellows@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
---
 target-arm/cpu.h | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 63fdcbf..5a62032 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -1148,6 +1148,13 @@ bool write_cpustate_to_list(ARMCPU *cpu);
 static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx)
 {
     CPUARMState *env = cs->env_ptr;
+    unsigned int cur_el = arm_current_pl(env);
+    unsigned int target_el = arm_excp_target_el(cs, excp_idx);
+
+    /* Don't take exceptions if they target a lower EL.  */
+    if (cur_el > target_el) {
+        return false;
+    }
 
     switch (excp_idx) {
     case EXCP_FIQ:
-- 
1.9.1

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

* [Qemu-devel] [PATCH v4 06/10] target-arm: A64: Correct updates to FAR and ESR on exceptions
  2014-08-05  8:49 [Qemu-devel] [PATCH v4 00/10] target-arm: Parts of the AArch64 EL2/3 exception model Edgar E. Iglesias
                   ` (4 preceding siblings ...)
  2014-08-05  8:49 ` [Qemu-devel] [PATCH v4 05/10] target-arm: Don't take interrupts targeting lower ELs Edgar E. Iglesias
@ 2014-08-05  8:50 ` Edgar E. Iglesias
  2014-08-05  8:50 ` [Qemu-devel] [PATCH v4 07/10] target-arm: A64: Emulate the HVC insn Edgar E. Iglesias
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Edgar E. Iglesias @ 2014-08-05  8:50 UTC (permalink / raw)
  To: qemu-devel, peter.maydell
  Cc: rob.herring, peter.crosthwaite, aggelerf, agraf, blauwirbel,
	greg.bellows, pbonzini, alex.bennee, christoffer.dall, rth

From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>

Not all exception types update both FAR and ESR.

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Greg Bellows <greg.bellows@linaro.org>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
---
 target-arm/helper-a64.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/target-arm/helper-a64.c b/target-arm/helper-a64.c
index 4be0784..c6ef8e9 100644
--- a/target-arm/helper-a64.c
+++ b/target-arm/helper-a64.c
@@ -466,18 +466,17 @@ void aarch64_cpu_do_interrupt(CPUState *cs)
                       env->exception.syndrome);
     }
 
-    env->cp15.esr_el[new_el] = env->exception.syndrome;
-    env->cp15.far_el[new_el] = env->exception.vaddress;
-
     switch (cs->exception_index) {
     case EXCP_PREFETCH_ABORT:
     case EXCP_DATA_ABORT:
+        env->cp15.far_el[new_el] = env->exception.vaddress;
         qemu_log_mask(CPU_LOG_INT, "...with FAR 0x%" PRIx64 "\n",
                       env->cp15.far_el[new_el]);
-        break;
+        /* fall through */
     case EXCP_BKPT:
     case EXCP_UDEF:
     case EXCP_SWI:
+        env->cp15.esr_el[new_el] = env->exception.syndrome;
         break;
     case EXCP_IRQ:
         addr += 0x80;
-- 
1.9.1

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

* [Qemu-devel] [PATCH v4 07/10] target-arm: A64: Emulate the HVC insn
  2014-08-05  8:49 [Qemu-devel] [PATCH v4 00/10] target-arm: Parts of the AArch64 EL2/3 exception model Edgar E. Iglesias
                   ` (5 preceding siblings ...)
  2014-08-05  8:50 ` [Qemu-devel] [PATCH v4 06/10] target-arm: A64: Correct updates to FAR and ESR on exceptions Edgar E. Iglesias
@ 2014-08-05  8:50 ` Edgar E. Iglesias
  2014-08-05  8:50 ` [Qemu-devel] [PATCH v4 08/10] target-arm: A64: Emulate the SMC insn Edgar E. Iglesias
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Edgar E. Iglesias @ 2014-08-05  8:50 UTC (permalink / raw)
  To: qemu-devel, peter.maydell
  Cc: rob.herring, peter.crosthwaite, aggelerf, agraf, blauwirbel,
	greg.bellows, pbonzini, alex.bennee, christoffer.dall, rth

From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>

Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
---
 target-arm/cpu.h           |  1 +
 target-arm/helper-a64.c    |  1 +
 target-arm/helper.c        | 28 +++++++++++++++++++++++++++-
 target-arm/helper.h        |  1 +
 target-arm/internals.h     |  6 ++++++
 target-arm/op_helper.c     | 35 +++++++++++++++++++++++++++++++++++
 target-arm/translate-a64.c | 21 ++++++++++++++++-----
 7 files changed, 87 insertions(+), 6 deletions(-)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 5a62032..7fd2f5a 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -51,6 +51,7 @@
 #define EXCP_EXCEPTION_EXIT  8   /* Return from v7M exception.  */
 #define EXCP_KERNEL_TRAP     9   /* Jumped to kernel code page.  */
 #define EXCP_STREX          10
+#define EXCP_HVC            11   /* HyperVisor Call */
 
 #define ARMV7M_EXCP_RESET   1
 #define ARMV7M_EXCP_NMI     2
diff --git a/target-arm/helper-a64.c b/target-arm/helper-a64.c
index c6ef8e9..4e6ca26 100644
--- a/target-arm/helper-a64.c
+++ b/target-arm/helper-a64.c
@@ -476,6 +476,7 @@ void aarch64_cpu_do_interrupt(CPUState *cs)
     case EXCP_BKPT:
     case EXCP_UDEF:
     case EXCP_SWI:
+    case EXCP_HVC:
         env->cp15.esr_el[new_el] = env->exception.syndrome;
         break;
     case EXCP_IRQ:
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 5bbcb3e..a57a919 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -3307,7 +3307,33 @@ void switch_mode(CPUARMState *env, int mode)
  */
 unsigned int arm_excp_target_el(CPUState *cs, unsigned int excp_idx)
 {
-    return 1;
+    CPUARMState *env = cs->env_ptr;
+    unsigned int cur_el = arm_current_pl(env);
+    unsigned int target_el = 1;
+    bool route_to_el2 = false;
+    /* FIXME: Use actual secure state.  */
+    bool secure = false;
+
+    if (!env->aarch64) {
+        /* TODO: Add EL2 and 3 exception handling for AArch32.  */
+        return 1;
+    }
+
+    if (!secure
+        && arm_feature(env, ARM_FEATURE_EL2)
+        && cur_el < 2
+        && (env->cp15.hcr_el2 & HCR_TGE)) {
+        route_to_el2 = true;
+    }
+
+    target_el = MAX(cur_el, route_to_el2 ? 2 : 1);
+
+    switch (excp_idx) {
+    case EXCP_HVC:
+        target_el = MAX(target_el, 2);
+        break;
+    }
+    return target_el;
 }
 
 static void v7m_push(CPUARMState *env, uint32_t val)
diff --git a/target-arm/helper.h b/target-arm/helper.h
index facfcd2..70cfd28 100644
--- a/target-arm/helper.h
+++ b/target-arm/helper.h
@@ -50,6 +50,7 @@ DEF_HELPER_2(exception_internal, void, env, i32)
 DEF_HELPER_3(exception_with_syndrome, void, env, i32, i32)
 DEF_HELPER_1(wfi, void, env)
 DEF_HELPER_1(wfe, void, env)
+DEF_HELPER_2(hvc, void, env, i32)
 
 DEF_HELPER_3(cpsr_write, void, env, i32, i32)
 DEF_HELPER_1(cpsr_read, i32, env)
diff --git a/target-arm/internals.h b/target-arm/internals.h
index 08fa697..b08381c 100644
--- a/target-arm/internals.h
+++ b/target-arm/internals.h
@@ -53,6 +53,7 @@ static const char * const excnames[] = {
     [EXCP_EXCEPTION_EXIT] = "QEMU v7M exception exit",
     [EXCP_KERNEL_TRAP] = "QEMU intercept of kernel commpage",
     [EXCP_STREX] = "QEMU intercept of STREX",
+    [EXCP_HVC] = "Hypervisor Call",
 };
 
 static inline void arm_log_exception(int idx)
@@ -204,6 +205,11 @@ static inline uint32_t syn_aa64_svc(uint32_t imm16)
     return (EC_AA64_SVC << ARM_EL_EC_SHIFT) | ARM_EL_IL | (imm16 & 0xffff);
 }
 
+static inline uint32_t syn_aa64_hvc(uint32_t imm16)
+{
+    return (EC_AA64_HVC << ARM_EL_EC_SHIFT) | ARM_EL_IL | (imm16 & 0xffff);
+}
+
 static inline uint32_t syn_aa32_svc(uint32_t imm16, bool is_thumb)
 {
     return (EC_AA32_SVC << ARM_EL_EC_SHIFT) | (imm16 & 0xffff)
diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
index 25ad902..d08c6a7 100644
--- a/target-arm/op_helper.c
+++ b/target-arm/op_helper.c
@@ -369,6 +369,41 @@ void HELPER(msr_i_pstate)(CPUARMState *env, uint32_t op, uint32_t imm)
     }
 }
 
+void HELPER(hvc)(CPUARMState *env, uint32_t syndrome)
+{
+    int cur_el = arm_current_pl(env);
+    /* FIXME: Use actual secure state.  */
+    bool secure = false;
+    bool udef;
+
+    /* We've already checked that EL2 exists at translation time.
+     * EL3.HCE has priority over EL2.HCD.
+     */
+    if (arm_feature(env, ARM_FEATURE_EL3)) {
+        udef = !(env->cp15.scr_el3 & SCR_HCE);
+    } else {
+        udef = env->cp15.hcr_el2 & HCR_HCD;
+    }
+
+    /* In ARMv7 and ARMv8/AArch32, HVC is udef in secure state.
+     * For ARMv8/AArch64, HVC is allowed in EL3.
+     * Note that we've already trapped HVC from EL0 at translation
+     * time.
+     */
+    if (secure && (!is_a64(env) || cur_el == 1)) {
+        udef = true;
+    }
+
+    if (udef) {
+        /* UDEFs trap on the HVC, roll back to the PC to the HVC insn.  */
+        env->pc -= 4;
+        env->exception.syndrome = syn_uncategorized();
+        raise_exception(env, EXCP_UDEF);
+    }
+    env->exception.syndrome = syndrome;
+    raise_exception(env, EXCP_HVC);
+}
+
 void HELPER(exception_return)(CPUARMState *env)
 {
     int cur_el = arm_current_pl(env);
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index 33b5025..9867d14 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -1436,17 +1436,28 @@ static void disas_exc(DisasContext *s, uint32_t insn)
     int opc = extract32(insn, 21, 3);
     int op2_ll = extract32(insn, 0, 5);
     int imm16 = extract32(insn, 5, 16);
+    TCGv_i32 tmp;
 
     switch (opc) {
     case 0:
-        /* SVC, HVC, SMC; since we don't support the Virtualization
-         * or TrustZone extensions these all UNDEF except SVC.
-         */
-        if (op2_ll != 1) {
+        switch (op2_ll) {
+        case 1:
+            gen_exception_insn(s, 0, EXCP_SWI, syn_aa64_svc(imm16));
+            break;
+        case 2:
+            if (!arm_dc_feature(s, ARM_FEATURE_EL2) || s->current_pl == 0) {
+                unallocated_encoding(s);
+                break;
+            }
+            tmp = tcg_const_i32(syn_aa64_hvc(imm16));
+            gen_a64_set_pc_im(s->pc);
+            gen_helper_hvc(cpu_env, tmp);
+            tcg_temp_free_i32(tmp);
+            break;
+        default:
             unallocated_encoding(s);
             break;
         }
-        gen_exception_insn(s, 0, EXCP_SWI, syn_aa64_svc(imm16));
         break;
     case 1:
         if (op2_ll != 0) {
-- 
1.9.1

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

* [Qemu-devel] [PATCH v4 08/10] target-arm: A64: Emulate the SMC insn
  2014-08-05  8:49 [Qemu-devel] [PATCH v4 00/10] target-arm: Parts of the AArch64 EL2/3 exception model Edgar E. Iglesias
                   ` (6 preceding siblings ...)
  2014-08-05  8:50 ` [Qemu-devel] [PATCH v4 07/10] target-arm: A64: Emulate the HVC insn Edgar E. Iglesias
@ 2014-08-05  8:50 ` Edgar E. Iglesias
  2014-08-05  8:50 ` [Qemu-devel] [PATCH v4 09/10] target-arm: Add IRQ and FIQ routing to EL2 and 3 Edgar E. Iglesias
  2014-08-05  8:50 ` [Qemu-devel] [PATCH v4 10/10] target-arm: Add support for VIRQ and VFIQ Edgar E. Iglesias
  9 siblings, 0 replies; 11+ messages in thread
From: Edgar E. Iglesias @ 2014-08-05  8:50 UTC (permalink / raw)
  To: qemu-devel, peter.maydell
  Cc: rob.herring, peter.crosthwaite, aggelerf, agraf, blauwirbel,
	greg.bellows, pbonzini, alex.bennee, christoffer.dall, rth

From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>

Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
---
 target-arm/cpu.h           |  1 +
 target-arm/helper-a64.c    |  1 +
 target-arm/helper.c        |  6 ++++++
 target-arm/helper.h        |  1 +
 target-arm/internals.h     |  6 ++++++
 target-arm/op_helper.c     | 31 +++++++++++++++++++++++++++++++
 target-arm/translate-a64.c | 10 ++++++++++
 7 files changed, 56 insertions(+)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 7fd2f5a..f8e976d 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -52,6 +52,7 @@
 #define EXCP_KERNEL_TRAP     9   /* Jumped to kernel code page.  */
 #define EXCP_STREX          10
 #define EXCP_HVC            11   /* HyperVisor Call */
+#define EXCP_SMC            12   /* Secure Monitor Call */
 
 #define ARMV7M_EXCP_RESET   1
 #define ARMV7M_EXCP_NMI     2
diff --git a/target-arm/helper-a64.c b/target-arm/helper-a64.c
index 4e6ca26..996dfea 100644
--- a/target-arm/helper-a64.c
+++ b/target-arm/helper-a64.c
@@ -477,6 +477,7 @@ void aarch64_cpu_do_interrupt(CPUState *cs)
     case EXCP_UDEF:
     case EXCP_SWI:
     case EXCP_HVC:
+    case EXCP_SMC:
         env->cp15.esr_el[new_el] = env->exception.syndrome;
         break;
     case EXCP_IRQ:
diff --git a/target-arm/helper.c b/target-arm/helper.c
index a57a919..a0a210d 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -3332,6 +3332,12 @@ unsigned int arm_excp_target_el(CPUState *cs, unsigned int excp_idx)
     case EXCP_HVC:
         target_el = MAX(target_el, 2);
         break;
+    case EXCP_SMC:
+        target_el = 3;
+        if (!secure && cur_el == 1 && (env->cp15.hcr_el2 & HCR_TSC)) {
+            target_el = 2;
+        }
+        break;
     }
     return target_el;
 }
diff --git a/target-arm/helper.h b/target-arm/helper.h
index 70cfd28..4293453 100644
--- a/target-arm/helper.h
+++ b/target-arm/helper.h
@@ -51,6 +51,7 @@ DEF_HELPER_3(exception_with_syndrome, void, env, i32, i32)
 DEF_HELPER_1(wfi, void, env)
 DEF_HELPER_1(wfe, void, env)
 DEF_HELPER_2(hvc, void, env, i32)
+DEF_HELPER_2(smc, void, env, i32)
 
 DEF_HELPER_3(cpsr_write, void, env, i32, i32)
 DEF_HELPER_1(cpsr_read, i32, env)
diff --git a/target-arm/internals.h b/target-arm/internals.h
index b08381c..e50a68e 100644
--- a/target-arm/internals.h
+++ b/target-arm/internals.h
@@ -54,6 +54,7 @@ static const char * const excnames[] = {
     [EXCP_KERNEL_TRAP] = "QEMU intercept of kernel commpage",
     [EXCP_STREX] = "QEMU intercept of STREX",
     [EXCP_HVC] = "Hypervisor Call",
+    [EXCP_SMC] = "Secure Monitor Call",
 };
 
 static inline void arm_log_exception(int idx)
@@ -210,6 +211,11 @@ static inline uint32_t syn_aa64_hvc(uint32_t imm16)
     return (EC_AA64_HVC << ARM_EL_EC_SHIFT) | ARM_EL_IL | (imm16 & 0xffff);
 }
 
+static inline uint32_t syn_aa64_smc(uint32_t imm16)
+{
+    return (EC_AA64_SMC << ARM_EL_EC_SHIFT) | ARM_EL_IL | (imm16 & 0xffff);
+}
+
 static inline uint32_t syn_aa32_svc(uint32_t imm16, bool is_thumb)
 {
     return (EC_AA32_SVC << ARM_EL_EC_SHIFT) | (imm16 & 0xffff)
diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
index d08c6a7..afd1dba 100644
--- a/target-arm/op_helper.c
+++ b/target-arm/op_helper.c
@@ -404,6 +404,37 @@ void HELPER(hvc)(CPUARMState *env, uint32_t syndrome)
     raise_exception(env, EXCP_HVC);
 }
 
+void HELPER(smc)(CPUARMState *env, uint32_t syndrome)
+{
+    int cur_el = arm_current_pl(env);
+    /* FIXME: Use real secure state.  */
+    bool secure = false;
+    bool smd = env->cp15.scr_el3 & SCR_SMD;
+    /* On ARMv8 AArch32, SMD only applies to NS mode.
+     * On ARMv7 SMD only applies to NS mode and only if EL2 is available.
+     * For ARMv7 non EL2, we force SMD to zero so we don't need to re-check
+     * the EL2 condition here.
+     */
+    bool udef = is_a64(env) ? smd : !secure && smd;
+
+    /* In NS EL1, HCR controlled routing to EL2 has priority over SMD.  */
+    if (!secure && cur_el == 1 && (env->cp15.hcr_el2 & HCR_TSC)) {
+        /* When routing SMCs to EL2, the trap is taken at the SMC insn.  */
+        env->pc -= 4;
+        udef = false;
+    }
+
+    /* We've already checked that EL3 exists at translation time.  */
+    if (udef) {
+        /* UDEFs trap on the SMC, roll back to the PC to the SMC insn.  */
+        env->pc -= 4;
+        env->exception.syndrome = syn_uncategorized();
+        raise_exception(env, EXCP_UDEF);
+    }
+    env->exception.syndrome = syndrome;
+    raise_exception(env, EXCP_SMC);
+}
+
 void HELPER(exception_return)(CPUARMState *env)
 {
     int cur_el = arm_current_pl(env);
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index 9867d14..927bc80 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -1454,6 +1454,16 @@ static void disas_exc(DisasContext *s, uint32_t insn)
             gen_helper_hvc(cpu_env, tmp);
             tcg_temp_free_i32(tmp);
             break;
+        case 3:
+            if (!arm_dc_feature(s, ARM_FEATURE_EL3) || s->current_pl == 0) {
+                unallocated_encoding(s);
+                break;
+            }
+            tmp = tcg_const_i32(syn_aa64_smc(imm16));
+            gen_a64_set_pc_im(s->pc);
+            gen_helper_smc(cpu_env, tmp);
+            tcg_temp_free_i32(tmp);
+            break;
         default:
             unallocated_encoding(s);
             break;
-- 
1.9.1

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

* [Qemu-devel] [PATCH v4 09/10] target-arm: Add IRQ and FIQ routing to EL2 and 3
  2014-08-05  8:49 [Qemu-devel] [PATCH v4 00/10] target-arm: Parts of the AArch64 EL2/3 exception model Edgar E. Iglesias
                   ` (7 preceding siblings ...)
  2014-08-05  8:50 ` [Qemu-devel] [PATCH v4 08/10] target-arm: A64: Emulate the SMC insn Edgar E. Iglesias
@ 2014-08-05  8:50 ` Edgar E. Iglesias
  2014-08-05  8:50 ` [Qemu-devel] [PATCH v4 10/10] target-arm: Add support for VIRQ and VFIQ Edgar E. Iglesias
  9 siblings, 0 replies; 11+ messages in thread
From: Edgar E. Iglesias @ 2014-08-05  8:50 UTC (permalink / raw)
  To: qemu-devel, peter.maydell
  Cc: rob.herring, peter.crosthwaite, aggelerf, agraf, blauwirbel,
	greg.bellows, pbonzini, alex.bennee, christoffer.dall, rth

From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>

Reviewed-by: Greg Bellows <greg.bellows@linaro.org>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
---
 target-arm/cpu.h    | 12 ++++++++++++
 target-arm/helper.c | 14 ++++++++++++++
 2 files changed, 26 insertions(+)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index f8e976d..6e1cb1f 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -1152,6 +1152,12 @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx)
     CPUARMState *env = cs->env_ptr;
     unsigned int cur_el = arm_current_pl(env);
     unsigned int target_el = arm_excp_target_el(cs, excp_idx);
+    /* FIXME: Use actual secure state.  */
+    bool secure = false;
+    /* Interrupts can only be hypervised and routed to
+     * EL2 if we are in NS EL0/1.
+     */
+    bool irq_can_hyp = !secure && cur_el < 2 && target_el == 2;
 
     /* Don't take exceptions if they target a lower EL.  */
     if (cur_el > target_el) {
@@ -1160,8 +1166,14 @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx)
 
     switch (excp_idx) {
     case EXCP_FIQ:
+        if (irq_can_hyp && (env->cp15.hcr_el2 & HCR_FMO)) {
+            return true;
+        }
         return !(env->daif & PSTATE_F);
     case EXCP_IRQ:
+        if (irq_can_hyp && (env->cp15.hcr_el2 & HCR_IMO)) {
+            return true;
+        }
         return ((IS_M(env) && env->regs[15] < 0xfffffff0)
                             || !(env->daif & PSTATE_I));
     default:
diff --git a/target-arm/helper.c b/target-arm/helper.c
index a0a210d..92ee7cd 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -3338,6 +3338,20 @@ unsigned int arm_excp_target_el(CPUState *cs, unsigned int excp_idx)
             target_el = 2;
         }
         break;
+    case EXCP_FIQ:
+    case EXCP_IRQ:
+    {
+        const uint64_t hcr_mask = excp_idx == EXCP_FIQ ? HCR_FMO : HCR_IMO;
+        const uint32_t scr_mask = excp_idx == EXCP_FIQ ? SCR_FIQ : SCR_IRQ;
+
+        if (!secure && (env->cp15.hcr_el2 & hcr_mask)) {
+            target_el = 2;
+        }
+        if (env->cp15.scr_el3 & scr_mask) {
+            target_el = 3;
+        }
+        break;
+    }
     }
     return target_el;
 }
-- 
1.9.1

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

* [Qemu-devel] [PATCH v4 10/10] target-arm: Add support for VIRQ and VFIQ
  2014-08-05  8:49 [Qemu-devel] [PATCH v4 00/10] target-arm: Parts of the AArch64 EL2/3 exception model Edgar E. Iglesias
                   ` (8 preceding siblings ...)
  2014-08-05  8:50 ` [Qemu-devel] [PATCH v4 09/10] target-arm: Add IRQ and FIQ routing to EL2 and 3 Edgar E. Iglesias
@ 2014-08-05  8:50 ` Edgar E. Iglesias
  9 siblings, 0 replies; 11+ messages in thread
From: Edgar E. Iglesias @ 2014-08-05  8:50 UTC (permalink / raw)
  To: qemu-devel, peter.maydell
  Cc: rob.herring, peter.crosthwaite, aggelerf, agraf, blauwirbel,
	greg.bellows, pbonzini, alex.bennee, christoffer.dall, rth

From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>

Acked-by: Greg Bellows <greg.bellows@linaro.org>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
---
 cpu-exec.c              | 12 ++++++++++++
 target-arm/cpu.c        | 25 +++++++++++++++----------
 target-arm/cpu.h        | 36 +++++++++++++++++++++++++++++++++---
 target-arm/helper-a64.c |  2 ++
 target-arm/helper.c     |  4 ++++
 target-arm/internals.h  |  2 ++
 6 files changed, 68 insertions(+), 13 deletions(-)

diff --git a/cpu-exec.c b/cpu-exec.c
index a579ffc..baf5643 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -498,6 +498,18 @@ int cpu_exec(CPUArchState *env)
                         cc->do_interrupt(cpu);
                         next_tb = 0;
                     }
+                    if (interrupt_request & CPU_INTERRUPT_VIRQ
+                        && arm_excp_unmasked(cpu, EXCP_VIRQ)) {
+                        cpu->exception_index = EXCP_VIRQ;
+                        cc->do_interrupt(cpu);
+                        next_tb = 0;
+                    }
+                    if (interrupt_request & CPU_INTERRUPT_VFIQ
+                        && arm_excp_unmasked(cpu, EXCP_VFIQ)) {
+                        cpu->exception_index = EXCP_VFIQ;
+                        cc->do_interrupt(cpu);
+                        next_tb = 0;
+                    }
 #elif defined(TARGET_UNICORE32)
                     if (interrupt_request & CPU_INTERRUPT_HARD
                         && !(env->uncached_asr & ASR_I)) {
diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index 7cebb76..3d7e0bb 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -179,20 +179,22 @@ static void arm_cpu_set_irq(void *opaque, int irq, int level)
 {
     ARMCPU *cpu = opaque;
     CPUState *cs = CPU(cpu);
+    static const int mask[] = {
+        [ARM_CPU_IRQ] = CPU_INTERRUPT_HARD,
+        [ARM_CPU_FIQ] = CPU_INTERRUPT_FIQ,
+        [ARM_CPU_VIRQ] = CPU_INTERRUPT_VIRQ,
+        [ARM_CPU_VFIQ] = CPU_INTERRUPT_VFIQ
+    };
 
     switch (irq) {
     case ARM_CPU_IRQ:
-        if (level) {
-            cpu_interrupt(cs, CPU_INTERRUPT_HARD);
-        } else {
-            cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
-        }
-        break;
     case ARM_CPU_FIQ:
+    case ARM_CPU_VIRQ:
+    case ARM_CPU_VFIQ:
         if (level) {
-            cpu_interrupt(cs, CPU_INTERRUPT_FIQ);
+            cpu_interrupt(cs, mask[irq]);
         } else {
-            cpu_reset_interrupt(cs, CPU_INTERRUPT_FIQ);
+            cpu_reset_interrupt(cs, mask[irq]);
         }
         break;
     default:
@@ -242,9 +244,12 @@ static void arm_cpu_initfn(Object *obj)
 #ifndef CONFIG_USER_ONLY
     /* Our inbound IRQ and FIQ lines */
     if (kvm_enabled()) {
-        qdev_init_gpio_in(DEVICE(cpu), arm_cpu_kvm_set_irq, 2);
+        /* VIRQ and VFIQ are unused with KVM but we add them to maintain
+         * the same interface as non-KVM CPUs.
+         */
+        qdev_init_gpio_in(DEVICE(cpu), arm_cpu_kvm_set_irq, 4);
     } else {
-        qdev_init_gpio_in(DEVICE(cpu), arm_cpu_set_irq, 2);
+        qdev_init_gpio_in(DEVICE(cpu), arm_cpu_set_irq, 4);
     }
 
     cpu->gt_timer[GTIMER_PHYS] = timer_new(QEMU_CLOCK_VIRTUAL, GTIMER_SCALE,
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 6e1cb1f..0a6c1b9 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -53,6 +53,8 @@
 #define EXCP_STREX          10
 #define EXCP_HVC            11   /* HyperVisor Call */
 #define EXCP_SMC            12   /* Secure Monitor Call */
+#define EXCP_VIRQ           13
+#define EXCP_VFIQ           14
 
 #define ARMV7M_EXCP_RESET   1
 #define ARMV7M_EXCP_NMI     2
@@ -67,6 +69,8 @@
 
 /* ARM-specific interrupt pending bits.  */
 #define CPU_INTERRUPT_FIQ   CPU_INTERRUPT_TGT_EXT_1
+#define CPU_INTERRUPT_VIRQ  CPU_INTERRUPT_TGT_EXT_2
+#define CPU_INTERRUPT_VFIQ  CPU_INTERRUPT_TGT_EXT_3
 
 /* The usual mapping for an AArch64 system register to its AArch32
  * counterpart is for the 32 bit world to have access to the lower
@@ -82,9 +86,12 @@
 #define offsetofhigh32(S, M) (offsetof(S, M) + sizeof(uint32_t))
 #endif
 
-/* Meanings of the ARMCPU object's two inbound GPIO lines */
+/* Meanings of the ARMCPU object's four inbound GPIO lines */
 #define ARM_CPU_IRQ 0
 #define ARM_CPU_FIQ 1
+#define ARM_CPU_VIRQ 2
+#define ARM_CPU_VFIQ 3
+
 
 typedef void ARMWriteCPFunc(void *opaque, int cp_info,
                             int srcreg, int operand, uint32_t value);
@@ -1158,6 +1165,18 @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx)
      * EL2 if we are in NS EL0/1.
      */
     bool irq_can_hyp = !secure && cur_el < 2 && target_el == 2;
+    /* ARMv7-M interrupt return works by loading a magic value
+     * into the PC.  On real hardware the load causes the
+     * return to occur.  The qemu implementation performs the
+     * jump normally, then does the exception return when the
+     * CPU tries to execute code at the magic address.
+     * This will cause the magic PC value to be pushed to
+     * the stack if an interrupt occurred at the wrong time.
+     * We avoid this by disabling interrupts when
+     * pc contains a magic address.
+     */
+    bool irq_unmasked = ((IS_M(env) && env->regs[15] < 0xfffffff0)
+                          || !(env->daif & PSTATE_I));
 
     /* Don't take exceptions if they target a lower EL.  */
     if (cur_el > target_el) {
@@ -1174,8 +1193,19 @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx)
         if (irq_can_hyp && (env->cp15.hcr_el2 & HCR_IMO)) {
             return true;
         }
-        return ((IS_M(env) && env->regs[15] < 0xfffffff0)
-                            || !(env->daif & PSTATE_I));
+        return irq_unmasked;
+    case EXCP_VFIQ:
+        if (!secure && !(env->cp15.hcr_el2 & HCR_FMO)) {
+            /* VFIQs are only taken when hypervized and non-secure.  */
+            return false;
+        }
+        return !(env->daif & PSTATE_F);
+    case EXCP_VIRQ:
+        if (!secure && !(env->cp15.hcr_el2 & HCR_IMO)) {
+            /* VIRQs are only taken when hypervized and non-secure.  */
+            return false;
+        }
+        return irq_unmasked;
     default:
         g_assert_not_reached();
     }
diff --git a/target-arm/helper-a64.c b/target-arm/helper-a64.c
index 996dfea..bd16fe3 100644
--- a/target-arm/helper-a64.c
+++ b/target-arm/helper-a64.c
@@ -481,9 +481,11 @@ void aarch64_cpu_do_interrupt(CPUState *cs)
         env->cp15.esr_el[new_el] = env->exception.syndrome;
         break;
     case EXCP_IRQ:
+    case EXCP_VIRQ:
         addr += 0x80;
         break;
     case EXCP_FIQ:
+    case EXCP_VFIQ:
         addr += 0x100;
         break;
     default:
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 92ee7cd..75f659f 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -3352,6 +3352,10 @@ unsigned int arm_excp_target_el(CPUState *cs, unsigned int excp_idx)
         }
         break;
     }
+    case EXCP_VIRQ:
+    case EXCP_VFIQ:
+        target_el = 1;
+        break;
     }
     return target_el;
 }
diff --git a/target-arm/internals.h b/target-arm/internals.h
index e50a68e..b1d2d4e 100644
--- a/target-arm/internals.h
+++ b/target-arm/internals.h
@@ -55,6 +55,8 @@ static const char * const excnames[] = {
     [EXCP_STREX] = "QEMU intercept of STREX",
     [EXCP_HVC] = "Hypervisor Call",
     [EXCP_SMC] = "Secure Monitor Call",
+    [EXCP_VIRQ] = "Virtual IRQ",
+    [EXCP_VFIQ] = "Virtual FIQ",
 };
 
 static inline void arm_log_exception(int idx)
-- 
1.9.1

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

end of thread, other threads:[~2014-08-05  9:00 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-08-05  8:49 [Qemu-devel] [PATCH v4 00/10] target-arm: Parts of the AArch64 EL2/3 exception model Edgar E. Iglesias
2014-08-05  8:49 ` [Qemu-devel] [PATCH v4 01/10] target-arm: Add HCR_EL2 Edgar E. Iglesias
2014-08-05  8:49 ` [Qemu-devel] [PATCH v4 02/10] target-arm: Add SCR_EL3 Edgar E. Iglesias
2014-08-05  8:49 ` [Qemu-devel] [PATCH v4 03/10] target-arm: A64: Refactor aarch64_cpu_do_interrupt Edgar E. Iglesias
2014-08-05  8:49 ` [Qemu-devel] [PATCH v4 04/10] target-arm: Break out exception masking to a separate func Edgar E. Iglesias
2014-08-05  8:49 ` [Qemu-devel] [PATCH v4 05/10] target-arm: Don't take interrupts targeting lower ELs Edgar E. Iglesias
2014-08-05  8:50 ` [Qemu-devel] [PATCH v4 06/10] target-arm: A64: Correct updates to FAR and ESR on exceptions Edgar E. Iglesias
2014-08-05  8:50 ` [Qemu-devel] [PATCH v4 07/10] target-arm: A64: Emulate the HVC insn Edgar E. Iglesias
2014-08-05  8:50 ` [Qemu-devel] [PATCH v4 08/10] target-arm: A64: Emulate the SMC insn Edgar E. Iglesias
2014-08-05  8:50 ` [Qemu-devel] [PATCH v4 09/10] target-arm: Add IRQ and FIQ routing to EL2 and 3 Edgar E. Iglesias
2014-08-05  8:50 ` [Qemu-devel] [PATCH v4 10/10] target-arm: Add support for VIRQ and VFIQ Edgar E. Iglesias

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).