All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v7 00/32] target-arm: add Security Extensions for CPUs
@ 2014-10-21 16:55 Greg Bellows
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 01/32] target-arm: increase arrays of registers R13 & R14 Greg Bellows
                   ` (32 more replies)
  0 siblings, 33 replies; 53+ messages in thread
From: Greg Bellows @ 2014-10-21 16:55 UTC (permalink / raw)
  To: qemu-devel, peter.maydell, serge.fdrv, edgar.iglesias, aggelerf
  Cc: greg.bellows

Version 7 of the ARM processor security extension (TrustZone) support.
This patchset includes changes to support the processor security extensions
on ARMv7 aarch32 with hooks for later enabling v8 aarch64/32.

Summary of changes from v6 -> v7:
- Fixed comment and commit message issues
- Updated linux-user uses of tpidr*_el to use array version
- Fixed anonymous struct/union issue when building with gcc-4.4

Fabian Aggeler (26):
  target-arm: increase arrays of registers R13 & R14
  target-arm: add arm_is_secure() function
  target-arm: make arm_current_el() return EL3
  target-arm: A32: Emulate the SMC instruction
  target-arm: extend async excp masking
  target-arm: add async excp target_el function
  target-arm: add banked register accessors
  target-arm: add CPREG secure state support
  target-arm: insert AArch32 cpregs twice into hashtable
  target-arm: move AArch32 SCR into security reglist
  target-arm: implement IRQ/FIQ routing to Monitor mode
  target-arm: respect SCR.FW, SCR.AW and SCTLR.NMFI
  target-arm: add NSACR register
  target-arm: add MVBAR support
  target-arm: add SCTLR_EL3 and make SCTLR banked
  target-arm: make CSSELR banked
  target-arm: add TTBR0_EL3 and make TTBR0/1 banked
  target-arm: add TCR_EL3 and make TTBCR banked
  target-arm: make c2_mask and c2_base_mask banked
  target-arm: make DACR banked
  target-arm: make IFSR banked
  target-arm: make DFSR banked
  target-arm: make IFAR/DFAR banked
  target-arm: make PAR banked
  target-arm: make c13 cp regs banked (FCSEIDR, ...)
  target-arm: add cpu feature EL3 to CPUs with Security Extensions

Greg Bellows (3):
  target-arm: rename arm_current_pl to arm_current_el
  target-arm: add secure state bit to CPREG hash
  target-arm: make MAIR0/1 banked

Sergey Fedorov (3):
  target-arm: reject switching to monitor mode
  target-arm: add non-secure Translation Block flag
  target-arm: add SDER definition

 hw/arm/pxa2xx.c                 |   8 +-
 linux-user/aarch64/target_cpu.h |   2 +-
 linux-user/arm/target_cpu.h     |   2 +-
 linux-user/main.c               |  72 ++--
 target-arm/cpu.c                |  11 +-
 target-arm/cpu.h                | 531 ++++++++++++++++++++++++----
 target-arm/helper-a64.c         |   6 +-
 target-arm/helper.c             | 742 ++++++++++++++++++++++++++++++----------
 target-arm/internals.h          |   4 +-
 target-arm/machine.c            |   4 +-
 target-arm/op_helper.c          |  21 +-
 target-arm/translate-a64.c      |  16 +-
 target-arm/translate.c          |  21 +-
 target-arm/translate.h          |   5 +-
 14 files changed, 1122 insertions(+), 323 deletions(-)

-- 
1.8.3.2

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

* [Qemu-devel] [PATCH v7 01/32] target-arm: increase arrays of registers R13 & R14
  2014-10-21 16:55 [Qemu-devel] [PATCH v7 00/32] target-arm: add Security Extensions for CPUs Greg Bellows
@ 2014-10-21 16:55 ` Greg Bellows
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 02/32] target-arm: add arm_is_secure() function Greg Bellows
                   ` (31 subsequent siblings)
  32 siblings, 0 replies; 53+ messages in thread
From: Greg Bellows @ 2014-10-21 16:55 UTC (permalink / raw)
  To: qemu-devel, peter.maydell, serge.fdrv, edgar.iglesias, aggelerf
  Cc: greg.bellows

From: Fabian Aggeler <aggelerf@ethz.ch>

Increasing banked_r13 and banked_r14 to store LR_mon and SP_mon (bank
index 7).

Signed-off-by: Fabian Aggeler <aggelerf@ethz.ch>
Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

==========

v5 -> v6
- Updated vmstate_arm_cpu versioning from 20 to 21

Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
---
 target-arm/cpu.h     | 4 ++--
 target-arm/machine.c | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 690686c..e0e3f9b 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -153,8 +153,8 @@ typedef struct CPUARMState {
 
     /* Banked registers.  */
     uint64_t banked_spsr[8];
-    uint32_t banked_r13[6];
-    uint32_t banked_r14[6];
+    uint32_t banked_r13[8];
+    uint32_t banked_r14[8];
 
     /* These hold r8-r12.  */
     uint32_t usr_regs[5];
diff --git a/target-arm/machine.c b/target-arm/machine.c
index 5776ee0..6437690 100644
--- a/target-arm/machine.c
+++ b/target-arm/machine.c
@@ -238,8 +238,8 @@ const VMStateDescription vmstate_arm_cpu = {
         },
         VMSTATE_UINT32(env.spsr, ARMCPU),
         VMSTATE_UINT64_ARRAY(env.banked_spsr, ARMCPU, 8),
-        VMSTATE_UINT32_ARRAY(env.banked_r13, ARMCPU, 6),
-        VMSTATE_UINT32_ARRAY(env.banked_r14, ARMCPU, 6),
+        VMSTATE_UINT32_ARRAY(env.banked_r13, ARMCPU, 8),
+        VMSTATE_UINT32_ARRAY(env.banked_r14, ARMCPU, 8),
         VMSTATE_UINT32_ARRAY(env.usr_regs, ARMCPU, 5),
         VMSTATE_UINT32_ARRAY(env.fiq_regs, ARMCPU, 5),
         VMSTATE_UINT64_ARRAY(env.elr_el, ARMCPU, 4),
-- 
1.8.3.2

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

* [Qemu-devel] [PATCH v7 02/32] target-arm: add arm_is_secure() function
  2014-10-21 16:55 [Qemu-devel] [PATCH v7 00/32] target-arm: add Security Extensions for CPUs Greg Bellows
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 01/32] target-arm: increase arrays of registers R13 & R14 Greg Bellows
@ 2014-10-21 16:55 ` Greg Bellows
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 03/32] target-arm: reject switching to monitor mode Greg Bellows
                   ` (30 subsequent siblings)
  32 siblings, 0 replies; 53+ messages in thread
From: Greg Bellows @ 2014-10-21 16:55 UTC (permalink / raw)
  To: qemu-devel, peter.maydell, serge.fdrv, edgar.iglesias, aggelerf
  Cc: greg.bellows

From: Fabian Aggeler <aggelerf@ethz.ch>

arm_is_secure() function allows to determine CPU security state
if the CPU implements Security Extensions/EL3.
arm_is_secure_below_el3() returns true if CPU is in secure state
below EL3.

Signed-off-by: Sergey Fedorov <s.fedorov@samsung.com>
Signed-off-by: Fabian Aggeler <aggelerf@ethz.ch>
Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

==========

v6 -> v7
- Fix arm_is_secure comment

v5 -> v6
- Broaden CONFIG_USER conditional
- Merge resulting false returns with common comment
- Globally change Aarch# to AArch#
- Replace direct access of env->aarch64 with is_a64()

Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
---
 target-arm/cpu.h | 47 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 47 insertions(+)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index e0e3f9b..44ed6fe 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -753,6 +753,53 @@ static inline int arm_feature(CPUARMState *env, int feature)
     return (env->features & (1ULL << feature)) != 0;
 }
 
+#if !defined(CONFIG_USER_ONLY)
+/* Return true if exception levels below EL3 are in secure state,
+ * or would be following an exception return to that level.
+ * Unlike arm_is_secure() (which is always a question about the
+ * _current_ state of the CPU) this doesn't care about the current
+ * EL or mode.
+ */
+static inline bool arm_is_secure_below_el3(CPUARMState *env)
+{
+    if (arm_feature(env, ARM_FEATURE_EL3)) {
+        return !(env->cp15.scr_el3 & SCR_NS);
+    } else {
+        /* If EL2 is not supported then the secure state is implementation
+         * defined, in which case QEMU defaults to non-secure.
+         */
+        return false;
+    }
+}
+
+/* Return true if the processor is in secure state */
+static inline bool arm_is_secure(CPUARMState *env)
+{
+    if (arm_feature(env, ARM_FEATURE_EL3)) {
+        if (is_a64(env) && extract32(env->pstate, 2, 2) == 3) {
+            /* CPU currently in AArch64 state and EL3 */
+            return true;
+        } else if (!is_a64(env) &&
+                (env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_MON) {
+            /* CPU currently in AArch32 state and monitor mode */
+            return true;
+        }
+    }
+    return arm_is_secure_below_el3(env);
+}
+
+#else
+static inline bool arm_is_secure_below_el3(CPUARMState *env)
+{
+    return false;
+}
+
+static inline bool arm_is_secure(CPUARMState *env)
+{
+    return false;
+}
+#endif
+
 /* Return true if the specified exception level is running in AArch64 state. */
 static inline bool arm_el_is_aa64(CPUARMState *env, int el)
 {
-- 
1.8.3.2

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

* [Qemu-devel] [PATCH v7 03/32] target-arm: reject switching to monitor mode
  2014-10-21 16:55 [Qemu-devel] [PATCH v7 00/32] target-arm: add Security Extensions for CPUs Greg Bellows
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 01/32] target-arm: increase arrays of registers R13 & R14 Greg Bellows
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 02/32] target-arm: add arm_is_secure() function Greg Bellows
@ 2014-10-21 16:55 ` Greg Bellows
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 04/32] target-arm: rename arm_current_pl to arm_current_el Greg Bellows
                   ` (29 subsequent siblings)
  32 siblings, 0 replies; 53+ messages in thread
From: Greg Bellows @ 2014-10-21 16:55 UTC (permalink / raw)
  To: qemu-devel, peter.maydell, serge.fdrv, edgar.iglesias, aggelerf
  Cc: greg.bellows

From: Sergey Fedorov <s.fedorov@samsung.com>

Reject switching to monitor mode from non-secure state.

Signed-off-by: Sergey Fedorov <s.fedorov@samsung.com>
Signed-off-by: Fabian Aggeler <aggelerf@ethz.ch>
Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
---
 target-arm/helper.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/target-arm/helper.c b/target-arm/helper.c
index d837820..c36ee6a 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -3531,6 +3531,8 @@ static int bad_mode_switch(CPUARMState *env, int mode)
     case ARM_CPU_MODE_IRQ:
     case ARM_CPU_MODE_FIQ:
         return 0;
+    case ARM_CPU_MODE_MON:
+        return !arm_is_secure(env);
     default:
         return 1;
     }
-- 
1.8.3.2

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

* [Qemu-devel] [PATCH v7 04/32] target-arm: rename arm_current_pl to arm_current_el
  2014-10-21 16:55 [Qemu-devel] [PATCH v7 00/32] target-arm: add Security Extensions for CPUs Greg Bellows
                   ` (2 preceding siblings ...)
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 03/32] target-arm: reject switching to monitor mode Greg Bellows
@ 2014-10-21 16:55 ` Greg Bellows
  2014-10-23 14:53   ` Peter Maydell
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 05/32] target-arm: make arm_current_el() return EL3 Greg Bellows
                   ` (28 subsequent siblings)
  32 siblings, 1 reply; 53+ messages in thread
From: Greg Bellows @ 2014-10-21 16:55 UTC (permalink / raw)
  To: qemu-devel, peter.maydell, serge.fdrv, edgar.iglesias, aggelerf
  Cc: greg.bellows

Renamed the arm_current_pl CPU function to more accurately represent that it
returns the ARMv8 EL rather than ARMv7 PL.

Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

==========

v6 -> v7
- Fix comment

v5 -> v6
- Renamed DisasContext current_pl field to current_el
- Added comment to arm_current_el on handling v7 PL
- Fixed comments referencing PL

Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
---
 target-arm/cpu.h           | 27 +++++++++++++++------------
 target-arm/helper-a64.c    |  6 +++---
 target-arm/helper.c        | 22 +++++++++++-----------
 target-arm/internals.h     |  2 +-
 target-arm/op_helper.c     | 16 ++++++++--------
 target-arm/translate-a64.c | 16 ++++++++--------
 target-arm/translate.c     |  4 ++--
 target-arm/translate.h     |  4 ++--
 8 files changed, 50 insertions(+), 47 deletions(-)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 44ed6fe..1138539 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -991,7 +991,10 @@ static inline bool cptype_valid(int cptype)
 #define PL1_RW (PL1_R | PL1_W)
 #define PL0_RW (PL0_R | PL0_W)
 
-static inline int arm_current_pl(CPUARMState *env)
+/* Return the current Exception Level (as per ARMv8; note that this differs
+ * from the ARMv7 Privilege Level).
+ */
+static inline int arm_current_el(CPUARMState *env)
 {
     if (env->aarch64) {
         return extract32(env->pstate, 2, 2);
@@ -1001,7 +1004,7 @@ static inline int arm_current_pl(CPUARMState *env)
         return 0;
     }
     /* We don't currently implement the Virtualization or TrustZone
-     * extensions, so PL2 and PL3 don't exist for us.
+     * extensions, so EL2 and EL3 don't exist for us.
      */
     return 1;
 }
@@ -1164,10 +1167,10 @@ static inline bool cpreg_field_is_64bit(const ARMCPRegInfo *ri)
     return (ri->state == ARM_CP_STATE_AA64) || (ri->type & ARM_CP_64BIT);
 }
 
-static inline bool cp_access_ok(int current_pl,
+static inline bool cp_access_ok(int current_el,
                                 const ARMCPRegInfo *ri, int isread)
 {
-    return (ri->access >> ((current_pl * 2) + isread)) & 1;
+    return (ri->access >> ((current_el * 2) + isread)) & 1;
 }
 
 /**
@@ -1231,7 +1234,7 @@ 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 cur_el = arm_current_el(env);
     unsigned int target_el = arm_excp_target_el(cs, excp_idx);
     /* FIXME: Use actual secure state.  */
     bool secure = false;
@@ -1303,7 +1306,7 @@ static inline CPUARMState *cpu_init(const char *cpu_model)
 #define MMU_USER_IDX 0
 static inline int cpu_mmu_index (CPUARMState *env)
 {
-    return arm_current_pl(env);
+    return arm_current_el(env);
 }
 
 /* Return the Exception Level targeted by debug exceptions;
@@ -1316,7 +1319,7 @@ static inline int arm_debug_target_el(CPUARMState *env)
 
 static inline bool aa64_generate_debug_exceptions(CPUARMState *env)
 {
-    if (arm_current_pl(env) == arm_debug_target_el(env)) {
+    if (arm_current_el(env) == arm_debug_target_el(env)) {
         if ((extract32(env->cp15.mdscr_el1, 13, 1) == 0)
             || (env->daif & PSTATE_D)) {
             return false;
@@ -1327,10 +1330,10 @@ static inline bool aa64_generate_debug_exceptions(CPUARMState *env)
 
 static inline bool aa32_generate_debug_exceptions(CPUARMState *env)
 {
-    if (arm_current_pl(env) == 0 && arm_el_is_aa64(env, 1)) {
+    if (arm_current_el(env) == 0 && arm_el_is_aa64(env, 1)) {
         return aa64_generate_debug_exceptions(env);
     }
-    return arm_current_pl(env) != 2;
+    return arm_current_el(env) != 2;
 }
 
 /* Return true if debugging exceptions are currently enabled.
@@ -1460,8 +1463,8 @@ static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
     if (is_a64(env)) {
         *pc = env->pc;
         *flags = ARM_TBFLAG_AARCH64_STATE_MASK
-            | (arm_current_pl(env) << ARM_TBFLAG_AA64_EL_SHIFT);
-        if (fpen == 3 || (fpen == 1 && arm_current_pl(env) != 0)) {
+            | (arm_current_el(env) << ARM_TBFLAG_AA64_EL_SHIFT);
+        if (fpen == 3 || (fpen == 1 && arm_current_el(env) != 0)) {
             *flags |= ARM_TBFLAG_AA64_FPEN_MASK;
         }
         /* The SS_ACTIVE and PSTATE_SS bits correspond to the state machine
@@ -1497,7 +1500,7 @@ static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
             || arm_el_is_aa64(env, 1)) {
             *flags |= ARM_TBFLAG_VFPEN_MASK;
         }
-        if (fpen == 3 || (fpen == 1 && arm_current_pl(env) != 0)) {
+        if (fpen == 3 || (fpen == 1 && arm_current_el(env) != 0)) {
             *flags |= ARM_TBFLAG_CPACR_FPEN_MASK;
         }
         /* The SS_ACTIVE and PSTATE_SS bits correspond to the state machine
diff --git a/target-arm/helper-a64.c b/target-arm/helper-a64.c
index daf5adc..81066ca 100644
--- a/target-arm/helper-a64.c
+++ b/target-arm/helper-a64.c
@@ -450,7 +450,7 @@ void aarch64_cpu_do_interrupt(CPUState *cs)
     unsigned int new_mode = aarch64_pstate_mode(new_el, true);
     int i;
 
-    if (arm_current_pl(env) < new_el) {
+    if (arm_current_el(env) < new_el) {
         if (env->aarch64) {
             addr += 0x400;
         } else {
@@ -461,7 +461,7 @@ void aarch64_cpu_do_interrupt(CPUState *cs)
     }
 
     arm_log_exception(cs->exception_index);
-    qemu_log_mask(CPU_LOG_INT, "...from EL%d\n", arm_current_pl(env));
+    qemu_log_mask(CPU_LOG_INT, "...from EL%d\n", arm_current_el(env));
     if (qemu_loglevel_mask(CPU_LOG_INT)
         && !excp_is_internal(cs->exception_index)) {
         qemu_log_mask(CPU_LOG_INT, "...with ESR 0x%" PRIx32 "\n",
@@ -503,7 +503,7 @@ void aarch64_cpu_do_interrupt(CPUState *cs)
 
     if (is_a64(env)) {
         env->banked_spsr[aarch64_banked_spsr_index(new_el)] = pstate_read(env);
-        aarch64_save_sp(env, arm_current_pl(env));
+        aarch64_save_sp(env, arm_current_el(env));
         env->elr_el[new_el] = env->pc;
     } else {
         env->banked_spsr[0] = cpsr_read(env);
diff --git a/target-arm/helper.c b/target-arm/helper.c
index c36ee6a..033b18f 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -571,7 +571,7 @@ static CPAccessResult pmreg_access(CPUARMState *env, const ARMCPRegInfo *ri)
     /* Performance monitor registers user accessibility is controlled
      * by PMUSERENR.
      */
-    if (arm_current_pl(env) == 0 && !env->cp15.c9_pmuserenr) {
+    if (arm_current_el(env) == 0 && !env->cp15.c9_pmuserenr) {
         return CP_ACCESS_TRAP;
     }
     return CP_ACCESS_OK;
@@ -996,7 +996,7 @@ static void teecr_write(CPUARMState *env, const ARMCPRegInfo *ri,
 
 static CPAccessResult teehbr_access(CPUARMState *env, const ARMCPRegInfo *ri)
 {
-    if (arm_current_pl(env) == 0 && (env->teecr & 1)) {
+    if (arm_current_el(env) == 0 && (env->teecr & 1)) {
         return CP_ACCESS_TRAP;
     }
     return CP_ACCESS_OK;
@@ -1042,7 +1042,7 @@ static const ARMCPRegInfo v6k_cp_reginfo[] = {
 static CPAccessResult gt_cntfrq_access(CPUARMState *env, const ARMCPRegInfo *ri)
 {
     /* CNTFRQ: not visible from PL0 if both PL0PCTEN and PL0VCTEN are zero */
-    if (arm_current_pl(env) == 0 && !extract32(env->cp15.c14_cntkctl, 0, 2)) {
+    if (arm_current_el(env) == 0 && !extract32(env->cp15.c14_cntkctl, 0, 2)) {
         return CP_ACCESS_TRAP;
     }
     return CP_ACCESS_OK;
@@ -1051,7 +1051,7 @@ static CPAccessResult gt_cntfrq_access(CPUARMState *env, const ARMCPRegInfo *ri)
 static CPAccessResult gt_counter_access(CPUARMState *env, int timeridx)
 {
     /* CNT[PV]CT: not visible from PL0 if ELO[PV]CTEN is zero */
-    if (arm_current_pl(env) == 0 &&
+    if (arm_current_el(env) == 0 &&
         !extract32(env->cp15.c14_cntkctl, timeridx, 1)) {
         return CP_ACCESS_TRAP;
     }
@@ -1063,7 +1063,7 @@ static CPAccessResult gt_timer_access(CPUARMState *env, int timeridx)
     /* CNT[PV]_CVAL, CNT[PV]_CTL, CNT[PV]_TVAL: not visible from PL0 if
      * EL0[PV]TEN is zero.
      */
-    if (arm_current_pl(env) == 0 &&
+    if (arm_current_el(env) == 0 &&
         !extract32(env->cp15.c14_cntkctl, 9 - timeridx, 1)) {
         return CP_ACCESS_TRAP;
     }
@@ -1911,7 +1911,7 @@ static void aa64_fpsr_write(CPUARMState *env, const ARMCPRegInfo *ri,
 
 static CPAccessResult aa64_daif_access(CPUARMState *env, const ARMCPRegInfo *ri)
 {
-    if (arm_current_pl(env) == 0 && !(env->cp15.c1_sys & SCTLR_UMA)) {
+    if (arm_current_el(env) == 0 && !(env->cp15.c1_sys & SCTLR_UMA)) {
         return CP_ACCESS_TRAP;
     }
     return CP_ACCESS_OK;
@@ -1929,7 +1929,7 @@ static CPAccessResult aa64_cacheop_access(CPUARMState *env,
     /* Cache invalidate/clean: NOP, but EL0 must UNDEF unless
      * SCTLR_EL1.UCI is set.
      */
-    if (arm_current_pl(env) == 0 && !(env->cp15.c1_sys & SCTLR_UCI)) {
+    if (arm_current_el(env) == 0 && !(env->cp15.c1_sys & SCTLR_UCI)) {
         return CP_ACCESS_TRAP;
     }
     return CP_ACCESS_OK;
@@ -2006,7 +2006,7 @@ static CPAccessResult aa64_zva_access(CPUARMState *env, const ARMCPRegInfo *ri)
     /* We don't implement EL2, so the only control on DC ZVA is the
      * bit in the SCTLR which can prohibit access for EL0.
      */
-    if (arm_current_pl(env) == 0 && !(env->cp15.c1_sys & SCTLR_DZE)) {
+    if (arm_current_el(env) == 0 && !(env->cp15.c1_sys & SCTLR_DZE)) {
         return CP_ACCESS_TRAP;
     }
     return CP_ACCESS_OK;
@@ -2366,7 +2366,7 @@ static CPAccessResult ctr_el0_access(CPUARMState *env, const ARMCPRegInfo *ri)
     /* Only accessible in EL0 if SCTLR.UCT is set (and only in AArch64,
      * but the AArch32 CTR has its own reginfo struct)
      */
-    if (arm_current_pl(env) == 0 && !(env->cp15.c1_sys & SCTLR_UCT)) {
+    if (arm_current_el(env) == 0 && !(env->cp15.c1_sys & SCTLR_UCT)) {
         return CP_ACCESS_TRAP;
     }
     return CP_ACCESS_OK;
@@ -3768,7 +3768,7 @@ unsigned int arm_excp_target_el(CPUState *cs, unsigned int excp_idx)
 {
     ARMCPU *cpu = ARM_CPU(cs);
     CPUARMState *env = &cpu->env;
-    unsigned int cur_el = arm_current_pl(env);
+    unsigned int cur_el = arm_current_el(env);
     unsigned int target_el;
     /* FIXME: Use actual secure state.  */
     bool secure = false;
@@ -4770,7 +4770,7 @@ int arm_cpu_handle_mmu_fault(CPUState *cs, vaddr address,
     int prot;
     int ret, is_user;
     uint32_t syn;
-    bool same_el = (arm_current_pl(env) != 0);
+    bool same_el = (arm_current_el(env) != 0);
 
     is_user = mmu_idx == MMU_USER_IDX;
     ret = get_phys_addr(env, address, access_type, is_user, &phys_addr, &prot,
diff --git a/target-arm/internals.h b/target-arm/internals.h
index 51c5c16..2dff4ff 100644
--- a/target-arm/internals.h
+++ b/target-arm/internals.h
@@ -130,7 +130,7 @@ static inline void aarch64_restore_sp(CPUARMState *env, int el)
 
 static inline void update_spsel(CPUARMState *env, uint32_t imm)
 {
-    unsigned int cur_el = arm_current_pl(env);
+    unsigned int cur_el = arm_current_el(env);
     /* Update PSTATE SPSel bit; this requires us to update the
      * working stack pointer in xregs[31].
      */
diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
index 464a5ce..6cc3387 100644
--- a/target-arm/op_helper.c
+++ b/target-arm/op_helper.c
@@ -361,7 +361,7 @@ void HELPER(msr_i_pstate)(CPUARMState *env, uint32_t op, uint32_t imm)
      * Note that SPSel is never OK from EL0; we rely on handle_msr_i()
      * to catch that case at translate time.
      */
-    if (arm_current_pl(env) == 0 && !(env->cp15.c1_sys & SCTLR_UMA)) {
+    if (arm_current_el(env) == 0 && !(env->cp15.c1_sys & SCTLR_UMA)) {
         raise_exception(env, EXCP_UDEF);
     }
 
@@ -388,7 +388,7 @@ void HELPER(clear_pstate_ss)(CPUARMState *env)
 void HELPER(pre_hvc)(CPUARMState *env)
 {
     ARMCPU *cpu = arm_env_get_cpu(env);
-    int cur_el = arm_current_pl(env);
+    int cur_el = arm_current_el(env);
     /* FIXME: Use actual secure state.  */
     bool secure = false;
     bool undef;
@@ -428,7 +428,7 @@ void HELPER(pre_hvc)(CPUARMState *env)
 void HELPER(pre_smc)(CPUARMState *env, uint32_t syndrome)
 {
     ARMCPU *cpu = arm_env_get_cpu(env);
-    int cur_el = arm_current_pl(env);
+    int cur_el = arm_current_el(env);
     /* FIXME: Use real secure state.  */
     bool secure = false;
     bool smd = env->cp15.scr_el3 & SCR_SMD;
@@ -463,7 +463,7 @@ void HELPER(pre_smc)(CPUARMState *env, uint32_t syndrome)
 
 void HELPER(exception_return)(CPUARMState *env)
 {
-    int cur_el = arm_current_pl(env);
+    int cur_el = arm_current_el(env);
     unsigned int spsr_idx = aarch64_banked_spsr_index(cur_el);
     uint32_t spsr = env->banked_spsr[spsr_idx];
     int new_el, i;
@@ -580,7 +580,7 @@ static bool linked_bp_matches(ARMCPU *cpu, int lbn)
 
     switch (bt) {
     case 3: /* linked context ID match */
-        if (arm_current_pl(env) > 1) {
+        if (arm_current_el(env) > 1) {
             /* Context matches never fire in EL2 or (AArch64) EL3 */
             return false;
         }
@@ -660,7 +660,7 @@ static bool bp_wp_matches(ARMCPU *cpu, int n, bool is_wp)
      * rely on this behaviour currently.
      * For breakpoints we do want to use the current CPU state.
      */
-    switch (arm_current_pl(env)) {
+    switch (arm_current_el(env)) {
     case 3:
     case 2:
         if (!hmc) {
@@ -747,7 +747,7 @@ void arm_debug_excp_handler(CPUState *cs)
             cs->watchpoint_hit = NULL;
             if (check_watchpoints(cpu)) {
                 bool wnr = (wp_hit->flags & BP_WATCHPOINT_HIT_WRITE) != 0;
-                bool same_el = arm_debug_target_el(env) == arm_current_pl(env);
+                bool same_el = arm_debug_target_el(env) == arm_current_el(env);
 
                 env->exception.syndrome = syn_watchpoint(same_el, 0, wnr);
                 if (extended_addresses_enabled(env)) {
@@ -763,7 +763,7 @@ void arm_debug_excp_handler(CPUState *cs)
         }
     } else {
         if (check_breakpoints(cpu)) {
-            bool same_el = (arm_debug_target_el(env) == arm_current_pl(env));
+            bool same_el = (arm_debug_target_el(env) == arm_current_el(env));
             env->exception.syndrome = syn_breakpoint(same_el);
             if (extended_addresses_enabled(env)) {
                 env->exception.fsr = (1 << 9) | 0x22;
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index b15261b..b141452 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -1226,7 +1226,7 @@ static void handle_msr_i(DisasContext *s, uint32_t insn,
     int op = op1 << 3 | op2;
     switch (op) {
     case 0x05: /* SPSel */
-        if (s->current_pl == 0) {
+        if (s->current_el == 0) {
             unallocated_encoding(s);
             return;
         }
@@ -1323,7 +1323,7 @@ static void handle_sys(DisasContext *s, uint32_t insn, bool isread,
     }
 
     /* Check access permissions */
-    if (!cp_access_ok(s->current_pl, ri, isread)) {
+    if (!cp_access_ok(s->current_el, ri, isread)) {
         unallocated_encoding(s);
         return;
     }
@@ -1362,7 +1362,7 @@ static void handle_sys(DisasContext *s, uint32_t insn, bool isread,
          * guaranteed to be constant by the tb flags.
          */
         tcg_rt = cpu_reg(s, rt);
-        tcg_gen_movi_i64(tcg_rt, s->current_pl << 2);
+        tcg_gen_movi_i64(tcg_rt, s->current_el << 2);
         return;
     case ARM_CP_DC_ZVA:
         /* Writes clear the aligned block of memory which rt points into. */
@@ -1485,7 +1485,7 @@ static void disas_exc(DisasContext *s, uint32_t insn)
             gen_exception_insn(s, 0, EXCP_SWI, syn_aa64_svc(imm16));
             break;
         case 2:
-            if (s->current_pl == 0) {
+            if (!arm_dc_feature(s, ARM_FEATURE_EL2) || s->current_el == 0) {
                 unallocated_encoding(s);
                 break;
             }
@@ -1498,7 +1498,7 @@ static void disas_exc(DisasContext *s, uint32_t insn)
             gen_exception_insn(s, 0, EXCP_HVC, syn_aa64_hvc(imm16));
             break;
         case 3:
-            if (s->current_pl == 0) {
+            if (!arm_dc_feature(s, ARM_FEATURE_EL3) || s->current_el == 0) {
                 unallocated_encoding(s);
                 break;
             }
@@ -1575,7 +1575,7 @@ static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
         tcg_gen_movi_i64(cpu_reg(s, 30), s->pc);
         break;
     case 4: /* ERET */
-        if (s->current_pl == 0) {
+        if (s->current_el == 0) {
             unallocated_encoding(s);
             return;
         }
@@ -10930,7 +10930,7 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu,
     dc->vec_len = 0;
     dc->vec_stride = 0;
     dc->cp_regs = cpu->cp_regs;
-    dc->current_pl = arm_current_pl(env);
+    dc->current_el = arm_current_el(env);
     dc->features = env->features;
 
     /* Single step state. The code-generation logic here is:
@@ -10951,7 +10951,7 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu,
     dc->ss_active = ARM_TBFLAG_AA64_SS_ACTIVE(tb->flags);
     dc->pstate_ss = ARM_TBFLAG_AA64_PSTATE_SS(tb->flags);
     dc->is_ldex = false;
-    dc->ss_same_el = (arm_debug_target_el(env) == dc->current_pl);
+    dc->ss_same_el = (arm_debug_target_el(env) == dc->current_el);
 
     init_tmp_a64_array(dc);
 
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 4e764d3..91958b6 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -7074,7 +7074,7 @@ static int disas_coproc_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
                             ENCODE_CP_REG(cpnum, is64, crn, crm, opc1, opc2));
     if (ri) {
         /* Check access permissions */
-        if (!cp_access_ok(s->current_pl, ri, isread)) {
+        if (!cp_access_ok(s->current_el, ri, isread)) {
             return 1;
         }
 
@@ -11008,7 +11008,7 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
     dc->vec_stride = ARM_TBFLAG_VECSTRIDE(tb->flags);
     dc->c15_cpar = ARM_TBFLAG_XSCALE_CPAR(tb->flags);
     dc->cp_regs = cpu->cp_regs;
-    dc->current_pl = arm_current_pl(env);
+    dc->current_el = arm_current_el(env);
     dc->features = env->features;
 
     /* Single step state. The code-generation logic here is:
diff --git a/target-arm/translate.h b/target-arm/translate.h
index 83fbf38..41a9071 100644
--- a/target-arm/translate.h
+++ b/target-arm/translate.h
@@ -29,7 +29,7 @@ typedef struct DisasContext {
      */
     uint32_t svc_imm;
     int aarch64;
-    int current_pl;
+    int current_el;
     GHashTable *cp_regs;
     uint64_t features; /* CPU features bits */
     /* Because unallocated encodings generate different exception syndrome
@@ -68,7 +68,7 @@ static inline int arm_dc_feature(DisasContext *dc, int feature)
 
 static inline int get_mem_index(DisasContext *s)
 {
-    return s->current_pl;
+    return s->current_el;
 }
 
 /* target-specific extra values for is_jmp */
-- 
1.8.3.2

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

* [Qemu-devel] [PATCH v7 05/32] target-arm: make arm_current_el() return EL3
  2014-10-21 16:55 [Qemu-devel] [PATCH v7 00/32] target-arm: add Security Extensions for CPUs Greg Bellows
                   ` (3 preceding siblings ...)
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 04/32] target-arm: rename arm_current_pl to arm_current_el Greg Bellows
@ 2014-10-21 16:55 ` Greg Bellows
  2015-01-16 18:36   ` Peter Maydell
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 06/32] target-arm: A32: Emulate the SMC instruction Greg Bellows
                   ` (27 subsequent siblings)
  32 siblings, 1 reply; 53+ messages in thread
From: Greg Bellows @ 2014-10-21 16:55 UTC (permalink / raw)
  To: qemu-devel, peter.maydell, serge.fdrv, edgar.iglesias, aggelerf
  Cc: greg.bellows

From: Fabian Aggeler <aggelerf@ethz.ch>

Make arm_current_el() return EL3 for secure PL1 and monitor mode.
Increase MMU modes since mmu_index is directly inferred from arm_
current_el(). Change assertion in arm_el_is_aa64() to allow EL3.

Signed-off-by: Fabian Aggeler <aggelerf@ethz.ch>
Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

==========

v6 -> v7
- Fix commit message

v5 -> v6
- Rework arm_current_el() logic to properly return EL3 for secure PL1 when EL3
  is 32-bit.
- Replace direct access of env->aarch64 with is_a64()

Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
---
 target-arm/cpu.h | 29 ++++++++++++++++++++---------
 1 file changed, 20 insertions(+), 9 deletions(-)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 1138539..cb6ec5c 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -100,7 +100,7 @@ typedef uint32_t ARMReadCPFunc(void *opaque, int cp_info,
 
 struct arm_boot_info;
 
-#define NB_MMU_MODES 2
+#define NB_MMU_MODES 4
 
 /* We currently assume float and double are IEEE single and double
    precision respectively.
@@ -803,11 +803,12 @@ static inline bool arm_is_secure(CPUARMState *env)
 /* Return true if the specified exception level is running in AArch64 state. */
 static inline bool arm_el_is_aa64(CPUARMState *env, int el)
 {
-    /* We don't currently support EL2 or EL3, and this isn't valid for EL0
+    /* We don't currently support EL2, and this isn't valid for EL0
      * (if we're in EL0, is_a64() is what you want, and if we're not in EL0
      * then the state of EL0 isn't well defined.)
      */
-    assert(el == 1);
+    assert(el == 1 || el == 3);
+
     /* AArch64-capable CPUs always run with EL1 in AArch64 mode. This
      * is a QEMU-imposed simplification which we may wish to change later.
      * If we in future support EL2 and/or EL3, then the state of lower
@@ -996,17 +997,27 @@ static inline bool cptype_valid(int cptype)
  */
 static inline int arm_current_el(CPUARMState *env)
 {
-    if (env->aarch64) {
+    if (is_a64(env)) {
         return extract32(env->pstate, 2, 2);
     }
 
-    if ((env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_USR) {
+    switch (env->uncached_cpsr & 0x1f) {
+    case ARM_CPU_MODE_USR:
         return 0;
+    case ARM_CPU_MODE_HYP:
+        return 2;
+    case ARM_CPU_MODE_MON:
+        return 3;
+    default:
+        if (arm_is_secure(env) && !arm_el_is_aa64(env, 3)) {
+            /* If EL3 is 32-bit then all secure privileged modes run in
+             * EL3
+             */
+            return 3;
+        }
+
+        return 1;
     }
-    /* We don't currently implement the Virtualization or TrustZone
-     * extensions, so EL2 and EL3 don't exist for us.
-     */
-    return 1;
 }
 
 typedef struct ARMCPRegInfo ARMCPRegInfo;
-- 
1.8.3.2

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

* [Qemu-devel] [PATCH v7 06/32] target-arm: A32: Emulate the SMC instruction
  2014-10-21 16:55 [Qemu-devel] [PATCH v7 00/32] target-arm: add Security Extensions for CPUs Greg Bellows
                   ` (4 preceding siblings ...)
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 05/32] target-arm: make arm_current_el() return EL3 Greg Bellows
@ 2014-10-21 16:55 ` Greg Bellows
  2014-10-23 14:06   ` Peter Maydell
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 07/32] target-arm: extend async excp masking Greg Bellows
                   ` (26 subsequent siblings)
  32 siblings, 1 reply; 53+ messages in thread
From: Greg Bellows @ 2014-10-21 16:55 UTC (permalink / raw)
  To: qemu-devel, peter.maydell, serge.fdrv, edgar.iglesias, aggelerf
  Cc: greg.bellows

From: Fabian Aggeler <aggelerf@ethz.ch>

Implements SMC instruction in AArch32 using the A32 syndrome. When executing
SMC instruction from monitor CPU mode SCR.NS bit is reset.

Signed-off-by: Sergey Fedorov <s.fedorov@samsung.com>
Signed-off-by: Fabian Aggeler <aggelerf@ethz.ch>
Signed-off-by: Greg Bellows <greg.bellows@linaro.org>

==========

v5 -> v6
- Fixed PC offsetting for presmc
- Removed extraneous semi-colon
- Fixed merge issue

v4 -> v5
- Merge pre_smc upstream changes and incorporated ss_advance

Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
---
 target-arm/helper.c    | 11 +++++++++++
 target-arm/op_helper.c |  3 +--
 2 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/target-arm/helper.c b/target-arm/helper.c
index 033b18f..38d9f7b 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -4091,6 +4091,12 @@ void arm_cpu_do_interrupt(CPUState *cs)
         mask = CPSR_A | CPSR_I | CPSR_F;
         offset = 4;
         break;
+    case EXCP_SMC:
+        new_mode = ARM_CPU_MODE_MON;
+        addr = 0x08;
+        mask = CPSR_A | CPSR_I | CPSR_F;
+        offset = 0;
+        break;
     default:
         cpu_abort(cs, "Unhandled exception 0x%x\n", cs->exception_index);
         return; /* Never happens.  Keep compiler happy.  */
@@ -4109,6 +4115,11 @@ void arm_cpu_do_interrupt(CPUState *cs)
          */
         addr += env->cp15.vbar_el[1];
     }
+
+    if ((env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_MON) {
+        env->cp15.scr_el3 &= ~SCR_NS;
+    }
+
     switch_mode (env, new_mode);
     /* For exceptions taken to AArch32 we must clear the SS bit in both
      * PSTATE and in the old-state value we save to SPSR_<mode>, so zero it now.
diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
index 6cc3387..62012c3 100644
--- a/target-arm/op_helper.c
+++ b/target-arm/op_helper.c
@@ -429,8 +429,7 @@ void HELPER(pre_smc)(CPUARMState *env, uint32_t syndrome)
 {
     ARMCPU *cpu = arm_env_get_cpu(env);
     int cur_el = arm_current_el(env);
-    /* FIXME: Use real secure state.  */
-    bool secure = false;
+    bool secure = arm_is_secure(env);
     bool smd = env->cp15.scr_el3 & SCR_SMD;
     /* On ARMv8 AArch32, SMD only applies to NS state.
      * On ARMv7 SMD only applies to NS state and only if EL2 is available.
-- 
1.8.3.2

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

* [Qemu-devel] [PATCH v7 07/32] target-arm: extend async excp masking
  2014-10-21 16:55 [Qemu-devel] [PATCH v7 00/32] target-arm: add Security Extensions for CPUs Greg Bellows
                   ` (5 preceding siblings ...)
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 06/32] target-arm: A32: Emulate the SMC instruction Greg Bellows
@ 2014-10-21 16:55 ` Greg Bellows
  2014-10-24 16:25   ` Peter Maydell
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 08/32] target-arm: add async excp target_el function Greg Bellows
                   ` (25 subsequent siblings)
  32 siblings, 1 reply; 53+ messages in thread
From: Greg Bellows @ 2014-10-21 16:55 UTC (permalink / raw)
  To: qemu-devel, peter.maydell, serge.fdrv, edgar.iglesias, aggelerf
  Cc: greg.bellows

From: Fabian Aggeler <aggelerf@ethz.ch>

This patch extends arm_excp_unmasked() according to ARM ARMv7 and
ARM ARMv8 (all EL running in AArch32) and adds comments.

If EL3 is using AArch64 IRQ/FIQ masking is ignored in
all exception levels other than EL3 if SCR.{FIQ|IRQ} is
set to 1 (routed to EL3).

Signed-off-by: Fabian Aggeler <aggelerf@ethz.ch>
Signed-off-by: Greg Bellows <greg.bellows@linaro.org>

==========

v5 -> v6
- Globally change Aarch# to AArch#
- Fixed comment termination

v4 -> v5
- Merge with v4 patch 10

Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
---
 target-arm/cpu.h | 117 ++++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 107 insertions(+), 10 deletions(-)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index cb6ec5c..1a564b9 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -1246,11 +1246,8 @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx)
 {
     CPUARMState *env = cs->env_ptr;
     unsigned int cur_el = arm_current_el(env);
-    unsigned int target_el = arm_excp_target_el(cs, excp_idx);
-    /* FIXME: Use actual secure state.  */
-    bool secure = false;
-    /* If in EL1/0, Physical IRQ routing to EL2 only happens from NS state.  */
-    bool irq_can_hyp = !secure && cur_el < 2 && target_el == 2;
+    bool secure = arm_is_secure(env);
+
     /* 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
@@ -1265,19 +1262,119 @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx)
                         && (!IS_M(env) || env->regs[15] < 0xfffffff0);
 
     /* Don't take exceptions if they target a lower EL.  */
-    if (cur_el > target_el) {
+    if (cur_el > arm_excp_target_el(cs, excp_idx)) {
         return false;
     }
 
+    /* ARM ARMv7 B1.8.6  Asynchronous exception masking (table B1-12/B1-13)
+     * ARM ARMv8 G1.11.3 Asynchronous exception masking controls
+     * (table G1-18/G1-19)
+     */
     switch (excp_idx) {
     case EXCP_FIQ:
-        if (irq_can_hyp && (env->cp15.hcr_el2 & HCR_FMO)) {
-            return true;
+        if (arm_feature(env, ARM_FEATURE_EL3) && arm_el_is_aa64(env, 3)) {
+            /* If EL3 is using AArch64 and FIQs are routed to EL3 masking is
+             * ignored in all exception levels except EL3.
+             */
+            if ((env->cp15.scr_el3 & SCR_FIQ) && cur_el < 3) {
+                return true;
+            }
+            /* If we are in EL3 but FIQs are not routed to EL3 the exception
+             * is not taken but remains pending.
+             */
+            if (!(env->cp15.scr_el3 & SCR_FIQ) && cur_el == 3) {
+                return false;
+            }
+        }
+        if (!secure) {
+            if (arm_feature(env, ARM_FEATURE_EL2)) {
+                if (env->cp15.hcr_el2 & HCR_FMO) {
+                    /* CPSR.F/PSTATE.F ignored if
+                     *  - exception is taken from Non-secure state
+                     *  - HCR.FMO == 1
+                     *  - either:  - not in Hyp mode
+                     *             - SCR.FIQ routes exception to monitor mode
+                     *               (EL3 in AArch32)
+                     */
+                    if (cur_el < 2) {
+                        return true;
+                    } else if (arm_feature(env, ARM_FEATURE_EL3) &&
+                            (env->cp15.scr_el3 & SCR_FIQ) &&
+                            !arm_el_is_aa64(env, 3)) {
+                        return true;
+                    }
+                } else if (arm_el_is_aa64(env, 3) &&
+                          (env->cp15.scr_el3 & SCR_RW) &&
+                          cur_el == 2) {
+                    /* FIQs not routed to EL2 but currently in EL2 (A64).
+                     * Exception is not taken but remains pending. */
+                    return false;
+                }
+            }
+            /* In ARMv7 only applies if both Security Extensions (EL3) and
+             * Hypervirtualization Extensions (EL2) implemented, while
+             * for ARMv8 it applies also if only EL3 implemented.
+             */
+            if (arm_feature(env, ARM_FEATURE_EL3) &&
+                    (arm_feature(env, ARM_FEATURE_EL2) ||
+                            arm_feature(env, ARM_FEATURE_V8))) {
+                /* CPSR.F/PSTATE.F ignored if
+                 * - exception is taken from Non-secure state
+                 * - SCR.FIQ routes exception to monitor mode
+                 * - SCR.FW bit is set to 0
+                 * - HCR.FMO == 0 (if EL2 implemented)
+                 */
+                if ((env->cp15.scr_el3 & SCR_FIQ) &&
+                        !(env->cp15.scr_el3 & SCR_FW)) {
+                    if (!arm_feature(env, ARM_FEATURE_EL2)) {
+                        return true;
+                    } else if (!(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;
+        if (arm_feature(env, ARM_FEATURE_EL3) && arm_el_is_aa64(env, 3)) {
+            /* If EL3 is using AArch64 and IRQs are routed to EL3 masking is
+             * ignored in all exception levels except EL3.
+             */
+            if ((env->cp15.scr_el3 & SCR_IRQ) && cur_el < 3) {
+                return true;
+            }
+            /* If we are in EL3 but IRQ s are not routed to EL3 the exception
+             * is not taken but remains pending.
+             */
+            if (!(env->cp15.scr_el3 & SCR_IRQ) && cur_el == 3) {
+                return false;
+            }
+        }
+        if (!secure) {
+            if (arm_feature(env, ARM_FEATURE_EL2)) {
+                if (env->cp15.hcr_el2 & HCR_IMO) {
+                    /* CPSR.I/PSTATE.I ignored if
+                     *  - exception is taken from Non-secure state
+                     *  - HCR.IMO == 1
+                     *  - either:  - not in Hyp mode
+                     *             - SCR.IRQ routes exception to monitor mode
+                     *                (EL3 in AArch32)
+                     */
+                    if (cur_el < 2) {
+                        return true;
+                    } else if (arm_feature(env, ARM_FEATURE_EL3) &&
+                            (env->cp15.scr_el3 & SCR_IRQ) &&
+                            !arm_el_is_aa64(env, 3)) {
+                        return true;
+                    }
+                } else if (arm_el_is_aa64(env, 3) &&
+                          (env->cp15.scr_el3 & SCR_RW) &&
+                          cur_el == 2) {
+                    /* IRQs not routed to EL2 but currently in EL2 (A64).
+                     * Exception is not taken but remains pending. */
+                    return false;
+                }
+            }
         }
         return irq_unmasked;
     case EXCP_VFIQ:
-- 
1.8.3.2

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

* [Qemu-devel] [PATCH v7 08/32] target-arm: add async excp target_el function
  2014-10-21 16:55 [Qemu-devel] [PATCH v7 00/32] target-arm: add Security Extensions for CPUs Greg Bellows
                   ` (6 preceding siblings ...)
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 07/32] target-arm: extend async excp masking Greg Bellows
@ 2014-10-21 16:55 ` Greg Bellows
  2014-10-24 16:26   ` Peter Maydell
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 09/32] target-arm: add banked register accessors Greg Bellows
                   ` (24 subsequent siblings)
  32 siblings, 1 reply; 53+ messages in thread
From: Greg Bellows @ 2014-10-21 16:55 UTC (permalink / raw)
  To: qemu-devel, peter.maydell, serge.fdrv, edgar.iglesias, aggelerf
  Cc: greg.bellows

From: Fabian Aggeler <aggelerf@ethz.ch>

Adds a dedicated function for IRQ and FIQ exceptions to determine
target_el and mode (AArch32) according to tables in ARM ARMv8 and
ARM ARM v7.

Signed-off-by: Fabian Aggeler <aggelerf@ethz.ch>
Signed-off-by: Greg Bellows <greg.bellows@linaro.org>

==========

v5 -> v6
- Removed unneeded arm_phys_excp_target_el() function prototype.
- Removed unneeded arm_phys_excp_target_el() USER_ONLY function.
- Fixed up arm_phys_excp_target_el() function definition to be static.
- Globally replace Aarch# with AArch#

v4 -> v5
- Simplify target EL function including removal of mode which was unused
- Merged with patch that plugs in the use of the function

v3 -> v4
- Fixed arm_phys_excp_target_el() 0/0/0 case to return excp_mode when EL<2
  rather than ABORT.

Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
---
 target-arm/helper.c | 97 ++++++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 77 insertions(+), 20 deletions(-)

diff --git a/target-arm/helper.c b/target-arm/helper.c
index 38d9f7b..78aeb31 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -3762,6 +3762,80 @@ void switch_mode(CPUARMState *env, int mode)
 }
 
 /*
+ * Determine the target EL for physical exceptions
+ */
+static inline uint32_t arm_phys_excp_target_el(CPUState *cs, uint32_t excp_idx,
+                                        uint32_t cur_el, bool secure)
+{
+    CPUARMState *env = cs->env_ptr;
+    uint32_t target_el = 1;
+
+    /* There is no SCR or HCR routing unless the respective EL3 and EL2
+     * extensions are supported.  This initial setting affects whether any
+     * other conditions matter.
+     */
+    bool scr_routing = arm_feature(env, ARM_FEATURE_EL3); /* IRQ, FIQ, EA */
+    bool hcr_routing = arm_feature(env, ARM_FEATURE_EL2); /* IMO, FMO, AMO */
+
+    /* Fast-path if EL2 and EL3 are not enabled */
+    if (!scr_routing && !hcr_routing) {
+        return target_el;
+    }
+
+    switch (excp_idx) {
+    case EXCP_IRQ:
+        scr_routing &= ((env->cp15.scr_el3 & SCR_IRQ) == SCR_IRQ);
+        hcr_routing &= ((env->cp15.hcr_el2 & HCR_IMO) == HCR_IMO);
+        break;
+    case EXCP_FIQ:
+        scr_routing &= ((env->cp15.scr_el3 & SCR_FIQ) == SCR_FIQ);
+        hcr_routing &= ((env->cp15.hcr_el2 & HCR_FMO) == HCR_FMO);
+    }
+
+    /* If SCR routing is enabled we always go to EL3 regardless of EL3
+     * execution state
+     */
+    if (scr_routing) {
+        /* IRQ|FIQ|EA == 1 */
+        return 3;
+    }
+
+    /* If HCR.TGE is set all exceptions that would be routed to EL1 are
+     * routed to EL2 (in non-secure world).
+     */
+    hcr_routing &= (env->cp15.hcr_el2 & HCR_TGE) == HCR_TGE;
+
+    /* Determine target EL according to ARM ARMv8 tables G1-15 and G1-16 */
+    if (arm_el_is_aa64(env, 3)) {
+        /* EL3 in AArch64 */
+        if (!secure) {
+            /* If non-secure, we may route to EL2 depending on other state.
+             * If we are coming from the secure world then we always route to
+             * EL1.
+             */
+            if (hcr_routing ||
+                (cur_el == 2 && !(env->cp15.scr_el3 & SCR_RW))) {
+                /* If HCR.FMO/IMO is set or we already in EL2 and it is not
+                 * configured to be AArch64 then route to EL2.
+                 */
+                target_el = 2;
+            }
+        }
+    } else {
+        /* EL3 in AArch32 */
+        if (secure) {
+            /* If coming from secure always route to EL3 */
+            target_el = 3;
+        } else if (hcr_routing || cur_el == 2) {
+            /* If HCR.FMO/IMO is set or we are already EL2 then route to EL2 */
+            target_el = 2;
+        }
+    }
+
+    return target_el;
+}
+
+/*
  * Determine the target EL for a given exception type.
  */
 unsigned int arm_excp_target_el(CPUState *cs, unsigned int excp_idx)
@@ -3769,14 +3843,8 @@ unsigned int arm_excp_target_el(CPUState *cs, unsigned int excp_idx)
     ARMCPU *cpu = ARM_CPU(cs);
     CPUARMState *env = &cpu->env;
     unsigned int cur_el = arm_current_el(env);
-    unsigned int target_el;
-    /* FIXME: Use actual secure state.  */
-    bool secure = false;
-
-    if (!env->aarch64) {
-        /* TODO: Add EL2 and 3 exception handling for AArch32.  */
-        return 1;
-    }
+    unsigned int target_el = 1;
+    bool secure = arm_is_secure(env);
 
     switch (excp_idx) {
     case EXCP_HVC:
@@ -3788,19 +3856,8 @@ unsigned int arm_excp_target_el(CPUState *cs, unsigned int excp_idx)
         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;
-
-        target_el = 1;
-        if (!secure && (env->cp15.hcr_el2 & hcr_mask)) {
-            target_el = 2;
-        }
-        if (env->cp15.scr_el3 & scr_mask) {
-            target_el = 3;
-        }
+        target_el = arm_phys_excp_target_el(cs, excp_idx, cur_el, secure);
         break;
-    }
     case EXCP_VIRQ:
     case EXCP_VFIQ:
         target_el = 1;
-- 
1.8.3.2

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

* [Qemu-devel] [PATCH v7 09/32] target-arm: add banked register accessors
  2014-10-21 16:55 [Qemu-devel] [PATCH v7 00/32] target-arm: add Security Extensions for CPUs Greg Bellows
                   ` (7 preceding siblings ...)
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 08/32] target-arm: add async excp target_el function Greg Bellows
@ 2014-10-21 16:55 ` Greg Bellows
  2014-10-24 16:37   ` Peter Maydell
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 10/32] target-arm: add non-secure Translation Block flag Greg Bellows
                   ` (23 subsequent siblings)
  32 siblings, 1 reply; 53+ messages in thread
From: Greg Bellows @ 2014-10-21 16:55 UTC (permalink / raw)
  To: qemu-devel, peter.maydell, serge.fdrv, edgar.iglesias, aggelerf
  Cc: greg.bellows

From: Fabian Aggeler <aggelerf@ethz.ch>

If EL3 is in AArch32 state certain cp registers are banked (secure and
non-secure instance). When reading or writing to coprocessor registers
the following macros can be used.

- A32_BANKED macros are used for choosing the banked register based on provided
  input security argument.  This macro is used to choose the bank during
  translation of MRC/MCR instructions that are dependent on something other
  than the current secure state.
- A32_BANKED_CURRENT macros are used for choosing the banked register based on
  current secure state.  This is NOT to be used for choosing the bank used
  during translation as it breaks monitor mode.

If EL3 is operating in AArch64 state coprocessor registers are not
banked anymore. The macros use the non-secure instance (_ns) in this
case, which is architecturally mapped to the AArch64 EL register.

Signed-off-by: Sergey Fedorov <s.fedorov@samsung.com>
Signed-off-by: Fabian Aggeler <aggelerf@ethz.ch>
Signed-off-by: Greg Bellows <greg.bellows@linaro.org>

==========

v5 -> v6
- Converted macro USE_SECURE_REG() into inlince function use_secure_reg()
- Globally replace Aarch# with AArch#

v4 -> v5
- Cleaned-up macros to try and alleviate misuse.  Made A32_BANKED macros take
  secure arg indicator rather than relying on USE_SECURE_REG.  Incorporated the
  A32_BANKED macros into the A32_BANKED_CURRENT.  CURRENT is now the only one
  that automatically chooses based on current secure state.

Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
---
 target-arm/cpu.h | 40 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 40 insertions(+)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 1a564b9..b48b81a 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -817,6 +817,46 @@ static inline bool arm_el_is_aa64(CPUARMState *env, int el)
     return arm_feature(env, ARM_FEATURE_AARCH64);
 }
 
+/* Function for determing whether to use the secure or non-secure bank of a CP
+ * register.  When EL3 is operating in AArch32 state, the NS-bit determines
+ * whether the secure instance of a cp-register should be used.
+ */
+static inline bool use_secure_reg(CPUARMState *env)
+{
+    bool ret = (arm_feature(env, ARM_FEATURE_EL3) &&
+                !arm_el_is_aa64(env, 3) &&
+                !(env->cp15.scr_el3 & SCR_NS));
+
+    return ret;
+}
+
+/* Macros for accessing a specified CP register bank */
+#define A32_BANKED_REG_GET(_env, _regname, _secure)    \
+    ((_secure) ? (_env)->cp15._regname##_s : (_env)->cp15._regname##_ns)
+
+#define A32_BANKED_REG_SET(_env, _regname, _secure, _val)   \
+    do {                                                \
+        if (_secure) {                                   \
+            (_env)->cp15._regname##_s = (_val);            \
+        } else {                                        \
+            (_env)->cp15._regname##_ns = (_val);           \
+        }                                               \
+    } while (0)
+
+/* Macros for automatically accessing a specific CP register bank depending on
+ * the current secure state of the system.  These macros are not intended for
+ * supporting instruction translation reads/writes as these are dependent
+ * solely on the SCR.NS bit and not the mode.
+ */
+#define A32_BANKED_CURRENT_REG_GET(_env, _regname)        \
+    A32_BANKED_REG_GET((_env), _regname,                \
+                       ((!arm_el_is_aa64((_env), 3) && arm_is_secure(_env))))
+
+#define A32_BANKED_CURRENT_REG_SET(_env, _regname, _val)                       \
+    A32_BANKED_REG_SET((_env), _regname,                                    \
+                       ((!arm_el_is_aa64((_env), 3) && arm_is_secure(_env))),  \
+                       (_val))
+
 void arm_cpu_list(FILE *f, fprintf_function cpu_fprintf);
 unsigned int arm_excp_target_el(CPUState *cs, unsigned int excp_idx);
 
-- 
1.8.3.2

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

* [Qemu-devel] [PATCH v7 10/32] target-arm: add non-secure Translation Block flag
  2014-10-21 16:55 [Qemu-devel] [PATCH v7 00/32] target-arm: add Security Extensions for CPUs Greg Bellows
                   ` (8 preceding siblings ...)
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 09/32] target-arm: add banked register accessors Greg Bellows
@ 2014-10-21 16:55 ` Greg Bellows
  2014-10-24 16:40   ` Peter Maydell
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 11/32] target-arm: add CPREG secure state support Greg Bellows
                   ` (22 subsequent siblings)
  32 siblings, 1 reply; 53+ messages in thread
From: Greg Bellows @ 2014-10-21 16:55 UTC (permalink / raw)
  To: qemu-devel, peter.maydell, serge.fdrv, edgar.iglesias, aggelerf
  Cc: greg.bellows

From: Sergey Fedorov <s.fedorov@samsung.com>

This patch is based on idea found in patch at
git://github.com/jowinter/qemu-trustzone.git
f3d955c6c0ed8c46bc0eb10b634201032a651dd2 by
Johannes Winter <johannes.winter@iaik.tugraz.at>.

The TBFLAG captures the SCR NS secure state at the time when a TB is created so
the correct bank is accessed on system register accesses.  It also allows to
generate different TCG code depending on CPU secure state.

Signed-off-by: Sergey Fedorov <s.fedorov@samsung.com>
Signed-off-by: Fabian Aggeler <aggelerf@ethz.ch>
Signed-off-by: Greg Bellows <greg.bellows@linaro.org>

==========

v5 -> v6
- Removed 64-bit NS TBFLAG macros as they are not needed
- Added comment on DisasContext ns field
- Replaced use of USE_SECURE_REG with use_secure_reg

v4 -> v5
- Merge changes
- Fixed issue where TB secure state flag was incorrectly being set based on
  secure state rather than NS setting.  This caused an issue where monitor mode
  MRC/MCR accesses were always secure rather than being based on NS bit
  setting.
- Added separate 64/32 TB secure state flags
- Unconditionalized the setting of the DC ns bit
- Removed IS_NS macro and replaced with direct usage.

Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
---
 target-arm/cpu.h       | 7 +++++++
 target-arm/translate.c | 1 +
 target-arm/translate.h | 1 +
 3 files changed, 9 insertions(+)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index b48b81a..e041437 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -1551,6 +1551,8 @@ static inline bool arm_singlestep_active(CPUARMState *env)
  */
 #define ARM_TBFLAG_XSCALE_CPAR_SHIFT 20
 #define ARM_TBFLAG_XSCALE_CPAR_MASK (3 << ARM_TBFLAG_XSCALE_CPAR_SHIFT)
+#define ARM_TBFLAG_NS_SHIFT         22
+#define ARM_TBFLAG_NS_MASK          (1 << ARM_TBFLAG_NS_SHIFT)
 
 /* Bit usage when in AArch64 state */
 #define ARM_TBFLAG_AA64_EL_SHIFT    0
@@ -1595,6 +1597,8 @@ static inline bool arm_singlestep_active(CPUARMState *env)
     (((F) & ARM_TBFLAG_AA64_SS_ACTIVE_MASK) >> ARM_TBFLAG_AA64_SS_ACTIVE_SHIFT)
 #define ARM_TBFLAG_AA64_PSTATE_SS(F) \
     (((F) & ARM_TBFLAG_AA64_PSTATE_SS_MASK) >> ARM_TBFLAG_AA64_PSTATE_SS_SHIFT)
+#define ARM_TBFLAG_NS(F) \
+    (((F) & ARM_TBFLAG_NS_MASK) >> ARM_TBFLAG_NS_SHIFT)
 
 static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
                                         target_ulong *cs_base, int *flags)
@@ -1644,6 +1648,9 @@ static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
         if (privmode) {
             *flags |= ARM_TBFLAG_PRIV_MASK;
         }
+        if (!(use_secure_reg(env))) {
+            *flags |= ARM_TBFLAG_NS_MASK;
+        }
         if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)
             || arm_el_is_aa64(env, 1)) {
             *flags |= ARM_TBFLAG_VFPEN_MASK;
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 91958b6..aa17a20 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -11002,6 +11002,7 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
 #if !defined(CONFIG_USER_ONLY)
     dc->user = (ARM_TBFLAG_PRIV(tb->flags) == 0);
 #endif
+    dc->ns = ARM_TBFLAG_NS(tb->flags);
     dc->cpacr_fpen = ARM_TBFLAG_CPACR_FPEN(tb->flags);
     dc->vfp_enabled = ARM_TBFLAG_VFPEN(tb->flags);
     dc->vec_len = ARM_TBFLAG_VECLEN(tb->flags);
diff --git a/target-arm/translate.h b/target-arm/translate.h
index 41a9071..f6ee789 100644
--- a/target-arm/translate.h
+++ b/target-arm/translate.h
@@ -20,6 +20,7 @@ typedef struct DisasContext {
 #if !defined(CONFIG_USER_ONLY)
     int user;
 #endif
+    bool ns;        /* Use non-secure CPREG bank on access */
     bool cpacr_fpen; /* FP enabled via CPACR.FPEN */
     bool vfp_enabled; /* FP enabled via FPSCR.EN */
     int vec_len;
-- 
1.8.3.2

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

* [Qemu-devel] [PATCH v7 11/32] target-arm: add CPREG secure state support
  2014-10-21 16:55 [Qemu-devel] [PATCH v7 00/32] target-arm: add Security Extensions for CPUs Greg Bellows
                   ` (9 preceding siblings ...)
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 10/32] target-arm: add non-secure Translation Block flag Greg Bellows
@ 2014-10-21 16:55 ` Greg Bellows
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 12/32] target-arm: add secure state bit to CPREG hash Greg Bellows
                   ` (21 subsequent siblings)
  32 siblings, 0 replies; 53+ messages in thread
From: Greg Bellows @ 2014-10-21 16:55 UTC (permalink / raw)
  To: qemu-devel, peter.maydell, serge.fdrv, edgar.iglesias, aggelerf
  Cc: greg.bellows

From: Fabian Aggeler <aggelerf@ethz.ch>

Prepare ARMCPRegInfo to support specifying two fieldoffsets per
register definition. This will allow us to keep one register
definition for banked registers (different offsets for secure/
non-secure world).

Also added secure state tracking field and flags.  This allows for
identification of the register info secure state.

Signed-off-by: Fabian Aggeler <aggelerf@ethz.ch>
Signed-off-by: Greg Bellows <greg.bellows@linaro.org>

==========

v6 -> v7
- Add naming for fieldoffset fields and macros for accessing.  This was needed
  to overcome issues with the GCC-4.4 compiler.

v5 -> v6
- Separate out secure CPREG flags
- Add convenience macro for testing flags
- Removed extraneous newline
- Move add_cpreg_to_hashtable() functionality to a later commit for which it is
  dependent on.
- Added comment explaining fieldoffset padding

v4 -> v5
- Added ARM CP register secure and non-secure bank flags
- Added setting of secure and non-secure flags furing registration

Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
---
 target-arm/cpu.h | 50 +++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 47 insertions(+), 3 deletions(-)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index e041437..786deac 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -990,6 +990,24 @@ enum {
     ARM_CP_STATE_BOTH = 2,
 };
 
+/* ARM CP register secure state flags.  These flags identify security state
+ * attributes for a given CP register entry.
+ * The existence of both or neither secure and non-secure flags indicates that
+ * the register has both a secure and non-secure hash entry.  A single one of
+ * these flags causes the register to only be hashed for the specified
+ * security state.
+ * Although definitions may have any combination of the S/NS bits, each
+ * registered entry will only have one to identify whether the entry is secure
+ * or non-secure.
+ */
+enum {
+    ARM_CP_SECSTATE_S =   (1 << 0), /* bit[0]: Secure state register */
+    ARM_CP_SECSTATE_NS =  (1 << 1), /* bit[1]: Non-secure state register */
+};
+
+/* Convenience macro for checking for a specific bit */
+#define ARM_CP_SECSTATE_TEST(_ri, _flag) (((_ri)->secure & (_flag)) == (_flag))
+
 /* Return true if cptype is a valid type field. This is used to try to
  * catch errors where the sentinel has been accidentally left off the end
  * of a list of registers.
@@ -1124,6 +1142,8 @@ struct ARMCPRegInfo {
     int type;
     /* Access rights: PL*_[RW] */
     int access;
+    /* Security state: ARM_CP_SECSTATE_* bits/values */
+    int secure;
     /* The opaque pointer passed to define_arm_cp_regs_with_opaque() when
      * this register was defined: can be used to hand data through to the
      * register read/write functions, since they are passed the ARMCPRegInfo*.
@@ -1133,12 +1153,36 @@ struct ARMCPRegInfo {
      * fieldoffset is non-zero, the reset value of the register.
      */
     uint64_t resetvalue;
-    /* Offset of the field in CPUARMState for this register. This is not
-     * needed if either:
+    /* Offsets of the fields (secure/non-secure) in CPUARMState for this
+     * register. The array will be accessed by the ns bit which means the
+     * secure instance has to be at [0] while the non-secure instance must be
+     * at [1]. If a register is not banked .fieldoffset can be used, which maps
+     * to the non-secure bank.
+     *
+     * Extra padding is added to align the default fieldoffset field with the
+     * non-secure bank_fieldoffsets entry.  This is necessary for maintaining
+     * the same storage offset when AArch64 and banked AArch32 are seperately
+     * defined.
+     *
+     * This is not needed if either:
      *  1. type is ARM_CP_CONST or one of the ARM_CP_SPECIALs
      *  2. both readfn and writefn are specified
      */
-    ptrdiff_t fieldoffset; /* offsetof(CPUARMState, field) */
+    union { /* offsetof(CPUARMState, field) */
+        struct {
+            ptrdiff_t _fieldoffset_padding;
+            ptrdiff_t fieldoffset;
+        } _fieldoffset_s;
+        ptrdiff_t bank_fieldoffsets[2];
+    } _fieldoffset_u;
+
+/*
+ * GCC-4.4 can't handle the anonymous union/struct combos, so we'll add names
+ * along with macros for short-cutting the field names.
+ */
+#define bank_fieldoffsets _fieldoffset_u.bank_fieldoffsets
+#define fieldoffset _fieldoffset_u._fieldoffset_s.fieldoffset
+
     /* Function for making any access checks for this register in addition to
      * those specified by the 'access' permissions bits. If NULL, no extra
      * checks required. The access check is performed at runtime, not at
-- 
1.8.3.2

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

* [Qemu-devel] [PATCH v7 12/32] target-arm: add secure state bit to CPREG hash
  2014-10-21 16:55 [Qemu-devel] [PATCH v7 00/32] target-arm: add Security Extensions for CPUs Greg Bellows
                   ` (10 preceding siblings ...)
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 11/32] target-arm: add CPREG secure state support Greg Bellows
@ 2014-10-21 16:55 ` Greg Bellows
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 13/32] target-arm: insert AArch32 cpregs twice into hashtable Greg Bellows
                   ` (20 subsequent siblings)
  32 siblings, 0 replies; 53+ messages in thread
From: Greg Bellows @ 2014-10-21 16:55 UTC (permalink / raw)
  To: qemu-devel, peter.maydell, serge.fdrv, edgar.iglesias, aggelerf
  Cc: greg.bellows

Added additional NS-bit to CPREG hash encoding.  Updated hash lookup
locations to specify hash bit currently set to non-secure.

Signed-off-by: Greg Bellows <greg.bellows@linaro.org>

==========

v5 -> v6
- Globally replace Aarch# with AArch#

Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
---
 target-arm/cpu.h       | 25 ++++++++++++++++++++-----
 target-arm/helper.c    |  6 +++---
 target-arm/translate.c | 16 ++++++++++------
 3 files changed, 33 insertions(+), 14 deletions(-)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 786deac..4273621 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -876,6 +876,7 @@ void armv7m_nvic_complete_irq(void *opaque, int irq);
  *  Crn, Crm, opc1, opc2 fields
  *  32 or 64 bit register (ie is it accessed via MRC/MCR
  *    or via MRRC/MCRR?)
+ *  non-secure/secure bank (AArch32 only)
  * We allow 4 bits for opc1 because MRRC/MCRR have a 4 bit field.
  * (In this case crn and opc2 should be zero.)
  * For AArch64, there is no 32/64 bit size distinction;
@@ -893,9 +894,16 @@ void armv7m_nvic_complete_irq(void *opaque, int irq);
 #define CP_REG_AA64_SHIFT 28
 #define CP_REG_AA64_MASK (1 << CP_REG_AA64_SHIFT)
 
-#define ENCODE_CP_REG(cp, is64, crn, crm, opc1, opc2)   \
-    (((cp) << 16) | ((is64) << 15) | ((crn) << 11) |    \
-     ((crm) << 7) | ((opc1) << 3) | (opc2))
+/* To enable banking of coprocessor registers depending on ns-bit we
+ * add a bit to distinguish between secure and non-secure cpregs in the
+ * hashtable.
+ */
+#define CP_REG_NS_SHIFT 29
+#define CP_REG_NS_MASK(nsbit) (nsbit << CP_REG_NS_SHIFT)
+
+#define ENCODE_CP_REG(cp, is64, crn, crm, opc1, opc2, ns)   \
+    (CP_REG_NS_MASK(ns) | ((cp) << 16) | ((is64) << 15) |   \
+     ((crn) << 11) | ((crm) << 7) | ((opc1) << 3) | (opc2))
 
 #define ENCODE_AA64_CP_REG(cp, crn, crm, op0, op1, op2) \
     (CP_REG_AA64_MASK |                                 \
@@ -914,8 +922,15 @@ static inline uint32_t kvm_to_cpreg_id(uint64_t kvmid)
     uint32_t cpregid = kvmid;
     if ((kvmid & CP_REG_ARCH_MASK) == CP_REG_ARM64) {
         cpregid |= CP_REG_AA64_MASK;
-    } else if ((kvmid & CP_REG_SIZE_MASK) == CP_REG_SIZE_U64) {
-        cpregid |= (1 << 15);
+    } else {
+        if ((kvmid & CP_REG_SIZE_MASK) == CP_REG_SIZE_U64) {
+            cpregid |= (1 << 15);
+        }
+
+        /* KVM is always non-secure so add the NS flag on AArch32 register
+         * entries.
+         */
+         cpregid |= CP_REG_NS_MASK(SCR_NS);
     }
     return cpregid;
 }
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 78aeb31..5f3bdc0 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -3288,7 +3288,7 @@ CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp)
 
 static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
                                    void *opaque, int state,
-                                   int crm, int opc1, int opc2)
+                                   int crm, int opc1, int opc2, int nsbit)
 {
     /* Private utility function for define_one_arm_cp_reg_with_opaque():
      * add a single reginfo struct to the hash table.
@@ -3327,7 +3327,7 @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
         *key = ENCODE_AA64_CP_REG(r2->cp, r2->crn, crm,
                                   r2->opc0, opc1, opc2);
     } else {
-        *key = ENCODE_CP_REG(r2->cp, is64, r2->crn, crm, opc1, opc2);
+        *key = ENCODE_CP_REG(r2->cp, is64, r2->crn, crm, opc1, opc2, nsbit);
     }
     if (opaque) {
         r2->opaque = opaque;
@@ -3477,7 +3477,7 @@ void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
                         continue;
                     }
                     add_cpreg_to_hashtable(cpu, r, opaque, state,
-                                           crm, opc1, opc2);
+                                           crm, opc1, opc2, SCR_NS);
                 }
             }
         }
diff --git a/target-arm/translate.c b/target-arm/translate.c
index aa17a20..459fedc 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -712,7 +712,7 @@ static void gen_thumb2_parallel_addsub(int op1, int op2, TCGv_i32 a, TCGv_i32 b)
 
 /*
  * generate a conditional branch based on ARM condition code cc.
- * This is common between ARM and Aarch64 targets.
+ * This is common between ARM and AArch64 targets.
  */
 void arm_gen_test_cc(int cc, int label)
 {
@@ -7071,7 +7071,7 @@ static int disas_coproc_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
     rt = (insn >> 12) & 0xf;
 
     ri = get_arm_cp_reginfo(s->cp_regs,
-                            ENCODE_CP_REG(cpnum, is64, crn, crm, opc1, opc2));
+            ENCODE_CP_REG(cpnum, is64, crn, crm, opc1, opc2, s->ns));
     if (ri) {
         /* Check access permissions */
         if (!cp_access_ok(s->current_el, ri, isread)) {
@@ -7261,12 +7261,16 @@ static int disas_coproc_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
      */
     if (is64) {
         qemu_log_mask(LOG_UNIMP, "%s access to unsupported AArch32 "
-                      "64 bit system register cp:%d opc1: %d crm:%d\n",
-                      isread ? "read" : "write", cpnum, opc1, crm);
+                      "64 bit system register cp:%d opc1: %d crm:%d "
+                      "(%s)\n",
+                      isread ? "read" : "write", cpnum, opc1, crm,
+                      s->ns ? "non-secure" : "secure");
     } else {
         qemu_log_mask(LOG_UNIMP, "%s access to unsupported AArch32 "
-                      "system register cp:%d opc1:%d crn:%d crm:%d opc2:%d\n",
-                      isread ? "read" : "write", cpnum, opc1, crn, crm, opc2);
+                      "system register cp:%d opc1:%d crn:%d crm:%d opc2:%d "
+                      "(%s)\n",
+                      isread ? "read" : "write", cpnum, opc1, crn, crm, opc2,
+                      s->ns ? "non-secure" : "secure");
     }
 
     return 1;
-- 
1.8.3.2

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

* [Qemu-devel] [PATCH v7 13/32] target-arm: insert AArch32 cpregs twice into hashtable
  2014-10-21 16:55 [Qemu-devel] [PATCH v7 00/32] target-arm: add Security Extensions for CPUs Greg Bellows
                   ` (11 preceding siblings ...)
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 12/32] target-arm: add secure state bit to CPREG hash Greg Bellows
@ 2014-10-21 16:55 ` Greg Bellows
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 14/32] target-arm: move AArch32 SCR into security reglist Greg Bellows
                   ` (19 subsequent siblings)
  32 siblings, 0 replies; 53+ messages in thread
From: Greg Bellows @ 2014-10-21 16:55 UTC (permalink / raw)
  To: qemu-devel, peter.maydell, serge.fdrv, edgar.iglesias, aggelerf
  Cc: greg.bellows

From: Fabian Aggeler <aggelerf@ethz.ch>

Prepare for cp register banking by inserting every cp register twice,
once for secure world and once for non-secure world.

Signed-off-by: Fabian Aggeler <aggelerf@ethz.ch>
Signed-off-by: Greg Bellows <greg.bellows@linaro.org>

==========

v5 -> v6
- Fixed NS-bit number in the CPREG hash lookup from 27 to 29.
- Switched to dedicated CPREG secure flags.
- Fixed disablement of reset and migration of common 32/64-bit registers.
- Globally replace Aarch# with AArch#

v4 -> v5
- Added use of ARM CP secure/non-secure bank flags during register processing
  in define_one_arm_cp_reg_with_opaque().  We now only register the specified
  bank if only one flag is specified, otherwise we register both a secure and
  non-secure instance.

Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
---
 target-arm/helper.c | 90 ++++++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 75 insertions(+), 15 deletions(-)

diff --git a/target-arm/helper.c b/target-arm/helper.c
index 5f3bdc0..37cd389 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -3296,22 +3296,60 @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
     uint32_t *key = g_new(uint32_t, 1);
     ARMCPRegInfo *r2 = g_memdup(r, sizeof(ARMCPRegInfo));
     int is64 = (r->type & ARM_CP_64BIT) ? 1 : 0;
-    if (r->state == ARM_CP_STATE_BOTH && state == ARM_CP_STATE_AA32) {
-        /* The AArch32 view of a shared register sees the lower 32 bits
-         * of a 64 bit backing field. It is not migratable as the AArch64
-         * view handles that. AArch64 also handles reset.
-         * We assume it is a cp15 register if the .cp field is left unset.
-         */
-        if (r2->cp == 0) {
-            r2->cp = 15;
+
+    if (state == ARM_CP_STATE_AA32) {
+        /* Clear the secure state flags and set based on incoming nsbit */
+        r2->secure &= ~(ARM_CP_SECSTATE_S | ARM_CP_SECSTATE_NS);
+        r2->secure |= ARM_CP_SECSTATE_S << nsbit;
+
+        if (r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1]) {
+            /* Register is banked (using both entries in array).
+             * Overwriting fieldoffset as the array was only used to define
+             * banked registers but later only fieldoffset is used.
+             */
+            r2->fieldoffset = r->bank_fieldoffsets[nsbit];
+
+            /* If V8 is enabled then we don't need to migrate or reset the
+             * AArch32 version of the banked registers as this will be handled
+             * through the AArch64 view.
+             * If v7 then we don't need to migrate or reset the AArch32
+             * non-secure bank as this will be handled through the AArch64
+             * view.  In this case the secure bank is not mirrored, so we must
+             * preserve it's reset criteria and allow it to be migrated.
+             *
+             * The exception to the above is cpregs with a crn of 13
+             * (specifically FCSEIDR and CONTEXTIDR) in which case there may
+             * not be an AArch64 equivalent for one or either bank so migration
+             * and reset must be preserved.
+             */
+            if (r->state == ARM_CP_STATE_BOTH) {
+                if ((arm_feature(&cpu->env, ARM_FEATURE_V8) && r->crn != 13) ||
+                    nsbit) {
+                    r2->type |= ARM_CP_NO_MIGRATE;
+                    r2->resetfn = arm_cp_reset_ignore;
+                }
+            }
+        } else if (!nsbit) {
+            /* The register is not banked so we only want to allow migration of
+             * the non-secure instance.
+             */
+            r2->type |= ARM_CP_NO_MIGRATE;
+            r2->resetfn = arm_cp_reset_ignore;
         }
-        r2->type |= ARM_CP_NO_MIGRATE;
-        r2->resetfn = arm_cp_reset_ignore;
+
+        if (r->state == ARM_CP_STATE_BOTH) {
+            /* We assume it is a cp15 register if the .cp field is left unset.
+             */
+            if (r2->cp == 0) {
+                r2->cp = 15;
+            }
+
 #ifdef HOST_WORDS_BIGENDIAN
-        if (r2->fieldoffset) {
-            r2->fieldoffset += sizeof(uint32_t);
-        }
+            if (r2->fieldoffset) {
+                r2->fieldoffset += sizeof(uint32_t);
+            }
 #endif
+        }
     }
     if (state == ARM_CP_STATE_AA64) {
         /* To allow abbreviation of ARMCPRegInfo
@@ -3476,8 +3514,30 @@ void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
                     if (r->state != state && r->state != ARM_CP_STATE_BOTH) {
                         continue;
                     }
-                    add_cpreg_to_hashtable(cpu, r, opaque, state,
-                                           crm, opc1, opc2, SCR_NS);
+                    if (state == ARM_CP_STATE_AA32) {
+                        /* Under AArch32 CP registers can be common
+                         * (same for secure and non-secure world) or banked.
+                         */
+                        uint32_t s =
+                          r->secure & (ARM_CP_SECSTATE_S | ARM_CP_SECSTATE_NS);
+                        if (ARM_CP_SECSTATE_S == s) {
+                            add_cpreg_to_hashtable(cpu, r, opaque, state,
+                                    crm, opc1, opc2, !SCR_NS);
+                        } else if (ARM_CP_SECSTATE_NS == s) {
+                            add_cpreg_to_hashtable(cpu, r, opaque, state,
+                                    crm, opc1, opc2, SCR_NS);
+                        } else {
+                            add_cpreg_to_hashtable(cpu, r, opaque, state,
+                                    crm, opc1, opc2, !SCR_NS);
+                            add_cpreg_to_hashtable(cpu, r, opaque, state,
+                                    crm, opc1, opc2, SCR_NS);
+                        }
+                    } else {
+                        /* AArch64 registers get mapped to non-secure instance
+                         * of AArch32 */
+                        add_cpreg_to_hashtable(cpu, r, opaque, state,
+                                crm, opc1, opc2, SCR_NS);
+                    }
                 }
             }
         }
-- 
1.8.3.2

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

* [Qemu-devel] [PATCH v7 14/32] target-arm: move AArch32 SCR into security reglist
  2014-10-21 16:55 [Qemu-devel] [PATCH v7 00/32] target-arm: add Security Extensions for CPUs Greg Bellows
                   ` (12 preceding siblings ...)
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 13/32] target-arm: insert AArch32 cpregs twice into hashtable Greg Bellows
@ 2014-10-21 16:55 ` Greg Bellows
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 15/32] target-arm: implement IRQ/FIQ routing to Monitor mode Greg Bellows
                   ` (18 subsequent siblings)
  32 siblings, 0 replies; 53+ messages in thread
From: Greg Bellows @ 2014-10-21 16:55 UTC (permalink / raw)
  To: qemu-devel, peter.maydell, serge.fdrv, edgar.iglesias, aggelerf
  Cc: greg.bellows

From: Fabian Aggeler <aggelerf@ethz.ch>

Define a new ARM CP register info list for the ARMv7 Security Extension
feature. Register that list only for ARM cores with Security Extension/EL3
support. Moving AArch32 SCR into Security Extension register group.

Signed-off-by: Sergey Fedorov <s.fedorov@samsung.com>
Signed-off-by: Fabian Aggeler <aggelerf@ethz.ch>
Signed-off-by: Greg Bellows <greg.bellows@linaro.org>

------------------
v4 -> v5
- Added reset value on SCR_EL3
- Squashed SCR Migration fix (previously patch 33)
  This patch adds code to mark duplicate CP register registrations as
  NO_MIGRATE to avoid duplicate migrations.

v3 -> v4
- Renamed security_cp_reginfo to v7_el3_cp_reginfo
- Conditionalized define on whether v7 or v8 were enabled

Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
---
 target-arm/helper.c | 26 +++++++++++++++++++-------
 1 file changed, 19 insertions(+), 7 deletions(-)

diff --git a/target-arm/helper.c b/target-arm/helper.c
index 37cd389..bc82951 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -898,9 +898,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 = offsetoflow32(CPUARMState, cp15.scr_el3),
-      .resetvalue = 0, .writefn = scr_write },
     { .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 },
@@ -2335,11 +2332,21 @@ static const ARMCPRegInfo v8_el3_cp_reginfo[] = {
       .access = PL3_RW, .writefn = vbar_write,
       .fieldoffset = offsetof(CPUARMState, cp15.vbar_el[3]),
       .resetvalue = 0 },
-    { .name = "SCR_EL3", .state = ARM_CP_STATE_AA64,
-      .type = ARM_CP_NO_MIGRATE,
+      /* SCR will always be registered for v7, but not necessarily for v8, so
+       * this entry is marked to allow migration to be handled by the v7
+       * registration instance.
+       */
+    { .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 },
+      .resetvalue = 0, .writefn = scr_write },
+    REGINFO_SENTINEL
+};
+
+static const ARMCPRegInfo v7_el3_cp_reginfo[] = {
+    { .name = "SCR", .cp = 15, .crn = 1, .crm = 1, .opc1 = 0, .opc2 = 0,
+      .access = PL3_RW, .fieldoffset = offsetof(CPUARMState, cp15.scr_el3),
+      .resetvalue = 0, .writefn = scr_write},
     REGINFO_SENTINEL
 };
 
@@ -2960,7 +2967,12 @@ void register_cp_regs_for_features(ARMCPU *cpu)
         }
     }
     if (arm_feature(env, ARM_FEATURE_EL3)) {
-        define_arm_cp_regs(cpu, v8_el3_cp_reginfo);
+        if (arm_feature(env, ARM_FEATURE_V8)) {
+            define_arm_cp_regs(cpu, v8_el3_cp_reginfo);
+        }
+        if (arm_feature(env, ARM_FEATURE_V7)) {
+            define_arm_cp_regs(cpu, v7_el3_cp_reginfo);
+        }
     }
     if (arm_feature(env, ARM_FEATURE_MPU)) {
         /* These are the MPU registers prior to PMSAv6. Any new
-- 
1.8.3.2

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

* [Qemu-devel] [PATCH v7 15/32] target-arm: implement IRQ/FIQ routing to Monitor mode
  2014-10-21 16:55 [Qemu-devel] [PATCH v7 00/32] target-arm: add Security Extensions for CPUs Greg Bellows
                   ` (13 preceding siblings ...)
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 14/32] target-arm: move AArch32 SCR into security reglist Greg Bellows
@ 2014-10-21 16:55 ` Greg Bellows
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 16/32] target-arm: respect SCR.FW, SCR.AW and SCTLR.NMFI Greg Bellows
                   ` (17 subsequent siblings)
  32 siblings, 0 replies; 53+ messages in thread
From: Greg Bellows @ 2014-10-21 16:55 UTC (permalink / raw)
  To: qemu-devel, peter.maydell, serge.fdrv, edgar.iglesias, aggelerf
  Cc: greg.bellows

From: Fabian Aggeler <aggelerf@ethz.ch>

SCR.{IRQ/FIQ} bits allow to route IRQ/FIQ exceptions to monitor CPU
mode. When taking IRQ exception to monitor mode FIQ exception is
additionally masked.

Signed-off-by: Sergey Fedorov <s.fedorov@samsung.com>
Signed-off-by: Fabian Aggeler <aggelerf@ethz.ch>
Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
---
 target-arm/helper.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/target-arm/helper.c b/target-arm/helper.c
index bc82951..a22fcb2 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -4212,12 +4212,21 @@ void arm_cpu_do_interrupt(CPUState *cs)
         /* Disable IRQ and imprecise data aborts.  */
         mask = CPSR_A | CPSR_I;
         offset = 4;
+        if (env->cp15.scr_el3 & SCR_IRQ) {
+            /* IRQ routed to monitor mode */
+            new_mode = ARM_CPU_MODE_MON;
+            mask |= CPSR_F;
+        }
         break;
     case EXCP_FIQ:
         new_mode = ARM_CPU_MODE_FIQ;
         addr = 0x1c;
         /* Disable FIQ, IRQ and imprecise data aborts.  */
         mask = CPSR_A | CPSR_I | CPSR_F;
+        if (env->cp15.scr_el3 & SCR_FIQ) {
+            /* FIQ routed to monitor mode */
+            new_mode = ARM_CPU_MODE_MON;
+        }
         offset = 4;
         break;
     case EXCP_SMC:
-- 
1.8.3.2

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

* [Qemu-devel] [PATCH v7 16/32] target-arm: respect SCR.FW, SCR.AW and SCTLR.NMFI
  2014-10-21 16:55 [Qemu-devel] [PATCH v7 00/32] target-arm: add Security Extensions for CPUs Greg Bellows
                   ` (14 preceding siblings ...)
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 15/32] target-arm: implement IRQ/FIQ routing to Monitor mode Greg Bellows
@ 2014-10-21 16:55 ` Greg Bellows
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 17/32] target-arm: add NSACR register Greg Bellows
                   ` (16 subsequent siblings)
  32 siblings, 0 replies; 53+ messages in thread
From: Greg Bellows @ 2014-10-21 16:55 UTC (permalink / raw)
  To: qemu-devel, peter.maydell, serge.fdrv, edgar.iglesias, aggelerf
  Cc: greg.bellows

From: Fabian Aggeler <aggelerf@ethz.ch>

bits when modifying CPSR.

Signed-off-by: Fabian Aggeler <aggelerf@ethz.ch>
Signed-off-by: Greg Bellows <greg.bellows@linaro.org>

---------------
v3 -> v4
- Fixed up conditions for ignoring CPSR.A/F updates by isolating to v7 and
  checking for the existence of EL3 and non-existence of EL2.

Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
---
 target-arm/helper.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 59 insertions(+), 3 deletions(-)

diff --git a/target-arm/helper.c b/target-arm/helper.c
index a22fcb2..2af8fbb 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -3645,9 +3645,6 @@ void cpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
         env->GE = (val >> 16) & 0xf;
     }
 
-    env->daif &= ~(CPSR_AIF & mask);
-    env->daif |= val & CPSR_AIF & mask;
-
     if ((env->uncached_cpsr ^ val) & mask & CPSR_M) {
         if (bad_mode_switch(env, val & CPSR_M)) {
             /* Attempt to switch to an invalid mode: this is UNPREDICTABLE.
@@ -3659,6 +3656,65 @@ void cpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
             switch_mode(env, val & CPSR_M);
         }
     }
+
+    /* In a V7 implementation that incldoes the security extensions but does
+     * not include Virtualization Extensions the SCR.FW and SCR.AW bits control
+     * whether non-secure software is allowed to change the CPSR_F and CPSR_A
+     * bits respectively.
+     *
+     * In a V8 implementation, it is permitted for privileged software to
+     * change the CPSR A/F bits regardless of the SCR.AW/FW bits.  However,
+     * when the SPSR is copied to the CPSR, the SCR.AW/FW bits control whether
+     * the CPSR.A/F bits are copied.
+     */
+    if (!arm_feature(env, ARM_FEATURE_V8)) {
+        if ((mask & CPSR_A) &&
+            (val & CPSR_A) != (env->uncached_cpsr & CPSR_A) &&
+            arm_feature(env, ARM_FEATURE_EL3) &&
+            !arm_feature(env, ARM_FEATURE_EL2) &&
+            !(env->cp15.scr_el3 & SCR_AW) && !arm_is_secure(env)) {
+            qemu_log_mask(LOG_GUEST_ERROR,
+                          "Ignoring attempt to switch CPSR_A flag from "
+                          "non-secure world with SCR.AW bit clear\n");
+            mask &= ~CPSR_A;
+        }
+
+        if ((mask & CPSR_F) &&
+            (val & CPSR_F) != (env->uncached_cpsr & CPSR_F)) {
+            /*
+             * The existence of the security extension (EL3) and the
+             * non-existence of the virtualization extension affects whether
+             * the CPSR.F bit can be modified.
+             */
+            if (arm_feature(env, ARM_FEATURE_EL3) &&
+                !arm_feature(env, ARM_FEATURE_EL2)) {
+                /* CPSR.F cannot be changed in nonsecure with SCR.FW clear */
+                if (!(env->cp15.scr_el3 & SCR_FW) && !arm_is_secure(env)) {
+                    qemu_log_mask(LOG_GUEST_ERROR,
+                                  "Ignoring attempt to switch CPSR_F flag from "
+                                  "non-secure world with SCR.FW bit clear\n");
+                    mask &= ~CPSR_F;
+                }
+
+                /* Check whether non-maskable FIQ (NMFI) support is enabled.
+                 * If this bit is set software is not allowed to mask
+                 * FIQs, but is allowed to set CPSR_F to 0.
+                 */
+                if ((A32_BANKED_CURRENT_REG_GET(env, sctlr) & SCTLR_NMFI) &&
+                    (val & CPSR_F)) {
+                    qemu_log_mask(LOG_GUEST_ERROR,
+                                  "Ignoring attempt to enable CPSR_F flag "
+                                  "(non-maskable FIQ [NMFI] support "
+                                  "enabled)\n");
+                    mask &= ~CPSR_F;
+                }
+            }
+        }
+    }
+
+    env->daif &= ~(CPSR_AIF & mask);
+    env->daif |= val & CPSR_AIF & mask;
+
     mask &= ~CACHED_CPSR_BITS;
     env->uncached_cpsr = (env->uncached_cpsr & ~mask) | (val & mask);
 }
-- 
1.8.3.2

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

* [Qemu-devel] [PATCH v7 17/32] target-arm: add NSACR register
  2014-10-21 16:55 [Qemu-devel] [PATCH v7 00/32] target-arm: add Security Extensions for CPUs Greg Bellows
                   ` (15 preceding siblings ...)
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 16/32] target-arm: respect SCR.FW, SCR.AW and SCTLR.NMFI Greg Bellows
@ 2014-10-21 16:55 ` Greg Bellows
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 18/32] target-arm: add SDER definition Greg Bellows
                   ` (15 subsequent siblings)
  32 siblings, 0 replies; 53+ messages in thread
From: Greg Bellows @ 2014-10-21 16:55 UTC (permalink / raw)
  To: qemu-devel, peter.maydell, serge.fdrv, edgar.iglesias, aggelerf
  Cc: greg.bellows

From: Fabian Aggeler <aggelerf@ethz.ch>

Implements NSACR register with corresponding read/write functions
for ARMv7 and ARMv8.

Signed-off-by: Sergey Fedorov <s.fedorov@samsung.com>
Signed-off-by: Fabian Aggeler <aggelerf@ethz.ch>
Signed-off-by: Greg Bellows <greg.bellows@linaro.org>

----------
v4 -> v5
- Changed to use renamed arm_current_el()

Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
---
 target-arm/cpu.h    |  6 +++++
 target-arm/helper.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 73 insertions(+), 1 deletion(-)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 4273621..f9221a4 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -181,6 +181,7 @@ 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_nsacr; /* Non-secure access control 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.  */
@@ -634,6 +635,11 @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
 #define SCR_AARCH32_MASK      (0x3fff & ~(SCR_RW | SCR_ST))
 #define SCR_AARCH64_MASK      (0x3fff & ~SCR_NET)
 
+#define NSACR_NSTRCDIS (1U << 20)
+#define NSACR_RFR      (1U << 19)
+#define NSACR_NSASEDIS (1U << 15)
+#define NSACR_NSD32DIS (1U << 14)
+
 /* 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 2af8fbb..f12181f 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -520,7 +520,19 @@ static void cpacr_write(CPUARMState *env, const ARMCPRegInfo *ri,
             /* VFP coprocessor: cp10 & cp11 [23:20] */
             mask |= (1 << 31) | (1 << 30) | (0xf << 20);
 
-            if (!arm_feature(env, ARM_FEATURE_NEON)) {
+            if (arm_feature(env, ARM_FEATURE_NEON)) {
+                /* NSACR can disable non-secure writes to
+                 * ASEDIS [31] or D32DIS [30]
+                 */
+                if (arm_feature(env, ARM_FEATURE_EL3) && !arm_is_secure(env)) {
+                    if ((env->cp15.c1_nsacr & NSACR_NSASEDIS)) {
+                        mask &= ~(1 << 31);
+                    }
+                    if ((env->cp15.c1_nsacr & NSACR_NSD32DIS)) {
+                        mask &= ~(1 << 30);
+                    }
+                }
+            } else {
                 /* ASEDIS [31] bit is RAO/WI */
                 value |= (1 << 31);
             }
@@ -532,6 +544,7 @@ static void cpacr_write(CPUARMState *env, const ARMCPRegInfo *ri,
                     !arm_feature(env, ARM_FEATURE_VFP3)) {
                 /* D32DIS [30] is RAO/WI if D16-31 are not implemented. */
                 value |= (1 << 30);
+                mask |= (1 << 30);
             }
         }
         value &= mask;
@@ -2310,6 +2323,55 @@ static const ARMCPRegInfo v8_el2_cp_reginfo[] = {
     REGINFO_SENTINEL
 };
 
+static void nsacr_write(CPUARMState *env, const ARMCPRegInfo *ri,
+                      uint64_t value)
+{
+    uint32_t mask = 0;
+
+    /* Pre ARMv8 some bits are RAO or UNK/SBZP */
+    if (!arm_feature(env, ARM_FEATURE_V8)) {
+
+        if (arm_feature(env, ARM_FEATURE_VFP)) {
+            mask |= NSACR_NSASEDIS | NSACR_NSD32DIS;
+
+            if (!arm_feature(env, ARM_FEATURE_NEON)) {
+                /* NSASEDIS are RAO/WI */
+                value |= NSACR_NSASEDIS;
+            }
+
+            /* VFPv3 and upwards with NEON implement 32 double precision
+             * registers (D0-D31).
+             */
+            if (!arm_feature(env, ARM_FEATURE_NEON) ||
+                    !arm_feature(env, ARM_FEATURE_VFP3)) {
+                /* NSD32DIS is RAO/WI if D16-31 are not implemented. */
+                value |= NSACR_NSD32DIS;
+            }
+        }
+
+        /* cpn bits [13:0] */
+        mask = 0x3fff;
+
+        value &= mask;
+    }
+
+    raw_write(env, ri, value);
+}
+
+static uint64_t nsacr_read(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+    uint64_t ret = raw_read(env, ri);
+
+    if (arm_feature(env, ARM_FEATURE_V8)) {
+        if (!arm_feature(env, ARM_FEATURE_EL3) || (
+                arm_el_is_aa64(env, 3) && !is_a64(env) &&
+                arm_current_el(env) != 3)) {
+            ret = 0x0000C00;
+        }
+    }
+    return ret;
+}
+
 static const ARMCPRegInfo v8_el3_cp_reginfo[] = {
     { .name = "ELR_EL3", .state = ARM_CP_STATE_AA64,
       .type = ARM_CP_NO_MIGRATE,
@@ -2347,6 +2409,10 @@ static const ARMCPRegInfo v7_el3_cp_reginfo[] = {
     { .name = "SCR", .cp = 15, .crn = 1, .crm = 1, .opc1 = 0, .opc2 = 0,
       .access = PL3_RW, .fieldoffset = offsetof(CPUARMState, cp15.scr_el3),
       .resetvalue = 0, .writefn = scr_write},
+    { .name = "NSACR", .cp = 15, .crn = 1, .crm = 1, .opc1 = 0, .opc2 = 2,
+      .access = PL3_RW | PL1_R, .resetvalue = 0,
+      .writefn = nsacr_write, .readfn = nsacr_read,
+      .fieldoffset = offsetof(CPUARMState, cp15.c1_nsacr) },
     REGINFO_SENTINEL
 };
 
-- 
1.8.3.2

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

* [Qemu-devel] [PATCH v7 18/32] target-arm: add SDER definition
  2014-10-21 16:55 [Qemu-devel] [PATCH v7 00/32] target-arm: add Security Extensions for CPUs Greg Bellows
                   ` (16 preceding siblings ...)
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 17/32] target-arm: add NSACR register Greg Bellows
@ 2014-10-21 16:55 ` Greg Bellows
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 19/32] target-arm: add MVBAR support Greg Bellows
                   ` (14 subsequent siblings)
  32 siblings, 0 replies; 53+ messages in thread
From: Greg Bellows @ 2014-10-21 16:55 UTC (permalink / raw)
  To: qemu-devel, peter.maydell, serge.fdrv, edgar.iglesias, aggelerf
  Cc: greg.bellows

From: Sergey Fedorov <s.fedorov@samsung.com>

Signed-off-by: Sergey Fedorov <s.fedorov@samsung.com>
Signed-off-by: Fabian Aggeler <aggelerf@ethz.ch>
Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
---
 target-arm/cpu.h    | 1 +
 target-arm/helper.c | 3 +++
 2 files changed, 4 insertions(+)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index f9221a4..2202465 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -181,6 +181,7 @@ 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_sder; /* Secure debug enable register. */
         uint32_t c1_nsacr; /* Non-secure access control register. */
         uint64_t ttbr0_el1; /* MMU translation table base 0. */
         uint64_t ttbr1_el1; /* MMU translation table base 1. */
diff --git a/target-arm/helper.c b/target-arm/helper.c
index f12181f..af62074 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -2409,6 +2409,9 @@ static const ARMCPRegInfo v7_el3_cp_reginfo[] = {
     { .name = "SCR", .cp = 15, .crn = 1, .crm = 1, .opc1 = 0, .opc2 = 0,
       .access = PL3_RW, .fieldoffset = offsetof(CPUARMState, cp15.scr_el3),
       .resetvalue = 0, .writefn = scr_write},
+    { .name = "SDER", .cp = 15, .crn = 1, .crm = 1, .opc1 = 0, .opc2 = 1,
+      .access = PL3_RW, .resetvalue = 0,
+      .fieldoffset = offsetof(CPUARMState, cp15.c1_sder) },
     { .name = "NSACR", .cp = 15, .crn = 1, .crm = 1, .opc1 = 0, .opc2 = 2,
       .access = PL3_RW | PL1_R, .resetvalue = 0,
       .writefn = nsacr_write, .readfn = nsacr_read,
-- 
1.8.3.2

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

* [Qemu-devel] [PATCH v7 19/32] target-arm: add MVBAR support
  2014-10-21 16:55 [Qemu-devel] [PATCH v7 00/32] target-arm: add Security Extensions for CPUs Greg Bellows
                   ` (17 preceding siblings ...)
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 18/32] target-arm: add SDER definition Greg Bellows
@ 2014-10-21 16:55 ` Greg Bellows
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 20/32] target-arm: add SCTLR_EL3 and make SCTLR banked Greg Bellows
                   ` (13 subsequent siblings)
  32 siblings, 0 replies; 53+ messages in thread
From: Greg Bellows @ 2014-10-21 16:55 UTC (permalink / raw)
  To: qemu-devel, peter.maydell, serge.fdrv, edgar.iglesias, aggelerf
  Cc: greg.bellows

From: Fabian Aggeler <aggelerf@ethz.ch>

Use MVBAR register as exception vector base address for
exceptions taken to CPU monitor mode.

Signed-off-by: Sergey Fedorov <s.fedorov@samsung.com>
Signed-off-by: Fabian Aggeler <aggelerf@ethz.ch>
Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
---
 target-arm/cpu.h    |  1 +
 target-arm/helper.c | 15 +++++++++------
 2 files changed, 10 insertions(+), 6 deletions(-)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 2202465..bd6c5b2 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -211,6 +211,7 @@ typedef struct CPUARMState {
         uint32_t c9_pminten; /* perf monitor interrupt enables */
         uint64_t mair_el1;
         uint64_t vbar_el[4]; /* vector base address register */
+        uint64_t mvbar; /* (monitor) vector base address register */
         uint32_t c13_fcse; /* FCSE PID.  */
         uint64_t contextidr_el1; /* Context ID.  */
         uint64_t tpidr_el0; /* User RW Thread register.  */
diff --git a/target-arm/helper.c b/target-arm/helper.c
index af62074..9929c27 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -2416,6 +2416,9 @@ static const ARMCPRegInfo v7_el3_cp_reginfo[] = {
       .access = PL3_RW | PL1_R, .resetvalue = 0,
       .writefn = nsacr_write, .readfn = nsacr_read,
       .fieldoffset = offsetof(CPUARMState, cp15.c1_nsacr) },
+    { .name = "MVBAR", .cp = 15, .crn = 12, .crm = 0, .opc1 = 0, .opc2 = 1,
+      .access = PL3_RW, .writefn = vbar_write, .resetvalue = 0,
+      .fieldoffset = offsetof(CPUARMState, cp15.mvbar) },
     REGINFO_SENTINEL
 };
 
@@ -4364,16 +4367,16 @@ void arm_cpu_do_interrupt(CPUState *cs)
         cpu_abort(cs, "Unhandled exception 0x%x\n", cs->exception_index);
         return; /* Never happens.  Keep compiler happy.  */
     }
-    /* High vectors.  */
-    if (env->cp15.c1_sys & SCTLR_V) {
-        /* when enabled, base address cannot be remapped.  */
+
+    if (new_mode == ARM_CPU_MODE_MON) {
+        addr += env->cp15.mvbar;
+    } else if (env->cp15.c1_sys & SCTLR_V) {
+        /* High vectors. When enabled, base address cannot be remapped. */
         addr += 0xffff0000;
     } else {
         /* ARM v7 architectures provide a vector base address register to remap
          * the interrupt vector table.
-         * This register is only followed in non-monitor mode, and has a secure
-         * and un-secure copy. Since the cpu is always in a un-secure operation
-         * and is never in monitor mode this feature is always active.
+         * This register is only followed in non-monitor mode, and is banked.
          * Note: only bits 31:5 are valid.
          */
         addr += env->cp15.vbar_el[1];
-- 
1.8.3.2

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

* [Qemu-devel] [PATCH v7 20/32] target-arm: add SCTLR_EL3 and make SCTLR banked
  2014-10-21 16:55 [Qemu-devel] [PATCH v7 00/32] target-arm: add Security Extensions for CPUs Greg Bellows
                   ` (18 preceding siblings ...)
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 19/32] target-arm: add MVBAR support Greg Bellows
@ 2014-10-21 16:55 ` Greg Bellows
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 21/32] target-arm: make CSSELR banked Greg Bellows
                   ` (12 subsequent siblings)
  32 siblings, 0 replies; 53+ messages in thread
From: Greg Bellows @ 2014-10-21 16:55 UTC (permalink / raw)
  To: qemu-devel, peter.maydell, serge.fdrv, edgar.iglesias, aggelerf
  Cc: greg.bellows

From: Fabian Aggeler <aggelerf@ethz.ch>

Implements SCTLR_EL3 and uses secure/non-secure instance when
needed.

Signed-off-by: Fabian Aggeler <aggelerf@ethz.ch>
Signed-off-by: Greg Bellows <greg.bellows@linaro.org>

==========

v5 -> v6
- Changed _el field variants to be array based
- Consolidate SCTLR and SCTLR_EL1 reginfo entries

Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
---
 hw/arm/pxa2xx.c        |  2 +-
 target-arm/cpu.c       |  5 ++--
 target-arm/cpu.h       | 10 ++++++-
 target-arm/helper.c    | 72 +++++++++++++++++++++++++++++---------------------
 target-arm/op_helper.c |  2 +-
 5 files changed, 56 insertions(+), 35 deletions(-)

diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c
index 7d306fb..0114597 100644
--- a/hw/arm/pxa2xx.c
+++ b/hw/arm/pxa2xx.c
@@ -272,7 +272,7 @@ static void pxa2xx_pwrmode_write(CPUARMState *env, const ARMCPRegInfo *ri,
     case 3:
         s->cpu->env.uncached_cpsr = ARM_CPU_MODE_SVC;
         s->cpu->env.daif = PSTATE_A | PSTATE_F | PSTATE_I;
-        s->cpu->env.cp15.c1_sys = 0;
+        s->cpu->env.cp15.sctlr_ns = 0;
         s->cpu->env.cp15.c1_coproc = 0;
         s->cpu->env.cp15.ttbr0_el1 = 0;
         s->cpu->env.cp15.c3 = 0;
diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index e837f64..fdb6de4 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -109,7 +109,7 @@ static void arm_cpu_reset(CPUState *s)
 #if defined(CONFIG_USER_ONLY)
         env->pstate = PSTATE_MODE_EL0t;
         /* Userspace expects access to CTL_EL0 and the cache ops */
-        env->cp15.c1_sys |= SCTLR_UCT | SCTLR_UCI;
+        env->cp15.sctlr_el[1] |= SCTLR_UCT | SCTLR_UCI;
         /* and to the FP/Neon instructions */
         env->cp15.c1_coproc = deposit64(env->cp15.c1_coproc, 20, 2, 3);
 #else
@@ -167,7 +167,8 @@ static void arm_cpu_reset(CPUState *s)
         env->thumb = initial_pc & 1;
     }
 
-    if (env->cp15.c1_sys & SCTLR_V) {
+    if (!arm_feature(env, ARM_FEATURE_V8)
+            && (A32_BANKED_CURRENT_REG_GET(env, sctlr) & SCTLR_V)) {
         env->regs[15] = 0xFFFF0000;
     }
 
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index bd6c5b2..a46ab7b 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -178,7 +178,15 @@ typedef struct CPUARMState {
     struct {
         uint32_t c0_cpuid;
         uint64_t c0_cssel; /* Cache size selection.  */
-        uint64_t c1_sys; /* System control register.  */
+        union { /* System control register. */
+            struct {
+                uint64_t _unused_sctlr;
+                uint64_t sctlr_ns;
+                uint64_t hsctlr;
+                uint64_t sctlr_s;
+            };
+            uint64_t sctlr_el[4];
+        };
         uint64_t c1_coproc; /* Coprocessor access register.  */
         uint32_t c1_xscaleauxcr; /* XScale auxiliary control register.  */
         uint32_t c1_sder; /* Secure debug enable register. */
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 9929c27..6a7c112 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1921,7 +1921,7 @@ static void aa64_fpsr_write(CPUARMState *env, const ARMCPRegInfo *ri,
 
 static CPAccessResult aa64_daif_access(CPUARMState *env, const ARMCPRegInfo *ri)
 {
-    if (arm_current_el(env) == 0 && !(env->cp15.c1_sys & SCTLR_UMA)) {
+    if (arm_current_el(env) == 0 && !(env->cp15.sctlr_el[1] & SCTLR_UMA)) {
         return CP_ACCESS_TRAP;
     }
     return CP_ACCESS_OK;
@@ -1939,7 +1939,7 @@ static CPAccessResult aa64_cacheop_access(CPUARMState *env,
     /* Cache invalidate/clean: NOP, but EL0 must UNDEF unless
      * SCTLR_EL1.UCI is set.
      */
-    if (arm_current_el(env) == 0 && !(env->cp15.c1_sys & SCTLR_UCI)) {
+    if (arm_current_el(env) == 0 && !(env->cp15.sctlr_el[1] & SCTLR_UCI)) {
         return CP_ACCESS_TRAP;
     }
     return CP_ACCESS_OK;
@@ -2016,7 +2016,7 @@ static CPAccessResult aa64_zva_access(CPUARMState *env, const ARMCPRegInfo *ri)
     /* We don't implement EL2, so the only control on DC ZVA is the
      * bit in the SCTLR which can prohibit access for EL0.
      */
-    if (arm_current_el(env) == 0 && !(env->cp15.c1_sys & SCTLR_DZE)) {
+    if (arm_current_el(env) == 0 && !(env->cp15.sctlr_el[1] & SCTLR_DZE)) {
         return CP_ACCESS_TRAP;
     }
     return CP_ACCESS_OK;
@@ -2055,6 +2055,24 @@ static void spsel_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t val)
     update_spsel(env, val);
 }
 
+static void sctlr_write(CPUARMState *env, const ARMCPRegInfo *ri,
+                        uint64_t value)
+{
+    ARMCPU *cpu = arm_env_get_cpu(env);
+
+    if (raw_read(env, ri) == value) {
+        /* Skip the TLB flush if nothing actually changed; Linux likes
+         * to do a lot of pointless SCTLR writes.
+         */
+        return;
+    }
+
+    raw_write(env, ri, value);
+    /* ??? Lots of these bits are not implemented.  */
+    /* This may enable/disable the MMU, so do a TLB flush.  */
+    tlb_flush(CPU(cpu), 1);
+}
+
 static const ARMCPRegInfo v8_cp_reginfo[] = {
     /* Minimal set of EL0-visible registers. This will need to be expanded
      * significantly for system emulation of AArch64 CPUs.
@@ -2373,6 +2391,10 @@ static uint64_t nsacr_read(CPUARMState *env, const ARMCPRegInfo *ri)
 }
 
 static const ARMCPRegInfo v8_el3_cp_reginfo[] = {
+    { .name = "SCTLR_EL3", .state = ARM_CP_STATE_AA64,
+      .opc0 = 3, .crn = 1, .crm = 0, .opc1 = 6, .opc2 = 0,
+      .access = PL3_RW, .raw_writefn = raw_write, .writefn = sctlr_write,
+      .fieldoffset = offsetof(CPUARMState, cp15.sctlr_el[3]) },
     { .name = "ELR_EL3", .state = ARM_CP_STATE_AA64,
       .type = ARM_CP_NO_MIGRATE,
       .opc0 = 3, .opc1 = 6, .crn = 4, .crm = 0, .opc2 = 1,
@@ -2422,30 +2444,12 @@ static const ARMCPRegInfo v7_el3_cp_reginfo[] = {
     REGINFO_SENTINEL
 };
 
-static void sctlr_write(CPUARMState *env, const ARMCPRegInfo *ri,
-                        uint64_t value)
-{
-    ARMCPU *cpu = arm_env_get_cpu(env);
-
-    if (raw_read(env, ri) == value) {
-        /* Skip the TLB flush if nothing actually changed; Linux likes
-         * to do a lot of pointless SCTLR writes.
-         */
-        return;
-    }
-
-    raw_write(env, ri, value);
-    /* ??? Lots of these bits are not implemented.  */
-    /* This may enable/disable the MMU, so do a TLB flush.  */
-    tlb_flush(CPU(cpu), 1);
-}
-
 static CPAccessResult ctr_el0_access(CPUARMState *env, const ARMCPRegInfo *ri)
 {
     /* Only accessible in EL0 if SCTLR.UCT is set (and only in AArch64,
      * but the AArch32 CTR has its own reginfo struct)
      */
-    if (arm_current_el(env) == 0 && !(env->cp15.c1_sys & SCTLR_UCT)) {
+    if (arm_current_el(env) == 0 && !(env->cp15.sctlr_el[1] & SCTLR_UCT)) {
         return CP_ACCESS_TRAP;
     }
     return CP_ACCESS_OK;
@@ -3244,8 +3248,10 @@ void register_cp_regs_for_features(ARMCPU *cpu)
     {
         ARMCPRegInfo sctlr = {
             .name = "SCTLR", .state = ARM_CP_STATE_BOTH,
-            .opc0 = 3, .crn = 1, .crm = 0, .opc1 = 0, .opc2 = 0,
-            .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.c1_sys),
+            .cp = 15, .crn = 1, .crm = 0, .opc1 = 0, .opc2 = 0,
+            .access = PL1_RW,
+            .bank_fieldoffsets = { offsetof(CPUARMState, cp15.sctlr_s),
+                                   offsetof(CPUARMState, cp15.sctlr_ns) },
             .writefn = sctlr_write, .resetvalue = cpu->reset_sctlr,
             .raw_writefn = raw_write,
         };
@@ -4370,7 +4376,7 @@ void arm_cpu_do_interrupt(CPUState *cs)
 
     if (new_mode == ARM_CPU_MODE_MON) {
         addr += env->cp15.mvbar;
-    } else if (env->cp15.c1_sys & SCTLR_V) {
+    } else if (A32_BANKED_CURRENT_REG_GET(env, sctlr) & SCTLR_V) {
         /* High vectors. When enabled, base address cannot be remapped. */
         addr += 0xffff0000;
     } else {
@@ -4400,7 +4406,7 @@ void arm_cpu_do_interrupt(CPUState *cs)
     /* this is a lie, as the was no c1_sys on V4T/V5, but who cares
      * and we should just guard the thumb mode on V4 */
     if (arm_feature(env, ARM_FEATURE_V4T)) {
-        env->thumb = (env->cp15.c1_sys & SCTLR_TE) != 0;
+        env->thumb = (A32_BANKED_CURRENT_REG_GET(env, sctlr) & SCTLR_TE) != 0;
     }
     env->regs[14] = env->regs[15] + offset;
     env->regs[15] = addr;
@@ -4431,7 +4437,7 @@ static inline int check_ap(CPUARMState *env, int ap, int domain_prot,
       }
       if (access_type == 1)
           return 0;
-      switch (env->cp15.c1_sys & (SCTLR_S | SCTLR_R)) {
+      switch (A32_BANKED_CURRENT_REG_GET(env, sctlr) & (SCTLR_S | SCTLR_R)) {
       case SCTLR_S:
           return is_user ? 0 : PAGE_READ;
       case SCTLR_R:
@@ -4680,7 +4686,8 @@ static int get_phys_addr_v6(CPUARMState *env, uint32_t address, int access_type,
             goto do_fault;
 
         /* The simplified model uses AP[0] as an access control bit.  */
-        if ((env->cp15.c1_sys & SCTLR_AFE) && (ap & 1) == 0) {
+        if ((A32_BANKED_CURRENT_REG_GET(env, sctlr) & SCTLR_AFE)
+                && (ap & 1) == 0) {
             /* Access flag fault.  */
             code = (code == 15) ? 6 : 3;
             goto do_fault;
@@ -5011,11 +5018,16 @@ static inline int get_phys_addr(CPUARMState *env, target_ulong address,
                                 hwaddr *phys_ptr, int *prot,
                                 target_ulong *page_size)
 {
+    /* This is not entirely correct as get_phys_addr() can also be called
+     * from ats_write() for an address translation of a specific regime.
+     */
+    uint32_t sctlr = A32_BANKED_CURRENT_REG_GET(env, sctlr);
+
     /* Fast Context Switch Extension.  */
     if (address < 0x02000000)
         address += env->cp15.c13_fcse;
 
-    if ((env->cp15.c1_sys & SCTLR_M) == 0) {
+    if ((sctlr & SCTLR_M) == 0) {
         /* MMU/MPU disabled.  */
         *phys_ptr = address;
         *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
@@ -5028,7 +5040,7 @@ static inline int get_phys_addr(CPUARMState *env, target_ulong address,
     } else if (extended_addresses_enabled(env)) {
         return get_phys_addr_lpae(env, address, access_type, is_user, phys_ptr,
                                   prot, page_size);
-    } else if (env->cp15.c1_sys & SCTLR_XP) {
+    } else if (sctlr & SCTLR_XP) {
         return get_phys_addr_v6(env, address, access_type, is_user, phys_ptr,
                                 prot, page_size);
     } else {
diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
index 62012c3..a8dea5a 100644
--- a/target-arm/op_helper.c
+++ b/target-arm/op_helper.c
@@ -361,7 +361,7 @@ void HELPER(msr_i_pstate)(CPUARMState *env, uint32_t op, uint32_t imm)
      * Note that SPSel is never OK from EL0; we rely on handle_msr_i()
      * to catch that case at translate time.
      */
-    if (arm_current_el(env) == 0 && !(env->cp15.c1_sys & SCTLR_UMA)) {
+    if (arm_current_el(env) == 0 && !(env->cp15.sctlr_el[1] & SCTLR_UMA)) {
         raise_exception(env, EXCP_UDEF);
     }
 
-- 
1.8.3.2

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

* [Qemu-devel] [PATCH v7 21/32] target-arm: make CSSELR banked
  2014-10-21 16:55 [Qemu-devel] [PATCH v7 00/32] target-arm: add Security Extensions for CPUs Greg Bellows
                   ` (19 preceding siblings ...)
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 20/32] target-arm: add SCTLR_EL3 and make SCTLR banked Greg Bellows
@ 2014-10-21 16:55 ` Greg Bellows
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 22/32] target-arm: add TTBR0_EL3 and make TTBR0/1 banked Greg Bellows
                   ` (11 subsequent siblings)
  32 siblings, 0 replies; 53+ messages in thread
From: Greg Bellows @ 2014-10-21 16:55 UTC (permalink / raw)
  To: qemu-devel, peter.maydell, serge.fdrv, edgar.iglesias, aggelerf
  Cc: greg.bellows

From: Fabian Aggeler <aggelerf@ethz.ch>

Rename CSSELR (cache size selection register) and add secure
instance (AArch32).

Signed-off-by: Fabian Aggeler <aggelerf@ethz.ch>
Signed-off-by: Greg Bellows <greg.bellows@linaro.org>

==========

v5 -> v6
- Changed _el field variants to be array based
- Switch to use distinct CPREG secure flags.
- Merged CSSELR and CSSELR_EL1 reginfo entries

v4 -> v5
- Changed to use the CCSIDR cpreg bank flag to select the csselr bank instead
  of the  A32_BANKED macro.  This more accurately uses the secure state bank
  matching the CCSIDR.

Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
---
 target-arm/cpu.h    | 10 +++++++++-
 target-arm/helper.c | 16 ++++++++++++----
 2 files changed, 21 insertions(+), 5 deletions(-)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index a46ab7b..8b98c62 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -177,7 +177,15 @@ typedef struct CPUARMState {
     /* System control coprocessor (cp15) */
     struct {
         uint32_t c0_cpuid;
-        uint64_t c0_cssel; /* Cache size selection.  */
+        union { /* Cache size selection */
+            struct {
+                uint64_t _unused_csselr0;
+                uint64_t csselr_ns;
+                uint64_t _unused_csselr1;
+                uint64_t csselr_s;
+            };
+            uint64_t csselr_el[4];
+        };
         union { /* System control register. */
             struct {
                 uint64_t _unused_sctlr;
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 6a7c112..a8fe482 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -789,7 +789,14 @@ static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
 static uint64_t ccsidr_read(CPUARMState *env, const ARMCPRegInfo *ri)
 {
     ARMCPU *cpu = arm_env_get_cpu(env);
-    return cpu->ccsidr[env->cp15.c0_cssel];
+
+    /* Acquire the CSSELR index from the bank corresponding to the CCSIDR
+     * bank
+     */
+    uint32_t index = A32_BANKED_REG_GET(env, csselr,
+                                 ARM_CP_SECSTATE_TEST(ri, ARM_CP_SECSTATE_S));
+
+    return cpu->ccsidr[index];
 }
 
 static void csselr_write(CPUARMState *env, const ARMCPRegInfo *ri,
@@ -915,9 +922,10 @@ static const ARMCPRegInfo v7_cp_reginfo[] = {
       .opc0 = 3, .crn = 0, .crm = 0, .opc1 = 1, .opc2 = 0,
       .access = PL1_R, .readfn = ccsidr_read, .type = ARM_CP_NO_MIGRATE },
     { .name = "CSSELR", .state = ARM_CP_STATE_BOTH,
-      .opc0 = 3, .crn = 0, .crm = 0, .opc1 = 2, .opc2 = 0,
-      .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.c0_cssel),
-      .writefn = csselr_write, .resetvalue = 0 },
+      .cp = 15, .crn = 0, .crm = 0, .opc1 = 2, .opc2 = 0,
+      .access = PL1_RW, .writefn = csselr_write, .resetvalue = 0,
+      .bank_fieldoffsets = { offsetof(CPUARMState, cp15.csselr_s),
+                             offsetof(CPUARMState, cp15.csselr_ns) } },
     /* Auxiliary ID register: this actually has an IMPDEF value but for now
      * just RAZ for all cores:
      */
-- 
1.8.3.2

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

* [Qemu-devel] [PATCH v7 22/32] target-arm: add TTBR0_EL3 and make TTBR0/1 banked
  2014-10-21 16:55 [Qemu-devel] [PATCH v7 00/32] target-arm: add Security Extensions for CPUs Greg Bellows
                   ` (20 preceding siblings ...)
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 21/32] target-arm: make CSSELR banked Greg Bellows
@ 2014-10-21 16:55 ` Greg Bellows
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 23/32] target-arm: add TCR_EL3 and make TTBCR banked Greg Bellows
                   ` (10 subsequent siblings)
  32 siblings, 0 replies; 53+ messages in thread
From: Greg Bellows @ 2014-10-21 16:55 UTC (permalink / raw)
  To: qemu-devel, peter.maydell, serge.fdrv, edgar.iglesias, aggelerf
  Cc: greg.bellows

From: Fabian Aggeler <aggelerf@ethz.ch>

Add TTBR0 and maps secure/non-secure instance of ttbr0 and ttbr1
accordingly (translation table base register).

Signed-off-by: Fabian Aggeler <aggelerf@ethz.ch>
Signed-off-by: Greg Bellows <greg.bellows@linaro.org>

==========

v5 -> v6
- Changed _el field variants to be array based
- Merged TTBR# and TTBR#_EL1 reginfo entries
- Globally replace Aarch# with AArch#

Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
---
 hw/arm/pxa2xx.c     |  4 ++--
 target-arm/cpu.h    | 20 ++++++++++++++++++--
 target-arm/helper.c | 54 +++++++++++++++++++++++++++++++++++++++--------------
 3 files changed, 60 insertions(+), 18 deletions(-)

diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c
index 0114597..13261d0 100644
--- a/hw/arm/pxa2xx.c
+++ b/hw/arm/pxa2xx.c
@@ -274,7 +274,7 @@ static void pxa2xx_pwrmode_write(CPUARMState *env, const ARMCPRegInfo *ri,
         s->cpu->env.daif = PSTATE_A | PSTATE_F | PSTATE_I;
         s->cpu->env.cp15.sctlr_ns = 0;
         s->cpu->env.cp15.c1_coproc = 0;
-        s->cpu->env.cp15.ttbr0_el1 = 0;
+        s->cpu->env.cp15.ttbr0_el[1] = 0;
         s->cpu->env.cp15.c3 = 0;
         s->pm_regs[PSSR >> 2] |= 0x8; /* Set STS */
         s->pm_regs[RCSR >> 2] |= 0x8; /* Set GPR */
@@ -2046,7 +2046,7 @@ PXA2xxState *pxa270_init(MemoryRegion *address_space,
     }
     if (!revision)
         revision = "pxa270";
-    
+
     s->cpu = cpu_arm_init(revision);
     if (s->cpu == NULL) {
         fprintf(stderr, "Unable to find CPU definition\n");
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 8b98c62..f31b2d4 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -199,8 +199,24 @@ typedef struct CPUARMState {
         uint32_t c1_xscaleauxcr; /* XScale auxiliary control register.  */
         uint32_t c1_sder; /* Secure debug enable register. */
         uint32_t c1_nsacr; /* Non-secure access control register. */
-        uint64_t ttbr0_el1; /* MMU translation table base 0. */
-        uint64_t ttbr1_el1; /* MMU translation table base 1. */
+        union { /* MMU translation table base 0. */
+            struct {
+                uint64_t _unused_ttbr0_0;
+                uint64_t ttbr0_ns;
+                uint64_t _unused_ttbr0_1;
+                uint64_t ttbr0_s;
+            };
+            uint64_t ttbr0_el[4];
+        };
+        union { /* MMU translation table base 1. */
+            struct {
+                uint64_t _unused_ttbr1_0;
+                uint64_t ttbr1_ns;
+                uint64_t _unused_ttbr1_1;
+                uint64_t ttbr1_s;
+            };
+            uint64_t ttbr1_el[4];
+        };
         uint64_t c2_control; /* MMU translation table base control.  */
         uint32_t c2_mask; /* MMU translation table base selection mask.  */
         uint32_t c2_base_mask; /* MMU translation table base 0 mask. */
diff --git a/target-arm/helper.c b/target-arm/helper.c
index a8fe482..34e5829 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1658,14 +1658,16 @@ static const ARMCPRegInfo vmsa_cp_reginfo[] = {
       .opc0 = 3, .crn = 5, .crm = 2, .opc1 = 0, .opc2 = 0,
       .access = PL1_RW,
       .fieldoffset = offsetof(CPUARMState, cp15.esr_el[1]), .resetvalue = 0, },
-    { .name = "TTBR0_EL1", .state = ARM_CP_STATE_BOTH,
-      .opc0 = 3, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 0,
-      .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.ttbr0_el1),
-      .writefn = vmsa_ttbr_write, .resetvalue = 0 },
-    { .name = "TTBR1_EL1", .state = ARM_CP_STATE_BOTH,
-      .opc0 = 3, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 1,
-      .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.ttbr1_el1),
-      .writefn = vmsa_ttbr_write, .resetvalue = 0 },
+    { .name = "TTBR0", .state = ARM_CP_STATE_BOTH,
+      .cp = 15, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 0,
+      .access = PL1_RW, .writefn = vmsa_ttbr_write, .resetvalue = 0,
+      .bank_fieldoffsets = { offsetof(CPUARMState, cp15.ttbr0_s),
+                             offsetof(CPUARMState, cp15.ttbr0_ns) } },
+    { .name = "TTBR1", .state = ARM_CP_STATE_BOTH,
+      .cp = 15, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 1,
+      .access = PL1_RW, .writefn = vmsa_ttbr_write, .resetvalue = 0,
+      .bank_fieldoffsets = { offsetof(CPUARMState, cp15.ttbr1_s),
+                             offsetof(CPUARMState, cp15.ttbr1_ns) } },
     { .name = "TCR_EL1", .state = ARM_CP_STATE_AA64,
       .opc0 = 3, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 2,
       .access = PL1_RW, .writefn = vmsa_tcr_el1_write,
@@ -1896,11 +1898,13 @@ static const ARMCPRegInfo lpae_cp_reginfo[] = {
       .fieldoffset = offsetof(CPUARMState, cp15.par_el1), .resetvalue = 0 },
     { .name = "TTBR0", .cp = 15, .crm = 2, .opc1 = 0,
       .access = PL1_RW, .type = ARM_CP_64BIT | ARM_CP_NO_MIGRATE,
-      .fieldoffset = offsetof(CPUARMState, cp15.ttbr0_el1),
+      .bank_fieldoffsets = { offsetof(CPUARMState, cp15.ttbr0_s),
+                             offsetof(CPUARMState, cp15.ttbr0_ns) },
       .writefn = vmsa_ttbr_write, .resetfn = arm_cp_reset_ignore },
     { .name = "TTBR1", .cp = 15, .crm = 2, .opc1 = 1,
       .access = PL1_RW, .type = ARM_CP_64BIT | ARM_CP_NO_MIGRATE,
-      .fieldoffset = offsetof(CPUARMState, cp15.ttbr1_el1),
+      .bank_fieldoffsets = { offsetof(CPUARMState, cp15.ttbr1_s),
+                             offsetof(CPUARMState, cp15.ttbr1_ns) },
       .writefn = vmsa_ttbr_write, .resetfn = arm_cp_reset_ignore },
     REGINFO_SENTINEL
 };
@@ -2403,6 +2407,10 @@ static const ARMCPRegInfo v8_el3_cp_reginfo[] = {
       .opc0 = 3, .crn = 1, .crm = 0, .opc1 = 6, .opc2 = 0,
       .access = PL3_RW, .raw_writefn = raw_write, .writefn = sctlr_write,
       .fieldoffset = offsetof(CPUARMState, cp15.sctlr_el[3]) },
+    { .name = "TTBR0_EL3", .state = ARM_CP_STATE_AA64,
+      .opc0 = 3, .crn = 2, .crm = 0, .opc1 = 6, .opc2 = 0,
+      .access = PL3_RW, .writefn = vmsa_ttbr_write, .resetvalue = 0,
+      .fieldoffset = offsetof(CPUARMState, cp15.ttbr0_el[3]) },
     { .name = "ELR_EL3", .state = ARM_CP_STATE_AA64,
       .type = ARM_CP_NO_MIGRATE,
       .opc0 = 3, .opc1 = 6, .crn = 4, .crm = 0, .opc2 = 1,
@@ -4480,18 +4488,23 @@ static inline int check_ap(CPUARMState *env, int ap, int domain_prot,
 static bool get_level1_table_address(CPUARMState *env, uint32_t *table,
                                          uint32_t address)
 {
+    /* We only get here if EL1 is running in AArch32. If EL3 is running in
+     * AArch32 there is a secure and non-secure instance of the translation
+     * table registers.
+     */
     if (address & env->cp15.c2_mask) {
         if ((env->cp15.c2_control & TTBCR_PD1)) {
             /* Translation table walk disabled for TTBR1 */
             return false;
         }
-        *table = env->cp15.ttbr1_el1 & 0xffffc000;
+        *table = A32_BANKED_CURRENT_REG_GET(env, ttbr1) & 0xffffc000;
     } else {
         if ((env->cp15.c2_control & TTBCR_PD0)) {
             /* Translation table walk disabled for TTBR0 */
             return false;
         }
-        *table = env->cp15.ttbr0_el1 & env->cp15.c2_base_mask;
+        *table = A32_BANKED_CURRENT_REG_GET(env, ttbr0) &
+                 env->cp15.c2_base_mask;
     }
     *table |= (address >> 18) & 0x3ffc;
     return true;
@@ -4745,6 +4758,7 @@ static int get_phys_addr_lpae(CPUARMState *env, target_ulong address,
     int32_t granule_sz = 9;
     int32_t va_size = 32;
     int32_t tbi = 0;
+    uint32_t cur_el = arm_current_el(env);
 
     if (arm_el_is_aa64(env, 1)) {
         va_size = 64;
@@ -4796,7 +4810,19 @@ static int get_phys_addr_lpae(CPUARMState *env, target_ulong address,
      * we will always flush the TLB any time the ASID is changed).
      */
     if (ttbr_select == 0) {
-        ttbr = env->cp15.ttbr0_el1;
+        if (arm_el_is_aa64(env, 3)) {
+            switch (cur_el) {
+            case 3:
+                ttbr = env->cp15.ttbr0_el[3];
+                break;
+            case 1:
+            case 0:
+            default:
+                ttbr = env->cp15.ttbr0_el[1];
+            }
+        } else {
+            ttbr = A32_BANKED_CURRENT_REG_GET(env, ttbr0);
+        }
         epd = extract32(env->cp15.c2_control, 7, 1);
         tsz = t0sz;
 
@@ -4808,7 +4834,7 @@ static int get_phys_addr_lpae(CPUARMState *env, target_ulong address,
             granule_sz = 11;
         }
     } else {
-        ttbr = env->cp15.ttbr1_el1;
+        ttbr = A32_BANKED_CURRENT_REG_GET(env, ttbr1);
         epd = extract32(env->cp15.c2_control, 23, 1);
         tsz = t1sz;
 
-- 
1.8.3.2

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

* [Qemu-devel] [PATCH v7 23/32] target-arm: add TCR_EL3 and make TTBCR banked
  2014-10-21 16:55 [Qemu-devel] [PATCH v7 00/32] target-arm: add Security Extensions for CPUs Greg Bellows
                   ` (21 preceding siblings ...)
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 22/32] target-arm: add TTBR0_EL3 and make TTBR0/1 banked Greg Bellows
@ 2014-10-21 16:55 ` Greg Bellows
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 24/32] target-arm: make c2_mask and c2_base_mask banked Greg Bellows
                   ` (9 subsequent siblings)
  32 siblings, 0 replies; 53+ messages in thread
From: Greg Bellows @ 2014-10-21 16:55 UTC (permalink / raw)
  To: qemu-devel, peter.maydell, serge.fdrv, edgar.iglesias, aggelerf
  Cc: greg.bellows

From: Fabian Aggeler <aggelerf@ethz.ch>

Adds TCR_EL3 system register and makes existing TTBCR banked. Adjust
translation functions to use TCR/TTBCR instance depending on CPU state.

Signed-off-by: Fabian Aggeler <aggelerf@ethz.ch>
Signed-off-by: Greg Bellows <greg.bellows@linaro.org>

==========

v5 -> v6
- Changed _el field variants to be array based

v4 -> v5
- Changed c2_mask updates to use the TTBCR cpreg bank flag for selcting the
  secure bank instead of the A32_BANKED_CURRENT macro.  This more accurately
  chooses the correct bank matching that of the TTBCR being accessed.

Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
---
 target-arm/cpu.h       | 10 +++++++++-
 target-arm/helper.c    | 48 +++++++++++++++++++++++++++++++++++-------------
 target-arm/internals.h |  2 +-
 3 files changed, 45 insertions(+), 15 deletions(-)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index f31b2d4..76c4ef8 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -217,7 +217,15 @@ typedef struct CPUARMState {
             };
             uint64_t ttbr1_el[4];
         };
-        uint64_t c2_control; /* MMU translation table base control.  */
+        union { /* MMU translation table base control. */
+            struct {
+                uint64_t _unused_ttbcr_0;
+                uint64_t ttbcr_ns;
+                uint64_t _unused_ttbcr_1;
+                uint64_t ttbcr_s;
+            };
+            uint64_t tcr_el[4];
+        };
         uint32_t c2_mask; /* MMU translation table base selection mask.  */
         uint32_t c2_base_mask; /* MMU translation table base 0 mask. */
         uint32_t c2_data; /* MPU data cachable bits.  */
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 34e5829..caab8ce 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1672,11 +1672,12 @@ static const ARMCPRegInfo vmsa_cp_reginfo[] = {
       .opc0 = 3, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 2,
       .access = PL1_RW, .writefn = vmsa_tcr_el1_write,
       .resetfn = vmsa_ttbcr_reset, .raw_writefn = raw_write,
-      .fieldoffset = offsetof(CPUARMState, cp15.c2_control) },
+      .fieldoffset = offsetof(CPUARMState, cp15.tcr_el[1]) },
     { .name = "TTBCR", .cp = 15, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 2,
       .access = PL1_RW, .type = ARM_CP_NO_MIGRATE, .writefn = vmsa_ttbcr_write,
       .resetfn = arm_cp_reset_ignore, .raw_writefn = vmsa_ttbcr_raw_write,
-      .fieldoffset = offsetoflow32(CPUARMState, cp15.c2_control) },
+      .bank_fieldoffsets = { offsetoflow32(CPUARMState, cp15.ttbcr_s),
+                             offsetoflow32(CPUARMState, cp15.ttbcr_ns) } },
     /* 64-bit FAR; this entry also gives us the AArch32 DFAR */
     { .name = "FAR_EL1", .state = ARM_CP_STATE_BOTH,
       .opc0 = 3, .crn = 6, .crm = 0, .opc1 = 0, .opc2 = 0,
@@ -2411,6 +2412,11 @@ static const ARMCPRegInfo v8_el3_cp_reginfo[] = {
       .opc0 = 3, .crn = 2, .crm = 0, .opc1 = 6, .opc2 = 0,
       .access = PL3_RW, .writefn = vmsa_ttbr_write, .resetvalue = 0,
       .fieldoffset = offsetof(CPUARMState, cp15.ttbr0_el[3]) },
+    { .name = "TCR_EL3", .state = ARM_CP_STATE_AA64,
+      .opc0 = 3, .crn = 2, .crm = 0, .opc1 = 6, .opc2 = 2,
+      .access = PL3_RW, .writefn = vmsa_tcr_el1_write,
+      .resetfn = vmsa_ttbcr_reset, .raw_writefn = raw_write,
+      .fieldoffset = offsetof(CPUARMState, cp15.tcr_el[3]) },
     { .name = "ELR_EL3", .state = ARM_CP_STATE_AA64,
       .type = ARM_CP_NO_MIGRATE,
       .opc0 = 3, .opc1 = 6, .crn = 4, .crm = 0, .opc2 = 1,
@@ -4493,13 +4499,13 @@ static bool get_level1_table_address(CPUARMState *env, uint32_t *table,
      * table registers.
      */
     if (address & env->cp15.c2_mask) {
-        if ((env->cp15.c2_control & TTBCR_PD1)) {
+        if (A32_BANKED_CURRENT_REG_GET(env, ttbcr) & TTBCR_PD1) {
             /* Translation table walk disabled for TTBR1 */
             return false;
         }
         *table = A32_BANKED_CURRENT_REG_GET(env, ttbr1) & 0xffffc000;
     } else {
-        if ((env->cp15.c2_control & TTBCR_PD0)) {
+        if (A32_BANKED_CURRENT_REG_GET(env, ttbcr) & TTBCR_PD0) {
             /* Translation table walk disabled for TTBR0 */
             return false;
         }
@@ -4759,13 +4765,29 @@ static int get_phys_addr_lpae(CPUARMState *env, target_ulong address,
     int32_t va_size = 32;
     int32_t tbi = 0;
     uint32_t cur_el = arm_current_el(env);
+    uint64_t tcr;
 
-    if (arm_el_is_aa64(env, 1)) {
+    if (arm_el_is_aa64(env, 3)) {
+        switch (cur_el) {
+        case 3:
+            tcr = env->cp15.tcr_el[3];
+            break;
+        case 1:
+        case 0:
+        default:
+            tcr = env->cp15.tcr_el[1];
+        }
+
+    } else {
+        tcr = A32_BANKED_CURRENT_REG_GET(env, ttbcr);
+    }
+
+    if (arm_el_is_aa64(env, 1) && (cur_el == 0 || cur_el == 1)) {
         va_size = 64;
         if (extract64(address, 55, 1))
-            tbi = extract64(env->cp15.c2_control, 38, 1);
+            tbi = extract64(tcr, 38, 1);
         else
-            tbi = extract64(env->cp15.c2_control, 37, 1);
+            tbi = extract64(tcr, 37, 1);
         tbi *= 8;
     }
 
@@ -4774,12 +4796,12 @@ static int get_phys_addr_lpae(CPUARMState *env, target_ulong address,
      * This is a Non-secure PL0/1 stage 1 translation, so controlled by
      * TTBCR/TTBR0/TTBR1 in accordance with ARM ARM DDI0406C table B-32:
      */
-    uint32_t t0sz = extract32(env->cp15.c2_control, 0, 6);
+    uint32_t t0sz = extract32(tcr, 0, 6);
     if (arm_el_is_aa64(env, 1)) {
         t0sz = MIN(t0sz, 39);
         t0sz = MAX(t0sz, 16);
     }
-    uint32_t t1sz = extract32(env->cp15.c2_control, 16, 6);
+    uint32_t t1sz = extract32(tcr, 16, 6);
     if (arm_el_is_aa64(env, 1)) {
         t1sz = MIN(t1sz, 39);
         t1sz = MAX(t1sz, 16);
@@ -4823,10 +4845,10 @@ static int get_phys_addr_lpae(CPUARMState *env, target_ulong address,
         } else {
             ttbr = A32_BANKED_CURRENT_REG_GET(env, ttbr0);
         }
-        epd = extract32(env->cp15.c2_control, 7, 1);
+        epd = extract32(tcr, 7, 1);
         tsz = t0sz;
 
-        tg = extract32(env->cp15.c2_control, 14, 2);
+        tg = extract32(tcr, 14, 2);
         if (tg == 1) { /* 64KB pages */
             granule_sz = 13;
         }
@@ -4835,10 +4857,10 @@ static int get_phys_addr_lpae(CPUARMState *env, target_ulong address,
         }
     } else {
         ttbr = A32_BANKED_CURRENT_REG_GET(env, ttbr1);
-        epd = extract32(env->cp15.c2_control, 23, 1);
+        epd = extract32(tcr, 23, 1);
         tsz = t1sz;
 
-        tg = extract32(env->cp15.c2_control, 30, 2);
+        tg = extract32(tcr, 30, 2);
         if (tg == 3)  { /* 64KB pages */
             granule_sz = 13;
         }
diff --git a/target-arm/internals.h b/target-arm/internals.h
index 2dff4ff..8c451c6 100644
--- a/target-arm/internals.h
+++ b/target-arm/internals.h
@@ -155,7 +155,7 @@ static inline bool extended_addresses_enabled(CPUARMState *env)
 {
     return arm_el_is_aa64(env, 1)
         || ((arm_feature(env, ARM_FEATURE_LPAE)
-             && (env->cp15.c2_control & TTBCR_EAE)));
+             && (A32_BANKED_CURRENT_REG_GET(env, ttbcr) & TTBCR_EAE)));
 }
 
 /* Valid Syndrome Register EC field values */
-- 
1.8.3.2

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

* [Qemu-devel] [PATCH v7 24/32] target-arm: make c2_mask and c2_base_mask banked
  2014-10-21 16:55 [Qemu-devel] [PATCH v7 00/32] target-arm: add Security Extensions for CPUs Greg Bellows
                   ` (22 preceding siblings ...)
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 23/32] target-arm: add TCR_EL3 and make TTBCR banked Greg Bellows
@ 2014-10-21 16:55 ` Greg Bellows
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 25/32] target-arm: make DACR banked Greg Bellows
                   ` (8 subsequent siblings)
  32 siblings, 0 replies; 53+ messages in thread
From: Greg Bellows @ 2014-10-21 16:55 UTC (permalink / raw)
  To: qemu-devel, peter.maydell, serge.fdrv, edgar.iglesias, aggelerf
  Cc: greg.bellows

From: Fabian Aggeler <aggelerf@ethz.ch>

Since TTBCR is banked we will bank c2_mask and c2_base_mask too. This
avoids recalculating them on switches from secure to non-secure world.

Signed-off-by: Fabian Aggeler <aggelerf@ethz.ch>
Signed-off-by: Greg Bellows <greg.bellows@linaro.org>

==========

v5 -> v6
- Switch to use distinct CPREG secure flags

v4 -> v5
- Changed c2_mask updates to use the TTBCR cpreg bank flag for selcting the
  secure bank instead of the A32_BANKED_CURRENT macro.  This more accurately
  chooses the correct bank matching that of the TTBCR being accessed.

Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
---
 target-arm/cpu.h    | 10 ++++++++--
 target-arm/helper.c | 24 ++++++++++++++++++------
 2 files changed, 26 insertions(+), 8 deletions(-)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 76c4ef8..785eab3 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -226,8 +226,14 @@ typedef struct CPUARMState {
             };
             uint64_t tcr_el[4];
         };
-        uint32_t c2_mask; /* MMU translation table base selection mask.  */
-        uint32_t c2_base_mask; /* MMU translation table base 0 mask. */
+        struct { /* MMU translation table base selection mask. */
+            uint32_t c2_mask_ns;
+            uint32_t c2_mask_s;
+        };
+        struct { /* MMU translation table base 0 mask. */
+            uint32_t c2_base_mask_ns;
+            uint32_t c2_base_mask_s;
+        };
         uint32_t c2_data; /* MPU data cachable bits.  */
         uint32_t c2_insn; /* MPU instruction cachable bits.  */
         uint32_t c3; /* MMU domain access control register
diff --git a/target-arm/helper.c b/target-arm/helper.c
index caab8ce..046d81c 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1597,8 +1597,14 @@ static void vmsa_ttbcr_raw_write(CPUARMState *env, const ARMCPRegInfo *ri,
      * and the c2_mask and c2_base_mask values are meaningless.
      */
     raw_write(env, ri, value);
-    env->cp15.c2_mask = ~(((uint32_t)0xffffffffu) >> maskshift);
-    env->cp15.c2_base_mask = ~((uint32_t)0x3fffu >> maskshift);
+
+    /* Update the masks corresponding to the the TTBCR bank being written */
+    A32_BANKED_REG_SET(env, c2_mask,
+                       ARM_CP_SECSTATE_TEST(ri, ARM_CP_SECSTATE_S),
+                       ~(((uint32_t)0xffffffffu) >> maskshift));
+    A32_BANKED_REG_SET(env, c2_base_mask,
+                       ARM_CP_SECSTATE_TEST(ri, ARM_CP_SECSTATE_S),
+                       ~((uint32_t)0x3fffu >> maskshift));
 }
 
 static void vmsa_ttbcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
@@ -1617,9 +1623,15 @@ static void vmsa_ttbcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
 
 static void vmsa_ttbcr_reset(CPUARMState *env, const ARMCPRegInfo *ri)
 {
-    env->cp15.c2_base_mask = 0xffffc000u;
+    /* Rest both the TTBCR as well as the masks corresponding to the bank of
+     * the TTBCR being reset.
+     */
+    A32_BANKED_REG_SET(env, c2_base_mask,
+                       ARM_CP_SECSTATE_TEST(ri, ARM_CP_SECSTATE_S),
+                       0xffffc000u);
+    A32_BANKED_REG_SET(env, c2_mask,
+                       ARM_CP_SECSTATE_TEST(ri, ARM_CP_SECSTATE_S), 0);
     raw_write(env, ri, 0);
-    env->cp15.c2_mask = 0;
 }
 
 static void vmsa_tcr_el1_write(CPUARMState *env, const ARMCPRegInfo *ri,
@@ -4498,7 +4510,7 @@ static bool get_level1_table_address(CPUARMState *env, uint32_t *table,
      * AArch32 there is a secure and non-secure instance of the translation
      * table registers.
      */
-    if (address & env->cp15.c2_mask) {
+    if (address & A32_BANKED_CURRENT_REG_GET(env, c2_mask)) {
         if (A32_BANKED_CURRENT_REG_GET(env, ttbcr) & TTBCR_PD1) {
             /* Translation table walk disabled for TTBR1 */
             return false;
@@ -4510,7 +4522,7 @@ static bool get_level1_table_address(CPUARMState *env, uint32_t *table,
             return false;
         }
         *table = A32_BANKED_CURRENT_REG_GET(env, ttbr0) &
-                 env->cp15.c2_base_mask;
+                 A32_BANKED_CURRENT_REG_GET(env, c2_base_mask);
     }
     *table |= (address >> 18) & 0x3ffc;
     return true;
-- 
1.8.3.2

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

* [Qemu-devel] [PATCH v7 25/32] target-arm: make DACR banked
  2014-10-21 16:55 [Qemu-devel] [PATCH v7 00/32] target-arm: add Security Extensions for CPUs Greg Bellows
                   ` (23 preceding siblings ...)
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 24/32] target-arm: make c2_mask and c2_base_mask banked Greg Bellows
@ 2014-10-21 16:55 ` Greg Bellows
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 26/32] target-arm: make IFSR banked Greg Bellows
                   ` (7 subsequent siblings)
  32 siblings, 0 replies; 53+ messages in thread
From: Greg Bellows @ 2014-10-21 16:55 UTC (permalink / raw)
  To: qemu-devel, peter.maydell, serge.fdrv, edgar.iglesias, aggelerf
  Cc: greg.bellows

From: Fabian Aggeler <aggelerf@ethz.ch>

When EL3 is running in AArch32 (or ARMv7 with Security Extensions)
DACR has a secure and a non-secure instance.

Signed-off-by: Fabian Aggeler <aggelerf@ethz.ch>
Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
---
 hw/arm/pxa2xx.c     |  2 +-
 target-arm/cpu.h    | 13 +++++++++++--
 target-arm/helper.c | 19 +++++++++++--------
 3 files changed, 23 insertions(+), 11 deletions(-)

diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c
index 13261d0..51d9fe8 100644
--- a/hw/arm/pxa2xx.c
+++ b/hw/arm/pxa2xx.c
@@ -275,7 +275,7 @@ static void pxa2xx_pwrmode_write(CPUARMState *env, const ARMCPRegInfo *ri,
         s->cpu->env.cp15.sctlr_ns = 0;
         s->cpu->env.cp15.c1_coproc = 0;
         s->cpu->env.cp15.ttbr0_el[1] = 0;
-        s->cpu->env.cp15.c3 = 0;
+        s->cpu->env.cp15.dacr_ns = 0;
         s->pm_regs[PSSR >> 2] |= 0x8; /* Set STS */
         s->pm_regs[RCSR >> 2] |= 0x8; /* Set GPR */
 
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 785eab3..9392769 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -236,8 +236,17 @@ typedef struct CPUARMState {
         };
         uint32_t c2_data; /* MPU data cachable bits.  */
         uint32_t c2_insn; /* MPU instruction cachable bits.  */
-        uint32_t c3; /* MMU domain access control register
-                        MPU write buffer control.  */
+        union { /* MMU domain access control register
+                 * MPU write buffer control.
+                 */
+            struct {
+                uint32_t dacr_ns;
+                uint32_t dacr_s;
+            };
+            struct {
+                uint32_t dacr32_el2;
+            };
+        };
         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 */
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 046d81c..903207a 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -437,8 +437,10 @@ static const ARMCPRegInfo not_v8_cp_reginfo[] = {
     /* MMU Domain access control / MPU write buffer control */
     { .name = "DACR", .cp = 15,
       .crn = 3, .crm = CP_ANY, .opc1 = CP_ANY, .opc2 = CP_ANY,
-      .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.c3),
-      .resetvalue = 0, .writefn = dacr_write, .raw_writefn = raw_write, },
+      .access = PL1_RW, .resetvalue = 0,
+      .writefn = dacr_write, .raw_writefn = raw_write,
+      .bank_fieldoffsets = { offsetof(CPUARMState, cp15.dacr_s),
+                             offsetof(CPUARMState, cp15.dacr_ns) } },
     /* ??? This covers not just the impdef TLB lockdown registers but also
      * some v7VMSA registers relating to TEX remap, so it is overly broad.
      */
@@ -2269,10 +2271,11 @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
     { .name = "DCCISW", .cp = 15, .opc1 = 0, .crn = 7, .crm = 14, .opc2 = 2,
       .type = ARM_CP_NOP, .access = PL1_W },
     /* MMU Domain access control / MPU write buffer control */
-    { .name = "DACR", .cp = 15,
-      .opc1 = 0, .crn = 3, .crm = 0, .opc2 = 0,
-      .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.c3),
-      .resetvalue = 0, .writefn = dacr_write, .raw_writefn = raw_write, },
+    { .name = "DACR", .cp = 15, .opc1 = 0, .crn = 3, .crm = 0, .opc2 = 0,
+      .access = PL1_RW, .resetvalue = 0,
+      .writefn = dacr_write, .raw_writefn = raw_write,
+      .bank_fieldoffsets = { offsetof(CPUARMState, cp15.dacr_s),
+                             offsetof(CPUARMState, cp15.dacr_ns) } },
     { .name = "ELR_EL1", .state = ARM_CP_STATE_AA64,
       .type = ARM_CP_NO_MIGRATE,
       .opc0 = 3, .opc1 = 0, .crn = 4, .crm = 0, .opc2 = 1,
@@ -4552,7 +4555,7 @@ static int get_phys_addr_v5(CPUARMState *env, uint32_t address, int access_type,
     desc = ldl_phys(cs->as, table);
     type = (desc & 3);
     domain = (desc >> 5) & 0x0f;
-    domain_prot = (env->cp15.c3 >> (domain * 2)) & 3;
+    domain_prot = (A32_BANKED_CURRENT_REG_GET(env, dacr) >> (domain * 2)) & 3;
     if (type == 0) {
         /* Section translation fault.  */
         code = 5;
@@ -4664,7 +4667,7 @@ static int get_phys_addr_v6(CPUARMState *env, uint32_t address, int access_type,
         /* Page or Section.  */
         domain = (desc >> 5) & 0x0f;
     }
-    domain_prot = (env->cp15.c3 >> (domain * 2)) & 3;
+    domain_prot = (A32_BANKED_CURRENT_REG_GET(env, dacr) >> (domain * 2)) & 3;
     if (domain_prot == 0 || domain_prot == 2) {
         if (type != 1) {
             code = 9; /* Section domain fault.  */
-- 
1.8.3.2

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

* [Qemu-devel] [PATCH v7 26/32] target-arm: make IFSR banked
  2014-10-21 16:55 [Qemu-devel] [PATCH v7 00/32] target-arm: add Security Extensions for CPUs Greg Bellows
                   ` (24 preceding siblings ...)
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 25/32] target-arm: make DACR banked Greg Bellows
@ 2014-10-21 16:55 ` Greg Bellows
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 27/32] target-arm: make DFSR banked Greg Bellows
                   ` (6 subsequent siblings)
  32 siblings, 0 replies; 53+ messages in thread
From: Greg Bellows @ 2014-10-21 16:55 UTC (permalink / raw)
  To: qemu-devel, peter.maydell, serge.fdrv, edgar.iglesias, aggelerf
  Cc: greg.bellows

From: Fabian Aggeler <aggelerf@ethz.ch>

When EL3 is running in AArch32 (or ARMv7 with Security Extensions)
IFSR has a secure and a non-secure instance.

Signed-off-by: Fabian Aggeler <aggelerf@ethz.ch>
Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
---
 target-arm/cpu.h    | 10 +++++++++-
 target-arm/helper.c |  9 +++++----
 2 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 9392769..261b881 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -251,7 +251,15 @@ typedef struct CPUARMState {
         uint32_t pmsav5_insn_ap; /* PMSAv5 MPU insn access permissions */
         uint64_t hcr_el2; /* Hypervisor configuration register */
         uint64_t scr_el3; /* Secure configuration register.  */
-        uint32_t ifsr_el2; /* Fault status registers.  */
+        union { /* Fault status registers.  */
+            struct {
+                uint32_t ifsr_ns;
+                uint32_t ifsr_s;
+            };
+            struct {
+                uint32_t ifsr32_el2;
+            };
+        };
         uint64_t esr_el[4];
         uint32_t c6_region[8]; /* MPU base/size registers.  */
         uint64_t far_el[4]; /* Fault address registers.  */
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 903207a..7498f71 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1666,8 +1666,9 @@ static const ARMCPRegInfo vmsa_cp_reginfo[] = {
       .fieldoffset = offsetoflow32(CPUARMState, cp15.esr_el[1]),
       .resetfn = arm_cp_reset_ignore, },
     { .name = "IFSR", .cp = 15, .crn = 5, .crm = 0, .opc1 = 0, .opc2 = 1,
-      .access = PL1_RW,
-      .fieldoffset = offsetof(CPUARMState, cp15.ifsr_el2), .resetvalue = 0, },
+      .access = PL1_RW, .resetvalue = 0,
+      .bank_fieldoffsets = { offsetof(CPUARMState, cp15.ifsr_s),
+                             offsetof(CPUARMState, cp15.ifsr_ns) } },
     { .name = "ESR_EL1", .state = ARM_CP_STATE_AA64,
       .opc0 = 3, .crn = 5, .crm = 2, .opc1 = 0, .opc2 = 0,
       .access = PL1_RW,
@@ -4355,11 +4356,11 @@ void arm_cpu_do_interrupt(CPUState *cs)
         env->exception.fsr = 2;
         /* Fall through to prefetch abort.  */
     case EXCP_PREFETCH_ABORT:
-        env->cp15.ifsr_el2 = env->exception.fsr;
+        A32_BANKED_CURRENT_REG_SET(env, ifsr, env->exception.fsr);
         env->cp15.far_el[1] = deposit64(env->cp15.far_el[1], 32, 32,
                                         env->exception.vaddress);
         qemu_log_mask(CPU_LOG_INT, "...with IFSR 0x%x IFAR 0x%x\n",
-                      env->cp15.ifsr_el2, (uint32_t)env->exception.vaddress);
+                      env->exception.fsr, (uint32_t)env->exception.vaddress);
         new_mode = ARM_CPU_MODE_ABT;
         addr = 0x0c;
         mask = CPSR_A | CPSR_I;
-- 
1.8.3.2

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

* [Qemu-devel] [PATCH v7 27/32] target-arm: make DFSR banked
  2014-10-21 16:55 [Qemu-devel] [PATCH v7 00/32] target-arm: add Security Extensions for CPUs Greg Bellows
                   ` (25 preceding siblings ...)
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 26/32] target-arm: make IFSR banked Greg Bellows
@ 2014-10-21 16:55 ` Greg Bellows
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 28/32] target-arm: make IFAR/DFAR banked Greg Bellows
                   ` (5 subsequent siblings)
  32 siblings, 0 replies; 53+ messages in thread
From: Greg Bellows @ 2014-10-21 16:55 UTC (permalink / raw)
  To: qemu-devel, peter.maydell, serge.fdrv, edgar.iglesias, aggelerf
  Cc: greg.bellows

From: Fabian Aggeler <aggelerf@ethz.ch>

When EL3 is running in AArch32 (or ARMv7 with Security Extensions)
DFSR has a secure and a non-secure instance.

Signed-off-by: Fabian Aggeler <aggelerf@ethz.ch>
Signed-off-by: Greg Bellows <greg.bellows@linaro.org>

---------------
v3 -> v4
- Reverted esr/dfsr back to array-based notation as a union with v7 naming.

Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
---
 target-arm/cpu.h    | 10 +++++++++-
 target-arm/helper.c |  7 ++++---
 2 files changed, 13 insertions(+), 4 deletions(-)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 261b881..1f12a2c 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -260,7 +260,15 @@ typedef struct CPUARMState {
                 uint32_t ifsr32_el2;
             };
         };
-        uint64_t esr_el[4];
+        union {
+            struct {
+                uint64_t _unused_dfsr;
+                uint64_t dfsr_ns;
+                uint64_t hsr;
+                uint64_t dfsr_s;
+            };
+            uint64_t esr_el[4];
+        };
         uint32_t c6_region[8]; /* MPU base/size registers.  */
         uint64_t far_el[4]; /* Fault address registers.  */
         uint64_t par_el1;  /* Translation result. */
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 7498f71..01f4ce7 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1663,7 +1663,8 @@ static void vmsa_ttbr_write(CPUARMState *env, const ARMCPRegInfo *ri,
 static const ARMCPRegInfo vmsa_cp_reginfo[] = {
     { .name = "DFSR", .cp = 15, .crn = 5, .crm = 0, .opc1 = 0, .opc2 = 0,
       .access = PL1_RW, .type = ARM_CP_NO_MIGRATE,
-      .fieldoffset = offsetoflow32(CPUARMState, cp15.esr_el[1]),
+      .bank_fieldoffsets = { offsetoflow32(CPUARMState, cp15.dfsr_s),
+                             offsetoflow32(CPUARMState, cp15.dfsr_ns) },
       .resetfn = arm_cp_reset_ignore, },
     { .name = "IFSR", .cp = 15, .crn = 5, .crm = 0, .opc1 = 0, .opc2 = 1,
       .access = PL1_RW, .resetvalue = 0,
@@ -4367,11 +4368,11 @@ void arm_cpu_do_interrupt(CPUState *cs)
         offset = 4;
         break;
     case EXCP_DATA_ABORT:
-        env->cp15.esr_el[1] = env->exception.fsr;
+        A32_BANKED_CURRENT_REG_SET(env, dfsr, env->exception.fsr);
         env->cp15.far_el[1] = deposit64(env->cp15.far_el[1], 0, 32,
                                         env->exception.vaddress);
         qemu_log_mask(CPU_LOG_INT, "...with DFSR 0x%x DFAR 0x%x\n",
-                      (uint32_t)env->cp15.esr_el[1],
+                      env->exception.fsr,
                       (uint32_t)env->exception.vaddress);
         new_mode = ARM_CPU_MODE_ABT;
         addr = 0x10;
-- 
1.8.3.2

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

* [Qemu-devel] [PATCH v7 28/32] target-arm: make IFAR/DFAR banked
  2014-10-21 16:55 [Qemu-devel] [PATCH v7 00/32] target-arm: add Security Extensions for CPUs Greg Bellows
                   ` (26 preceding siblings ...)
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 27/32] target-arm: make DFSR banked Greg Bellows
@ 2014-10-21 16:55 ` Greg Bellows
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 29/32] target-arm: make PAR banked Greg Bellows
                   ` (4 subsequent siblings)
  32 siblings, 0 replies; 53+ messages in thread
From: Greg Bellows @ 2014-10-21 16:55 UTC (permalink / raw)
  To: qemu-devel, peter.maydell, serge.fdrv, edgar.iglesias, aggelerf
  Cc: greg.bellows

From: Fabian Aggeler <aggelerf@ethz.ch>

When EL3 is running in AArch32 (or ARMv7 with Security Extensions)
IFAR and DFAR have a secure and a non-secure instance.

Signed-off-by: Fabian Aggeler <aggelerf@ethz.ch>
Signed-off-by: Greg Bellows <greg.bellows@linaro.org>

-----------------
v3 -> v4
- Revert to array-based notation of far_el in combination with v7 naming

Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
---
 target-arm/cpu.c    |  2 +-
 target-arm/cpu.h    | 19 ++++++++++++++++++-
 target-arm/helper.c | 20 +++++++++++---------
 3 files changed, 30 insertions(+), 11 deletions(-)

diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index fdb6de4..63573c6 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -522,7 +522,7 @@ static void arm1026_initfn(Object *obj)
         ARMCPRegInfo ifar = {
             .name = "IFAR", .cp = 15, .crn = 6, .crm = 0, .opc1 = 0, .opc2 = 1,
             .access = PL1_RW,
-            .fieldoffset = offsetofhigh32(CPUARMState, cp15.far_el[1]),
+            .fieldoffset = offsetof(CPUARMState, cp15.ifar_ns),
             .resetvalue = 0
         };
         define_one_arm_cp_reg(cpu, &ifar);
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 1f12a2c..600528e 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -270,7 +270,24 @@ typedef struct CPUARMState {
             uint64_t esr_el[4];
         };
         uint32_t c6_region[8]; /* MPU base/size registers.  */
-        uint64_t far_el[4]; /* Fault address registers.  */
+        union { /* Fault address registers. */
+            struct {
+                uint64_t _unused_far0;
+#ifdef HOST_WORDS_BIGENDIAN
+                uint32_t ifar_ns;
+                uint32_t dfar_ns;
+                uint32_t ifar_s;
+                uint32_t dfar_s;
+#else
+                uint32_t dfar_ns;
+                uint32_t ifar_ns;
+                uint32_t dfar_s;
+                uint32_t ifar_s;
+#endif
+                uint64_t _unused_far3;;
+            };
+            uint64_t far_el[4];
+        };
         uint64_t par_el1;  /* Translation result. */
         uint32_t c9_insn; /* Cache lockdown registers.  */
         uint32_t c9_data;
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 01f4ce7..f46bc2a 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -567,7 +567,8 @@ static const ARMCPRegInfo v6_cp_reginfo[] = {
       .access = PL0_W, .type = ARM_CP_NOP },
     { .name = "IFAR", .cp = 15, .crn = 6, .crm = 0, .opc1 = 0, .opc2 = 2,
       .access = PL1_RW,
-      .fieldoffset = offsetofhigh32(CPUARMState, cp15.far_el[1]),
+      .bank_fieldoffsets = { offsetof(CPUARMState, cp15.ifar_s),
+                             offsetof(CPUARMState, cp15.ifar_ns) },
       .resetvalue = 0, },
     /* Watchpoint Fault Address Register : should actually only be present
      * for 1136, 1176, 11MPCore.
@@ -1694,11 +1695,14 @@ static const ARMCPRegInfo vmsa_cp_reginfo[] = {
       .resetfn = arm_cp_reset_ignore, .raw_writefn = vmsa_ttbcr_raw_write,
       .bank_fieldoffsets = { offsetoflow32(CPUARMState, cp15.ttbcr_s),
                              offsetoflow32(CPUARMState, cp15.ttbcr_ns) } },
-    /* 64-bit FAR; this entry also gives us the AArch32 DFAR */
-    { .name = "FAR_EL1", .state = ARM_CP_STATE_BOTH,
+    { .name = "DFAR", .cp = 15, .crn = 6, .crm = 0, .opc1 = 0, .opc2 = 0,
+      .access = PL1_RW, .resetvalue = 0,
+      .bank_fieldoffsets = { offsetof(CPUARMState, cp15.dfar_s),
+                             offsetof(CPUARMState, cp15.dfar_ns) } },
+    { .name = "FAR_EL1", .state = ARM_CP_STATE_AA64,
       .opc0 = 3, .crn = 6, .crm = 0, .opc1 = 0, .opc2 = 0,
-      .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.far_el[1]),
-      .resetvalue = 0, },
+      .access = PL1_RW, .resetvalue = 0,
+      .fieldoffset = offsetof(CPUARMState, cp15.far_el[1]) },
     REGINFO_SENTINEL
 };
 
@@ -4358,8 +4362,7 @@ void arm_cpu_do_interrupt(CPUState *cs)
         /* Fall through to prefetch abort.  */
     case EXCP_PREFETCH_ABORT:
         A32_BANKED_CURRENT_REG_SET(env, ifsr, env->exception.fsr);
-        env->cp15.far_el[1] = deposit64(env->cp15.far_el[1], 32, 32,
-                                        env->exception.vaddress);
+        A32_BANKED_CURRENT_REG_SET(env, ifar, env->exception.vaddress);
         qemu_log_mask(CPU_LOG_INT, "...with IFSR 0x%x IFAR 0x%x\n",
                       env->exception.fsr, (uint32_t)env->exception.vaddress);
         new_mode = ARM_CPU_MODE_ABT;
@@ -4369,8 +4372,7 @@ void arm_cpu_do_interrupt(CPUState *cs)
         break;
     case EXCP_DATA_ABORT:
         A32_BANKED_CURRENT_REG_SET(env, dfsr, env->exception.fsr);
-        env->cp15.far_el[1] = deposit64(env->cp15.far_el[1], 0, 32,
-                                        env->exception.vaddress);
+        A32_BANKED_CURRENT_REG_SET(env, dfar, env->exception.vaddress);
         qemu_log_mask(CPU_LOG_INT, "...with DFSR 0x%x DFAR 0x%x\n",
                       env->exception.fsr,
                       (uint32_t)env->exception.vaddress);
-- 
1.8.3.2

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

* [Qemu-devel] [PATCH v7 29/32] target-arm: make PAR banked
  2014-10-21 16:55 [Qemu-devel] [PATCH v7 00/32] target-arm: add Security Extensions for CPUs Greg Bellows
                   ` (27 preceding siblings ...)
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 28/32] target-arm: make IFAR/DFAR banked Greg Bellows
@ 2014-10-21 16:55 ` Greg Bellows
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 30/32] target-arm: make c13 cp regs banked (FCSEIDR, ...) Greg Bellows
                   ` (3 subsequent siblings)
  32 siblings, 0 replies; 53+ messages in thread
From: Greg Bellows @ 2014-10-21 16:55 UTC (permalink / raw)
  To: qemu-devel, peter.maydell, serge.fdrv, edgar.iglesias, aggelerf
  Cc: greg.bellows

From: Fabian Aggeler <aggelerf@ethz.ch>

When EL3 is running in AArch32 (or ARMv7 with Security Extensions)
PAR has a secure and a non-secure instance.

Signed-off-by: Fabian Aggeler <aggelerf@ethz.ch>
Signed-off-by: Greg Bellows <greg.bellows@linaro.org>

==========

v5 -> v6
- Changed _el field variants to be array based
- Merged VBAR and VBAR_EL1 reginfo entries

v3 -> v4
- Fix par union/structure definition

Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
---
 target-arm/cpu.h    | 20 ++++++++++++++++++--
 target-arm/helper.c | 33 ++++++++++++++++++---------------
 2 files changed, 36 insertions(+), 17 deletions(-)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 600528e..e018f74 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -288,7 +288,15 @@ typedef struct CPUARMState {
             };
             uint64_t far_el[4];
         };
-        uint64_t par_el1;  /* Translation result. */
+        union { /* Translation result. */
+            struct {
+                uint64_t _unused_par_0;
+                uint64_t par_ns;
+                uint64_t _unused_par_1;
+                uint64_t par_s;
+            };
+            uint64_t par_el[4];
+        };
         uint32_t c9_insn; /* Cache lockdown registers.  */
         uint32_t c9_data;
         uint64_t c9_pmcr; /* performance monitor control register */
@@ -298,7 +306,15 @@ typedef struct CPUARMState {
         uint32_t c9_pmuserenr; /* perf monitor user enable */
         uint32_t c9_pminten; /* perf monitor interrupt enables */
         uint64_t mair_el1;
-        uint64_t vbar_el[4]; /* vector base address register */
+        union { /* vector base address register */
+            struct {
+                uint64_t _unused_vbar;
+                uint64_t vbar_ns;
+                uint64_t hvbar;
+                uint64_t vbar_s;
+            };
+            uint64_t vbar_el[4];
+        };
         uint64_t mvbar; /* (monitor) vector base address register */
         uint32_t c13_fcse; /* FCSE PID.  */
         uint64_t contextidr_el1; /* Context ID.  */
diff --git a/target-arm/helper.c b/target-arm/helper.c
index f46bc2a..8b0a327 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -918,9 +918,9 @@ static const ARMCPRegInfo v7_cp_reginfo[] = {
       .resetvalue = 0, .writefn = pmintenclr_write, },
     { .name = "VBAR", .state = ARM_CP_STATE_BOTH,
       .opc0 = 3, .crn = 12, .crm = 0, .opc1 = 0, .opc2 = 0,
-      .access = PL1_RW, .writefn = vbar_write,
-      .fieldoffset = offsetof(CPUARMState, cp15.vbar_el[1]),
-      .resetvalue = 0 },
+      .access = PL1_RW, .writefn = vbar_write, .resetvalue = 0,
+      .bank_fieldoffsets = { offsetof(CPUARMState, cp15.vbar_s),
+                             offsetof(CPUARMState, cp15.vbar_ns) } },
     { .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 },
@@ -1432,7 +1432,7 @@ static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
              * fault.
              */
         }
-        env->cp15.par_el1 = par64;
+        A32_BANKED_CURRENT_REG_SET(env, par, par64);
     } else {
         /* ret is a DFSR/IFSR value for the short descriptor
          * translation table format (with WnR always clear).
@@ -1442,14 +1442,16 @@ static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
             /* We do not set any attribute bits in the PAR */
             if (page_size == (1 << 24)
                 && arm_feature(env, ARM_FEATURE_V7)) {
-                env->cp15.par_el1 = (phys_addr & 0xff000000) | 1 << 1;
+                A32_BANKED_CURRENT_REG_SET(env, par,
+                        (phys_addr & 0xff000000) | 1 << 1);
             } else {
-                env->cp15.par_el1 = phys_addr & 0xfffff000;
+                A32_BANKED_CURRENT_REG_SET(env, par, phys_addr & 0xfffff000);
             }
         } else {
-            env->cp15.par_el1 = ((ret & (1 << 10)) >> 5) |
-                ((ret & (1 << 12)) >> 6) |
-                ((ret & 0xf) << 1) | 1;
+            A32_BANKED_CURRENT_REG_SET(env, par,
+                    ((ret & (1 << 10)) >> 5) |
+                    ((ret & (1 << 12)) >> 6) |
+                    ((ret & 0xf) << 1) | 1);
         }
     }
 }
@@ -1457,9 +1459,9 @@ static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
 
 static const ARMCPRegInfo vapa_cp_reginfo[] = {
     { .name = "PAR", .cp = 15, .crn = 7, .crm = 4, .opc1 = 0, .opc2 = 0,
-      .access = PL1_RW, .resetvalue = 0,
-      .fieldoffset = offsetoflow32(CPUARMState, cp15.par_el1),
-      .writefn = par_write },
+      .access = PL1_RW, .resetvalue = 0, .writefn = par_write,
+      .bank_fieldoffsets = { offsetoflow32(CPUARMState, cp15.par_s),
+                             offsetoflow32(CPUARMState, cp15.par_ns) } },
 #ifndef CONFIG_USER_ONLY
     { .name = "ATS", .cp = 15, .crn = 7, .crm = 8, .opc1 = 0, .opc2 = CP_ANY,
       .access = PL1_W, .accessfn = ats_access,
@@ -1915,8 +1917,9 @@ static const ARMCPRegInfo lpae_cp_reginfo[] = {
       .access = PL1_RW, .type = ARM_CP_CONST | ARM_CP_OVERRIDE,
       .resetvalue = 0 },
     { .name = "PAR", .cp = 15, .crm = 7, .opc1 = 0,
-      .access = PL1_RW, .type = ARM_CP_64BIT,
-      .fieldoffset = offsetof(CPUARMState, cp15.par_el1), .resetvalue = 0 },
+      .access = PL1_RW, .type = ARM_CP_64BIT, .resetvalue = 0,
+      .bank_fieldoffsets = { offsetof(CPUARMState, cp15.par_s),
+                             offsetof(CPUARMState, cp15.par_ns)} },
     { .name = "TTBR0", .cp = 15, .crm = 2, .opc1 = 0,
       .access = PL1_RW, .type = ARM_CP_64BIT | ARM_CP_NO_MIGRATE,
       .bank_fieldoffsets = { offsetof(CPUARMState, cp15.ttbr0_s),
@@ -4426,7 +4429,7 @@ void arm_cpu_do_interrupt(CPUState *cs)
          * This register is only followed in non-monitor mode, and is banked.
          * Note: only bits 31:5 are valid.
          */
-        addr += env->cp15.vbar_el[1];
+        addr += A32_BANKED_CURRENT_REG_GET(env, vbar);
     }
 
     if ((env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_MON) {
-- 
1.8.3.2

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

* [Qemu-devel] [PATCH v7 30/32] target-arm: make c13 cp regs banked (FCSEIDR, ...)
  2014-10-21 16:55 [Qemu-devel] [PATCH v7 00/32] target-arm: add Security Extensions for CPUs Greg Bellows
                   ` (28 preceding siblings ...)
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 29/32] target-arm: make PAR banked Greg Bellows
@ 2014-10-21 16:55 ` Greg Bellows
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 31/32] target-arm: make MAIR0/1 banked Greg Bellows
                   ` (2 subsequent siblings)
  32 siblings, 0 replies; 53+ messages in thread
From: Greg Bellows @ 2014-10-21 16:55 UTC (permalink / raw)
  To: qemu-devel, peter.maydell, serge.fdrv, edgar.iglesias, aggelerf
  Cc: greg.bellows

From: Fabian Aggeler <aggelerf@ethz.ch>

When EL3 is running in AArch32 (or ARMv7 with Security Extensions)
FCSEIDR, CONTEXTIDR, TPIDRURW, TPIDRURO and TPIDRPRW have a secure
and a non-secure instance.

Signed-off-by: Fabian Aggeler <aggelerf@ethz.ch>
Signed-off-by: Greg Bellows <greg.bellows@linaro.org>

==========

v6 -> v7
- Fix linux-user/arm/target-cpu.h to use array based tpidr_el.
- Fix linux-user/main.c to use array based tpidrro_el.
- Remove tab identified by checkpatch failure.
- FIx linux-user/aarch64/target_cpu.h to use array based tpidr_el.

v5 -> v6
- Changed _el field variants to be array based
- Rework data layout for correct aliasing
- Merged CONTEXTIDR and CONTEXTIDR_EL1 reginfo entries

v3 -> v4
- Fix tpidrprw mapping

Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
---
 linux-user/aarch64/target_cpu.h |  2 +-
 linux-user/arm/target_cpu.h     |  2 +-
 linux-user/main.c               | 72 ++++++++++++++++++++---------------------
 target-arm/cpu.h                | 35 +++++++++++++++++---
 target-arm/helper.c             | 37 ++++++++++++---------
 target-arm/op_helper.c          |  2 +-
 6 files changed, 91 insertions(+), 59 deletions(-)

diff --git a/linux-user/aarch64/target_cpu.h b/linux-user/aarch64/target_cpu.h
index 21560ef..b5593dc 100644
--- a/linux-user/aarch64/target_cpu.h
+++ b/linux-user/aarch64/target_cpu.h
@@ -32,7 +32,7 @@ static inline void cpu_set_tls(CPUARMState *env, target_ulong newtls)
     /* Note that AArch64 Linux keeps the TLS pointer in TPIDR; this is
      * different from AArch32 Linux, which uses TPIDRRO.
      */
-    env->cp15.tpidr_el0 = newtls;
+    env->cp15.tpidr_el[0] = newtls;
 }
 
 #endif
diff --git a/linux-user/arm/target_cpu.h b/linux-user/arm/target_cpu.h
index 39d65b6..d8a534d 100644
--- a/linux-user/arm/target_cpu.h
+++ b/linux-user/arm/target_cpu.h
@@ -29,7 +29,7 @@ static inline void cpu_clone_regs(CPUARMState *env, target_ulong newsp)
 
 static inline void cpu_set_tls(CPUARMState *env, target_ulong newtls)
 {
-    env->cp15.tpidrro_el0 = newtls;
+    env->cp15.tpidrro_el[0] = newtls;
 }
 
 #endif
diff --git a/linux-user/main.c b/linux-user/main.c
index 483eb3f..4f2bae2 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -564,7 +564,7 @@ do_kernel_trap(CPUARMState *env)
         end_exclusive();
         break;
     case 0xffff0fe0: /* __kernel_get_tls */
-        env->regs[0] = env->cp15.tpidrro_el0;
+        env->regs[0] = env->cp15.tpidrro_el[0];
         break;
     case 0xffff0f60: /* __kernel_cmpxchg64 */
         arm_kernel_cmpxchg64_helper(env);
@@ -2804,7 +2804,7 @@ void cpu_loop(CPUCRISState *env)
     CPUState *cs = CPU(cris_env_get_cpu(env));
     int trapnr, ret;
     target_siginfo_t info;
-    
+
     while (1) {
         trapnr = cpu_cris_exec (env);
         switch (trapnr) {
@@ -2822,13 +2822,13 @@ void cpu_loop(CPUCRISState *env)
 	  /* just indicate that signals should be handled asap */
 	  break;
         case EXCP_BREAK:
-            ret = do_syscall(env, 
-                             env->regs[9], 
-                             env->regs[10], 
-                             env->regs[11], 
-                             env->regs[12], 
-                             env->regs[13], 
-                             env->pregs[7], 
+            ret = do_syscall(env,
+                             env->regs[9],
+                             env->regs[10],
+                             env->regs[11],
+                             env->regs[12],
+                             env->regs[13],
+                             env->pregs[7],
                              env->pregs[11],
                              0, 0);
             env->regs[10] = ret;
@@ -2863,7 +2863,7 @@ void cpu_loop(CPUMBState *env)
     CPUState *cs = CPU(mb_env_get_cpu(env));
     int trapnr, ret;
     target_siginfo_t info;
-    
+
     while (1) {
         trapnr = cpu_mb_exec (env);
         switch (trapnr) {
@@ -2884,13 +2884,13 @@ void cpu_loop(CPUMBState *env)
             /* Return address is 4 bytes after the call.  */
             env->regs[14] += 4;
             env->sregs[SR_PC] = env->regs[14];
-            ret = do_syscall(env, 
-                             env->regs[12], 
-                             env->regs[5], 
-                             env->regs[6], 
-                             env->regs[7], 
-                             env->regs[8], 
-                             env->regs[9], 
+            ret = do_syscall(env,
+                             env->regs[12],
+                             env->regs[5],
+                             env->regs[6],
+                             env->regs[7],
+                             env->regs[8],
+                             env->regs[9],
                              env->regs[10],
                              0, 0);
             env->regs[3] = ret;
@@ -3424,7 +3424,7 @@ void stop_all_tasks(void)
 void init_task_state(TaskState *ts)
 {
     int i;
- 
+
     ts->used = 1;
     ts->first_free = ts->sigqueue_table;
     for (i = 0; i < MAX_SIGQUEUE_SIZE - 1; i++) {
@@ -4271,23 +4271,23 @@ int main(int argc, char **argv, char **envp)
         env->regs[12] = regs->r12;
         env->regs[13] = regs->r13;
         env->regs[14] = regs->r14;
-        env->regs[15] = regs->r15;	    
-        env->regs[16] = regs->r16;	    
-        env->regs[17] = regs->r17;	    
-        env->regs[18] = regs->r18;	    
-        env->regs[19] = regs->r19;	    
-        env->regs[20] = regs->r20;	    
-        env->regs[21] = regs->r21;	    
-        env->regs[22] = regs->r22;	    
-        env->regs[23] = regs->r23;	    
-        env->regs[24] = regs->r24;	    
-        env->regs[25] = regs->r25;	    
-        env->regs[26] = regs->r26;	    
-        env->regs[27] = regs->r27;	    
-        env->regs[28] = regs->r28;	    
-        env->regs[29] = regs->r29;	    
-        env->regs[30] = regs->r30;	    
-        env->regs[31] = regs->r31;	    
+        env->regs[15] = regs->r15;
+        env->regs[16] = regs->r16;
+        env->regs[17] = regs->r17;
+        env->regs[18] = regs->r18;
+        env->regs[19] = regs->r19;
+        env->regs[20] = regs->r20;
+        env->regs[21] = regs->r21;
+        env->regs[22] = regs->r22;
+        env->regs[23] = regs->r23;
+        env->regs[24] = regs->r24;
+        env->regs[25] = regs->r25;
+        env->regs[26] = regs->r26;
+        env->regs[27] = regs->r27;
+        env->regs[28] = regs->r28;
+        env->regs[29] = regs->r29;
+        env->regs[30] = regs->r30;
+        env->regs[31] = regs->r31;
         env->sregs[SR_PC] = regs->pc;
     }
 #elif defined(TARGET_MIPS)
@@ -4349,7 +4349,7 @@ int main(int argc, char **argv, char **envp)
 	    env->regs[12] = regs->r12;
 	    env->regs[13] = regs->r13;
 	    env->regs[14] = info->start_stack;
-	    env->regs[15] = regs->acr;	    
+        env->regs[15] = regs->acr;
 	    env->pc = regs->erp;
     }
 #elif defined(TARGET_S390X)
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index e018f74..82fc018 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -316,11 +316,36 @@ typedef struct CPUARMState {
             uint64_t vbar_el[4];
         };
         uint64_t mvbar; /* (monitor) vector base address register */
-        uint32_t c13_fcse; /* FCSE PID.  */
-        uint64_t contextidr_el1; /* Context ID.  */
-        uint64_t tpidr_el0; /* User RW Thread register.  */
-        uint64_t tpidrro_el0; /* User RO Thread register.  */
-        uint64_t tpidr_el1; /* Privileged Thread register.  */
+        struct { /* FCSE PID. */
+            uint32_t fcseidr_ns;
+            uint32_t fcseidr_s;
+        };
+        union { /* Context ID. */
+            struct {
+                uint64_t _unused_contextidr;
+                uint64_t contextidr_ns;
+                uint64_t contextidr_s;
+            };
+            uint64_t contextidr_el[2];
+        };
+        union { /* User RW Thread register. */
+            struct {
+                uint64_t tpidrurw_ns;
+                uint64_t tpidrprw_ns;
+                uint64_t htpidr;
+                uint64_t _tpidr_el3;
+            };
+            uint64_t tpidr_el[4];
+        };
+        /* The secure banks of these registers don't map anywhere */
+        uint64_t tpidrurw_s;
+        uint64_t tpidrprw_s;
+        uint64_t tpidruro_s;
+
+        union { /* User RO Thread register. */
+            uint64_t tpidruro_ns;
+            uint64_t tpidrro_el[1];
+        };
         uint64_t c14_cntfrq; /* Counter Frequency register */
         uint64_t c14_cntkctl; /* Timer Control register */
         ARMGenericTimer c14_timer[NUM_GTIMERS];
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 8b0a327..f8e2eed 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -420,12 +420,15 @@ static void tlbimvaa_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
 
 static const ARMCPRegInfo cp_reginfo[] = {
     { .name = "FCSEIDR", .cp = 15, .crn = 13, .crm = 0, .opc1 = 0, .opc2 = 0,
-      .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.c13_fcse),
+      .access = PL1_RW,
+      .bank_fieldoffsets = { offsetof(CPUARMState, cp15.fcseidr_s),
+                             offsetof(CPUARMState, cp15.fcseidr_ns) },
       .resetvalue = 0, .writefn = fcse_write, .raw_writefn = raw_write, },
     { .name = "CONTEXTIDR", .state = ARM_CP_STATE_BOTH,
-      .opc0 = 3, .opc1 = 0, .crn = 13, .crm = 0, .opc2 = 1,
+      .cp = 15, .opc1 = 0, .crn = 13, .crm = 0, .opc2 = 1,
       .access = PL1_RW,
-      .fieldoffset = offsetof(CPUARMState, cp15.contextidr_el1),
+      .bank_fieldoffsets = { offsetof(CPUARMState, cp15.contextidr_s),
+                             offsetof(CPUARMState, cp15.contextidr_ns) },
       .resetvalue = 0, .writefn = contextidr_write, .raw_writefn = raw_write, },
     REGINFO_SENTINEL
 };
@@ -1038,23 +1041,27 @@ static const ARMCPRegInfo v6k_cp_reginfo[] = {
     { .name = "TPIDR_EL0", .state = ARM_CP_STATE_AA64,
       .opc0 = 3, .opc1 = 3, .opc2 = 2, .crn = 13, .crm = 0,
       .access = PL0_RW,
-      .fieldoffset = offsetof(CPUARMState, cp15.tpidr_el0), .resetvalue = 0 },
+      .fieldoffset = offsetof(CPUARMState, cp15.tpidr_el[0]), .resetvalue = 0 },
     { .name = "TPIDRURW", .cp = 15, .crn = 13, .crm = 0, .opc1 = 0, .opc2 = 2,
-      .access = PL0_RW,
-      .fieldoffset = offsetoflow32(CPUARMState, cp15.tpidr_el0),
-      .resetfn = arm_cp_reset_ignore },
+      .access = PL0_RW, .resetvalue = 0,
+      .bank_fieldoffsets = { offsetoflow32(CPUARMState, cp15.tpidrurw_s),
+                             offsetoflow32(CPUARMState, cp15.tpidrurw_ns) } },
     { .name = "TPIDRRO_EL0", .state = ARM_CP_STATE_AA64,
       .opc0 = 3, .opc1 = 3, .opc2 = 3, .crn = 13, .crm = 0,
-      .access = PL0_R|PL1_W,
-      .fieldoffset = offsetof(CPUARMState, cp15.tpidrro_el0), .resetvalue = 0 },
+      .access = PL0_R|PL1_W, .resetvalue = 0,
+      .fieldoffset = offsetof(CPUARMState, cp15.tpidrro_el[0]) },
     { .name = "TPIDRURO", .cp = 15, .crn = 13, .crm = 0, .opc1 = 0, .opc2 = 3,
-      .access = PL0_R|PL1_W,
-      .fieldoffset = offsetoflow32(CPUARMState, cp15.tpidrro_el0),
-      .resetfn = arm_cp_reset_ignore },
-    { .name = "TPIDR_EL1", .state = ARM_CP_STATE_BOTH,
+      .access = PL0_R|PL1_W, .resetvalue = 0,
+      .bank_fieldoffsets = { offsetoflow32(CPUARMState, cp15.tpidruro_s),
+                             offsetoflow32(CPUARMState, cp15.tpidruro_ns) } },
+    { .name = "TPIDR_EL1", .state = ARM_CP_STATE_AA64,
       .opc0 = 3, .opc1 = 0, .opc2 = 4, .crn = 13, .crm = 0,
       .access = PL1_RW,
-      .fieldoffset = offsetof(CPUARMState, cp15.tpidr_el1), .resetvalue = 0 },
+      .fieldoffset = offsetof(CPUARMState, cp15.tpidr_el[1]), .resetvalue = 0 },
+    { .name = "TPIDRPRW", .cp = 15, .crn = 13, .crm = 0, .opc1 = 0, .opc2 = 4,
+      .access = PL1_RW, .resetvalue = 0,
+      .bank_fieldoffsets = { offsetoflow32(CPUARMState, cp15.tpidrprw_s),
+                             offsetoflow32(CPUARMState, cp15.tpidrprw_ns) } },
     REGINFO_SENTINEL
 };
 
@@ -5103,7 +5110,7 @@ static inline int get_phys_addr(CPUARMState *env, target_ulong address,
 
     /* Fast Context Switch Extension.  */
     if (address < 0x02000000)
-        address += env->cp15.c13_fcse;
+        address += A32_BANKED_CURRENT_REG_GET(env, fcseidr);
 
     if ((sctlr & SCTLR_M) == 0) {
         /* MMU/MPU disabled.  */
diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
index a8dea5a..2bed914 100644
--- a/target-arm/op_helper.c
+++ b/target-arm/op_helper.c
@@ -575,7 +575,7 @@ static bool linked_bp_matches(ARMCPU *cpu, int lbn)
      * short descriptor format (in which case it holds both PROCID and ASID),
      * since we don't implement the optional v7 context ID masking.
      */
-    contextidr = extract64(env->cp15.contextidr_el1, 0, 32);
+    contextidr = extract64(env->cp15.contextidr_el[1], 0, 32);
 
     switch (bt) {
     case 3: /* linked context ID match */
-- 
1.8.3.2

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

* [Qemu-devel] [PATCH v7 31/32] target-arm: make MAIR0/1 banked
  2014-10-21 16:55 [Qemu-devel] [PATCH v7 00/32] target-arm: add Security Extensions for CPUs Greg Bellows
                   ` (29 preceding siblings ...)
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 30/32] target-arm: make c13 cp regs banked (FCSEIDR, ...) Greg Bellows
@ 2014-10-21 16:55 ` Greg Bellows
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 32/32] target-arm: add cpu feature EL3 to CPUs with Security Extensions Greg Bellows
  2014-10-23 14:19 ` [Qemu-devel] [PATCH v7 00/32] target-arm: add Security Extensions for CPUs Peter Maydell
  32 siblings, 0 replies; 53+ messages in thread
From: Greg Bellows @ 2014-10-21 16:55 UTC (permalink / raw)
  To: qemu-devel, peter.maydell, serge.fdrv, edgar.iglesias, aggelerf
  Cc: greg.bellows

Added CP register info entries for the ARMv7 MAIR0/1 secure banks.

Signed-off-by: Greg Bellows <greg.bellows@linaro.org>

==========

v5 -> v6
- Changed _el field variants to be array based

Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
---
 target-arm/cpu.h    | 12 +++++++++++-
 target-arm/helper.c |  8 +++++---
 2 files changed, 16 insertions(+), 4 deletions(-)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 82fc018..ebc2931 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -305,7 +305,17 @@ typedef struct CPUARMState {
         uint32_t c9_pmxevtyper; /* perf monitor event type */
         uint32_t c9_pmuserenr; /* perf monitor user enable */
         uint32_t c9_pminten; /* perf monitor interrupt enables */
-        uint64_t mair_el1;
+        union { /* Memory attribute redirection */
+            struct {
+                uint64_t _unused_mair_0;
+                uint32_t mair0_ns;
+                uint32_t mair1_ns;
+                uint64_t _unused_mair_1;
+                uint32_t mair0_s;
+                uint32_t mair1_s;
+            };
+            uint64_t mair_el[4];
+        };
         union { /* vector base address register */
             struct {
                 uint64_t _unused_vbar;
diff --git a/target-arm/helper.c b/target-arm/helper.c
index f8e2eed..9cbea28 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -952,7 +952,7 @@ static const ARMCPRegInfo v7_cp_reginfo[] = {
      */
     { .name = "MAIR_EL1", .state = ARM_CP_STATE_AA64,
       .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 2, .opc2 = 0,
-      .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.mair_el1),
+      .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.mair_el[1]),
       .resetvalue = 0 },
     /* For non-long-descriptor page tables these are PRRR and NMRR;
      * regardless they still act as reads-as-written for QEMU.
@@ -961,11 +961,13 @@ static const ARMCPRegInfo v7_cp_reginfo[] = {
      */
     { .name = "MAIR0", .state = ARM_CP_STATE_AA32, .type = ARM_CP_OVERRIDE,
       .cp = 15, .opc1 = 0, .crn = 10, .crm = 2, .opc2 = 0, .access = PL1_RW,
-      .fieldoffset = offsetoflow32(CPUARMState, cp15.mair_el1),
+      .bank_fieldoffsets = { offsetof(CPUARMState, cp15.mair0_s),
+                             offsetof(CPUARMState, cp15.mair0_ns) },
       .resetfn = arm_cp_reset_ignore },
     { .name = "MAIR1", .state = ARM_CP_STATE_AA32, .type = ARM_CP_OVERRIDE,
       .cp = 15, .opc1 = 0, .crn = 10, .crm = 2, .opc2 = 1, .access = PL1_RW,
-      .fieldoffset = offsetofhigh32(CPUARMState, cp15.mair_el1),
+      .bank_fieldoffsets = { offsetof(CPUARMState, cp15.mair1_s),
+                             offsetof(CPUARMState, cp15.mair1_ns) },
       .resetfn = arm_cp_reset_ignore },
     { .name = "ISR_EL1", .state = ARM_CP_STATE_BOTH,
       .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 1, .opc2 = 0,
-- 
1.8.3.2

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

* [Qemu-devel] [PATCH v7 32/32] target-arm: add cpu feature EL3 to CPUs with Security Extensions
  2014-10-21 16:55 [Qemu-devel] [PATCH v7 00/32] target-arm: add Security Extensions for CPUs Greg Bellows
                   ` (30 preceding siblings ...)
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 31/32] target-arm: make MAIR0/1 banked Greg Bellows
@ 2014-10-21 16:55 ` Greg Bellows
  2014-10-23 14:19 ` [Qemu-devel] [PATCH v7 00/32] target-arm: add Security Extensions for CPUs Peter Maydell
  32 siblings, 0 replies; 53+ messages in thread
From: Greg Bellows @ 2014-10-21 16:55 UTC (permalink / raw)
  To: qemu-devel, peter.maydell, serge.fdrv, edgar.iglesias, aggelerf
  Cc: greg.bellows

From: Fabian Aggeler <aggelerf@ethz.ch>

Set ARM_FEATURE_EL3 feature for CPUs that implement Security Extensions.

Signed-off-by: Fabian Aggeler <aggelerf@ethz.ch>
Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
---
 target-arm/cpu.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index 63573c6..1e93d7e 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -610,6 +610,7 @@ static void arm1176_initfn(Object *obj)
     set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
     set_feature(&cpu->env, ARM_FEATURE_CACHE_DIRTY_REG);
     set_feature(&cpu->env, ARM_FEATURE_CACHE_BLOCK_OPS);
+    set_feature(&cpu->env, ARM_FEATURE_EL3);
     cpu->midr = 0x410fb767;
     cpu->reset_fpsid = 0x410120b5;
     cpu->mvfr0 = 0x11111111;
@@ -696,6 +697,7 @@ static void cortex_a8_initfn(Object *obj)
     set_feature(&cpu->env, ARM_FEATURE_NEON);
     set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
     set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
+    set_feature(&cpu->env, ARM_FEATURE_EL3);
     cpu->midr = 0x410fc080;
     cpu->reset_fpsid = 0x410330c0;
     cpu->mvfr0 = 0x11110222;
@@ -763,6 +765,7 @@ static void cortex_a9_initfn(Object *obj)
     set_feature(&cpu->env, ARM_FEATURE_VFP_FP16);
     set_feature(&cpu->env, ARM_FEATURE_NEON);
     set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
+    set_feature(&cpu->env, ARM_FEATURE_EL3);
     /* Note that A9 supports the MP extensions even for
      * A9UP and single-core A9MP (which are both different
      * and valid configurations; we don't model A9UP).
@@ -830,6 +833,7 @@ static void cortex_a15_initfn(Object *obj)
     set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
     set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
     set_feature(&cpu->env, ARM_FEATURE_LPAE);
+    set_feature(&cpu->env, ARM_FEATURE_EL3);
     cpu->kvm_target = QEMU_KVM_ARM_TARGET_CORTEX_A15;
     cpu->midr = 0x412fc0f1;
     cpu->reset_fpsid = 0x410430f0;
-- 
1.8.3.2

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

* Re: [Qemu-devel] [PATCH v7 06/32] target-arm: A32: Emulate the SMC instruction
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 06/32] target-arm: A32: Emulate the SMC instruction Greg Bellows
@ 2014-10-23 14:06   ` Peter Maydell
  0 siblings, 0 replies; 53+ messages in thread
From: Peter Maydell @ 2014-10-23 14:06 UTC (permalink / raw)
  To: Greg Bellows
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler, Edgar E. Iglesias

On 21 October 2014 17:55, Greg Bellows <greg.bellows@linaro.org> wrote:
> From: Fabian Aggeler <aggelerf@ethz.ch>
>
> Implements SMC instruction in AArch32 using the A32 syndrome. When executing
> SMC instruction from monitor CPU mode SCR.NS bit is reset.
>
> Signed-off-by: Sergey Fedorov <s.fedorov@samsung.com>
> Signed-off-by: Fabian Aggeler <aggelerf@ethz.ch>
> Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
>

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v7 00/32] target-arm: add Security Extensions for CPUs
  2014-10-21 16:55 [Qemu-devel] [PATCH v7 00/32] target-arm: add Security Extensions for CPUs Greg Bellows
                   ` (31 preceding siblings ...)
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 32/32] target-arm: add cpu feature EL3 to CPUs with Security Extensions Greg Bellows
@ 2014-10-23 14:19 ` Peter Maydell
  32 siblings, 0 replies; 53+ messages in thread
From: Peter Maydell @ 2014-10-23 14:19 UTC (permalink / raw)
  To: Greg Bellows
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler, Edgar E. Iglesias

On 21 October 2014 17:55, Greg Bellows <greg.bellows@linaro.org> wrote:
> Version 7 of the ARM processor security extension (TrustZone) support.
> This patchset includes changes to support the processor security extensions
> on ARMv7 aarch32 with hooks for later enabling v8 aarch64/32.
>
> Summary of changes from v6 -> v7:
> - Fixed comment and commit message issues
> - Updated linux-user uses of tpidr*_el to use array version
> - Fixed anonymous struct/union issue when building with gcc-4.4

Patches 1..6 here are all good and so I'm pulling them into
target-arm.next in the interests of reducing the size of the
patchset a bit. 7 and up I still need to review.

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v7 04/32] target-arm: rename arm_current_pl to arm_current_el
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 04/32] target-arm: rename arm_current_pl to arm_current_el Greg Bellows
@ 2014-10-23 14:53   ` Peter Maydell
  0 siblings, 0 replies; 53+ messages in thread
From: Peter Maydell @ 2014-10-23 14:53 UTC (permalink / raw)
  To: Greg Bellows
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler, Edgar E. Iglesias

On 21 October 2014 17:55, Greg Bellows <greg.bellows@linaro.org> wrote:
> Renamed the arm_current_pl CPU function to more accurately represent that it
> returns the ARMv8 EL rather than ARMv7 PL.
>
> Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
> Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

> @@ -1485,7 +1485,7 @@ static void disas_exc(DisasContext *s, uint32_t insn)
>              gen_exception_insn(s, 0, EXCP_SWI, syn_aa64_svc(imm16));
>              break;
>          case 2:
> -            if (s->current_pl == 0) {
> +            if (!arm_dc_feature(s, ARM_FEATURE_EL2) || s->current_el == 0) {
>                  unallocated_encoding(s);
>                  break;
>              }
> @@ -1498,7 +1498,7 @@ static void disas_exc(DisasContext *s, uint32_t insn)
>              gen_exception_insn(s, 0, EXCP_HVC, syn_aa64_hvc(imm16));
>              break;
>          case 3:
> -            if (s->current_pl == 0) {
> +            if (!arm_dc_feature(s, ARM_FEATURE_EL3) || s->current_el == 0) {
>                  unallocated_encoding(s);
>                  break;
>              }

These hunks introduce spurious changes which break PSCI booting
of AArch64. I will fix up in target-arm.next.

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v7 07/32] target-arm: extend async excp masking
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 07/32] target-arm: extend async excp masking Greg Bellows
@ 2014-10-24 16:25   ` Peter Maydell
  2014-10-24 22:43     ` Greg Bellows
  0 siblings, 1 reply; 53+ messages in thread
From: Peter Maydell @ 2014-10-24 16:25 UTC (permalink / raw)
  To: Greg Bellows
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler, Edgar E. Iglesias

On 21 October 2014 17:55, Greg Bellows <greg.bellows@linaro.org> wrote:
> From: Fabian Aggeler <aggelerf@ethz.ch>
>
> This patch extends arm_excp_unmasked() according to ARM ARMv7 and
> ARM ARMv8 (all EL running in AArch32) and adds comments.
>
> If EL3 is using AArch64 IRQ/FIQ masking is ignored in
> all exception levels other than EL3 if SCR.{FIQ|IRQ} is
> set to 1 (routed to EL3).
>
> Signed-off-by: Fabian Aggeler <aggelerf@ethz.ch>
> Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
>
> ==========
>
> v5 -> v6
> - Globally change Aarch# to AArch#
> - Fixed comment termination
>
> v4 -> v5
> - Merge with v4 patch 10
>
> Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
> ---
>  target-arm/cpu.h | 117 ++++++++++++++++++++++++++++++++++++++++++++++++++-----
>  1 file changed, 107 insertions(+), 10 deletions(-)
>
> diff --git a/target-arm/cpu.h b/target-arm/cpu.h
> index cb6ec5c..1a564b9 100644
> --- a/target-arm/cpu.h
> +++ b/target-arm/cpu.h
> @@ -1246,11 +1246,8 @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx)
>  {
>      CPUARMState *env = cs->env_ptr;
>      unsigned int cur_el = arm_current_el(env);
> -    unsigned int target_el = arm_excp_target_el(cs, excp_idx);
> -    /* FIXME: Use actual secure state.  */
> -    bool secure = false;
> -    /* If in EL1/0, Physical IRQ routing to EL2 only happens from NS state.  */
> -    bool irq_can_hyp = !secure && cur_el < 2 && target_el == 2;
> +    bool secure = arm_is_secure(env);
> +
>      /* 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
> @@ -1265,19 +1262,119 @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx)
>                          && (!IS_M(env) || env->regs[15] < 0xfffffff0);
>
>      /* Don't take exceptions if they target a lower EL.  */
> -    if (cur_el > target_el) {
> +    if (cur_el > arm_excp_target_el(cs, excp_idx)) {
>          return false;
>      }
>
> +    /* ARM ARMv7 B1.8.6  Asynchronous exception masking (table B1-12/B1-13)
> +     * ARM ARMv8 G1.11.3 Asynchronous exception masking controls
> +     * (table G1-18/G1-19)
> +     */
>      switch (excp_idx) {
>      case EXCP_FIQ:
> -        if (irq_can_hyp && (env->cp15.hcr_el2 & HCR_FMO)) {
> -            return true;
> +        if (arm_feature(env, ARM_FEATURE_EL3) && arm_el_is_aa64(env, 3)) {
> +            /* If EL3 is using AArch64 and FIQs are routed to EL3 masking is
> +             * ignored in all exception levels except EL3.
> +             */
> +            if ((env->cp15.scr_el3 & SCR_FIQ) && cur_el < 3) {

Why are we recalculating whether the target level is EL3 by looking
at SCR_EL3.SCR_FIQ, rather than using the target_el which
arm_excp_target_el() returns?

> +                return true;
> +            }
> +            /* If we are in EL3 but FIQs are not routed to EL3 the exception
> +             * is not taken but remains pending.
> +             */
> +            if (!(env->cp15.scr_el3 & SCR_FIQ) && cur_el == 3) {
> +                return false;

Isn't this unreachable? If SCR_FIQ is clear then arm_excp_target_el()
will have returned either 1 or 2, and so we'll have returned false
due to the check on cur_el earlier.

> +            }
> +        }
> +        if (!secure) {
> +            if (arm_feature(env, ARM_FEATURE_EL2)) {
> +                if (env->cp15.hcr_el2 & HCR_FMO) {
> +                    /* CPSR.F/PSTATE.F ignored if
> +                     *  - exception is taken from Non-secure state
> +                     *  - HCR.FMO == 1
> +                     *  - either:  - not in Hyp mode
> +                     *             - SCR.FIQ routes exception to monitor mode
> +                     *               (EL3 in AArch32)
> +                     */
> +                    if (cur_el < 2) {
> +                        return true;
> +                    } else if (arm_feature(env, ARM_FEATURE_EL3) &&
> +                            (env->cp15.scr_el3 & SCR_FIQ) &&
> +                            !arm_el_is_aa64(env, 3)) {
> +                        return true;
> +                    }
> +                } else if (arm_el_is_aa64(env, 3) &&
> +                          (env->cp15.scr_el3 & SCR_RW) &&
> +                          cur_el == 2) {
> +                    /* FIQs not routed to EL2 but currently in EL2 (A64).
> +                     * Exception is not taken but remains pending. */
> +                    return false;
> +                }
> +            }
> +            /* In ARMv7 only applies if both Security Extensions (EL3) and
> +             * Hypervirtualization Extensions (EL2) implemented, while
> +             * for ARMv8 it applies also if only EL3 implemented.
> +             */
> +            if (arm_feature(env, ARM_FEATURE_EL3) &&
> +                    (arm_feature(env, ARM_FEATURE_EL2) ||
> +                            arm_feature(env, ARM_FEATURE_V8))) {
> +                /* CPSR.F/PSTATE.F ignored if
> +                 * - exception is taken from Non-secure state
> +                 * - SCR.FIQ routes exception to monitor mode
> +                 * - SCR.FW bit is set to 0
> +                 * - HCR.FMO == 0 (if EL2 implemented)
> +                 */
> +                if ((env->cp15.scr_el3 & SCR_FIQ) &&
> +                        !(env->cp15.scr_el3 & SCR_FW)) {

Something odd here -- in ARMv8 SCR_EL3 bit 4 is RES1, so this test
should never pass -- either this check is wrong or the check on
ARM_FEATURE_V8 in the outer if() is wrong, presumably.

> +                    if (!arm_feature(env, ARM_FEATURE_EL2)) {
> +                        return true;
> +                    } else if (!(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;
> +        if (arm_feature(env, ARM_FEATURE_EL3) && arm_el_is_aa64(env, 3)) {
> +            /* If EL3 is using AArch64 and IRQs are routed to EL3 masking is
> +             * ignored in all exception levels except EL3.
> +             */
> +            if ((env->cp15.scr_el3 & SCR_IRQ) && cur_el < 3) {
> +                return true;
> +            }
> +            /* If we are in EL3 but IRQ s are not routed to EL3 the exception
> +             * is not taken but remains pending.
> +             */
> +            if (!(env->cp15.scr_el3 & SCR_IRQ) && cur_el == 3) {
> +                return false;
> +            }
> +        }
> +        if (!secure) {
> +            if (arm_feature(env, ARM_FEATURE_EL2)) {
> +                if (env->cp15.hcr_el2 & HCR_IMO) {
> +                    /* CPSR.I/PSTATE.I ignored if
> +                     *  - exception is taken from Non-secure state
> +                     *  - HCR.IMO == 1
> +                     *  - either:  - not in Hyp mode
> +                     *             - SCR.IRQ routes exception to monitor mode
> +                     *                (EL3 in AArch32)
> +                     */
> +                    if (cur_el < 2) {
> +                        return true;
> +                    } else if (arm_feature(env, ARM_FEATURE_EL3) &&
> +                            (env->cp15.scr_el3 & SCR_IRQ) &&
> +                            !arm_el_is_aa64(env, 3)) {
> +                        return true;
> +                    }
> +                } else if (arm_el_is_aa64(env, 3) &&
> +                          (env->cp15.scr_el3 & SCR_RW) &&
> +                          cur_el == 2) {
> +                    /* IRQs not routed to EL2 but currently in EL2 (A64).
> +                     * Exception is not taken but remains pending. */
> +                    return false;
> +                }
> +            }
>          }
>          return irq_unmasked;
>      case EXCP_VFIQ:
> --
> 1.8.3.2

I have to say I find this set of nested conditionals pretty confusing,
and hard to relate to the tables in the ARM ARM. Maybe it would be better
if we actually had a set of data tables in our implementation which
we used to look up whether the exception should be always taken,
remain pending, or honour the PSTATE mask flag ?

I think it would also be good if our implementation tried to keep
the same separation of routing [ie "which exception level is this
exception going to go to?"] and masking [ie "do we take this exception
at this time?"] which the ARM ARM has. At the moment we sort of
have that in the arm_excp_target_el() and this function, but a lot
of the code here seems to be repeating bits of the routing calculation.

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v7 08/32] target-arm: add async excp target_el function
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 08/32] target-arm: add async excp target_el function Greg Bellows
@ 2014-10-24 16:26   ` Peter Maydell
  2014-10-28 14:50     ` Greg Bellows
  0 siblings, 1 reply; 53+ messages in thread
From: Peter Maydell @ 2014-10-24 16:26 UTC (permalink / raw)
  To: Greg Bellows
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler, Edgar E. Iglesias

On 21 October 2014 17:55, Greg Bellows <greg.bellows@linaro.org> wrote:
> From: Fabian Aggeler <aggelerf@ethz.ch>
>
> Adds a dedicated function for IRQ and FIQ exceptions to determine
> target_el and mode (AArch32) according to tables in ARM ARMv8 and
> ARM ARM v7.
>
> Signed-off-by: Fabian Aggeler <aggelerf@ethz.ch>
> Signed-off-by: Greg Bellows <greg.bellows@linaro.org>

This seems like a good candidate for implementing via a set
of tables too.

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v7 09/32] target-arm: add banked register accessors
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 09/32] target-arm: add banked register accessors Greg Bellows
@ 2014-10-24 16:37   ` Peter Maydell
  2014-10-28 18:42     ` Greg Bellows
  0 siblings, 1 reply; 53+ messages in thread
From: Peter Maydell @ 2014-10-24 16:37 UTC (permalink / raw)
  To: Greg Bellows
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler, Edgar E. Iglesias

On 21 October 2014 17:55, Greg Bellows <greg.bellows@linaro.org> wrote:
> From: Fabian Aggeler <aggelerf@ethz.ch>
>
> If EL3 is in AArch32 state certain cp registers are banked (secure and
> non-secure instance). When reading or writing to coprocessor registers
> the following macros can be used.
>
> - A32_BANKED macros are used for choosing the banked register based on provided
>   input security argument.  This macro is used to choose the bank during
>   translation of MRC/MCR instructions that are dependent on something other
>   than the current secure state.
> - A32_BANKED_CURRENT macros are used for choosing the banked register based on
>   current secure state.  This is NOT to be used for choosing the bank used
>   during translation as it breaks monitor mode.
>
> If EL3 is operating in AArch64 state coprocessor registers are not
> banked anymore. The macros use the non-secure instance (_ns) in this
> case, which is architecturally mapped to the AArch64 EL register.
>
> Signed-off-by: Sergey Fedorov <s.fedorov@samsung.com>
> Signed-off-by: Fabian Aggeler <aggelerf@ethz.ch>
> Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
>
> ==========

Can you make these separators the standard '---', please? Otherwise
when I apply these patches I'll have to go through them all manually
editing the version changes out...

> v5 -> v6
> - Converted macro USE_SECURE_REG() into inlince function use_secure_reg()
> - Globally replace Aarch# with AArch#
>
> v4 -> v5
> - Cleaned-up macros to try and alleviate misuse.  Made A32_BANKED macros take
>   secure arg indicator rather than relying on USE_SECURE_REG.  Incorporated the
>   A32_BANKED macros into the A32_BANKED_CURRENT.  CURRENT is now the only one
>   that automatically chooses based on current secure state.

...and as you can see your own patch tooling isn't handling them
right, because you now have two signed-off-by lines :-)

> Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
> ---
>  target-arm/cpu.h | 40 ++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 40 insertions(+)
>
> diff --git a/target-arm/cpu.h b/target-arm/cpu.h
> index 1a564b9..b48b81a 100644
> --- a/target-arm/cpu.h
> +++ b/target-arm/cpu.h
> @@ -817,6 +817,46 @@ static inline bool arm_el_is_aa64(CPUARMState *env, int el)
>      return arm_feature(env, ARM_FEATURE_AARCH64);
>  }
>
> +/* Function for determing whether to use the secure or non-secure bank of a CP
> + * register.  When EL3 is operating in AArch32 state, the NS-bit determines
> + * whether the secure instance of a cp-register should be used.
> + */
> +static inline bool use_secure_reg(CPUARMState *env)
> +{
> +    bool ret = (arm_feature(env, ARM_FEATURE_EL3) &&
> +                !arm_el_is_aa64(env, 3) &&
> +                !(env->cp15.scr_el3 & SCR_NS));
> +
> +    return ret;
> +}

This function is a bit misnamed, and it's actually only used for
setting the TBFLAG_NS bit, so:
 * name it access_secure_reg()
 * change the comment:
  /* Function for determing whether guest cp register reads and writes should
   * access the secure or non-secure bank of a cp register.  When EL3 is
   * operating in AArch32 state, the NS-bit determines whether the secure
   * instance of a cp register should be used. When EL3 is AArch64 (or if
   * it doesn't exist at all) then there is no register banking, and all
   * accesses are to the non-secure version.
   */
 * move it into patch 10 (the one which adds the TBFLAG_NS bit).

If you do that, then you can mark what's left in this patch
with my Reviewed-by tag.

> +
> +/* Macros for accessing a specified CP register bank */
> +#define A32_BANKED_REG_GET(_env, _regname, _secure)    \
> +    ((_secure) ? (_env)->cp15._regname##_s : (_env)->cp15._regname##_ns)
> +
> +#define A32_BANKED_REG_SET(_env, _regname, _secure, _val)   \
> +    do {                                                \
> +        if (_secure) {                                   \
> +            (_env)->cp15._regname##_s = (_val);            \
> +        } else {                                        \
> +            (_env)->cp15._regname##_ns = (_val);           \
> +        }                                               \
> +    } while (0)
> +
> +/* Macros for automatically accessing a specific CP register bank depending on
> + * the current secure state of the system.  These macros are not intended for
> + * supporting instruction translation reads/writes as these are dependent
> + * solely on the SCR.NS bit and not the mode.
> + */
> +#define A32_BANKED_CURRENT_REG_GET(_env, _regname)        \
> +    A32_BANKED_REG_GET((_env), _regname,                \
> +                       ((!arm_el_is_aa64((_env), 3) && arm_is_secure(_env))))
> +
> +#define A32_BANKED_CURRENT_REG_SET(_env, _regname, _val)                       \
> +    A32_BANKED_REG_SET((_env), _regname,                                    \
> +                       ((!arm_el_is_aa64((_env), 3) && arm_is_secure(_env))),  \
> +                       (_val))
> +
>  void arm_cpu_list(FILE *f, fprintf_function cpu_fprintf);
>  unsigned int arm_excp_target_el(CPUState *cs, unsigned int excp_idx);
>
> --
> 1.8.3.2

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v7 10/32] target-arm: add non-secure Translation Block flag
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 10/32] target-arm: add non-secure Translation Block flag Greg Bellows
@ 2014-10-24 16:40   ` Peter Maydell
  2014-10-28 15:21     ` Greg Bellows
  0 siblings, 1 reply; 53+ messages in thread
From: Peter Maydell @ 2014-10-24 16:40 UTC (permalink / raw)
  To: Greg Bellows
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler, Edgar E. Iglesias

On 21 October 2014 17:55, Greg Bellows <greg.bellows@linaro.org> wrote:
> From: Sergey Fedorov <s.fedorov@samsung.com>
>
> This patch is based on idea found in patch at
> git://github.com/jowinter/qemu-trustzone.git
> f3d955c6c0ed8c46bc0eb10b634201032a651dd2 by
> Johannes Winter <johannes.winter@iaik.tugraz.at>.
>
> The TBFLAG captures the SCR NS secure state at the time when a TB is created so
> the correct bank is accessed on system register accesses.  It also allows to
> generate different TCG code depending on CPU secure state.

This last sentence is wrong and should just be deleted.

> Signed-off-by: Sergey Fedorov <s.fedorov@samsung.com>
> Signed-off-by: Fabian Aggeler <aggelerf@ethz.ch>
> Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
>
> ==========
>
> v5 -> v6
> - Removed 64-bit NS TBFLAG macros as they are not needed
> - Added comment on DisasContext ns field
> - Replaced use of USE_SECURE_REG with use_secure_reg
>
> v4 -> v5
> - Merge changes
> - Fixed issue where TB secure state flag was incorrectly being set based on
>   secure state rather than NS setting.  This caused an issue where monitor mode
>   MRC/MCR accesses were always secure rather than being based on NS bit
>   setting.
> - Added separate 64/32 TB secure state flags
> - Unconditionalized the setting of the DC ns bit
> - Removed IS_NS macro and replaced with direct usage.
>
> Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
> ---
>  target-arm/cpu.h       | 7 +++++++
>  target-arm/translate.c | 1 +
>  target-arm/translate.h | 1 +
>  3 files changed, 9 insertions(+)
>
> diff --git a/target-arm/cpu.h b/target-arm/cpu.h
> index b48b81a..e041437 100644
> --- a/target-arm/cpu.h
> +++ b/target-arm/cpu.h
> @@ -1551,6 +1551,8 @@ static inline bool arm_singlestep_active(CPUARMState *env)
>   */
>  #define ARM_TBFLAG_XSCALE_CPAR_SHIFT 20
>  #define ARM_TBFLAG_XSCALE_CPAR_MASK (3 << ARM_TBFLAG_XSCALE_CPAR_SHIFT)

/* Indicates whether cp register reads and writes by guest code should access
 * the secure or nonsecure bank of banked registers; note that this is not
 * the same thing as the current security state of the processor!
 */

If you add this comment and move and rename the use_secure_reg()
function from the previous patch as I suggest, you can add my
reviewed-by tag.

> +#define ARM_TBFLAG_NS_SHIFT         22
> +#define ARM_TBFLAG_NS_MASK          (1 << ARM_TBFLAG_NS_SHIFT)
>
>  /* Bit usage when in AArch64 state */
>  #define ARM_TBFLAG_AA64_EL_SHIFT    0
> @@ -1595,6 +1597,8 @@ static inline bool arm_singlestep_active(CPUARMState *env)
>      (((F) & ARM_TBFLAG_AA64_SS_ACTIVE_MASK) >> ARM_TBFLAG_AA64_SS_ACTIVE_SHIFT)
>  #define ARM_TBFLAG_AA64_PSTATE_SS(F) \
>      (((F) & ARM_TBFLAG_AA64_PSTATE_SS_MASK) >> ARM_TBFLAG_AA64_PSTATE_SS_SHIFT)
> +#define ARM_TBFLAG_NS(F) \
> +    (((F) & ARM_TBFLAG_NS_MASK) >> ARM_TBFLAG_NS_SHIFT)
>
>  static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
>                                          target_ulong *cs_base, int *flags)
> @@ -1644,6 +1648,9 @@ static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
>          if (privmode) {
>              *flags |= ARM_TBFLAG_PRIV_MASK;
>          }
> +        if (!(use_secure_reg(env))) {
> +            *flags |= ARM_TBFLAG_NS_MASK;
> +        }
>          if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)
>              || arm_el_is_aa64(env, 1)) {
>              *flags |= ARM_TBFLAG_VFPEN_MASK;
> diff --git a/target-arm/translate.c b/target-arm/translate.c
> index 91958b6..aa17a20 100644
> --- a/target-arm/translate.c
> +++ b/target-arm/translate.c
> @@ -11002,6 +11002,7 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
>  #if !defined(CONFIG_USER_ONLY)
>      dc->user = (ARM_TBFLAG_PRIV(tb->flags) == 0);
>  #endif
> +    dc->ns = ARM_TBFLAG_NS(tb->flags);
>      dc->cpacr_fpen = ARM_TBFLAG_CPACR_FPEN(tb->flags);
>      dc->vfp_enabled = ARM_TBFLAG_VFPEN(tb->flags);
>      dc->vec_len = ARM_TBFLAG_VECLEN(tb->flags);
> diff --git a/target-arm/translate.h b/target-arm/translate.h
> index 41a9071..f6ee789 100644
> --- a/target-arm/translate.h
> +++ b/target-arm/translate.h
> @@ -20,6 +20,7 @@ typedef struct DisasContext {
>  #if !defined(CONFIG_USER_ONLY)
>      int user;
>  #endif
> +    bool ns;        /* Use non-secure CPREG bank on access */
>      bool cpacr_fpen; /* FP enabled via CPACR.FPEN */
>      bool vfp_enabled; /* FP enabled via FPSCR.EN */
>      int vec_len;
> --
> 1.8.3.2
>


thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v7 07/32] target-arm: extend async excp masking
  2014-10-24 16:25   ` Peter Maydell
@ 2014-10-24 22:43     ` Greg Bellows
  2014-10-26 22:30       ` Peter Maydell
  0 siblings, 1 reply; 53+ messages in thread
From: Greg Bellows @ 2014-10-24 22:43 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler, Edgar E. Iglesias

[-- Attachment #1: Type: text/plain, Size: 15671 bytes --]

Hi Peter,

Based on our discussion, I looked into a table lookup approach to replace
the arm_phys_excp_target_el() as we discussed.  I have something working
but still need to verify it is 100% correct.  Before I went much further, I
thought I'd share my findings.

In order to do the table in a way that it does not blow-up with a bunch of
duplicate data, we still need a function for accessing the table.  The
function will still have a good part of what the existing
arm_phys_excp_target_el() has at the beginning.  This is necessary as we
need to decide which of the SCR and HCR bits need to be plugged into the
table.

In addition, we need the following:

   - The table has to include special values to account for the cases where
   an interrupt is not taken so we will need logic on the other end to catch
   the special table value and return cur_el.
   - Either another dimension needs to be added to the table or a second
   table to handle the differences between 32/64-bit EL3. (Still needed)
   - Another dimension is needed to include HCR_TGE eventually.

Basically, I'm not sure that it buys us much other than a static table.
Otherwise, we are swapping one bunch of logic for a different set.

Below are the changes (convert to a fixed font for better table format):

Greg

=============================

diff --git a/target-arm/helper.c b/target-arm/helper.c
index b4db1a5..fd3d637 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -4028,6 +4028,44 @@ void switch_mode(CPUARMState *env, int mode)
     env->spsr = env->banked_spsr[i];
 }

+const unsigned int aarch64_target_el[2][2][2][2][4] = {
+    /* Physical Interrupt Target EL Lookup Table
+     *
+     * [ From ARM ARM section D1.14.1 (Table D1-11) ]
+     *
+     * The below multi-dimensional table is used for looking up the target
+     * exception level given numerous condition criteria.  Specifically,
the
+     * target EL is based on SCR and HCR routing controls as well as the
+     * currently executing EL and secure state.
+     *
+     *   The table values are as such:
+     *   0-3 = EL0-EL3
+     *     8 = Cannot occur
+     *     9 = Interrupt not taken
+     *
+     *      SCR     HCR
+     *       EA     AMO
+     *      IRQ     IMO             FROM
+     *      FIQ RW  FMO  NS    EL0 EL1 EL2 EL3
+     */
+    {{{{  /* 0   0   0   0  */  1,  1,  8,  9  },
+       {  /* 0   0   0   1  */  1,  1,  2,  8  },},
+      {{  /* 0   0   1   0  */  1,  1,  8,  9  },
+       {  /* 0   0   1   1  */  2,  2,  2,  8  },},},
+     {{{  /* 0   1   0   0  */  1,  1,  8,  9  },
+       {  /* 0   1   0   1  */  1,  1,  8,  8  },},
+      {{  /* 0   1   1   0  */  1,  1,  8,  9  },
+       {  /* 0   1   1   1  */  2,  2,  2,  8  },},},},
+    {{{{  /* 1   0   0   0  */  3,  3,  8,  3  },
+       {  /* 1   0   0   1  */  3,  3,  3,  8  },},
+      {{  /* 1   0   1   0  */  3,  3,  8,  3  },
+       {  /* 1   0   1   1  */  3,  3,  3,  8  },},},
+     {{{  /* 1   1   0   0  */  3,  3,  8,  3  },
+       {  /* 1   1   0   1  */  3,  3,  3,  8  },},
+      {{  /* 1   1   1   0  */  3,  3,  8,  3  },
+       {  /* 1   1   1   1  */  3,  3,  3,  8  },},},},
+};
+
 /*
  * Determine the target EL for physical exceptions
  */
@@ -4035,69 +4073,28 @@ static inline uint32_t
arm_phys_excp_target_el(CPUState *cs, ui
                                         uint32_t cur_el, bool secure)
 {
     CPUARMState *env = cs->env_ptr;
-    uint32_t target_el = 1;
-
-    /* There is no SCR or HCR routing unless the respective EL3 and EL2
-     * extensions are supported.  This initial setting affects whether any
-     * other conditions matter.
-     */
-    bool scr_routing = arm_feature(env, ARM_FEATURE_EL3); /* IRQ, FIQ, EA
*/
-    bool hcr_routing = arm_feature(env, ARM_FEATURE_EL2); /* IMO, FMO, AMO
*/
-
-    /* Fast-path if EL2 and EL3 are not enabled */
-    if (!scr_routing && !hcr_routing) {
-        return target_el;
-    }
+    uint32_t rw = ((env->cp15.scr_el3 & SCR_RW) == SCR_RW);
+    uint32_t scr;
+    uint32_t hcr;
+    uint32_t target_el;

     switch (excp_idx) {
     case EXCP_IRQ:
-        scr_routing &= ((env->cp15.scr_el3 & SCR_IRQ) == SCR_IRQ);
-        hcr_routing &= ((env->cp15.hcr_el2 & HCR_IMO) == HCR_IMO);
+        scr = ((env->cp15.scr_el3 & SCR_IRQ) == SCR_IRQ);
+        hcr = ((env->cp15.hcr_el2 & HCR_IMO) == HCR_IMO);
         break;
     case EXCP_FIQ:
-        scr_routing &= ((env->cp15.scr_el3 & SCR_FIQ) == SCR_FIQ);
-        hcr_routing &= ((env->cp15.hcr_el2 & HCR_FMO) == HCR_FMO);
-    }
-
-    /* If SCR routing is enabled we always go to EL3 regardless of EL3
-     * execution state
-     */
-    if (scr_routing) {
-        /* IRQ|FIQ|EA == 1 */
-        return 3;
-    }
-
-    /* If HCR.TGE is set all exceptions that would be routed to EL1 are
-     * routed to EL2 (in non-secure world).
-     */
-    hcr_routing &= (env->cp15.hcr_el2 & HCR_TGE) == HCR_TGE;
+        scr = ((env->cp15.scr_el3 & SCR_FIQ) == SCR_FIQ);
+        hcr = ((env->cp15.hcr_el2 & HCR_FMO) == HCR_FMO);
+        break;
+    default:
+        scr = ((env->cp15.scr_el3 & SCR_EA) == SCR_EA);
+        hcr = ((env->cp15.hcr_el2 & HCR_AMO) == HCR_AMO);
+        break;
+    };

-    /* Determine target EL according to ARM ARMv8 tables G1-15 and G1-16 */
-    if (arm_el_is_aa64(env, 3)) {
-        /* EL3 in AArch64 */
-        if (!secure) {
-            /* If non-secure, we may route to EL2 depending on other state.
-             * If we are coming from the secure world then we always route
to
-             * EL1.
-             */
-            if (hcr_routing ||
-                (cur_el == 2 && !(env->cp15.scr_el3 & SCR_RW))) {
-                /* If HCR.FMO/IMO is set or we already in EL2 and it is not
-                 * configured to be AArch64 then route to EL2.
-                 */
-                target_el = 2;
-            }
-        }
-    } else {
-        /* EL3 in AArch32 */
-        if (secure) {
-            /* If coming from secure always route to EL3 */
-            target_el = 3;
-        } else if (hcr_routing || cur_el == 2) {
-            /* If HCR.FMO/IMO is set or we are already EL2 then route to
EL2 */
-            target_el = 2;
-        }
-    }
+    target_el = aarch64_target_el[scr][rw][hcr][!secure][cur_el];
+    target_el = (target_el > 3) ? cur_el : target_el;

     return target_el;
 }



On 24 October 2014 11:25, Peter Maydell <peter.maydell@linaro.org> wrote:

> On 21 October 2014 17:55, Greg Bellows <greg.bellows@linaro.org> wrote:
> > From: Fabian Aggeler <aggelerf@ethz.ch>
> >
> > This patch extends arm_excp_unmasked() according to ARM ARMv7 and
> > ARM ARMv8 (all EL running in AArch32) and adds comments.
> >
> > If EL3 is using AArch64 IRQ/FIQ masking is ignored in
> > all exception levels other than EL3 if SCR.{FIQ|IRQ} is
> > set to 1 (routed to EL3).
> >
> > Signed-off-by: Fabian Aggeler <aggelerf@ethz.ch>
> > Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
> >
> > ==========
> >
> > v5 -> v6
> > - Globally change Aarch# to AArch#
> > - Fixed comment termination
> >
> > v4 -> v5
> > - Merge with v4 patch 10
> >
> > Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
> > ---
> >  target-arm/cpu.h | 117
> ++++++++++++++++++++++++++++++++++++++++++++++++++-----
> >  1 file changed, 107 insertions(+), 10 deletions(-)
> >
> > diff --git a/target-arm/cpu.h b/target-arm/cpu.h
> > index cb6ec5c..1a564b9 100644
> > --- a/target-arm/cpu.h
> > +++ b/target-arm/cpu.h
> > @@ -1246,11 +1246,8 @@ static inline bool arm_excp_unmasked(CPUState
> *cs, unsigned int excp_idx)
> >  {
> >      CPUARMState *env = cs->env_ptr;
> >      unsigned int cur_el = arm_current_el(env);
> > -    unsigned int target_el = arm_excp_target_el(cs, excp_idx);
> > -    /* FIXME: Use actual secure state.  */
> > -    bool secure = false;
> > -    /* If in EL1/0, Physical IRQ routing to EL2 only happens from NS
> state.  */
> > -    bool irq_can_hyp = !secure && cur_el < 2 && target_el == 2;
> > +    bool secure = arm_is_secure(env);
> > +
> >      /* 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
> > @@ -1265,19 +1262,119 @@ static inline bool arm_excp_unmasked(CPUState
> *cs, unsigned int excp_idx)
> >                          && (!IS_M(env) || env->regs[15] < 0xfffffff0);
> >
> >      /* Don't take exceptions if they target a lower EL.  */
> > -    if (cur_el > target_el) {
> > +    if (cur_el > arm_excp_target_el(cs, excp_idx)) {
> >          return false;
> >      }
> >
> > +    /* ARM ARMv7 B1.8.6  Asynchronous exception masking (table
> B1-12/B1-13)
> > +     * ARM ARMv8 G1.11.3 Asynchronous exception masking controls
> > +     * (table G1-18/G1-19)
> > +     */
> >      switch (excp_idx) {
> >      case EXCP_FIQ:
> > -        if (irq_can_hyp && (env->cp15.hcr_el2 & HCR_FMO)) {
> > -            return true;
> > +        if (arm_feature(env, ARM_FEATURE_EL3) && arm_el_is_aa64(env,
> 3)) {
> > +            /* If EL3 is using AArch64 and FIQs are routed to EL3
> masking is
> > +             * ignored in all exception levels except EL3.
> > +             */
> > +            if ((env->cp15.scr_el3 & SCR_FIQ) && cur_el < 3) {
>
> Why are we recalculating whether the target level is EL3 by looking
> at SCR_EL3.SCR_FIQ, rather than using the target_el which
> arm_excp_target_el() returns?
>
> > +                return true;
> > +            }
> > +            /* If we are in EL3 but FIQs are not routed to EL3 the
> exception
> > +             * is not taken but remains pending.
> > +             */
> > +            if (!(env->cp15.scr_el3 & SCR_FIQ) && cur_el == 3) {
> > +                return false;
>
> Isn't this unreachable? If SCR_FIQ is clear then arm_excp_target_el()
> will have returned either 1 or 2, and so we'll have returned false
> due to the check on cur_el earlier.
>
> > +            }
> > +        }
> > +        if (!secure) {
> > +            if (arm_feature(env, ARM_FEATURE_EL2)) {
> > +                if (env->cp15.hcr_el2 & HCR_FMO) {
> > +                    /* CPSR.F/PSTATE.F ignored if
> > +                     *  - exception is taken from Non-secure state
> > +                     *  - HCR.FMO == 1
> > +                     *  - either:  - not in Hyp mode
> > +                     *             - SCR.FIQ routes exception to
> monitor mode
> > +                     *               (EL3 in AArch32)
> > +                     */
> > +                    if (cur_el < 2) {
> > +                        return true;
> > +                    } else if (arm_feature(env, ARM_FEATURE_EL3) &&
> > +                            (env->cp15.scr_el3 & SCR_FIQ) &&
> > +                            !arm_el_is_aa64(env, 3)) {
> > +                        return true;
> > +                    }
> > +                } else if (arm_el_is_aa64(env, 3) &&
> > +                          (env->cp15.scr_el3 & SCR_RW) &&
> > +                          cur_el == 2) {
> > +                    /* FIQs not routed to EL2 but currently in EL2
> (A64).
> > +                     * Exception is not taken but remains pending. */
> > +                    return false;
> > +                }
> > +            }
> > +            /* In ARMv7 only applies if both Security Extensions (EL3)
> and
> > +             * Hypervirtualization Extensions (EL2) implemented, while
> > +             * for ARMv8 it applies also if only EL3 implemented.
> > +             */
> > +            if (arm_feature(env, ARM_FEATURE_EL3) &&
> > +                    (arm_feature(env, ARM_FEATURE_EL2) ||
> > +                            arm_feature(env, ARM_FEATURE_V8))) {
> > +                /* CPSR.F/PSTATE.F ignored if
> > +                 * - exception is taken from Non-secure state
> > +                 * - SCR.FIQ routes exception to monitor mode
> > +                 * - SCR.FW bit is set to 0
> > +                 * - HCR.FMO == 0 (if EL2 implemented)
> > +                 */
> > +                if ((env->cp15.scr_el3 & SCR_FIQ) &&
> > +                        !(env->cp15.scr_el3 & SCR_FW)) {
>
> Something odd here -- in ARMv8 SCR_EL3 bit 4 is RES1, so this test
> should never pass -- either this check is wrong or the check on
> ARM_FEATURE_V8 in the outer if() is wrong, presumably.
>
> > +                    if (!arm_feature(env, ARM_FEATURE_EL2)) {
> > +                        return true;
> > +                    } else if (!(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;
> > +        if (arm_feature(env, ARM_FEATURE_EL3) && arm_el_is_aa64(env,
> 3)) {
> > +            /* If EL3 is using AArch64 and IRQs are routed to EL3
> masking is
> > +             * ignored in all exception levels except EL3.
> > +             */
> > +            if ((env->cp15.scr_el3 & SCR_IRQ) && cur_el < 3) {
> > +                return true;
> > +            }
> > +            /* If we are in EL3 but IRQ s are not routed to EL3 the
> exception
> > +             * is not taken but remains pending.
> > +             */
> > +            if (!(env->cp15.scr_el3 & SCR_IRQ) && cur_el == 3) {
> > +                return false;
> > +            }
> > +        }
> > +        if (!secure) {
> > +            if (arm_feature(env, ARM_FEATURE_EL2)) {
> > +                if (env->cp15.hcr_el2 & HCR_IMO) {
> > +                    /* CPSR.I/PSTATE.I ignored if
> > +                     *  - exception is taken from Non-secure state
> > +                     *  - HCR.IMO == 1
> > +                     *  - either:  - not in Hyp mode
> > +                     *             - SCR.IRQ routes exception to
> monitor mode
> > +                     *                (EL3 in AArch32)
> > +                     */
> > +                    if (cur_el < 2) {
> > +                        return true;
> > +                    } else if (arm_feature(env, ARM_FEATURE_EL3) &&
> > +                            (env->cp15.scr_el3 & SCR_IRQ) &&
> > +                            !arm_el_is_aa64(env, 3)) {
> > +                        return true;
> > +                    }
> > +                } else if (arm_el_is_aa64(env, 3) &&
> > +                          (env->cp15.scr_el3 & SCR_RW) &&
> > +                          cur_el == 2) {
> > +                    /* IRQs not routed to EL2 but currently in EL2
> (A64).
> > +                     * Exception is not taken but remains pending. */
> > +                    return false;
> > +                }
> > +            }
> >          }
> >          return irq_unmasked;
> >      case EXCP_VFIQ:
> > --
> > 1.8.3.2
>
> I have to say I find this set of nested conditionals pretty confusing,
> and hard to relate to the tables in the ARM ARM. Maybe it would be better
> if we actually had a set of data tables in our implementation which
> we used to look up whether the exception should be always taken,
> remain pending, or honour the PSTATE mask flag ?
>
> I think it would also be good if our implementation tried to keep
> the same separation of routing [ie "which exception level is this
> exception going to go to?"] and masking [ie "do we take this exception
> at this time?"] which the ARM ARM has. At the moment we sort of
> have that in the arm_excp_target_el() and this function, but a lot
> of the code here seems to be repeating bits of the routing calculation.
>
> thanks
> -- PMM
>

[-- Attachment #2: Type: text/html, Size: 28187 bytes --]

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

* Re: [Qemu-devel] [PATCH v7 07/32] target-arm: extend async excp masking
  2014-10-24 22:43     ` Greg Bellows
@ 2014-10-26 22:30       ` Peter Maydell
  2014-10-27 11:57         ` Peter Maydell
  0 siblings, 1 reply; 53+ messages in thread
From: Peter Maydell @ 2014-10-26 22:30 UTC (permalink / raw)
  To: Greg Bellows
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler, Edgar E. Iglesias

On 24 October 2014 23:43, Greg Bellows <greg.bellows@linaro.org> wrote:
> Based on our discussion, I looked into a table lookup approach to replace
> the arm_phys_excp_target_el() as we discussed.  I have something working but
> still need to verify it is 100% correct.  Before I went much further, I
> thought I'd share my findings.

Thanks for writing this up. Personally I like the table lookup,
because I find it much easier to review and confirm that it matches
the ARM ARM (which also uses tables to describe asynchronous interrupt
routing). The table's only 64 bytes if you make it an int8_t array.

> In order to do the table in a way that it does not blow-up with a bunch of
> duplicate data, we still need a function for accessing the table.  The
> function will still have a good part of what the existing
> arm_phys_excp_target_el() has at the beginning.  This is necessary as we
> need to decide which of the SCR and HCR bits need to be plugged into the
> table.
>
> In addition, we need the following:
>
> The table has to include special values to account for the cases where an
> interrupt is not taken so we will need logic on the other end to catch the
> special table value and return cur_el.

I think you really want to return "exception not taken" to the
caller directly, because if you return the current exception level
we may go ahead and (wrongly) take the exception. This is actually
the thing that allows you to make the calling code in arm_excp_unmasked()
much simpler, because it then doesn't have to effectively repeat
the routing calculations to figure out whether it's one of the
"exception not taken" cases, and the "is this exception masked"
check then boils down to:
 if target_el == "masked" || target_el < current_el
     return false
 if target_el > current_el && target_el > 1
     /* PSTATE mask bits don't apply */
     return true
 return !(env->daif & PSTATE_whatever)

which is vastly simpler than the code I originally objected to
in the patchset...

(If you look at the masking tables in the ARM ARM you'll see they're
really just copies of the routing tables with this straightforward
logic applied to identify when the PSTATE mask bits should be checked.)

In fact, since all of the "exception is not taken" cases are for
"we are in secure EL3 and the exception is not being routed to
secure EL3" you could just make all those entries read "1" and
rely on the "target_el < current_el" check. That does slightly
harm readability though.

> Either another dimension needs to be added to the table or a second table to
> handle the differences between 32/64-bit EL3. (Still needed)
> Another dimension is needed to include HCR_TGE eventually.
>
> Basically, I'm not sure that it buys us much other than a static table.
> Otherwise, we are swapping one bunch of logic for a different set.

I would handle HCR.TGE by just making the AMO/IMO/FMO bit used in the
lookup 1, because that's how the ARM ARM describes its effect.
Similarly you can just squash the routing bits to 0 for the "EL2
not implemented and "EL3 not implemented" cases. Fabian's code
actually already does both of these things in calculating the
hcr_routing and scr_routing flags, so you can just reinstate
and use that code.

I looked through the tables for the AArch32 routing, and I can't
see anywhere where they're different from the AArch64 routing
handling. The SCR_EL3.RW bit needs to be squashed to 0, but that
seems to be it. (We don't need to encode the target AArch32 mode
in the tables, I think; at least in our current design the 32 bit
do_interrupt() function can figure it out based on the exception
number and what exception level it's in now. It's a bit ugly
that we do that by calling arm_excp_target_el() again but never
mind for now.) Did I miss something?

> Below are the changes (convert to a fixed font for better table format):
>
> Greg
>
> =============================
>
> diff --git a/target-arm/helper.c b/target-arm/helper.c
> index b4db1a5..fd3d637 100644
> --- a/target-arm/helper.c
> +++ b/target-arm/helper.c
> @@ -4028,6 +4028,44 @@ void switch_mode(CPUARMState *env, int mode)
>      env->spsr = env->banked_spsr[i];
>  }
>
> +const unsigned int aarch64_target_el[2][2][2][2][4] = {
> +    /* Physical Interrupt Target EL Lookup Table
> +     *
> +     * [ From ARM ARM section D1.14.1 (Table D1-11) ]
> +     *
> +     * The below multi-dimensional table is used for looking up the target
> +     * exception level given numerous condition criteria.  Specifically,
> the
> +     * target EL is based on SCR and HCR routing controls as well as the
> +     * currently executing EL and secure state.
> +     *
> +     *   The table values are as such:
> +     *   0-3 = EL0-EL3
> +     *     8 = Cannot occur
> +     *     9 = Interrupt not taken
> +     *
> +     *      SCR     HCR
> +     *       EA     AMO
> +     *      IRQ     IMO             FROM
> +     *      FIQ RW  FMO  NS    EL0 EL1 EL2 EL3
> +     */
> +    {{{{  /* 0   0   0   0  */  1,  1,  8,  9  },
> +       {  /* 0   0   0   1  */  1,  1,  2,  8  },},

If you make the index for S/NS be the "secure" flag rather than
"!secure" then you can have each line here be
          { 1, 1, 2, 8 }, { 1, 1, 8, 9 }

which matches the order of the columns in the ARM ARM.
(Some shortish symbolic names for the "can't happen" and
"don't take" cases would help readability too. And/or use
negative numbers.)

> +      {{  /* 0   0   1   0  */  1,  1,  8,  9  },
> +       {  /* 0   0   1   1  */  2,  2,  2,  8  },},},
> +     {{{  /* 0   1   0   0  */  1,  1,  8,  9  },
> +       {  /* 0   1   0   1  */  1,  1,  8,  8  },},
> +      {{  /* 0   1   1   0  */  1,  1,  8,  9  },
> +       {  /* 0   1   1   1  */  2,  2,  2,  8  },},},},
> +    {{{{  /* 1   0   0   0  */  3,  3,  8,  3  },
> +       {  /* 1   0   0   1  */  3,  3,  3,  8  },},
> +      {{  /* 1   0   1   0  */  3,  3,  8,  3  },
> +       {  /* 1   0   1   1  */  3,  3,  3,  8  },},},
> +     {{{  /* 1   1   0   0  */  3,  3,  8,  3  },
> +       {  /* 1   1   0   1  */  3,  3,  3,  8  },},
> +      {{  /* 1   1   1   0  */  3,  3,  8,  3  },
> +       {  /* 1   1   1   1  */  3,  3,  3,  8  },},},},
> +};
> +
>  /*
>   * Determine the target EL for physical exceptions
>   */
> @@ -4035,69 +4073,28 @@ static inline uint32_t
> arm_phys_excp_target_el(CPUState *cs, ui
>                                          uint32_t cur_el, bool secure)
>  {
>      CPUARMState *env = cs->env_ptr;
> -    uint32_t target_el = 1;
> -
> -    /* There is no SCR or HCR routing unless the respective EL3 and EL2
> -     * extensions are supported.  This initial setting affects whether any
> -     * other conditions matter.
> -     */
> -    bool scr_routing = arm_feature(env, ARM_FEATURE_EL3); /* IRQ, FIQ, EA
> */
> -    bool hcr_routing = arm_feature(env, ARM_FEATURE_EL2); /* IMO, FMO, AMO
> */
> -
> -    /* Fast-path if EL2 and EL3 are not enabled */
> -    if (!scr_routing && !hcr_routing) {
> -        return target_el;
> -    }
> +    uint32_t rw = ((env->cp15.scr_el3 & SCR_RW) == SCR_RW);
> +    uint32_t scr;
> +    uint32_t hcr;
> +    uint32_t target_el;
>
>      switch (excp_idx) {
>      case EXCP_IRQ:
> -        scr_routing &= ((env->cp15.scr_el3 & SCR_IRQ) == SCR_IRQ);
> -        hcr_routing &= ((env->cp15.hcr_el2 & HCR_IMO) == HCR_IMO);
> +        scr = ((env->cp15.scr_el3 & SCR_IRQ) == SCR_IRQ);
> +        hcr = ((env->cp15.hcr_el2 & HCR_IMO) == HCR_IMO);
>          break;
>      case EXCP_FIQ:
> -        scr_routing &= ((env->cp15.scr_el3 & SCR_FIQ) == SCR_FIQ);
> -        hcr_routing &= ((env->cp15.hcr_el2 & HCR_FMO) == HCR_FMO);
> -    }
> -
> -    /* If SCR routing is enabled we always go to EL3 regardless of EL3
> -     * execution state
> -     */
> -    if (scr_routing) {
> -        /* IRQ|FIQ|EA == 1 */
> -        return 3;
> -    }
> -
> -    /* If HCR.TGE is set all exceptions that would be routed to EL1 are
> -     * routed to EL2 (in non-secure world).
> -     */
> -    hcr_routing &= (env->cp15.hcr_el2 & HCR_TGE) == HCR_TGE;
> +        scr = ((env->cp15.scr_el3 & SCR_FIQ) == SCR_FIQ);
> +        hcr = ((env->cp15.hcr_el2 & HCR_FMO) == HCR_FMO);
> +        break;
> +    default:
> +        scr = ((env->cp15.scr_el3 & SCR_EA) == SCR_EA);
> +        hcr = ((env->cp15.hcr_el2 & HCR_AMO) == HCR_AMO);
> +        break;
> +    };
>
> -    /* Determine target EL according to ARM ARMv8 tables G1-15 and G1-16 */
> -    if (arm_el_is_aa64(env, 3)) {
> -        /* EL3 in AArch64 */
> -        if (!secure) {
> -            /* If non-secure, we may route to EL2 depending on other state.
> -             * If we are coming from the secure world then we always route
> to
> -             * EL1.
> -             */
> -            if (hcr_routing ||
> -                (cur_el == 2 && !(env->cp15.scr_el3 & SCR_RW))) {
> -                /* If HCR.FMO/IMO is set or we already in EL2 and it is not
> -                 * configured to be AArch64 then route to EL2.
> -                 */
> -                target_el = 2;
> -            }
> -        }
> -    } else {
> -        /* EL3 in AArch32 */
> -        if (secure) {
> -            /* If coming from secure always route to EL3 */
> -            target_el = 3;
> -        } else if (hcr_routing || cur_el == 2) {
> -            /* If HCR.FMO/IMO is set or we are already EL2 then route to
> EL2 */
> -            target_el = 2;
> -        }
> -    }
> +    target_el = aarch64_target_el[scr][rw][hcr][!secure][cur_el];
> +    target_el = (target_el > 3) ? cur_el : target_el;
>
>      return target_el;
>  }
>

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v7 07/32] target-arm: extend async excp masking
  2014-10-26 22:30       ` Peter Maydell
@ 2014-10-27 11:57         ` Peter Maydell
  2014-10-27 15:59           ` Greg Bellows
  0 siblings, 1 reply; 53+ messages in thread
From: Peter Maydell @ 2014-10-27 11:57 UTC (permalink / raw)
  To: Greg Bellows
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler, Edgar E. Iglesias

On 26 October 2014 22:30, Peter Maydell <peter.maydell@linaro.org> wrote:
> In fact, since all of the "exception is not taken" cases are for
> "we are in secure EL3 and the exception is not being routed to
> secure EL3" you could just make all those entries read "1" and
> rely on the "target_el < current_el" check. That does slightly
> harm readability though.

Thinking further about this I actually prefer it -- it completely
separates routing from masking. So you should make those entries
read '1' and then just use -1 for "not possible" (and assert
that the table lookup never gives you -1).

> I looked through the tables for the AArch32 routing, and I can't
> see anywhere where they're different from the AArch64 routing
> handling. [...] Did I miss something?

I did! If EL3 is AArch32 and the SCR.FIQ etc bits are clear then
the FIQ/IRQ in the secure world target EL3, not EL1 (since the
latter doesn't exist). We can handle that by using the AArch64 table
anyway and just having a bit at the end that says "if we're secure
and target_el is 1 then set it to 3", or if you prefer with a second
table.

-- PMM

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

* Re: [Qemu-devel] [PATCH v7 07/32] target-arm: extend async excp masking
  2014-10-27 11:57         ` Peter Maydell
@ 2014-10-27 15:59           ` Greg Bellows
  0 siblings, 0 replies; 53+ messages in thread
From: Greg Bellows @ 2014-10-27 15:59 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler, Edgar E. Iglesias

[-- Attachment #1: Type: text/plain, Size: 1578 bytes --]

On 27 October 2014 06:57, Peter Maydell <peter.maydell@linaro.org> wrote:

> On 26 October 2014 22:30, Peter Maydell <peter.maydell@linaro.org> wrote:
> > In fact, since all of the "exception is not taken" cases are for
> > "we are in secure EL3 and the exception is not being routed to
> > secure EL3" you could just make all those entries read "1" and
> > rely on the "target_el < current_el" check. That does slightly
> > harm readability though.
>
> Thinking further about this I actually prefer it -- it completely
> separates routing from masking. So you should make those entries
> read '1' and then just use -1 for "not possible" (and assert
> that the table lookup never gives you -1).
>
> > I looked through the tables for the AArch32 routing, and I can't
> > see anywhere where they're different from the AArch64 routing
> > handling. [...] Did I miss something?
>
> I did! If EL3 is AArch32 and the SCR.FIQ etc bits are clear then
> the FIQ/IRQ in the secure world target EL3, not EL1 (since the
> latter doesn't exist). We can handle that by using the AArch64 table
> anyway and just having a bit at the end that says "if we're secure
> and target_el is 1 then set it to 3", or if you prefer with a second
> table.
>
>
Right, this is what I was saying about either needing another column or or
table.  If we are going with the table approach I think we should go all
the way and not add a "conditional".  Besides, the tables are small
anyway.  I extended the existing able to take 32/64 bit identifier.

The changes discussed above will be made in v8.


> -- PMM
>

[-- Attachment #2: Type: text/html, Size: 2348 bytes --]

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

* Re: [Qemu-devel] [PATCH v7 08/32] target-arm: add async excp target_el function
  2014-10-24 16:26   ` Peter Maydell
@ 2014-10-28 14:50     ` Greg Bellows
  0 siblings, 0 replies; 53+ messages in thread
From: Greg Bellows @ 2014-10-28 14:50 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler, Edgar E. Iglesias

[-- Attachment #1: Type: text/plain, Size: 682 bytes --]

This is the table we were talking about in patch 7.  A table has been added
and the function reworked in v8.


On 24 October 2014 11:26, Peter Maydell <peter.maydell@linaro.org> wrote:

> On 21 October 2014 17:55, Greg Bellows <greg.bellows@linaro.org> wrote:
> > From: Fabian Aggeler <aggelerf@ethz.ch>
> >
> > Adds a dedicated function for IRQ and FIQ exceptions to determine
> > target_el and mode (AArch32) according to tables in ARM ARMv8 and
> > ARM ARM v7.
> >
> > Signed-off-by: Fabian Aggeler <aggelerf@ethz.ch>
> > Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
>
> This seems like a good candidate for implementing via a set
> of tables too.
>
> thanks
> -- PMM
>

[-- Attachment #2: Type: text/html, Size: 1277 bytes --]

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

* Re: [Qemu-devel] [PATCH v7 10/32] target-arm: add non-secure Translation Block flag
  2014-10-24 16:40   ` Peter Maydell
@ 2014-10-28 15:21     ` Greg Bellows
  0 siblings, 0 replies; 53+ messages in thread
From: Greg Bellows @ 2014-10-28 15:21 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler, Edgar E. Iglesias

[-- Attachment #1: Type: text/plain, Size: 4895 bytes --]

On 24 October 2014 11:40, Peter Maydell <peter.maydell@linaro.org> wrote:

> On 21 October 2014 17:55, Greg Bellows <greg.bellows@linaro.org> wrote:
> > From: Sergey Fedorov <s.fedorov@samsung.com>
> >
> > This patch is based on idea found in patch at
> > git://github.com/jowinter/qemu-trustzone.git
> > f3d955c6c0ed8c46bc0eb10b634201032a651dd2 by
> > Johannes Winter <johannes.winter@iaik.tugraz.at>.
> >
> > The TBFLAG captures the SCR NS secure state at the time when a TB is
> created so
> > the correct bank is accessed on system register accesses.  It also
> allows to
> > generate different TCG code depending on CPU secure state.
>
> This last sentence is wrong and should just be deleted.
>

Done.


>
> > Signed-off-by: Sergey Fedorov <s.fedorov@samsung.com>
> > Signed-off-by: Fabian Aggeler <aggelerf@ethz.ch>
> > Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
> >
> > ==========
> >
> > v5 -> v6
> > - Removed 64-bit NS TBFLAG macros as they are not needed
> > - Added comment on DisasContext ns field
> > - Replaced use of USE_SECURE_REG with use_secure_reg
> >
> > v4 -> v5
> > - Merge changes
> > - Fixed issue where TB secure state flag was incorrectly being set based
> on
> >   secure state rather than NS setting.  This caused an issue where
> monitor mode
> >   MRC/MCR accesses were always secure rather than being based on NS bit
> >   setting.
> > - Added separate 64/32 TB secure state flags
> > - Unconditionalized the setting of the DC ns bit
> > - Removed IS_NS macro and replaced with direct usage.
> >
> > Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
> > ---
> >  target-arm/cpu.h       | 7 +++++++
> >  target-arm/translate.c | 1 +
> >  target-arm/translate.h | 1 +
> >  3 files changed, 9 insertions(+)
> >
> > diff --git a/target-arm/cpu.h b/target-arm/cpu.h
> > index b48b81a..e041437 100644
> > --- a/target-arm/cpu.h
> > +++ b/target-arm/cpu.h
> > @@ -1551,6 +1551,8 @@ static inline bool
> arm_singlestep_active(CPUARMState *env)
> >   */
> >  #define ARM_TBFLAG_XSCALE_CPAR_SHIFT 20
> >  #define ARM_TBFLAG_XSCALE_CPAR_MASK (3 << ARM_TBFLAG_XSCALE_CPAR_SHIFT)
>
> /* Indicates whether cp register reads and writes by guest code should
> access
>  * the secure or nonsecure bank of banked registers; note that this is not
>  * the same thing as the current security state of the processor!
>  */
>
> If you add this comment and move and rename the use_secure_reg()
> function from the previous patch as I suggest, you can add my
> reviewed-by tag.
>
>
Function moved and renamed and comment added in v8.


> > +#define ARM_TBFLAG_NS_SHIFT         22
> > +#define ARM_TBFLAG_NS_MASK          (1 << ARM_TBFLAG_NS_SHIFT)
> >
> >  /* Bit usage when in AArch64 state */
> >  #define ARM_TBFLAG_AA64_EL_SHIFT    0
> > @@ -1595,6 +1597,8 @@ static inline bool
> arm_singlestep_active(CPUARMState *env)
> >      (((F) & ARM_TBFLAG_AA64_SS_ACTIVE_MASK) >>
> ARM_TBFLAG_AA64_SS_ACTIVE_SHIFT)
> >  #define ARM_TBFLAG_AA64_PSTATE_SS(F) \
> >      (((F) & ARM_TBFLAG_AA64_PSTATE_SS_MASK) >>
> ARM_TBFLAG_AA64_PSTATE_SS_SHIFT)
> > +#define ARM_TBFLAG_NS(F) \
> > +    (((F) & ARM_TBFLAG_NS_MASK) >> ARM_TBFLAG_NS_SHIFT)
> >
> >  static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong
> *pc,
> >                                          target_ulong *cs_base, int
> *flags)
> > @@ -1644,6 +1648,9 @@ static inline void
> cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
> >          if (privmode) {
> >              *flags |= ARM_TBFLAG_PRIV_MASK;
> >          }
> > +        if (!(use_secure_reg(env))) {
> > +            *flags |= ARM_TBFLAG_NS_MASK;
> > +        }
> >          if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)
> >              || arm_el_is_aa64(env, 1)) {
> >              *flags |= ARM_TBFLAG_VFPEN_MASK;
> > diff --git a/target-arm/translate.c b/target-arm/translate.c
> > index 91958b6..aa17a20 100644
> > --- a/target-arm/translate.c
> > +++ b/target-arm/translate.c
> > @@ -11002,6 +11002,7 @@ static inline void
> gen_intermediate_code_internal(ARMCPU *cpu,
> >  #if !defined(CONFIG_USER_ONLY)
> >      dc->user = (ARM_TBFLAG_PRIV(tb->flags) == 0);
> >  #endif
> > +    dc->ns = ARM_TBFLAG_NS(tb->flags);
> >      dc->cpacr_fpen = ARM_TBFLAG_CPACR_FPEN(tb->flags);
> >      dc->vfp_enabled = ARM_TBFLAG_VFPEN(tb->flags);
> >      dc->vec_len = ARM_TBFLAG_VECLEN(tb->flags);
> > diff --git a/target-arm/translate.h b/target-arm/translate.h
> > index 41a9071..f6ee789 100644
> > --- a/target-arm/translate.h
> > +++ b/target-arm/translate.h
> > @@ -20,6 +20,7 @@ typedef struct DisasContext {
> >  #if !defined(CONFIG_USER_ONLY)
> >      int user;
> >  #endif
> > +    bool ns;        /* Use non-secure CPREG bank on access */
> >      bool cpacr_fpen; /* FP enabled via CPACR.FPEN */
> >      bool vfp_enabled; /* FP enabled via FPSCR.EN */
> >      int vec_len;
> > --
> > 1.8.3.2
> >
>
>
> thanks
> -- PMM
>

[-- Attachment #2: Type: text/html, Size: 6907 bytes --]

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

* Re: [Qemu-devel] [PATCH v7 09/32] target-arm: add banked register accessors
  2014-10-24 16:37   ` Peter Maydell
@ 2014-10-28 18:42     ` Greg Bellows
  0 siblings, 0 replies; 53+ messages in thread
From: Greg Bellows @ 2014-10-28 18:42 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler, Edgar E. Iglesias

[-- Attachment #1: Type: text/plain, Size: 5578 bytes --]

On 24 October 2014 11:37, Peter Maydell <peter.maydell@linaro.org> wrote:

> On 21 October 2014 17:55, Greg Bellows <greg.bellows@linaro.org> wrote:
> > From: Fabian Aggeler <aggelerf@ethz.ch>
> >
> > If EL3 is in AArch32 state certain cp registers are banked (secure and
> > non-secure instance). When reading or writing to coprocessor registers
> > the following macros can be used.
> >
> > - A32_BANKED macros are used for choosing the banked register based on
> provided
> >   input security argument.  This macro is used to choose the bank during
> >   translation of MRC/MCR instructions that are dependent on something
> other
> >   than the current secure state.
> > - A32_BANKED_CURRENT macros are used for choosing the banked register
> based on
> >   current secure state.  This is NOT to be used for choosing the bank
> used
> >   during translation as it breaks monitor mode.
> >
> > If EL3 is operating in AArch64 state coprocessor registers are not
> > banked anymore. The macros use the non-secure instance (_ns) in this
> > case, which is architecturally mapped to the AArch64 EL register.
> >
> > Signed-off-by: Sergey Fedorov <s.fedorov@samsung.com>
> > Signed-off-by: Fabian Aggeler <aggelerf@ethz.ch>
> > Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
> >
> > ==========
>
> Can you make these separators the standard '---', please? Otherwise
> when I apply these patches I'll have to go through them all manually
> editing the version changes out...
>

I did not know there were standard separators.  I have fixed this in all
the patches.


> > v5 -> v6
> > - Converted macro USE_SECURE_REG() into inlince function use_secure_reg()
> > - Globally replace Aarch# with AArch#
> >
> > v4 -> v5
> > - Cleaned-up macros to try and alleviate misuse.  Made A32_BANKED macros
> take
> >   secure arg indicator rather than relying on USE_SECURE_REG.
> Incorporated the
> >   A32_BANKED macros into the A32_BANKED_CURRENT.  CURRENT is now the
> only one
> >   that automatically chooses based on current secure state.
>
> ...and as you can see your own patch tooling isn't handling them
> right, because you now have two signed-off-by lines :-)
>
> > Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
> > ---
> >  target-arm/cpu.h | 40 ++++++++++++++++++++++++++++++++++++++++
> >  1 file changed, 40 insertions(+)
> >
> > diff --git a/target-arm/cpu.h b/target-arm/cpu.h
> > index 1a564b9..b48b81a 100644
> > --- a/target-arm/cpu.h
> > +++ b/target-arm/cpu.h
> > @@ -817,6 +817,46 @@ static inline bool arm_el_is_aa64(CPUARMState *env,
> int el)
> >      return arm_feature(env, ARM_FEATURE_AARCH64);
> >  }
> >
> > +/* Function for determing whether to use the secure or non-secure bank
> of a CP
> > + * register.  When EL3 is operating in AArch32 state, the NS-bit
> determines
> > + * whether the secure instance of a cp-register should be used.
> > + */
> > +static inline bool use_secure_reg(CPUARMState *env)
> > +{
> > +    bool ret = (arm_feature(env, ARM_FEATURE_EL3) &&
> > +                !arm_el_is_aa64(env, 3) &&
> > +                !(env->cp15.scr_el3 & SCR_NS));
> > +
> > +    return ret;
> > +}
>
> This function is a bit misnamed, and it's actually only used for
> setting the TBFLAG_NS bit, so:
>  * name it access_secure_reg()
>  * change the comment:
>   /* Function for determing whether guest cp register reads and writes
> should
>    * access the secure or non-secure bank of a cp register.  When EL3 is
>    * operating in AArch32 state, the NS-bit determines whether the secure
>    * instance of a cp register should be used. When EL3 is AArch64 (or if
>    * it doesn't exist at all) then there is no register banking, and all
>    * accesses are to the non-secure version.
>    */
>  * move it into patch 10 (the one which adds the TBFLAG_NS bit).
>
> If you do that, then you can mark what's left in this patch
> with my Reviewed-by tag.
>

Done in v8


>
> > +
> > +/* Macros for accessing a specified CP register bank */
> > +#define A32_BANKED_REG_GET(_env, _regname, _secure)    \
> > +    ((_secure) ? (_env)->cp15._regname##_s : (_env)->cp15._regname##_ns)
> > +
> > +#define A32_BANKED_REG_SET(_env, _regname, _secure, _val)   \
> > +    do {                                                \
> > +        if (_secure) {                                   \
> > +            (_env)->cp15._regname##_s = (_val);            \
> > +        } else {                                        \
> > +            (_env)->cp15._regname##_ns = (_val);           \
> > +        }                                               \
> > +    } while (0)
> > +
> > +/* Macros for automatically accessing a specific CP register bank
> depending on
> > + * the current secure state of the system.  These macros are not
> intended for
> > + * supporting instruction translation reads/writes as these are
> dependent
> > + * solely on the SCR.NS bit and not the mode.
> > + */
> > +#define A32_BANKED_CURRENT_REG_GET(_env, _regname)        \
> > +    A32_BANKED_REG_GET((_env), _regname,                \
> > +                       ((!arm_el_is_aa64((_env), 3) &&
> arm_is_secure(_env))))
> > +
> > +#define A32_BANKED_CURRENT_REG_SET(_env, _regname, _val)
>        \
> > +    A32_BANKED_REG_SET((_env), _regname,
>     \
> > +                       ((!arm_el_is_aa64((_env), 3) &&
> arm_is_secure(_env))),  \
> > +                       (_val))
> > +
> >  void arm_cpu_list(FILE *f, fprintf_function cpu_fprintf);
> >  unsigned int arm_excp_target_el(CPUState *cs, unsigned int excp_idx);
> >
> > --
> > 1.8.3.2
>
> thanks
> -- PMM
>

[-- Attachment #2: Type: text/html, Size: 7640 bytes --]

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

* Re: [Qemu-devel] [PATCH v7 05/32] target-arm: make arm_current_el() return EL3
  2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 05/32] target-arm: make arm_current_el() return EL3 Greg Bellows
@ 2015-01-16 18:36   ` Peter Maydell
  2015-01-19 13:22     ` Peter Maydell
  0 siblings, 1 reply; 53+ messages in thread
From: Peter Maydell @ 2015-01-16 18:36 UTC (permalink / raw)
  To: Greg Bellows
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler, Edgar E. Iglesias

On 21 October 2014 at 17:55, Greg Bellows <greg.bellows@linaro.org> wrote:
> From: Fabian Aggeler <aggelerf@ethz.ch>
>
> Make arm_current_el() return EL3 for secure PL1 and monitor mode.
> Increase MMU modes since mmu_index is directly inferred from arm_
> current_el(). Change assertion in arm_el_is_aa64() to allow EL3.

> -#define NB_MMU_MODES 2
> +#define NB_MMU_MODES 4

So this turns out not to quite be what we want.
A QEMU MMU mode index basically defines a (vaddr -> paddr,permissions)
mapping. This is similar to the ARM ARM concept of a "translation
regime", with the differences that:
 * the ARM ARM translation regimes may have split permissions,
   for user and privileged code, so we need two mmu_idx values
   for a translation regime that applies to both EL0 and EL1
 * stage 1 and stage 2 translations for a VA->IPA->PA lookup
   for an EL1/EL0 hypervisor guest are two different translation
   regimes, but for QEMU we can just cache the whole VA->PA
   and use a single mmu_idx. [We only need to separately do
   VA->IPA and IPA->VA for the "do this address translation"
   system instructions, which don't need to touch the TLB;
   a combined stage1+stage2 TLB is permitted by the architecture.]

The translation regimes are:

If EL3 is 64-bit:
 * Secure EL3
 * Secure EL1 & EL0
 * NonSecure EL2
 * NonSecure EL1 & 0 stage 1
 * NonSecure EL1 & 0 stage 2
If EL3 is 32-bit:
 * Secure PL0 & PL1
 * NonSecure PL2
 * NonSecure PL1 & 0 stage 1
 * NonSecure PL1 & 0 stage 2
(reminder: for 32 bit EL3, Secure PL1 is *EL3*, not EL1.)

which we can give the following mmu indexes:

64 bit EL3:
 0 : NS EL0 stage 1+2
 1 : NS EL1 stage 1+2
 2 : NS EL2
 3 : S EL3
 4 : S EL0
 5 : S EL1

32 bit EL3:
 0 : NS EL0 (aka NS PL0) stage 1+2
 1 : NS EL1 (aka NS PL1) stage 1+2
 2 : NS EL2 (aka NS PL2)
 3 : S EL3 (aka S PL1)
 4 : S EL0 (aka S PL0)

Notice how they end up being the same, except that with a
64 bit EL3 we need an extra mmu index that 32 bit doesn't have.
They aren't simply "what is our current EL?", though as you
can see I've put them in an order that comes close.

So the right answer for NB_MMU_MODES is 6 :-)

-- PMM

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

* Re: [Qemu-devel] [PATCH v7 05/32] target-arm: make arm_current_el() return EL3
  2015-01-16 18:36   ` Peter Maydell
@ 2015-01-19 13:22     ` Peter Maydell
  2015-01-19 17:44       ` Richard Henderson
  0 siblings, 1 reply; 53+ messages in thread
From: Peter Maydell @ 2015-01-19 13:22 UTC (permalink / raw)
  To: Greg Bellows
  Cc: Sergey Fedorov, Richard Henderson, QEMU Developers,
	Fabian Aggeler, Edgar E. Iglesias

On 16 January 2015 at 18:36, Peter Maydell <peter.maydell@linaro.org> wrote:
> On 21 October 2014 at 17:55, Greg Bellows <greg.bellows@linaro.org> wrote:
>> -#define NB_MMU_MODES 2
>> +#define NB_MMU_MODES 4
>
> So this turns out not to quite be what we want.
> A QEMU MMU mode index basically defines a (vaddr -> paddr,permissions)
> mapping. This is similar to the ARM ARM concept of a "translation
> regime", with the differences that:
>  * the ARM ARM translation regimes may have split permissions,
>    for user and privileged code, so we need two mmu_idx values
>    for a translation regime that applies to both EL0 and EL1
>  * stage 1 and stage 2 translations for a VA->IPA->PA lookup
>    for an EL1/EL0 hypervisor guest are two different translation
>    regimes, but for QEMU we can just cache the whole VA->PA
>    and use a single mmu_idx. [We only need to separately do
>    VA->IPA and IPA->VA for the "do this address translation"
>    system instructions, which don't need to touch the TLB;
>    a combined stage1+stage2 TLB is permitted by the architecture.]
>
> The translation regimes are:
>
> If EL3 is 64-bit:
>  * Secure EL3
>  * Secure EL1 & EL0
>  * NonSecure EL2
>  * NonSecure EL1 & 0 stage 1
>  * NonSecure EL1 & 0 stage 2
> If EL3 is 32-bit:
>  * Secure PL0 & PL1
>  * NonSecure PL2
>  * NonSecure PL1 & 0 stage 1
>  * NonSecure PL1 & 0 stage 2
> (reminder: for 32 bit EL3, Secure PL1 is *EL3*, not EL1.)
>
> which we can give the following mmu indexes:
>
> 64 bit EL3:
>  0 : NS EL0 stage 1+2
>  1 : NS EL1 stage 1+2
>  2 : NS EL2
>  3 : S EL3
>  4 : S EL0
>  5 : S EL1
>
> 32 bit EL3:
>  0 : NS EL0 (aka NS PL0) stage 1+2
>  1 : NS EL1 (aka NS PL1) stage 1+2
>  2 : NS EL2 (aka NS PL2)
>  3 : S EL3 (aka S PL1)
>  4 : S EL0 (aka S PL0)
>
> Notice how they end up being the same, except that with a
> 64 bit EL3 we need an extra mmu index that 32 bit doesn't have.
> They aren't simply "what is our current EL?", though as you
> can see I've put them in an order that comes close.
>
> So the right answer for NB_MMU_MODES is 6 :-)

...except we would also kind of like to be able to cache
NS stage 2 lookups, because otherwise every access we make
to a stage 1 page table word (accessed by IPA) is going to
require a full stage 2 page table walk. That would mean
7 MMU modes.

Richard: do you have a feel for how expensive it is to
have lots and lots of mmu modes? I might be able to
merge "S EL1" with "NS EL1 stage 1+2" and ditto "S EL0"
with "NS EL0 stage1 + 2" but we'd need to do more TLB
flushing and it's not clear to me currently exactly
where the extra flushes would have to go...

-- PMM

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

* Re: [Qemu-devel] [PATCH v7 05/32] target-arm: make arm_current_el() return EL3
  2015-01-19 13:22     ` Peter Maydell
@ 2015-01-19 17:44       ` Richard Henderson
  2015-01-19 19:00         ` Peter Maydell
  0 siblings, 1 reply; 53+ messages in thread
From: Richard Henderson @ 2015-01-19 17:44 UTC (permalink / raw)
  To: Peter Maydell, Greg Bellows
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler, Edgar E. Iglesias

On 01/19/2015 05:22 AM, Peter Maydell wrote:
> Richard: do you have a feel for how expensive it is to
> have lots and lots of mmu modes? I might be able to
> merge "S EL1" with "NS EL1 stage 1+2" and ditto "S EL0"
> with "NS EL0 stage1 + 2" but we'd need to do more TLB
> flushing and it's not clear to me currently exactly
> where the extra flushes would have to go...

It's 10k per mmu mode, more or less.  That's what you've
got to memset (to -1) whenever a flush occurs.

With the obvious mathematics wrt flush rate that implies.


r~

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

* Re: [Qemu-devel] [PATCH v7 05/32] target-arm: make arm_current_el() return EL3
  2015-01-19 17:44       ` Richard Henderson
@ 2015-01-19 19:00         ` Peter Maydell
  2015-01-19 19:30           ` Richard Henderson
  0 siblings, 1 reply; 53+ messages in thread
From: Peter Maydell @ 2015-01-19 19:00 UTC (permalink / raw)
  To: Richard Henderson
  Cc: Sergey Fedorov, Edgar E. Iglesias, QEMU Developers,
	Fabian Aggeler, Greg Bellows

On 19 January 2015 at 17:44, Richard Henderson <rth@twiddle.net> wrote:
> On 01/19/2015 05:22 AM, Peter Maydell wrote:
>> Richard: do you have a feel for how expensive it is to
>> have lots and lots of mmu modes? I might be able to
>> merge "S EL1" with "NS EL1 stage 1+2" and ditto "S EL0"
>> with "NS EL0 stage1 + 2" but we'd need to do more TLB
>> flushing and it's not clear to me currently exactly
>> where the extra flushes would have to go...
>
> It's 10k per mmu mode, more or less.  That's what you've
> got to memset (to -1) whenever a flush occurs.

Hmm. If the tlb flush memset is the main perf issue, we
could let the target tell the generic code how many MMU
modes it was using at runtime. We might need 7 modes in
the general case, but we could avoid burdening "no TZ"
or "no virtualization" CPUs with the overhead of clearing
TLB entries that we never actually use.

Alternatively (better!), for a lot of the tlb_flush()es triggered
by target-arm code we could be more precise about the affected
mmu_idx values, since the common case is going to be
"NS EL1 did something that needs a TLB flush", and by definition
that can't affect TLB entries for EL2, EL3 or S-EL1/EL0.

So I think my preference would be to use 7 mmu indexes,
and add a tlb_flush_mmuidx() function. (Assuming I'm
not missing anything that makes that not workable...)

-- PMM

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

* Re: [Qemu-devel] [PATCH v7 05/32] target-arm: make arm_current_el() return EL3
  2015-01-19 19:00         ` Peter Maydell
@ 2015-01-19 19:30           ` Richard Henderson
  2015-01-19 22:54             ` Edgar E. Iglesias
  0 siblings, 1 reply; 53+ messages in thread
From: Richard Henderson @ 2015-01-19 19:30 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Sergey Fedorov, Edgar E. Iglesias, QEMU Developers,
	Fabian Aggeler, Greg Bellows

On 01/19/2015 11:00 AM, Peter Maydell wrote:
> Alternatively (better!), for a lot of the tlb_flush()es triggered
> by target-arm code we could be more precise about the affected
> mmu_idx values, since the common case is going to be
> "NS EL1 did something that needs a TLB flush", and by definition
> that can't affect TLB entries for EL2, EL3 or S-EL1/EL0.
> 
> So I think my preference would be to use 7 mmu indexes,
> and add a tlb_flush_mmuidx() function. (Assuming I'm
> not missing anything that makes that not workable...)

That new interface does seem very reasonable.

As to whether you've missed something in the ARM semantics,
I guess we'll find out.  ;-)


r~

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

* Re: [Qemu-devel] [PATCH v7 05/32] target-arm: make arm_current_el() return EL3
  2015-01-19 19:30           ` Richard Henderson
@ 2015-01-19 22:54             ` Edgar E. Iglesias
  0 siblings, 0 replies; 53+ messages in thread
From: Edgar E. Iglesias @ 2015-01-19 22:54 UTC (permalink / raw)
  To: Richard Henderson
  Cc: Peter Maydell, Sergey Fedorov, QEMU Developers, Fabian Aggeler,
	Greg Bellows

On Mon, Jan 19, 2015 at 11:30:51AM -0800, Richard Henderson wrote:
> On 01/19/2015 11:00 AM, Peter Maydell wrote:
> > Alternatively (better!), for a lot of the tlb_flush()es triggered
> > by target-arm code we could be more precise about the affected
> > mmu_idx values, since the common case is going to be
> > "NS EL1 did something that needs a TLB flush", and by definition
> > that can't affect TLB entries for EL2, EL3 or S-EL1/EL0.
> > 
> > So I think my preference would be to use 7 mmu indexes,
> > and add a tlb_flush_mmuidx() function. (Assuming I'm
> > not missing anything that makes that not workable...)
> 
> That new interface does seem very reasonable.
> 
> As to whether you've missed something in the ARM semantics,
> I guess we'll find out.  ;-)
>

Sounds like a good option to me too.

Cheers,
Edgar

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

end of thread, other threads:[~2015-01-19 22:57 UTC | newest]

Thread overview: 53+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-10-21 16:55 [Qemu-devel] [PATCH v7 00/32] target-arm: add Security Extensions for CPUs Greg Bellows
2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 01/32] target-arm: increase arrays of registers R13 & R14 Greg Bellows
2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 02/32] target-arm: add arm_is_secure() function Greg Bellows
2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 03/32] target-arm: reject switching to monitor mode Greg Bellows
2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 04/32] target-arm: rename arm_current_pl to arm_current_el Greg Bellows
2014-10-23 14:53   ` Peter Maydell
2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 05/32] target-arm: make arm_current_el() return EL3 Greg Bellows
2015-01-16 18:36   ` Peter Maydell
2015-01-19 13:22     ` Peter Maydell
2015-01-19 17:44       ` Richard Henderson
2015-01-19 19:00         ` Peter Maydell
2015-01-19 19:30           ` Richard Henderson
2015-01-19 22:54             ` Edgar E. Iglesias
2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 06/32] target-arm: A32: Emulate the SMC instruction Greg Bellows
2014-10-23 14:06   ` Peter Maydell
2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 07/32] target-arm: extend async excp masking Greg Bellows
2014-10-24 16:25   ` Peter Maydell
2014-10-24 22:43     ` Greg Bellows
2014-10-26 22:30       ` Peter Maydell
2014-10-27 11:57         ` Peter Maydell
2014-10-27 15:59           ` Greg Bellows
2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 08/32] target-arm: add async excp target_el function Greg Bellows
2014-10-24 16:26   ` Peter Maydell
2014-10-28 14:50     ` Greg Bellows
2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 09/32] target-arm: add banked register accessors Greg Bellows
2014-10-24 16:37   ` Peter Maydell
2014-10-28 18:42     ` Greg Bellows
2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 10/32] target-arm: add non-secure Translation Block flag Greg Bellows
2014-10-24 16:40   ` Peter Maydell
2014-10-28 15:21     ` Greg Bellows
2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 11/32] target-arm: add CPREG secure state support Greg Bellows
2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 12/32] target-arm: add secure state bit to CPREG hash Greg Bellows
2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 13/32] target-arm: insert AArch32 cpregs twice into hashtable Greg Bellows
2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 14/32] target-arm: move AArch32 SCR into security reglist Greg Bellows
2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 15/32] target-arm: implement IRQ/FIQ routing to Monitor mode Greg Bellows
2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 16/32] target-arm: respect SCR.FW, SCR.AW and SCTLR.NMFI Greg Bellows
2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 17/32] target-arm: add NSACR register Greg Bellows
2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 18/32] target-arm: add SDER definition Greg Bellows
2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 19/32] target-arm: add MVBAR support Greg Bellows
2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 20/32] target-arm: add SCTLR_EL3 and make SCTLR banked Greg Bellows
2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 21/32] target-arm: make CSSELR banked Greg Bellows
2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 22/32] target-arm: add TTBR0_EL3 and make TTBR0/1 banked Greg Bellows
2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 23/32] target-arm: add TCR_EL3 and make TTBCR banked Greg Bellows
2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 24/32] target-arm: make c2_mask and c2_base_mask banked Greg Bellows
2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 25/32] target-arm: make DACR banked Greg Bellows
2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 26/32] target-arm: make IFSR banked Greg Bellows
2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 27/32] target-arm: make DFSR banked Greg Bellows
2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 28/32] target-arm: make IFAR/DFAR banked Greg Bellows
2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 29/32] target-arm: make PAR banked Greg Bellows
2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 30/32] target-arm: make c13 cp regs banked (FCSEIDR, ...) Greg Bellows
2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 31/32] target-arm: make MAIR0/1 banked Greg Bellows
2014-10-21 16:55 ` [Qemu-devel] [PATCH v7 32/32] target-arm: add cpu feature EL3 to CPUs with Security Extensions Greg Bellows
2014-10-23 14:19 ` [Qemu-devel] [PATCH v7 00/32] target-arm: add Security Extensions for CPUs 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.