qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v8 00/27] target-arm: add Security Extensions for CPUs
@ 2014-10-30 21:28 Greg Bellows
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 01/27] target-arm: extend async excp masking Greg Bellows
                   ` (26 more replies)
  0 siblings, 27 replies; 81+ messages in thread
From: Greg Bellows @ 2014-10-30 21:28 UTC (permalink / raw)
  To: qemu-devel, peter.maydell, serge.fdrv, edgar.iglesias, aggelerf
  Cc: greg.bellows

Version 8 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.

Patches 1-6 of version 7 have already been accepted and committed.

Summary of changes from v7 -> v8:
- Reworked exception maskign and target EL functions to use table lookups
  instead of extensive conditionals.
- Moved and renamed use_secure_reg to access_secure_reg
- Redo fieldoffset definitions to eliminate #defines
- Consolidated common secure v7/v8 CP regs
- Removed NSACR read/write functions
- Fixed SDER and added SDER32_EL3
- Made MVBAR a 32-bit field
- Fixed CPSR write logic
- Fixed various code and commit comments
- Fixed CSSELR CP definition to use OPC0

Fabian Aggeler (20):
  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: add NSACR register
  target-arm: add MVBAR support
  target-arm: add SCTLR_EL3 and make SCTLR banked
  target-arm: respect SCR.FW, SCR.AW and SCTLR.NMFI
  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 (5):
  target-arm: extend async excp masking
  target-arm: add async excp target_el function
  target-arm: add secure state bit to CPREG hash
  target-arm: make VBAR banked
  target-arm: make MAIR0/1 banked

Sergey Fedorov (2):
  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                | 525 ++++++++++++++++++++++++++++----
 target-arm/helper.c             | 655 +++++++++++++++++++++++++++++-----------
 target-arm/internals.h          |   2 +-
 target-arm/op_helper.c          |   4 +-
 target-arm/translate.c          |  17 +-
 target-arm/translate.h          |   1 +
 11 files changed, 1015 insertions(+), 284 deletions(-)

--
1.8.3.2

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

* [Qemu-devel] [PATCH v8 01/27] target-arm: extend async excp masking
  2014-10-30 21:28 [Qemu-devel] [PATCH v8 00/27] target-arm: add Security Extensions for CPUs Greg Bellows
@ 2014-10-30 21:28 ` Greg Bellows
  2014-10-31 19:00   ` Peter Maydell
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 02/27] target-arm: add async excp target_el function Greg Bellows
                   ` (25 subsequent siblings)
  26 siblings, 1 reply; 81+ messages in thread
From: Greg Bellows @ 2014-10-30 21:28 UTC (permalink / raw)
  To: qemu-devel, peter.maydell, serge.fdrv, edgar.iglesias, aggelerf
  Cc: greg.bellows

This patch extends arm_excp_unmasked() to use lookup tables for determining
whether IRQ and FIQ exceptions are masked.  The lookup tables are based on the
ARMv8 and ARMv7 specification physical interrupt masking tables.

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: Greg Bellows <greg.bellows@linaro.org>

---

v7 -> v8
- Add IRQ and FIQ exeception masking lookup tables.
- Rewrite patch to use lookup tables for determining whether an excpetion is
  masked or not.

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

v4 -> v5
- Merge with v4 patch 10
---
 target-arm/cpu.h | 218 ++++++++++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 190 insertions(+), 28 deletions(-)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index cb6ec5c..be5d022 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -1242,44 +1242,200 @@ bool write_cpustate_to_list(ARMCPU *cpu);
 #  define TARGET_VIRT_ADDR_SPACE_BITS 32
 #endif
 
+/* Physical FIQ exception mask lookup table
+ *
+ * [ From ARM ARMv7 B1.8.6 Async exception masking (table B1-12) ]
+ * [ From ARM ARMv8 G1.11.3 Async exception masking (table G1-18) ]
+ *
+ * The below multi-dimensional table is used for looking up the masking
+ * behavior given the specified state conditions.  The table value are used
+ * for determining whether the PSTATE.AIF/CPSR.AIF bits control enterrupt
+ * masking or not.
+ *
+ *    Dimensions:
+ *    fiq_excp_mask_table[2][2][2][2][2][2][4]
+ *                        |  |  |  |  |  |  +--- Current EL
+ *                        |  |  |  |  |  +------ Non-secure(0)/Secure(1)
+ *                        |  |  |  |  +--------- HCR mask override
+ *                        |  |  |  +------------ SCR exec state control
+ *                        |  |  +--------------- SCR non-secure masking
+ *                        |  +------------------ SCR mask override
+ *                        +--------------------- 32-bit(0)/64-bit(1) EL3
+ *
+ *    The table values are as such:
+ *      0 = Exception is masked depending on PSTATE
+ *      1 = Exception is taken (unmasked) regardless of PSTATE
+ *     -1 = Cannot occur
+ *     -2 = Exception not taken, left pending
+ *
+ * Notes:
+ *    - RW is dont-care when EL3 is AArch32
+ *    - AW/FW are don't care when EL3 is AArch32
+ *    - Exceptions left pending (-2) is informational and should never escape
+ *      as the correct procedure involves first checking current to target EL.
+ *
+ *             SCR         HCR
+ *          64  EA         AMO                 From
+ *         BIT IRQ  AW     IMO      Non-secure         Secure
+ *         EL3 FIQ  FW  RW FMO   EL0 EL1 EL2 EL3   EL0 EL1 EL2 EL3
+ */
+static const int8_t fiq_excp_mask_table[2][2][2][2][2][2][4] = {
+    {{{{{/* 0   0   0   0   0 */{ 0,  0,  0, -1 },{ 0, -1, -1,  0 },},
+        {/* 0   0   0   0   1 */{ 1,  1,  0, -1 },{ 0, -1, -1,  0 },},},
+       {{/* 0   0   0   1   0 */{ 0,  0,  0, -1 },{ 0, -1, -1,  0 },},
+        {/* 0   0   0   1   1 */{ 1,  1,  0, -1 },{ 0, -1, -1,  0 },},},},
+      {{{/* 0   0   1   0   0 */{ 0,  0,  0, -1 },{ 0, -1, -1,  0 },},
+        {/* 0   0   1   0   1 */{ 1,  1,  0, -1 },{ 0, -1, -1,  0 },},},
+       {{/* 0   0   1   1   0 */{ 0,  0,  0, -1 },{ 0, -1, -1,  0 },},
+        {/* 0   0   1   1   1 */{ 1,  1,  0, -1 },{ 0, -1, -1,  0 },},},},},
+     {{{{/* 0   1   0   0   0 */{ 1,  1,  1, -1 },{ 0, -1, -1,  0 },},
+        {/* 0   1   0   0   1 */{ 1,  1,  1, -1 },{ 0, -1, -1,  0 },},},
+       {{/* 0   1   0   1   0 */{ 1,  1,  1, -1 },{ 0, -1, -1,  0 },},
+        {/* 0   1   0   1   1 */{ 1,  1,  1, -1 },{ 0, -1, -1,  0 },},},},
+      {{{/* 0   1   1   0   0 */{ 0,  0,  0, -1 },{ 0, -1, -1,  0 },},
+        {/* 0   1   1   0   1 */{ 1,  1,  1, -1 },{ 0, -1, -1,  0 },},},
+       {{/* 0   1   1   1   0 */{ 0,  0,  0, -1 },{ 0, -1, -1,  0 },},
+        {/* 0   1   1   1   1 */{ 1,  1,  1, -1 },{ 0, -1, -1,  0 },},},},},},
+    {{{{{/* 1   0   0   0   0 */{ 0,  0,  0, -1 },{ 0,  0, -1, -2 },},
+        {/* 1   0   0   0   1 */{ 1,  1,  0, -1 },{ 0,  0, -1, -2 },},},
+       {{/* 1   0   0   1   0 */{ 0,  0, -2, -1 },{ 0,  0, -1, -2 },},
+        {/* 1   0   0   1   1 */{ 1,  1,  0, -1 },{ 0,  0, -1, -2 },},},},
+      {{{/* 1   0   1   0   0 */{ 1,  1,  1, -1 },{ 0,  0, -1, -2 },},
+        {/* 1   0   1   0   1 */{ 1,  1,  0, -1 },{ 0,  0, -1, -2 },},},
+       {{/* 1   0   1   1   0 */{ 0,  0, -2, -1 },{ 0,  0, -1, -2 },},
+        {/* 1   0   1   1   1 */{ 1,  1,  0, -1 },{ 0,  0, -1, -2 },},},},},
+     {{{{/* 1   1   0   0   0 */{ 1,  1,  1, -1 },{ 1,  1, -1,  0 },},
+        {/* 1   1   0   0   1 */{ 1,  1,  1, -1 },{ 1,  1, -1,  0 },},},
+       {{/* 1   1   0   1   0 */{ 1,  1,  1, -1 },{ 1,  1, -1,  0 },},
+        {/* 1   1   0   1   1 */{ 1,  1,  1, -1 },{ 1,  1, -1,  0 },},},},
+      {{{/* 1   1   1   0   0 */{ 1,  1,  1, -1 },{ 1,  1, -1,  0 },},
+        {/* 1   1   1   0   1 */{ 1,  1,  1, -1 },{ 1,  1, -1,  0 },},},
+       {{/* 1   1   1   1   0 */{ 1,  1,  1, -1 },{ 1,  1, -1,  0 },},
+        {/* 1   1   1   1   1 */{ 1,  1,  1, -1 },{ 1,  1, -1,  0 },},},},},},
+};
+
+/* Physical IRQ exception mask lookup table
+ *
+ * [ From ARM ARMv7 B1.8.6 Async exception masking (table B1-13) ]
+ * [ From ARM ARMv8 G1.11.3 Async exception masking (table G1-19) ]
+ *
+ * The below multi-dimensional table is used for looking up the masking
+ * behavior given the specified state conditions.  The table value are used
+ * for determining whether the PSTATE.AIF/CPSR.AIF bits control enterrupt
+ * masking or not.
+ *
+ *    Dimensions:
+ *    irq_excp_mask_table[2][2][2][2][2][4]
+ *                        |  |  |  |  |  +--- Current EL
+ *                        |  |  |  |  +------ Non-secure(0)/Secure(1)
+ *                        |  |  |  +--------- HCR mask override
+ *                        |  |  +------------ SCR exec state control
+ *                        |  +--------------- SCR mask override
+ *                        +------------------ 32-bit(0)/64-bit(1) EL3
+ *
+ *    The table values are as such:
+ *      0 = Exception is masked depending on PSTATE
+ *      1 = Exception is taken (unmasked) regardless of PSTATE
+ *     -1 = Cannot occur
+ *     -2 = Exception not taken, left pending
+ *
+ * Notes:
+ *    - RW is dont-care when EL3 is AArch32
+ *    - Exceptions left pending (-2) is informational and should never escape
+ *      as the correct procedure involves first checking current to target EL.
+ *
+ *             SCR     HCR
+ *          64  EA     AMO                 From
+ *         BIT IRQ     IMO      Non-secure         Secure
+ *         EL3 FIQ  RW FMO   EL0 EL1 EL2 EL3   EL0 EL1 EL2 EL3
+ */
+static const int8_t irq_excp_mask_table[2][2][2][2][2][4] = {
+     {{{{/* 0   0   0   0 */{ 0,  0,  0, -1 },{ 0, -1, -1,  0 },},
+        {/* 0   0   0   1 */{ 1,  1,  0, -1 },{ 0, -1, -1,  0 },},},
+       {{/* 0   0   1   0 */{ 0,  0,  0, -1 },{ 0, -1, -1,  0 },},
+        {/* 0   0   1   1 */{ 1,  1,  0, -1 },{ 0, -1, -1,  0 },},},},
+      {{{/* 0   1   0   0 */{ 0,  0,  0, -1 },{ 0, -1, -1,  0 },},
+        {/* 0   1   0   1 */{ 1,  1,  1, -1 },{ 0, -1, -1,  0 },},},
+       {{/* 0   1   1   0 */{ 0,  0,  0, -1 },{ 0, -1, -1,  0 },},
+        {/* 0   1   1   1 */{ 1,  1,  1, -1 },{ 0, -1, -1,  0 },},},},},
+     {{{{/* 1   0   0   0 */{ 0,  0,  0, -1 },{ 0,  0, -1, -2 },},
+        {/* 1   0   0   1 */{ 1,  1,  0, -1 },{ 0,  0, -1, -2 },},},
+       {{/* 1   0   1   0 */{ 0,  0, -2, -1 },{ 0,  0, -1, -2 },},
+        {/* 1   0   1   1 */{ 1,  1,  0, -1 },{ 0,  0, -1, -2 },},},},
+      {{{/* 1   1   0   0 */{ 1,  1,  1, -1 },{ 1,  1, -1,  0 },},
+        {/* 1   1   0   1 */{ 1,  1,  1, -1 },{ 1,  1, -1,  0 },},},
+       {{/* 1   1   1   0 */{ 1,  1,  1, -1 },{ 1,  1, -1,  0 },},
+        {/* 1   1   1   1 */{ 1,  1,  1, -1 },{ 1,  1, -1,  0 },},},},},
+};
+
 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;
-    /* ARMv7-M interrupt return works by loading a magic value
-     * into the PC.  On real hardware the load causes the
-     * return to occur.  The qemu implementation performs the
-     * jump normally, then does the exception return when the
-     * CPU tries to execute code at the magic address.
-     * This will cause the magic PC value to be pushed to
-     * the stack if an interrupt occurred at the wrong time.
-     * We avoid this by disabling interrupts when
-     * pc contains a magic address.
+    bool secure = arm_is_secure(env);
+    uint32_t rw = ((env->cp15.scr_el3 & SCR_RW) == SCR_RW);
+    uint32_t is64 = arm_el_is_aa64(env, 3);
+    uint32_t fw;
+    uint32_t scr;
+    uint32_t hcr;
+    bool pstate_unmasked;
+    int8_t unmasked = 0;
+
+    /* Don't take exceptions if they target a lower EL.
+     * This check should catch any exceptions that would not be taken but left
+     * pending.
      */
-    bool irq_unmasked = !(env->daif & PSTATE_I)
-                        && (!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;
     }
 
     switch (excp_idx) {
     case EXCP_FIQ:
-        if (irq_can_hyp && (env->cp15.hcr_el2 & HCR_FMO)) {
-            return true;
-        }
-        return !(env->daif & PSTATE_F);
+        scr = ((env->cp15.scr_el3 & SCR_FIQ) == SCR_FIQ);
+        hcr = ((env->cp15.hcr_el2 & HCR_FMO) == HCR_FMO);
+
+        /* The SCR.FW bit only affects masking when the virtualization
+         * extension is present.  The unmasked table assumes that the extension
+         * is present, so when not present we must set FW to 1 to
+         * remain neutral.
+         */
+        fw = (!arm_feature(env, ARM_FEATURE_EL2) |
+              ((env->cp15.scr_el3 & SCR_FW) == SCR_FW));
+
+        /* FIQ are unmasked if PSTATE.F is clear */
+        pstate_unmasked = !(env->daif & PSTATE_F);
+
+        /* Perform a table lookup on whether the current state results in the
+         * exception being masked.  If the table lookup returns true(1) then
+         * PSTATE determines whether the interrupt is unmasked or not.
+         */
+        unmasked = fiq_excp_mask_table[is64][scr][fw][rw][hcr][secure][cur_el];
+        break;
+
     case EXCP_IRQ:
-        if (irq_can_hyp && (env->cp15.hcr_el2 & HCR_IMO)) {
-            return true;
-        }
-        return irq_unmasked;
+        scr = ((env->cp15.scr_el3 & SCR_IRQ) == SCR_IRQ);
+        hcr = ((env->cp15.hcr_el2 & HCR_IMO) == HCR_IMO);
+
+        /* ARMv7-M interrupt return works by loading a magic value
+         * into the PC.  On real hardware the load causes the
+         * return to occur.  The qemu implementation performs the
+         * jump normally, then does the exception return when the
+         * CPU tries to execute code at the magic address.
+         * This will cause the magic PC value to be pushed to
+         * the stack if an interrupt occurred at the wrong time.
+         * We avoid this by disabling interrupts when
+         * pc contains a magic address.
+         */
+        pstate_unmasked = !(env->daif & PSTATE_I)
+                          && (!IS_M(env) || env->regs[15] < 0xfffffff0);
+
+        /* Perform a table lookup on whether the current state results in the
+         * exception being masked.  If the table lookup returns true(1) then
+         * PSTATE determines whether the interrupt is unmasked or not.
+         */
+        unmasked = irq_excp_mask_table[is64][scr][rw][hcr][secure][cur_el];
+        break;
+
     case EXCP_VFIQ:
         if (!secure && !(env->cp15.hcr_el2 & HCR_FMO)) {
             /* VFIQs are only taken when hypervized and non-secure.  */
@@ -1291,10 +1447,16 @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx)
             /* VIRQs are only taken when hypervized and non-secure.  */
             return false;
         }
-        return irq_unmasked;
+        return !(env->daif & PSTATE_I)
+               && (!IS_M(env) || env->regs[15] < 0xfffffff0);
     default:
         g_assert_not_reached();
     }
+
+    /* We better not have a negative table value or something went wrong */
+    assert(unmasked >= 0);
+
+    return unmasked || pstate_unmasked;
 }
 
 static inline CPUARMState *cpu_init(const char *cpu_model)
-- 
1.8.3.2

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

* [Qemu-devel] [PATCH v8 02/27] target-arm: add async excp target_el function
  2014-10-30 21:28 [Qemu-devel] [PATCH v8 00/27] target-arm: add Security Extensions for CPUs Greg Bellows
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 01/27] target-arm: extend async excp masking Greg Bellows
@ 2014-10-30 21:28 ` Greg Bellows
  2014-10-31 11:56   ` Peter Maydell
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 03/27] target-arm: add banked register accessors Greg Bellows
                   ` (24 subsequent siblings)
  26 siblings, 1 reply; 81+ messages in thread
From: Greg Bellows @ 2014-10-30 21:28 UTC (permalink / raw)
  To: qemu-devel, peter.maydell, serge.fdrv, edgar.iglesias, aggelerf
  Cc: greg.bellows

Adds a dedicated function and a lookup table for determining the target
exception level of IRQ and FIQ exceptions.  The lookup table is taken from the
ARMv7 and ARMv8 specification exception routing tables.

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

---

v7 -> v8
- Added target EL lookup table
- Rework arm_phys_excp_target_el to use an EL lookup table rather than
  conditionals.

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.
---
 target-arm/helper.c | 111 ++++++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 91 insertions(+), 20 deletions(-)

diff --git a/target-arm/helper.c b/target-arm/helper.c
index c47487a..e610466 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -3761,6 +3761,94 @@ void switch_mode(CPUARMState *env, int mode)
     env->spsr = env->banked_spsr[i];
 }
 
+/* Physical Interrupt Target EL Lookup Table
+ *
+ * [ From ARM ARM section G1.13.4 (Table G1-15) ]
+ *
+ * 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.
+ *
+ *    Dimensions:
+ *    target_el_table[2][2][2][2][2][4]
+ *                    |  |  |  |  |  +--- Current EL
+ *                    |  |  |  |  +------ Non-secure(0)/Secure(1)
+ *                    |  |  |  +--------- HCR mask override
+ *                    |  |  +------------ SCR exec state control
+ *                    |  +--------------- SCR mask override
+ *                    +------------------ 32-bit(0)/64-bit(1) EL3
+ *
+ *    The table values are as such:
+ *    0-3 = EL0-EL3
+ *     -1 = Cannot occur
+ *
+ * In the case of exceptions not being taken, EL1 is returned.  These cases
+ * will be caught by the checks for target being >= current.
+ *
+ *            SCR     HCR
+ *         64  EA     AMO                 From
+ *        BIT IRQ     IMO      Non-secure         Secure
+ *        EL3 FIQ  RW FMO   EL0 EL1 EL2 EL3   EL0 EL1 EL2 EL3
+ */
+const int8_t target_el_table[2][2][2][2][2][4] = {
+    {{{{/* 0   0   0   0 */{ 1,  1,  2, -1 },{ 3,  3, -1,  3 },},
+       {/* 0   0   0   1 */{ 2,  2,  2, -1 },{ 3,  3, -1,  3 },},},
+      {{/* 0   0   1   0 */{ 1,  1,  2, -1 },{ 3,  3, -1,  3 },},
+       {/* 0   0   1   1 */{ 2,  2,  2, -1 },{ 3,  3, -1,  3 },},},},
+     {{{/* 0   1   0   0 */{ 3,  3,  3, -1 },{ 3,  3, -1,  3 },},
+       {/* 0   1   0   1 */{ 3,  3,  3, -1 },{ 3,  3, -1,  3 },},},
+      {{/* 0   1   1   0 */{ 3,  3,  3, -1 },{ 3,  3, -1,  3 },},
+       {/* 0   1   1   1 */{ 3,  3,  3, -1 },{ 3,  3, -1,  3 },},},},},
+    {{{{/* 1   0   0   0 */{ 1,  1,  2, -1 },{ 1,  1, -1,  1 },},
+       {/* 1   0   0   1 */{ 2,  2,  2, -1 },{ 1,  1, -1,  1 },},},
+      {{/* 1   0   1   0 */{ 1,  1,  1, -1 },{ 1,  1, -1,  1 },},
+       {/* 1   0   1   1 */{ 2,  2,  2, -1 },{ 1,  1, -1,  1 },},},},
+     {{{/* 1   1   0   0 */{ 3,  3,  3, -1 },{ 3,  3, -1,  3 },},
+       {/* 1   1   0   1 */{ 3,  3,  3, -1 },{ 3,  3, -1,  3 },},},
+      {{/* 1   1   1   0 */{ 3,  3,  3, -1 },{ 3,  3, -1,  3 },},
+       {/* 1   1   1   1 */{ 3,  3,  3, -1 },{ 3,  3, -1,  3 },},},},},
+};
+
+/*
+ * 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 rw = ((env->cp15.scr_el3 & SCR_RW) == SCR_RW);
+    uint32_t scr;
+    uint32_t hcr;
+    uint32_t target_el;
+    uint32_t is64 = arm_el_is_aa64(env, 3);
+
+    switch (excp_idx) {
+    case EXCP_IRQ:
+        scr = ((env->cp15.scr_el3 & SCR_IRQ) == SCR_IRQ);
+        hcr = ((env->cp15.hcr_el2 & HCR_IMO) == HCR_IMO);
+        break;
+    case EXCP_FIQ:
+        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;
+    };
+
+    /* If HCR.TGE is set then HCR is treated as being 1 */
+    hcr |= ((env->cp15.hcr_el2 & HCR_TGE) == HCR_TGE);
+
+    /* Perform a table-lookup for the target EL given the current state */
+    target_el = target_el_table[is64][scr][rw][hcr][secure][cur_el];
+
+    assert(target_el > 0);
+
+    return target_el;
+}
+
 /*
  * Determine the target EL for a given exception type.
  */
@@ -3769,14 +3857,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 +3870,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] 81+ messages in thread

* [Qemu-devel] [PATCH v8 03/27] target-arm: add banked register accessors
  2014-10-30 21:28 [Qemu-devel] [PATCH v8 00/27] target-arm: add Security Extensions for CPUs Greg Bellows
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 01/27] target-arm: extend async excp masking Greg Bellows
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 02/27] target-arm: add async excp target_el function Greg Bellows
@ 2014-10-30 21:28 ` Greg Bellows
  2014-10-31 16:50   ` Peter Maydell
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 04/27] target-arm: add non-secure Translation Block flag Greg Bellows
                   ` (23 subsequent siblings)
  26 siblings, 1 reply; 81+ messages in thread
From: Greg Bellows @ 2014-10-30 21:28 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>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

---

v7 -> v8
- Move use_secure_reg() function to the TBFLAG patch.

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.
---
 target-arm/cpu.h | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index be5d022..5117d4d 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -817,6 +817,33 @@ static inline bool arm_el_is_aa64(CPUARMState *env, int el)
     return arm_feature(env, ARM_FEATURE_AARCH64);
 }
 
+/* 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] 81+ messages in thread

* [Qemu-devel] [PATCH v8 04/27] target-arm: add non-secure Translation Block flag
  2014-10-30 21:28 [Qemu-devel] [PATCH v8 00/27] target-arm: add Security Extensions for CPUs Greg Bellows
                   ` (2 preceding siblings ...)
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 03/27] target-arm: add banked register accessors Greg Bellows
@ 2014-10-30 21:28 ` Greg Bellows
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 05/27] target-arm: add CPREG secure state support Greg Bellows
                   ` (22 subsequent siblings)
  26 siblings, 0 replies; 81+ messages in thread
From: Greg Bellows @ 2014-10-30 21:28 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.

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>

---

v7 -> v8
- Moved and renamed use_secure_reg() to this patch.  New name is
  access_secure_reg().
- Fixed function comment

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.
---
 target-arm/cpu.h       | 27 +++++++++++++++++++++++++++
 target-arm/translate.c |  1 +
 target-arm/translate.h |  1 +
 3 files changed, 29 insertions(+)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 5117d4d..ba621fa 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -817,6 +817,22 @@ static inline bool arm_el_is_aa64(CPUARMState *env, int el)
     return arm_feature(env, ARM_FEATURE_AARCH64);
 }
 
+/* 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.
+ */
+static inline bool access_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)
@@ -1603,6 +1619,12 @@ 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!
+ */
+#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
@@ -1647,6 +1669,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)
@@ -1696,6 +1720,9 @@ static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
         if (privmode) {
             *flags |= ARM_TBFLAG_PRIV_MASK;
         }
+        if (!(access_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 1d52e47..32eb7bb 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -11005,6 +11005,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] 81+ messages in thread

* [Qemu-devel] [PATCH v8 05/27] target-arm: add CPREG secure state support
  2014-10-30 21:28 [Qemu-devel] [PATCH v8 00/27] target-arm: add Security Extensions for CPUs Greg Bellows
                   ` (3 preceding siblings ...)
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 04/27] target-arm: add non-secure Translation Block flag Greg Bellows
@ 2014-10-30 21:28 ` Greg Bellows
  2014-10-31 12:15   ` Peter Maydell
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 06/27] target-arm: add secure state bit to CPREG hash Greg Bellows
                   ` (21 subsequent siblings)
  26 siblings, 1 reply; 81+ messages in thread
From: Greg Bellows @ 2014-10-30 21:28 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>

---

v7 -> v8
- Break up the fieldoffset union to avoid need for sometimes overwriting one
  bank when updating fieldoffset.  This also removes the need for the #define
  short-cut introduced in v7.

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
---
 target-arm/cpu.h | 41 ++++++++++++++++++++++++++++++++++++++---
 1 file changed, 38 insertions(+), 3 deletions(-)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index ba621fa..51117fb 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -993,6 +993,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.
@@ -1127,6 +1145,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*.
@@ -1136,12 +1156,27 @@ 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:
+    /* Offset of the field in CPUARMState for this register.
+     *
+     * 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) */
+    ptrdiff_t fieldoffset;
+
+    /* Offsets of the secure and non-secure fields in CPUARMState for the
+     * register if it is banked.  These fields are only used during the static
+     * registration of a register.  During hashing the bank associated
+     * with a given security state is copied to fieldoffset which is used from
+     * there on out.
+     *
+     * It is expected that register definitions use either fieldoffset or
+     * bank_fieldoffsets in the definition but not both.  It is also expected
+     * that both bank offsets are set when defining a banked register.  This
+     * use indicates that a register is banked.
+     */
+    ptrdiff_t bank_fieldoffsets[2];
+
     /* 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] 81+ messages in thread

* [Qemu-devel] [PATCH v8 06/27] target-arm: add secure state bit to CPREG hash
  2014-10-30 21:28 [Qemu-devel] [PATCH v8 00/27] target-arm: add Security Extensions for CPUs Greg Bellows
                   ` (4 preceding siblings ...)
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 05/27] target-arm: add CPREG secure state support Greg Bellows
@ 2014-10-30 21:28 ` Greg Bellows
  2014-10-31 12:28   ` Peter Maydell
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 07/27] target-arm: insert AArch32 cpregs twice into hashtable Greg Bellows
                   ` (20 subsequent siblings)
  26 siblings, 1 reply; 81+ messages in thread
From: Greg Bellows @ 2014-10-30 21:28 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#
---
 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 51117fb..6bb7d39 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -879,6 +879,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;
@@ -896,9 +897,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 |                                 \
@@ -917,8 +925,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 e610466..959a46e 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 32eb7bb..04a35d7 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)
 {
@@ -7074,7 +7074,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)) {
@@ -7264,12 +7264,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] 81+ messages in thread

* [Qemu-devel] [PATCH v8 07/27] target-arm: insert AArch32 cpregs twice into hashtable
  2014-10-30 21:28 [Qemu-devel] [PATCH v8 00/27] target-arm: add Security Extensions for CPUs Greg Bellows
                   ` (5 preceding siblings ...)
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 06/27] target-arm: add secure state bit to CPREG hash Greg Bellows
@ 2014-10-30 21:28 ` Greg Bellows
  2014-10-31 12:44   ` Peter Maydell
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 08/27] target-arm: move AArch32 SCR into security reglist Greg Bellows
                   ` (19 subsequent siblings)
  26 siblings, 1 reply; 81+ messages in thread
From: Greg Bellows @ 2014-10-30 21:28 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>

---

v7 -> v8
- Updated define registers asserts to allow either a non-zero fieldoffset or
  non-zero bank_fieldoffsets.
- Updated CP register hashing to always set the register fieldoffset when
  banked register offsets are specified.

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.
---
 target-arm/helper.c | 98 ++++++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 82 insertions(+), 16 deletions(-)

diff --git a/target-arm/helper.c b/target-arm/helper.c
index 959a46e..c1c6303 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -3296,22 +3296,62 @@ 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 (r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1]) {
+        /* Register is banked (using both entries in array).
+         * Overwriting fieldoffset as the array is only used to define
+         * banked registers but later only fieldoffset is used.
          */
-        if (r2->cp == 0) {
-            r2->cp = 15;
+        r2->fieldoffset = r->bank_fieldoffsets[nsbit];
+    }
+
+    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]) {
+            /* If the register is banked and 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
@@ -3460,10 +3500,14 @@ void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
      */
     if (!(r->type & (ARM_CP_SPECIAL|ARM_CP_CONST))) {
         if (r->access & PL3_R) {
-            assert(r->fieldoffset || r->readfn);
+            assert((r->fieldoffset ||
+                   (r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1])) ||
+                   r->readfn);
         }
         if (r->access & PL3_W) {
-            assert(r->fieldoffset || r->writefn);
+            assert((r->fieldoffset ||
+                   (r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1])) ||
+                   r->writefn);
         }
     }
     /* Bad type field probably means missing sentinel at end of reg list */
@@ -3476,8 +3520,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] 81+ messages in thread

* [Qemu-devel] [PATCH v8 08/27] target-arm: move AArch32 SCR into security reglist
  2014-10-30 21:28 [Qemu-devel] [PATCH v8 00/27] target-arm: add Security Extensions for CPUs Greg Bellows
                   ` (6 preceding siblings ...)
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 07/27] target-arm: insert AArch32 cpregs twice into hashtable Greg Bellows
@ 2014-10-30 21:28 ` Greg Bellows
  2014-10-31 12:06   ` Peter Maydell
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 09/27] target-arm: implement IRQ/FIQ routing to Monitor mode Greg Bellows
                   ` (18 subsequent siblings)
  26 siblings, 1 reply; 81+ messages in thread
From: Greg Bellows @ 2014-10-30 21:28 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>

---

v7 -> v8
- Fix SCR register fieldoffset to be offsetoflow32.
- Rename v7_el3_cp_reginfo to el3_cp_reginfo and remove v7 feature check when
  defining.  This allows all common v7/8 secure CP regs to be registered
  together leaving the v8_el3_cp_reginfo to only v8 specific EL3 registers.
- Move SCR_EL3 into el3_cp_reginfo.

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
---
 target-arm/helper.c | 19 +++++++++++++------
 1 file changed, 13 insertions(+), 6 deletions(-)

diff --git a/target-arm/helper.c b/target-arm/helper.c
index c1c6303..3fdd3c2 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,18 @@ static const ARMCPRegInfo v8_el3_cp_reginfo[] = {
       .access = PL3_RW, .writefn = vbar_write,
       .fieldoffset = offsetof(CPUARMState, cp15.vbar_el[3]),
       .resetvalue = 0 },
+    REGINFO_SENTINEL
+};
+
+static const ARMCPRegInfo el3_cp_reginfo[] = {
     { .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 },
+    { .name = "SCR",  .type = ARM_CP_NO_MIGRATE,
+      .cp = 15, .crn = 1, .crm = 1, .opc1 = 0, .opc2 = 0,
+      .access = PL3_RW, .resetvalue = 0, .writefn = scr_write,
+      .fieldoffset = offsetoflow32(CPUARMState, cp15.scr_el3) },
     REGINFO_SENTINEL
 };
 
@@ -2960,7 +2964,10 @@ 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);
+        }
+        define_arm_cp_regs(cpu, 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] 81+ messages in thread

* [Qemu-devel] [PATCH v8 09/27] target-arm: implement IRQ/FIQ routing to Monitor mode
  2014-10-30 21:28 [Qemu-devel] [PATCH v8 00/27] target-arm: add Security Extensions for CPUs Greg Bellows
                   ` (7 preceding siblings ...)
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 08/27] target-arm: move AArch32 SCR into security reglist Greg Bellows
@ 2014-10-30 21:28 ` Greg Bellows
  2014-10-31 12:01   ` Peter Maydell
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 10/27] target-arm: add NSACR register Greg Bellows
                   ` (17 subsequent siblings)
  26 siblings, 1 reply; 81+ messages in thread
From: Greg Bellows @ 2014-10-30 21:28 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 3fdd3c2..e73756d 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -4227,12 +4227,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] 81+ messages in thread

* [Qemu-devel] [PATCH v8 10/27] target-arm: add NSACR register
  2014-10-30 21:28 [Qemu-devel] [PATCH v8 00/27] target-arm: add Security Extensions for CPUs Greg Bellows
                   ` (8 preceding siblings ...)
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 09/27] target-arm: implement IRQ/FIQ routing to Monitor mode Greg Bellows
@ 2014-10-30 21:28 ` Greg Bellows
  2014-10-31 13:24   ` Peter Maydell
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 11/27] target-arm: add SDER definition Greg Bellows
                   ` (16 subsequent siblings)
  26 siblings, 1 reply; 81+ messages in thread
From: Greg Bellows @ 2014-10-30 21:28 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>

---

v7 -> v8
- Update naming from c1_nsacr to nsacr to match other registers being changed.
- Remove NSACR read/write functions

v4 -> v5
- Changed to use renamed arm_current_el()
---
 target-arm/cpu.h    | 6 ++++++
 target-arm/helper.c | 3 +++
 2 files changed, 9 insertions(+)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 6bb7d39..88e22fb 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 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 e73756d..3c12eb3 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -2344,6 +2344,9 @@ static const ARMCPRegInfo el3_cp_reginfo[] = {
       .cp = 15, .crn = 1, .crm = 1, .opc1 = 0, .opc2 = 0,
       .access = PL3_RW, .resetvalue = 0, .writefn = scr_write,
       .fieldoffset = offsetoflow32(CPUARMState, cp15.scr_el3) },
+    { .name = "NSACR", .cp = 15, .crn = 1, .crm = 1, .opc1 = 0, .opc2 = 2,
+      .access = PL3_RW | PL1_R, .resetvalue = 0,
+      .fieldoffset = offsetof(CPUARMState, cp15.nsacr) },
     REGINFO_SENTINEL
 };
 
-- 
1.8.3.2

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

* [Qemu-devel] [PATCH v8 11/27] target-arm: add SDER definition
  2014-10-30 21:28 [Qemu-devel] [PATCH v8 00/27] target-arm: add Security Extensions for CPUs Greg Bellows
                   ` (9 preceding siblings ...)
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 10/27] target-arm: add NSACR register Greg Bellows
@ 2014-10-30 21:28 ` Greg Bellows
  2014-10-31 13:30   ` Peter Maydell
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 12/27] target-arm: add MVBAR support Greg Bellows
                   ` (15 subsequent siblings)
  26 siblings, 1 reply; 81+ messages in thread
From: Greg Bellows @ 2014-10-30 21:28 UTC (permalink / raw)
  To: qemu-devel, peter.maydell, serge.fdrv, edgar.iglesias, aggelerf
  Cc: greg.bellows

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

Added CP register defintions for SDER and SDER32_EL3 as well as cp15.sder for
register storage.

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>

---

v7 -> v8
- Added SDER32_EL3 register definition
- Changed sder name from c1_sder to sder
- Changed sder from uint32_t to uint64_t.
---
 target-arm/cpu.h    | 1 +
 target-arm/helper.c | 8 ++++++++
 2 files changed, 9 insertions(+)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 88e22fb..62cf48a 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.  */
+        uint64_t sder; /* Secure debug enable register. */
         uint32_t 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 3c12eb3..0be19f3 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -2344,6 +2344,14 @@ static const ARMCPRegInfo el3_cp_reginfo[] = {
       .cp = 15, .crn = 1, .crm = 1, .opc1 = 0, .opc2 = 0,
       .access = PL3_RW, .resetvalue = 0, .writefn = scr_write,
       .fieldoffset = offsetoflow32(CPUARMState, cp15.scr_el3) },
+    { .name = "SDER32_EL3", .state = ARM_CP_STATE_AA64,
+      .opc0 = 3, .opc1 = 6, .crn = 1, .crm = 1, .opc2 = 1,
+      .access = PL3_RW, .resetvalue = 0,
+      .fieldoffset = offsetof(CPUARMState, cp15.sder) },
+    { .name = "SDER",
+      .cp = 15, .crn = 1, .crm = 1, .opc1 = 0, .opc2 = 1,
+      .access = PL3_RW, .resetvalue = 0,
+      .fieldoffset = offsetoflow32(CPUARMState, cp15.sder) },
     { .name = "NSACR", .cp = 15, .crn = 1, .crm = 1, .opc1 = 0, .opc2 = 2,
       .access = PL3_RW | PL1_R, .resetvalue = 0,
       .fieldoffset = offsetof(CPUARMState, cp15.nsacr) },
-- 
1.8.3.2

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

* [Qemu-devel] [PATCH v8 12/27] target-arm: add MVBAR support
  2014-10-30 21:28 [Qemu-devel] [PATCH v8 00/27] target-arm: add Security Extensions for CPUs Greg Bellows
                   ` (10 preceding siblings ...)
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 11/27] target-arm: add SDER definition Greg Bellows
@ 2014-10-30 21:28 ` Greg Bellows
  2014-10-31 13:35   ` Peter Maydell
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 13/27] target-arm: add SCTLR_EL3 and make SCTLR banked Greg Bellows
                   ` (14 subsequent siblings)
  26 siblings, 1 reply; 81+ messages in thread
From: Greg Bellows @ 2014-10-30 21:28 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>

---

v7 -> v8
- Changed the mvbar cp15 storage from uint64_t to uint32_t
---
 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 62cf48a..596bfae 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 */
+        uint32_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 0be19f3..3c56d8f 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -2355,6 +2355,9 @@ static const ARMCPRegInfo el3_cp_reginfo[] = {
     { .name = "NSACR", .cp = 15, .crn = 1, .crm = 1, .opc1 = 0, .opc2 = 2,
       .access = PL3_RW | PL1_R, .resetvalue = 0,
       .fieldoffset = offsetof(CPUARMState, cp15.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
 };
 
@@ -4265,16 +4268,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] 81+ messages in thread

* [Qemu-devel] [PATCH v8 13/27] target-arm: add SCTLR_EL3 and make SCTLR banked
  2014-10-30 21:28 [Qemu-devel] [PATCH v8 00/27] target-arm: add Security Extensions for CPUs Greg Bellows
                   ` (11 preceding siblings ...)
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 12/27] target-arm: add MVBAR support Greg Bellows
@ 2014-10-30 21:28 ` Greg Bellows
  2014-10-31 14:07   ` Peter Maydell
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 14/27] target-arm: respect SCR.FW, SCR.AW and SCTLR.NMFI Greg Bellows
                   ` (13 subsequent siblings)
  26 siblings, 1 reply; 81+ messages in thread
From: Greg Bellows @ 2014-10-30 21:28 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
---
 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 693dfec..11d51af 100644
--- a/hw/arm/pxa2xx.c
+++ b/hw/arm/pxa2xx.c
@@ -273,7 +273,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 e0b82a6..18f4726 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 DC ZVA, CTL_EL0 and the cache ops */
-        env->cp15.c1_sys |= SCTLR_UCT | SCTLR_UCI | SCTLR_DZE;
+        env->cp15.sctlr_el[1] |= SCTLR_UCT | SCTLR_UCI | SCTLR_DZE;
         /* 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 596bfae..8acc2b0 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.  */
         uint64_t sder; /* Secure debug enable register. */
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 3c56d8f..466459b 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1908,7 +1908,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;
@@ -1926,7 +1926,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;
@@ -2003,7 +2003,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;
@@ -2042,6 +2042,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.
@@ -2311,6 +2329,10 @@ static const ARMCPRegInfo v8_el2_cp_reginfo[] = {
 };
 
 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,
@@ -2361,30 +2383,12 @@ static const ARMCPRegInfo 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;
@@ -3181,8 +3185,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,
         };
@@ -4271,7 +4277,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 {
@@ -4301,7 +4307,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;
@@ -4332,7 +4338,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:
@@ -4581,7 +4587,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;
@@ -4912,11 +4919,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;
@@ -4929,7 +4941,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] 81+ messages in thread

* [Qemu-devel] [PATCH v8 14/27] target-arm: respect SCR.FW, SCR.AW and SCTLR.NMFI
  2014-10-30 21:28 [Qemu-devel] [PATCH v8 00/27] target-arm: add Security Extensions for CPUs Greg Bellows
                   ` (12 preceding siblings ...)
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 13/27] target-arm: add SCTLR_EL3 and make SCTLR banked Greg Bellows
@ 2014-10-30 21:28 ` Greg Bellows
  2014-10-31 14:18   ` Peter Maydell
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 15/27] target-arm: make CSSELR banked Greg Bellows
                   ` (12 subsequent siblings)
  26 siblings, 1 reply; 81+ messages in thread
From: Greg Bellows @ 2014-10-30 21:28 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>

---

v7 -> v8
- Fixed incorrect use of env->uncached_cpsr A/I/F to use env->daif instead.
- Removed incorrect statement about SPSR to CPSR copies being affected by
  SCR.AW/FW.
- Fix typo in comment.
- Simpified cpsr_write logic

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.
---
 target-arm/helper.c | 47 ++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 44 insertions(+), 3 deletions(-)

diff --git a/target-arm/helper.c b/target-arm/helper.c
index 466459b..03e6b62 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -3666,9 +3666,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.
@@ -3680,6 +3677,50 @@ void cpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
             switch_mode(env, val & CPSR_M);
         }
     }
+
+    /* In a V7 implementation that includes 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.
+     */
+    if (!arm_feature(env, ARM_FEATURE_V8) &&
+        arm_feature(env, ARM_FEATURE_EL3) &&
+        !arm_feature(env, ARM_FEATURE_EL2) &&
+        !arm_is_secure(env)) {
+        if (!(env->cp15.scr_el3 & SCR_AW)) {
+            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 (!(env->cp15.scr_el3 & SCR_FW)) {
+            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] 81+ messages in thread

* [Qemu-devel] [PATCH v8 15/27] target-arm: make CSSELR banked
  2014-10-30 21:28 [Qemu-devel] [PATCH v8 00/27] target-arm: add Security Extensions for CPUs Greg Bellows
                   ` (13 preceding siblings ...)
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 14/27] target-arm: respect SCR.FW, SCR.AW and SCTLR.NMFI Greg Bellows
@ 2014-10-30 21:28 ` Greg Bellows
  2014-10-31 14:23   ` Peter Maydell
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 16/27] target-arm: add TTBR0_EL3 and make TTBR0/1 banked Greg Bellows
                   ` (11 subsequent siblings)
  26 siblings, 1 reply; 81+ messages in thread
From: Greg Bellows @ 2014-10-30 21:28 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>

---

v7 -> v8
- Fix CSSELR CP register definition to use .opc0 rather than .cp.

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.
---
 target-arm/cpu.h    | 10 +++++++++-
 target-arm/helper.c | 14 +++++++++++---
 2 files changed, 20 insertions(+), 4 deletions(-)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 8acc2b0..3b776a1 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 03e6b62..f6a9b66 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -776,7 +776,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,
@@ -903,8 +910,9 @@ static const ARMCPRegInfo v7_cp_reginfo[] = {
       .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 },
+      .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] 81+ messages in thread

* [Qemu-devel] [PATCH v8 16/27] target-arm: add TTBR0_EL3 and make TTBR0/1 banked
  2014-10-30 21:28 [Qemu-devel] [PATCH v8 00/27] target-arm: add Security Extensions for CPUs Greg Bellows
                   ` (14 preceding siblings ...)
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 15/27] target-arm: make CSSELR banked Greg Bellows
@ 2014-10-30 21:28 ` Greg Bellows
  2014-10-31 15:04   ` Peter Maydell
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 17/27] target-arm: add TCR_EL3 and make TTBCR banked Greg Bellows
                   ` (10 subsequent siblings)
  26 siblings, 1 reply; 81+ messages in thread
From: Greg Bellows @ 2014-10-30 21:28 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#
---
 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 11d51af..641b148 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.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 */
@@ -2047,7 +2047,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 3b776a1..fe96869 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.  */
         uint64_t sder; /* Secure debug enable register. */
         uint32_t 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 f6a9b66..598f0d1 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1645,14 +1645,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,
@@ -1883,11 +1885,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
 };
@@ -2341,6 +2345,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,
@@ -4422,18 +4430,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;
@@ -4687,6 +4700,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;
@@ -4738,7 +4752,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;
 
@@ -4750,7 +4776,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] 81+ messages in thread

* [Qemu-devel] [PATCH v8 17/27] target-arm: add TCR_EL3 and make TTBCR banked
  2014-10-30 21:28 [Qemu-devel] [PATCH v8 00/27] target-arm: add Security Extensions for CPUs Greg Bellows
                   ` (15 preceding siblings ...)
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 16/27] target-arm: add TTBR0_EL3 and make TTBR0/1 banked Greg Bellows
@ 2014-10-30 21:28 ` Greg Bellows
  2014-10-31 15:07   ` Peter Maydell
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 18/27] target-arm: make c2_mask and c2_base_mask banked Greg Bellows
                   ` (9 subsequent siblings)
  26 siblings, 1 reply; 81+ messages in thread
From: Greg Bellows @ 2014-10-30 21:28 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.
---
 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 fe96869..f125bdd 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 598f0d1..896b40d 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1659,11 +1659,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,
@@ -2349,6 +2350,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,
@@ -4435,13 +4441,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;
         }
@@ -4701,13 +4707,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;
     }
 
@@ -4716,12 +4738,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);
@@ -4765,10 +4787,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;
         }
@@ -4777,10 +4799,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] 81+ messages in thread

* [Qemu-devel] [PATCH v8 18/27] target-arm: make c2_mask and c2_base_mask banked
  2014-10-30 21:28 [Qemu-devel] [PATCH v8 00/27] target-arm: add Security Extensions for CPUs Greg Bellows
                   ` (16 preceding siblings ...)
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 17/27] target-arm: add TCR_EL3 and make TTBCR banked Greg Bellows
@ 2014-10-30 21:28 ` Greg Bellows
  2014-10-31 15:26   ` Peter Maydell
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 19/27] target-arm: make DACR banked Greg Bellows
                   ` (8 subsequent siblings)
  26 siblings, 1 reply; 81+ messages in thread
From: Greg Bellows @ 2014-10-30 21:28 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.
---
 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 f125bdd..6e9f1c3 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 896b40d..27eaf9c 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1584,8 +1584,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,
@@ -1604,9 +1610,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,
@@ -4440,7 +4452,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;
@@ -4452,7 +4464,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] 81+ messages in thread

* [Qemu-devel] [PATCH v8 19/27] target-arm: make DACR banked
  2014-10-30 21:28 [Qemu-devel] [PATCH v8 00/27] target-arm: add Security Extensions for CPUs Greg Bellows
                   ` (17 preceding siblings ...)
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 18/27] target-arm: make c2_mask and c2_base_mask banked Greg Bellows
@ 2014-10-30 21:28 ` Greg Bellows
  2014-10-31 15:38   ` Peter Maydell
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 20/27] target-arm: make IFSR banked Greg Bellows
                   ` (7 subsequent siblings)
  26 siblings, 1 reply; 81+ messages in thread
From: Greg Bellows @ 2014-10-30 21:28 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 641b148..ac13d0b 100644
--- a/hw/arm/pxa2xx.c
+++ b/hw/arm/pxa2xx.c
@@ -276,7 +276,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 6e9f1c3..6d39af1 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 27eaf9c..eaae534 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.
      */
@@ -2256,10 +2258,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,
@@ -4494,7 +4497,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;
@@ -4606,7 +4609,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] 81+ messages in thread

* [Qemu-devel] [PATCH v8 20/27] target-arm: make IFSR banked
  2014-10-30 21:28 [Qemu-devel] [PATCH v8 00/27] target-arm: add Security Extensions for CPUs Greg Bellows
                   ` (18 preceding siblings ...)
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 19/27] target-arm: make DACR banked Greg Bellows
@ 2014-10-30 21:28 ` Greg Bellows
  2014-10-31 16:18   ` Peter Maydell
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 21/27] target-arm: make DFSR banked Greg Bellows
                   ` (6 subsequent siblings)
  26 siblings, 1 reply; 81+ messages in thread
From: Greg Bellows @ 2014-10-30 21:28 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 6d39af1..c44649e 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 eaae534..de355f5 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1653,8 +1653,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,
@@ -4297,11 +4298,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] 81+ messages in thread

* [Qemu-devel] [PATCH v8 21/27] target-arm: make DFSR banked
  2014-10-30 21:28 [Qemu-devel] [PATCH v8 00/27] target-arm: add Security Extensions for CPUs Greg Bellows
                   ` (19 preceding siblings ...)
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 20/27] target-arm: make IFSR banked Greg Bellows
@ 2014-10-30 21:28 ` Greg Bellows
  2014-10-31 16:19   ` Peter Maydell
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 22/27] target-arm: make IFAR/DFAR banked Greg Bellows
                   ` (5 subsequent siblings)
  26 siblings, 1 reply; 81+ messages in thread
From: Greg Bellows @ 2014-10-30 21:28 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.
---
 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 c44649e..29bf273 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 de355f5..c5948f7 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1650,7 +1650,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,
@@ -4309,11 +4310,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] 81+ messages in thread

* [Qemu-devel] [PATCH v8 22/27] target-arm: make IFAR/DFAR banked
  2014-10-30 21:28 [Qemu-devel] [PATCH v8 00/27] target-arm: add Security Extensions for CPUs Greg Bellows
                   ` (20 preceding siblings ...)
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 21/27] target-arm: make DFSR banked Greg Bellows
@ 2014-10-30 21:28 ` Greg Bellows
  2014-10-31 16:24   ` Peter Maydell
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 23/27] target-arm: make PAR banked Greg Bellows
                   ` (4 subsequent siblings)
  26 siblings, 1 reply; 81+ messages in thread
From: Greg Bellows @ 2014-10-30 21:28 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
---
 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 18f4726..a711834 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 29bf273..10985d4 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 c5948f7..c4d0db4 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -554,7 +554,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.
@@ -1681,11 +1682,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
 };
 
@@ -4300,8 +4304,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;
@@ -4311,8 +4314,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] 81+ messages in thread

* [Qemu-devel] [PATCH v8 23/27] target-arm: make PAR banked
  2014-10-30 21:28 [Qemu-devel] [PATCH v8 00/27] target-arm: add Security Extensions for CPUs Greg Bellows
                   ` (21 preceding siblings ...)
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 22/27] target-arm: make IFAR/DFAR banked Greg Bellows
@ 2014-10-30 21:28 ` Greg Bellows
  2014-10-31 17:21   ` Peter Maydell
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 24/27] target-arm: make VBAR banked Greg Bellows
                   ` (3 subsequent siblings)
  26 siblings, 1 reply; 81+ messages in thread
From: Greg Bellows @ 2014-10-30 21:28 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

v3 -> v4
- Fix par union/structure definition
---
 target-arm/cpu.h    | 10 +++++++++-
 target-arm/helper.c | 25 ++++++++++++++-----------
 2 files changed, 23 insertions(+), 12 deletions(-)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 10985d4..3c6ff4a 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 */
diff --git a/target-arm/helper.c b/target-arm/helper.c
index c4d0db4..ec957fb 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1419,7 +1419,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).
@@ -1429,14 +1429,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);
         }
     }
 }
@@ -1444,9 +1446,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,
@@ -1902,8 +1904,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),
-- 
1.8.3.2

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

* [Qemu-devel] [PATCH v8 24/27] target-arm: make VBAR banked
  2014-10-30 21:28 [Qemu-devel] [PATCH v8 00/27] target-arm: add Security Extensions for CPUs Greg Bellows
                   ` (22 preceding siblings ...)
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 23/27] target-arm: make PAR banked Greg Bellows
@ 2014-10-30 21:28 ` Greg Bellows
  2014-10-31 17:22   ` Peter Maydell
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 25/27] target-arm: make c13 cp regs banked (FCSEIDR, ...) Greg Bellows
                   ` (2 subsequent siblings)
  26 siblings, 1 reply; 81+ messages in thread
From: Greg Bellows @ 2014-10-30 21:28 UTC (permalink / raw)
  To: qemu-devel, peter.maydell, serge.fdrv, edgar.iglesias, aggelerf
  Cc: greg.bellows

When EL3 is running in Aarch32 (or ARMv7 with Security Extensions)
VBAR has a secure and a non-secure instance, which are mapped to
VBAR_EL1 and VBAR_EL3.

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 vbar union/structure definition
- Revert back to array-based vbar definition combined with v7 naming
---
 target-arm/cpu.h    | 10 +++++++++-
 target-arm/helper.c |  8 ++++----
 2 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 3c6ff4a..e0954c7 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -306,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];
+        };
         uint32_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 ec957fb..fb040d4 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -905,9 +905,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 },
@@ -4371,7 +4371,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] 81+ messages in thread

* [Qemu-devel] [PATCH v8 25/27] target-arm: make c13 cp regs banked (FCSEIDR, ...)
  2014-10-30 21:28 [Qemu-devel] [PATCH v8 00/27] target-arm: add Security Extensions for CPUs Greg Bellows
                   ` (23 preceding siblings ...)
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 24/27] target-arm: make VBAR banked Greg Bellows
@ 2014-10-30 21:28 ` Greg Bellows
  2014-10-31 17:27   ` Peter Maydell
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 26/27] target-arm: make MAIR0/1 banked Greg Bellows
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 27/27] target-arm: add cpu feature EL3 to CPUs with Security Extensions Greg Bellows
  26 siblings, 1 reply; 81+ messages in thread
From: Greg Bellows @ 2014-10-30 21:28 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
---
 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 e0954c7..348ce73 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -316,11 +316,36 @@ typedef struct CPUARMState {
             uint64_t vbar_el[4];
         };
         uint32_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 fb040d4..d782897 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
 };
@@ -1025,23 +1028,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
 };
 
@@ -5045,7 +5052,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] 81+ messages in thread

* [Qemu-devel] [PATCH v8 26/27] target-arm: make MAIR0/1 banked
  2014-10-30 21:28 [Qemu-devel] [PATCH v8 00/27] target-arm: add Security Extensions for CPUs Greg Bellows
                   ` (24 preceding siblings ...)
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 25/27] target-arm: make c13 cp regs banked (FCSEIDR, ...) Greg Bellows
@ 2014-10-30 21:28 ` Greg Bellows
  2014-10-31 17:31   ` Peter Maydell
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 27/27] target-arm: add cpu feature EL3 to CPUs with Security Extensions Greg Bellows
  26 siblings, 1 reply; 81+ messages in thread
From: Greg Bellows @ 2014-10-30 21:28 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
---
 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 348ce73..1a76fc6 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 d782897..fd5f074 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -939,7 +939,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.
@@ -948,11 +948,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] 81+ messages in thread

* [Qemu-devel] [PATCH v8 27/27] target-arm: add cpu feature EL3 to CPUs with Security Extensions
  2014-10-30 21:28 [Qemu-devel] [PATCH v8 00/27] target-arm: add Security Extensions for CPUs Greg Bellows
                   ` (25 preceding siblings ...)
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 26/27] target-arm: make MAIR0/1 banked Greg Bellows
@ 2014-10-30 21:28 ` Greg Bellows
  26 siblings, 0 replies; 81+ messages in thread
From: Greg Bellows @ 2014-10-30 21:28 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 a711834..d76b47e 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] 81+ messages in thread

* Re: [Qemu-devel] [PATCH v8 02/27] target-arm: add async excp target_el function
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 02/27] target-arm: add async excp target_el function Greg Bellows
@ 2014-10-31 11:56   ` Peter Maydell
  2014-10-31 14:14     ` Greg Bellows
  0 siblings, 1 reply; 81+ messages in thread
From: Peter Maydell @ 2014-10-31 11:56 UTC (permalink / raw)
  To: Greg Bellows
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler,
	Edgar E. Iglesias

On 30 October 2014 21:28, Greg Bellows <greg.bellows@linaro.org> wrote:
> Adds a dedicated function and a lookup table for determining the target
> exception level of IRQ and FIQ exceptions.  The lookup table is taken from the
> ARMv7 and ARMv8 specification exception routing tables.
>
> Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
>
> ---
>
> v7 -> v8
> - Added target EL lookup table
> - Rework arm_phys_excp_target_el to use an EL lookup table rather than
>   conditionals.
>
> 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.
> ---
>  target-arm/helper.c | 111 ++++++++++++++++++++++++++++++++++++++++++----------
>  1 file changed, 91 insertions(+), 20 deletions(-)
>
> diff --git a/target-arm/helper.c b/target-arm/helper.c
> index c47487a..e610466 100644
> --- a/target-arm/helper.c
> +++ b/target-arm/helper.c
> @@ -3761,6 +3761,94 @@ void switch_mode(CPUARMState *env, int mode)
>      env->spsr = env->banked_spsr[i];
>  }
>
> +/* Physical Interrupt Target EL Lookup Table
> + *
> + * [ From ARM ARM section G1.13.4 (Table G1-15) ]
> + *
> + * 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.
> + *
> + *    Dimensions:
> + *    target_el_table[2][2][2][2][2][4]
> + *                    |  |  |  |  |  +--- Current EL
> + *                    |  |  |  |  +------ Non-secure(0)/Secure(1)
> + *                    |  |  |  +--------- HCR mask override
> + *                    |  |  +------------ SCR exec state control
> + *                    |  +--------------- SCR mask override
> + *                    +------------------ 32-bit(0)/64-bit(1) EL3
> + *
> + *    The table values are as such:
> + *    0-3 = EL0-EL3
> + *     -1 = Cannot occur
> + *
> + * In the case of exceptions not being taken, EL1 is returned.  These cases
> + * will be caught by the checks for target being >= current.

This could use rephrasing to make it clearer why returning 1 is ok:

"The ARM ARM tables include some entries indicating 'exception not taken'.
These are for the cases where we are currently at EL3 and the
exception is not routed to EL3 by the SCR, or where we are currently
at EL2 and the exception is not routed to EL3 or EL2. We can therefore
put '1' in those entries in our array, and rely on the check for
"target EL >= current EL" in the caller to ensure that the exception
is not taken."

> + *
> + *            SCR     HCR
> + *         64  EA     AMO                 From
> + *        BIT IRQ     IMO      Non-secure         Secure
> + *        EL3 FIQ  RW FMO   EL0 EL1 EL2 EL3   EL0 EL1 EL2 EL3
> + */
> +const int8_t target_el_table[2][2][2][2][2][4] = {
> +    {{{{/* 0   0   0   0 */{ 1,  1,  2, -1 },{ 3,  3, -1,  3 },},
> +       {/* 0   0   0   1 */{ 2,  2,  2, -1 },{ 3,  3, -1,  3 },},},
> +      {{/* 0   0   1   0 */{ 1,  1,  2, -1 },{ 3,  3, -1,  3 },},
> +       {/* 0   0   1   1 */{ 2,  2,  2, -1 },{ 3,  3, -1,  3 },},},},
> +     {{{/* 0   1   0   0 */{ 3,  3,  3, -1 },{ 3,  3, -1,  3 },},
> +       {/* 0   1   0   1 */{ 3,  3,  3, -1 },{ 3,  3, -1,  3 },},},
> +      {{/* 0   1   1   0 */{ 3,  3,  3, -1 },{ 3,  3, -1,  3 },},
> +       {/* 0   1   1   1 */{ 3,  3,  3, -1 },{ 3,  3, -1,  3 },},},},},

Your entries for 32-bit EL3, exception from Secure EL1 should all
read "-1", not "3" -- it's not possible to have current_el be 1
in this case (this is why table G1-15 has a "-" in those entries).

> +    {{{{/* 1   0   0   0 */{ 1,  1,  2, -1 },{ 1,  1, -1,  1 },},
> +       {/* 1   0   0   1 */{ 2,  2,  2, -1 },{ 1,  1, -1,  1 },},},
> +      {{/* 1   0   1   0 */{ 1,  1,  1, -1 },{ 1,  1, -1,  1 },},
> +       {/* 1   0   1   1 */{ 2,  2,  2, -1 },{ 1,  1, -1,  1 },},},},
> +     {{{/* 1   1   0   0 */{ 3,  3,  3, -1 },{ 3,  3, -1,  3 },},
> +       {/* 1   1   0   1 */{ 3,  3,  3, -1 },{ 3,  3, -1,  3 },},},
> +      {{/* 1   1   1   0 */{ 3,  3,  3, -1 },{ 3,  3, -1,  3 },},
> +       {/* 1   1   1   1 */{ 3,  3,  3, -1 },{ 3,  3, -1,  3 },},},},},
> +};
> +
> +/*
> + * 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 rw = ((env->cp15.scr_el3 & SCR_RW) == SCR_RW);
> +    uint32_t scr;
> +    uint32_t hcr;
> +    uint32_t target_el;
> +    uint32_t is64 = arm_el_is_aa64(env, 3);

You can just make these all "int".

> +
> +    switch (excp_idx) {
> +    case EXCP_IRQ:
> +        scr = ((env->cp15.scr_el3 & SCR_IRQ) == SCR_IRQ);
> +        hcr = ((env->cp15.hcr_el2 & HCR_IMO) == HCR_IMO);
> +        break;
> +    case EXCP_FIQ:
> +        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;
> +    };
> +
> +    /* If HCR.TGE is set then HCR is treated as being 1 */
> +    hcr |= ((env->cp15.hcr_el2 & HCR_TGE) == HCR_TGE);
> +
> +    /* Perform a table-lookup for the target EL given the current state */
> +    target_el = target_el_table[is64][scr][rw][hcr][secure][cur_el];
> +
> +    assert(target_el > 0);
> +
> +    return target_el;
> +}
> +
>  /*
>   * Determine the target EL for a given exception type.
>   */
> @@ -3769,14 +3857,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;

Do you actually need to initialize this?

> +    bool secure = arm_is_secure(env);
>
>      switch (excp_idx) {
>      case EXCP_HVC:
> @@ -3788,19 +3870,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
>

Thanks for adding the table-driven code: I found this much easier
to review against the ARM ARM. If you make those minor changes I
mention above then you can add my reviewed-by tag.

-- PMM

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

* Re: [Qemu-devel] [PATCH v8 09/27] target-arm: implement IRQ/FIQ routing to Monitor mode
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 09/27] target-arm: implement IRQ/FIQ routing to Monitor mode Greg Bellows
@ 2014-10-31 12:01   ` Peter Maydell
  0 siblings, 0 replies; 81+ messages in thread
From: Peter Maydell @ 2014-10-31 12:01 UTC (permalink / raw)
  To: Greg Bellows
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler,
	Edgar E. Iglesias

On 30 October 2014 21:28, Greg Bellows <greg.bellows@linaro.org> wrote:
> 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>

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

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v8 08/27] target-arm: move AArch32 SCR into security reglist
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 08/27] target-arm: move AArch32 SCR into security reglist Greg Bellows
@ 2014-10-31 12:06   ` Peter Maydell
  0 siblings, 0 replies; 81+ messages in thread
From: Peter Maydell @ 2014-10-31 12:06 UTC (permalink / raw)
  To: Greg Bellows
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler,
	Edgar E. Iglesias

On 30 October 2014 21:28, Greg Bellows <greg.bellows@linaro.org> wrote:
> 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>

I have a feeling we might find we can just merge v8_el3_cp_reginfo
and el3_cp_reginfo together, but we can always do that later.

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

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v8 05/27] target-arm: add CPREG secure state support
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 05/27] target-arm: add CPREG secure state support Greg Bellows
@ 2014-10-31 12:15   ` Peter Maydell
  0 siblings, 0 replies; 81+ messages in thread
From: Peter Maydell @ 2014-10-31 12:15 UTC (permalink / raw)
  To: Greg Bellows
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler,
	Edgar E. Iglesias

On 30 October 2014 21:28, Greg Bellows <greg.bellows@linaro.org> wrote:
> 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>
>
> ---
>
> v7 -> v8
> - Break up the fieldoffset union to avoid need for sometimes overwriting one
>   bank when updating fieldoffset.  This also removes the need for the #define
>   short-cut introduced in v7.
>
> 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
> ---
>  target-arm/cpu.h | 41 ++++++++++++++++++++++++++++++++++++++---
>  1 file changed, 38 insertions(+), 3 deletions(-)
>
> diff --git a/target-arm/cpu.h b/target-arm/cpu.h
> index ba621fa..51117fb 100644
> --- a/target-arm/cpu.h
> +++ b/target-arm/cpu.h
> @@ -993,6 +993,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))

I don't think this macro gains us much; you can just write

 if (ri->secure & ARM_CP_SECSTATE_S) { ...

which is shorter than
 if (ARM_CP_SECSTATE_TEST(ri, ARM_CP_SECSTATE_S)) { ...

(note you don't need to do "((foo & bit) == bit)" if you're just
doing a true/false check.)

> +
>  /* 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.
> @@ -1127,6 +1145,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*.
> @@ -1136,12 +1156,27 @@ 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:
> +    /* Offset of the field in CPUARMState for this register.
> +     *
> +     * 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) */
> +    ptrdiff_t fieldoffset;

You could leave the helpful comment rather than deleting it ;-)

> +
> +    /* Offsets of the secure and non-secure fields in CPUARMState for the
> +     * register if it is banked.  These fields are only used during the static
> +     * registration of a register.  During hashing the bank associated
> +     * with a given security state is copied to fieldoffset which is used from
> +     * there on out.
> +     *
> +     * It is expected that register definitions use either fieldoffset or
> +     * bank_fieldoffsets in the definition but not both.  It is also expected
> +     * that both bank offsets are set when defining a banked register.  This
> +     * use indicates that a register is banked.
> +     */
> +    ptrdiff_t bank_fieldoffsets[2];
> +

This is a lot nicer looking than the unions and macros.

>      /* 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
>

If you drop the macro definition you can mark this
reviewed-by: me.

-- PMM

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

* Re: [Qemu-devel] [PATCH v8 06/27] target-arm: add secure state bit to CPREG hash
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 06/27] target-arm: add secure state bit to CPREG hash Greg Bellows
@ 2014-10-31 12:28   ` Peter Maydell
  2014-10-31 12:31     ` Peter Maydell
  0 siblings, 1 reply; 81+ messages in thread
From: Peter Maydell @ 2014-10-31 12:28 UTC (permalink / raw)
  To: Greg Bellows
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler,
	Edgar E. Iglesias

On 30 October 2014 21:28, Greg Bellows <greg.bellows@linaro.org> wrote:
> 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>

Some minor nits here but otherwise it looks fine.

>
> ---
>
> v5 -> v6
> - Globally replace Aarch# with AArch#
> ---
>  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 51117fb..6bb7d39 100644
> --- a/target-arm/cpu.h
> +++ b/target-arm/cpu.h
> @@ -879,6 +879,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;
> @@ -896,9 +897,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)

This is wrong, it should just be
#define CP_REG_NS_MASK (1 << CP_REG_AA64_SHIFT)
(compare the definition of CP_REG_AA64_MASK above).

> +
> +#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))

I think I'd rather we put 'ns' after 'is64' in this macro's
parameter list rather than at the end; it seems to make sense
to group the state related arguments together.

Also you want "(ns) << CP_REG_NS_SHIFT", not CP_REG_NS_MASK.

>  #define ENCODE_AA64_CP_REG(cp, crn, crm, op0, op1, op2) \
>      (CP_REG_AA64_MASK |                                 \
> @@ -917,8 +925,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 e610466..959a46e 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)

Again, I think I'd rather we put 'nsbit' after 'state' rather than at the end.
Also you probably want 'bool ns' rather than '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);

This is a misuse of SCR_NS, which is a bitmask defining a bit position
in the SCR register (and which just happens to be 1 because the bit is
at the bottom of the register). Use 'true' or '1' instead (depending how
you define the 'ns' argument to the add_cpreg_to_hashtable()).

>                  }
>              }
>          }
> diff --git a/target-arm/translate.c b/target-arm/translate.c
> index 32eb7bb..04a35d7 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)
>  {

Stray change unrelated to what you're doing in this series.
(You can submit it as a standalone patch if you like, or just
forget about it :-))

> @@ -7074,7 +7074,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)) {
> @@ -7264,12 +7264,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
>

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v8 06/27] target-arm: add secure state bit to CPREG hash
  2014-10-31 12:28   ` Peter Maydell
@ 2014-10-31 12:31     ` Peter Maydell
  2014-10-31 16:20       ` Greg Bellows
  0 siblings, 1 reply; 81+ messages in thread
From: Peter Maydell @ 2014-10-31 12:31 UTC (permalink / raw)
  To: Greg Bellows
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler,
	Edgar E. Iglesias

On 31 October 2014 12:28, Peter Maydell <peter.maydell@linaro.org> wrote:
> On 30 October 2014 21:28, Greg Bellows <greg.bellows@linaro.org> wrote:

>>  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)
>
> Again, I think I'd rather we put 'nsbit' after 'state' rather than at the end.
> Also you probably want 'bool ns' rather than 'int nsbit'.

...actually, what you want here is "int secstate" and pass in either
ARM_CP_SECSTATE_S or ARM_CP_SECSTATE_NS. (This matches the way the
'state' parameter takes one of the ARM_CP_STATE_* values.)

-- PMM

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

* Re: [Qemu-devel] [PATCH v8 07/27] target-arm: insert AArch32 cpregs twice into hashtable
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 07/27] target-arm: insert AArch32 cpregs twice into hashtable Greg Bellows
@ 2014-10-31 12:44   ` Peter Maydell
  2014-10-31 19:01     ` Greg Bellows
  0 siblings, 1 reply; 81+ messages in thread
From: Peter Maydell @ 2014-10-31 12:44 UTC (permalink / raw)
  To: Greg Bellows
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler,
	Edgar E. Iglesias

On 30 October 2014 21:28, Greg Bellows <greg.bellows@linaro.org> wrote:
> 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>
>
> ---
>
> v7 -> v8
> - Updated define registers asserts to allow either a non-zero fieldoffset or
>   non-zero bank_fieldoffsets.
> - Updated CP register hashing to always set the register fieldoffset when
>   banked register offsets are specified.
>
> 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.
> ---
>  target-arm/helper.c | 98 ++++++++++++++++++++++++++++++++++++++++++++---------
>  1 file changed, 82 insertions(+), 16 deletions(-)
>
> diff --git a/target-arm/helper.c b/target-arm/helper.c
> index 959a46e..c1c6303 100644
> --- a/target-arm/helper.c
> +++ b/target-arm/helper.c
> @@ -3296,22 +3296,62 @@ 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 (r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1]) {
> +        /* Register is banked (using both entries in array).
> +         * Overwriting fieldoffset as the array is only used to define
> +         * banked registers but later only fieldoffset is used.
>           */
> -        if (r2->cp == 0) {
> -            r2->cp = 15;
> +        r2->fieldoffset = r->bank_fieldoffsets[nsbit];
> +    }
> +
> +    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;

This bitmanipulation looks like leftover from when these were in 'state';
   r2->secure = secstate;
should be sufficient (and you might as well put this down below the
'r2->state = state' assignment, since it's harmless to do it for all
regdefs including 64 bit ones).

> +
> +        if (r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1]) {
> +            /* If the register is banked and 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.
> +             */

I'm not sure what this paragraph is trying to say. The AArch64 equivalent
of CONTEXTIDR(NS) is CONTEXTIDR_EL1. In v8 FCSEIDR is a constant RAZ/WI
register, so migration and reset aren't relevant anyway.

In any case, if we only have a couple of special case registers where
this bank handling doesn't work, I suggest that we should handle them
by having two separate reginfo structs for the S and NS versions,
rather than special casing a specific crn value here.

> +            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
> @@ -3460,10 +3500,14 @@ void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
>       */
>      if (!(r->type & (ARM_CP_SPECIAL|ARM_CP_CONST))) {
>          if (r->access & PL3_R) {
> -            assert(r->fieldoffset || r->readfn);
> +            assert((r->fieldoffset ||
> +                   (r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1])) ||
> +                   r->readfn);
>          }
>          if (r->access & PL3_W) {
> -            assert(r->fieldoffset || r->writefn);
> +            assert((r->fieldoffset ||
> +                   (r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1])) ||
> +                   r->writefn);
>          }
>      }
>      /* Bad type field probably means missing sentinel at end of reg list */
> @@ -3476,8 +3520,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) {

As a general remark, don't use this sort of "yoda conditional" with the
constant on the LHS of the ==, please.

> +                            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);
> +                        }

Given the change to make add_cpreg_to_hashtable() take an ARM_CP_SECSTATE*
constant that I suggested in the previous patch, you can simplify this to

    switch (r->secure) {
        case ARM_CP_SECSTATE_S:
        case ARM_CP_SECSTATE_NS:
            add_cpreg_to_hashtable(cpu, r, opaque, state, r->secure,
crm, opc1, opc2);
            break;
        default:
            add_cpreg_to_hashtable(cpu, r, opaque, state,
ARM_CP_SECSTATE_S, crm, opc1, opc2);
            add_cpreg_to_hashtable(cpu, r, opaque, state,
ARM_CP_SECSTATE_NS, crm, opc1, opc2);
            break;
    }


> +                    } 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

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v8 10/27] target-arm: add NSACR register
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 10/27] target-arm: add NSACR register Greg Bellows
@ 2014-10-31 13:24   ` Peter Maydell
  2014-10-31 21:09     ` Greg Bellows
  0 siblings, 1 reply; 81+ messages in thread
From: Peter Maydell @ 2014-10-31 13:24 UTC (permalink / raw)
  To: Greg Bellows
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler,
	Edgar E. Iglesias

On 30 October 2014 21:28, Greg Bellows <greg.bellows@linaro.org> wrote:
> 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>
>
> ---
>
> v7 -> v8
> - Update naming from c1_nsacr to nsacr to match other registers being changed.
> - Remove NSACR read/write functions
>
> v4 -> v5
> - Changed to use renamed arm_current_el()
> ---
>  target-arm/cpu.h    | 6 ++++++
>  target-arm/helper.c | 3 +++
>  2 files changed, 9 insertions(+)
>
> diff --git a/target-arm/cpu.h b/target-arm/cpu.h
> index 6bb7d39..88e22fb 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 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)

Not sure there's much point defining bit constants we don't use
(these don't match the v8 bits anyway).

> +
>  /* 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 e73756d..3c12eb3 100644
> --- a/target-arm/helper.c
> +++ b/target-arm/helper.c
> @@ -2344,6 +2344,9 @@ static const ARMCPRegInfo el3_cp_reginfo[] = {
>        .cp = 15, .crn = 1, .crm = 1, .opc1 = 0, .opc2 = 0,
>        .access = PL3_RW, .resetvalue = 0, .writefn = scr_write,
>        .fieldoffset = offsetoflow32(CPUARMState, cp15.scr_el3) },
> +    { .name = "NSACR", .cp = 15, .crn = 1, .crm = 1, .opc1 = 0, .opc2 = 2,
> +      .access = PL3_RW | PL1_R, .resetvalue = 0,
> +      .fieldoffset = offsetof(CPUARMState, cp15.nsacr) },

PL1_R implies PL3_R, so you can write the access value as
PL3_W | PL1_R.

It would be good to have a comment
   /* TODO: implement trapping of secure EL1 reads and writes to EL3. */

>      REGINFO_SENTINEL
>  };
>
> --
> 1.8.3.2

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

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v8 11/27] target-arm: add SDER definition
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 11/27] target-arm: add SDER definition Greg Bellows
@ 2014-10-31 13:30   ` Peter Maydell
  2014-10-31 21:17     ` Greg Bellows
  0 siblings, 1 reply; 81+ messages in thread
From: Peter Maydell @ 2014-10-31 13:30 UTC (permalink / raw)
  To: Greg Bellows
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler,
	Edgar E. Iglesias

On 30 October 2014 21:28, Greg Bellows <greg.bellows@linaro.org> wrote:
> From: Sergey Fedorov <s.fedorov@samsung.com>
>
> Added CP register defintions for SDER and SDER32_EL3 as well as cp15.sder for
> register storage.
>
> 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>
>
> ---
>
> v7 -> v8
> - Added SDER32_EL3 register definition
> - Changed sder name from c1_sder to sder
> - Changed sder from uint32_t to uint64_t.
> ---
>  target-arm/cpu.h    | 1 +
>  target-arm/helper.c | 8 ++++++++
>  2 files changed, 9 insertions(+)
>
> diff --git a/target-arm/cpu.h b/target-arm/cpu.h
> index 88e22fb..62cf48a 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.  */
> +        uint64_t sder; /* Secure debug enable register. */
>          uint32_t 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 3c12eb3..0be19f3 100644
> --- a/target-arm/helper.c
> +++ b/target-arm/helper.c
> @@ -2344,6 +2344,14 @@ static const ARMCPRegInfo el3_cp_reginfo[] = {
>        .cp = 15, .crn = 1, .crm = 1, .opc1 = 0, .opc2 = 0,
>        .access = PL3_RW, .resetvalue = 0, .writefn = scr_write,
>        .fieldoffset = offsetoflow32(CPUARMState, cp15.scr_el3) },
> +    { .name = "SDER32_EL3", .state = ARM_CP_STATE_AA64,
> +      .opc0 = 3, .opc1 = 6, .crn = 1, .crm = 1, .opc2 = 1,
> +      .access = PL3_RW, .resetvalue = 0,
> +      .fieldoffset = offsetof(CPUARMState, cp15.sder) },
> +    { .name = "SDER",
> +      .cp = 15, .crn = 1, .crm = 1, .opc1 = 0, .opc2 = 1,

Can you keep the ordering in reginfo fields to
 .cp [if needed], .opc0 [if needed], .opc1, .crn, .crm, .opc2
please? I know we have some existing reginfo structs which don't
follow that, but for new ones we're trying to follow the ordering
used in the v8 ARM ARM (which in turn matches the order used
in MRC/MCR instructions).

> +      .access = PL3_RW, .resetvalue = 0,
> +      .fieldoffset = offsetoflow32(CPUARMState, cp15.sder) },
>      { .name = "NSACR", .cp = 15, .crn = 1, .crm = 1, .opc1 = 0, .opc2 = 2,
>        .access = PL3_RW | PL1_R, .resetvalue = 0,
>        .fieldoffset = offsetof(CPUARMState, cp15.nsacr) },
> --
> 1.8.3.2
>

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

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v8 12/27] target-arm: add MVBAR support
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 12/27] target-arm: add MVBAR support Greg Bellows
@ 2014-10-31 13:35   ` Peter Maydell
  2014-10-31 21:19     ` Greg Bellows
  0 siblings, 1 reply; 81+ messages in thread
From: Peter Maydell @ 2014-10-31 13:35 UTC (permalink / raw)
  To: Greg Bellows
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler,
	Edgar E. Iglesias

On 30 October 2014 21:28, Greg Bellows <greg.bellows@linaro.org> wrote:
> 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>

If you put the cp/opc fields in the right order, then
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

(I shan't mention field ordering again but you can assume
it applies to all the other patches in this series too.)

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v8 13/27] target-arm: add SCTLR_EL3 and make SCTLR banked
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 13/27] target-arm: add SCTLR_EL3 and make SCTLR banked Greg Bellows
@ 2014-10-31 14:07   ` Peter Maydell
  2014-10-31 21:51     ` Greg Bellows
  0 siblings, 1 reply; 81+ messages in thread
From: Peter Maydell @ 2014-10-31 14:07 UTC (permalink / raw)
  To: Greg Bellows
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler,
	Edgar E. Iglesias

On 30 October 2014 21:28, Greg Bellows <greg.bellows@linaro.org> wrote:
> 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>

> diff --git a/target-arm/cpu.c b/target-arm/cpu.c
> index e0b82a6..18f4726 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 DC ZVA, CTL_EL0 and the cache ops */
> -        env->cp15.c1_sys |= SCTLR_UCT | SCTLR_UCI | SCTLR_DZE;
> +        env->cp15.sctlr_el[1] |= SCTLR_UCT | SCTLR_UCI | SCTLR_DZE;
>          /* 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;

Why has this condition had an "if not v8" added to it? The v8
spec doesn't drop support for hivecs as far as I can tell...

Patch looks good otherwise.

-- PMM

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

* Re: [Qemu-devel] [PATCH v8 02/27] target-arm: add async excp target_el function
  2014-10-31 11:56   ` Peter Maydell
@ 2014-10-31 14:14     ` Greg Bellows
  0 siblings, 0 replies; 81+ messages in thread
From: Greg Bellows @ 2014-10-31 14:14 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler,
	Edgar E. Iglesias

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

Thanks for the comments, responses inline.

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

> On 30 October 2014 21:28, Greg Bellows <greg.bellows@linaro.org> wrote:
> > Adds a dedicated function and a lookup table for determining the target
> > exception level of IRQ and FIQ exceptions.  The lookup table is taken
> from the
> > ARMv7 and ARMv8 specification exception routing tables.
> >
> > Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
> >
> > ---
> >
> > v7 -> v8
> > - Added target EL lookup table
> > - Rework arm_phys_excp_target_el to use an EL lookup table rather than
> >   conditionals.
> >
> > 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.
> > ---
> >  target-arm/helper.c | 111
> ++++++++++++++++++++++++++++++++++++++++++----------
> >  1 file changed, 91 insertions(+), 20 deletions(-)
> >
> > diff --git a/target-arm/helper.c b/target-arm/helper.c
> > index c47487a..e610466 100644
> > --- a/target-arm/helper.c
> > +++ b/target-arm/helper.c
> > @@ -3761,6 +3761,94 @@ void switch_mode(CPUARMState *env, int mode)
> >      env->spsr = env->banked_spsr[i];
> >  }
> >
> > +/* Physical Interrupt Target EL Lookup Table
> > + *
> > + * [ From ARM ARM section G1.13.4 (Table G1-15) ]
> > + *
> > + * 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.
> > + *
> > + *    Dimensions:
> > + *    target_el_table[2][2][2][2][2][4]
> > + *                    |  |  |  |  |  +--- Current EL
> > + *                    |  |  |  |  +------ Non-secure(0)/Secure(1)
> > + *                    |  |  |  +--------- HCR mask override
> > + *                    |  |  +------------ SCR exec state control
> > + *                    |  +--------------- SCR mask override
> > + *                    +------------------ 32-bit(0)/64-bit(1) EL3
> > + *
> > + *    The table values are as such:
> > + *    0-3 = EL0-EL3
> > + *     -1 = Cannot occur
> > + *
> > + * In the case of exceptions not being taken, EL1 is returned.  These
> cases
> > + * will be caught by the checks for target being >= current.
>
> This could use rephrasing to make it clearer why returning 1 is ok:
>
> "The ARM ARM tables include some entries indicating 'exception not taken'.
> These are for the cases where we are currently at EL3 and the
> exception is not routed to EL3 by the SCR, or where we are currently
> at EL2 and the exception is not routed to EL3 or EL2. We can therefore
> put '1' in those entries in our array, and rely on the check for
> "target EL >= current EL" in the caller to ensure that the exception
> is not taken."
>
>
Added to v9.


> > + *
> > + *            SCR     HCR
> > + *         64  EA     AMO                 From
> > + *        BIT IRQ     IMO      Non-secure         Secure
> > + *        EL3 FIQ  RW FMO   EL0 EL1 EL2 EL3   EL0 EL1 EL2 EL3
> > + */
> > +const int8_t target_el_table[2][2][2][2][2][4] = {
> > +    {{{{/* 0   0   0   0 */{ 1,  1,  2, -1 },{ 3,  3, -1,  3 },},
> > +       {/* 0   0   0   1 */{ 2,  2,  2, -1 },{ 3,  3, -1,  3 },},},
> > +      {{/* 0   0   1   0 */{ 1,  1,  2, -1 },{ 3,  3, -1,  3 },},
> > +       {/* 0   0   1   1 */{ 2,  2,  2, -1 },{ 3,  3, -1,  3 },},},},
> > +     {{{/* 0   1   0   0 */{ 3,  3,  3, -1 },{ 3,  3, -1,  3 },},
> > +       {/* 0   1   0   1 */{ 3,  3,  3, -1 },{ 3,  3, -1,  3 },},},
> > +      {{/* 0   1   1   0 */{ 3,  3,  3, -1 },{ 3,  3, -1,  3 },},
> > +       {/* 0   1   1   1 */{ 3,  3,  3, -1 },{ 3,  3, -1,  3 },},},},},
>
> Your entries for 32-bit EL3, exception from Secure EL1 should all
> read "-1", not "3" -- it's not possible to have current_el be 1
> in this case (this is why table G1-15 has a "-" in those entries).
>
>
Hmmm... I copied directly from the table and remember having two columns of
-1, so I'm not sure where the 3s came from, but you are right.  Fixed in v9.


> > +    {{{{/* 1   0   0   0 */{ 1,  1,  2, -1 },{ 1,  1, -1,  1 },},
> > +       {/* 1   0   0   1 */{ 2,  2,  2, -1 },{ 1,  1, -1,  1 },},},
> > +      {{/* 1   0   1   0 */{ 1,  1,  1, -1 },{ 1,  1, -1,  1 },},
> > +       {/* 1   0   1   1 */{ 2,  2,  2, -1 },{ 1,  1, -1,  1 },},},},
> > +     {{{/* 1   1   0   0 */{ 3,  3,  3, -1 },{ 3,  3, -1,  3 },},
> > +       {/* 1   1   0   1 */{ 3,  3,  3, -1 },{ 3,  3, -1,  3 },},},
> > +      {{/* 1   1   1   0 */{ 3,  3,  3, -1 },{ 3,  3, -1,  3 },},
> > +       {/* 1   1   1   1 */{ 3,  3,  3, -1 },{ 3,  3, -1,  3 },},},},},
> > +};
> > +
> > +/*
> > + * 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 rw = ((env->cp15.scr_el3 & SCR_RW) == SCR_RW);
> > +    uint32_t scr;
> > +    uint32_t hcr;
> > +    uint32_t target_el;
> > +    uint32_t is64 = arm_el_is_aa64(env, 3);
>
> You can just make these all "int".
>

Fixed in v9.


>
> > +
> > +    switch (excp_idx) {
> > +    case EXCP_IRQ:
> > +        scr = ((env->cp15.scr_el3 & SCR_IRQ) == SCR_IRQ);
> > +        hcr = ((env->cp15.hcr_el2 & HCR_IMO) == HCR_IMO);
> > +        break;
> > +    case EXCP_FIQ:
> > +        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;
> > +    };
> > +
> > +    /* If HCR.TGE is set then HCR is treated as being 1 */
> > +    hcr |= ((env->cp15.hcr_el2 & HCR_TGE) == HCR_TGE);
> > +
> > +    /* Perform a table-lookup for the target EL given the current state
> */
> > +    target_el = target_el_table[is64][scr][rw][hcr][secure][cur_el];
> > +
> > +    assert(target_el > 0);
> > +
> > +    return target_el;
> > +}
> > +
> >  /*
> >   * Determine the target EL for a given exception type.
> >   */
> > @@ -3769,14 +3857,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;
>
> Do you actually need to initialize this?
>

I think this was leftover from before, not needed now.  Fixed in v9.


>
> > +    bool secure = arm_is_secure(env);
> >
> >      switch (excp_idx) {
> >      case EXCP_HVC:
> > @@ -3788,19 +3870,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
> >
>
> Thanks for adding the table-driven code: I found this much easier
> to review against the ARM ARM. If you make those minor changes I
> mention above then you can add my reviewed-by tag.
>
> -- PMM
>

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

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

* Re: [Qemu-devel] [PATCH v8 14/27] target-arm: respect SCR.FW, SCR.AW and SCTLR.NMFI
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 14/27] target-arm: respect SCR.FW, SCR.AW and SCTLR.NMFI Greg Bellows
@ 2014-10-31 14:18   ` Peter Maydell
  2014-11-03 14:57     ` Greg Bellows
  0 siblings, 1 reply; 81+ messages in thread
From: Peter Maydell @ 2014-10-31 14:18 UTC (permalink / raw)
  To: Greg Bellows
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler,
	Edgar E. Iglesias

On 30 October 2014 21:28, Greg Bellows <greg.bellows@linaro.org> wrote:
> From: Fabian Aggeler <aggelerf@ethz.ch>
>
> bits when modifying CPSR.

I prefer it if we don't continue sentences from the subject
line into the main commit message body like this, it makes
them rather odd to read.

>
> Signed-off-by: Fabian Aggeler <aggelerf@ethz.ch>
> Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
>
> ---
>
> v7 -> v8
> - Fixed incorrect use of env->uncached_cpsr A/I/F to use env->daif instead.
> - Removed incorrect statement about SPSR to CPSR copies being affected by
>   SCR.AW/FW.
> - Fix typo in comment.
> - Simpified cpsr_write logic
>
> 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.
> ---
>  target-arm/helper.c | 47 ++++++++++++++++++++++++++++++++++++++++++++---
>  1 file changed, 44 insertions(+), 3 deletions(-)
>
> diff --git a/target-arm/helper.c b/target-arm/helper.c
> index 466459b..03e6b62 100644
> --- a/target-arm/helper.c
> +++ b/target-arm/helper.c
> @@ -3666,9 +3666,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.
> @@ -3680,6 +3677,50 @@ void cpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
>              switch_mode(env, val & CPSR_M);
>          }
>      }
> +

You've put this code hunk below the section of this function
which updates the mode bits in the CPU state. That means we'll
do the arm_is_secure() and BANKED_CURRENT_REG_GET below as
if from the mode we're going to, not the mode we started out in.
This is wrong -- compare the CPSRWriteByInstr pseudocode function,
which updates the mode field as the last thing it does.

> +    /* In a V7 implementation that includes 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.
> +     */
> +    if (!arm_feature(env, ARM_FEATURE_V8) &&
> +        arm_feature(env, ARM_FEATURE_EL3) &&
> +        !arm_feature(env, ARM_FEATURE_EL2) &&
> +        !arm_is_secure(env)) {
> +        if (!(env->cp15.scr_el3 & SCR_AW)) {
> +            qemu_log_mask(LOG_GUEST_ERROR,
> +                          "Ignoring attempt to switch CPSR_A flag from "
> +                          "non-secure world with SCR.AW bit clear\n");

This logging is now incorrect, because it will trigger even if the
guest wasn't attempting to change the value of CPSR.A. You could
either just drop the logging or alternatively only log
if ((env->daif ^ val) & mask & CPSR_A)
I guess.

> +            mask &= ~CPSR_A;
> +        }
> +
> +        if (!(env->cp15.scr_el3 & SCR_FW)) {
> +            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

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v8 15/27] target-arm: make CSSELR banked
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 15/27] target-arm: make CSSELR banked Greg Bellows
@ 2014-10-31 14:23   ` Peter Maydell
  0 siblings, 0 replies; 81+ messages in thread
From: Peter Maydell @ 2014-10-31 14:23 UTC (permalink / raw)
  To: Greg Bellows
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler,
	Edgar E. Iglesias

On 30 October 2014 21:28, Greg Bellows <greg.bellows@linaro.org> wrote:
> 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>

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

assuming you make the obvious update now the ARM_CP_SECSTATE_TEST
macro has been removed.

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v8 16/27] target-arm: add TTBR0_EL3 and make TTBR0/1 banked
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 16/27] target-arm: add TTBR0_EL3 and make TTBR0/1 banked Greg Bellows
@ 2014-10-31 15:04   ` Peter Maydell
  2014-11-04 22:44     ` Greg Bellows
  0 siblings, 1 reply; 81+ messages in thread
From: Peter Maydell @ 2014-10-31 15:04 UTC (permalink / raw)
  To: Greg Bellows
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler,
	Edgar E. Iglesias

On 30 October 2014 21:28, Greg Bellows <greg.bellows@linaro.org> wrote:
> From: Fabian Aggeler <aggelerf@ethz.ch>
>
> Add TTBR0 and maps secure/non-secure instance of ttbr0 and ttbr1

Is "maps" a typo for something, or have we lost a word here?

> 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#
> ---
>  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 11d51af..641b148 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.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 */
> @@ -2047,7 +2047,7 @@ PXA2xxState *pxa270_init(MemoryRegion *address_space,
>      }
>      if (!revision)
>          revision = "pxa270";
> -
> +

Stray whitespace change.

>      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 3b776a1..fe96869 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.  */
>          uint64_t sder; /* Secure debug enable register. */
>          uint32_t 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 f6a9b66..598f0d1 100644
> --- a/target-arm/helper.c
> +++ b/target-arm/helper.c
> @@ -1645,14 +1645,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,

You seem to have lost the .opc0 setting; surely this breaks AArch64?
Also you don't need to specify .cp = 15 explicitly for a STATE_BOTH
register. This whole hunk should just be changing the .fieldoffset
spec to .bank_fieldoffsets, really.

> +      .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,
> @@ -1883,11 +1885,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
>  };
> @@ -2341,6 +2345,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]) },

...isn't this migrated twice (since ttbr0_el[3] is in a
union with ttbr0_s)? In any case, see my comment below.

>      { .name = "ELR_EL3", .state = ARM_CP_STATE_AA64,
>        .type = ARM_CP_NO_MIGRATE,
>        .opc0 = 3, .opc1 = 6, .crn = 4, .crm = 0, .opc2 = 1,
> @@ -4422,18 +4430,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;
> @@ -4687,6 +4700,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;
> @@ -4738,7 +4752,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;
>
> @@ -4750,7 +4776,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;

This logic isn't actually sufficient to handle AArch64 EL3:
there is no TTBR1_EL3, and so the code that sets ttbr_select
also needs to change to not try to select TTBR1 if we're
not in EL0/EL1. We're also missing EL2 support (or at
least an assertion that the EL isn't 2.)

What I suggest is that you take most of these changes,
plus the definition of TTBR0_EL3, out of this patch and
put them in a separate patch. (So just leave both halves
of this if() with using BANKED_CURRENT_REG_GET, so that
AArch32 TZ works ok and AArch64 with just EL0/EL1 still
works.) Then put that patch at the end of your stack
of patches and don't actually send it out as part of this
series. Basically, put it on the shelf til we've got
through this lot and we can come back and address the
required code changes to support AArch64 EL3 in the
VA-to-PA translation as a set of self-standing patches.

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v8 17/27] target-arm: add TCR_EL3 and make TTBCR banked
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 17/27] target-arm: add TCR_EL3 and make TTBCR banked Greg Bellows
@ 2014-10-31 15:07   ` Peter Maydell
  2014-11-04 22:45     ` Greg Bellows
  0 siblings, 1 reply; 81+ messages in thread
From: Peter Maydell @ 2014-10-31 15:07 UTC (permalink / raw)
  To: Greg Bellows
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler,
	Edgar E. Iglesias

On 30 October 2014 21:28, Greg Bellows <greg.bellows@linaro.org> wrote:
> 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.
> ---
>  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 fe96869..f125bdd 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 598f0d1..896b40d 100644
> --- a/target-arm/helper.c
> +++ b/target-arm/helper.c
> @@ -1659,11 +1659,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,
> @@ -2349,6 +2350,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,
> @@ -4435,13 +4441,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;
>          }
> @@ -4701,13 +4707,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);
> +    }

Again, I would pull out the TCR_EL3 definition and attempts
at handling the 64 bit EL3 into their own patch and stick
them on the shelf for later.

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v8 18/27] target-arm: make c2_mask and c2_base_mask banked
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 18/27] target-arm: make c2_mask and c2_base_mask banked Greg Bellows
@ 2014-10-31 15:26   ` Peter Maydell
  2014-11-04 22:46     ` Greg Bellows
  0 siblings, 1 reply; 81+ messages in thread
From: Peter Maydell @ 2014-10-31 15:26 UTC (permalink / raw)
  To: Greg Bellows
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler,
	Edgar E. Iglesias

On 30 October 2014 21:28, Greg Bellows <greg.bellows@linaro.org> wrote:
> 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.

These fields are part of our TTBCR internal representation; we
should bank the whole TTBCR in one patch, not split over two.

> 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.
> ---
>  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 f125bdd..6e9f1c3 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;
> +        };

I think we should actually have:
    typedef struct {
        uint64_t raw_ttbcr;
        uint32_t mask;
        uint32_t base_mask;
    } TTBCR;

    and then have TTBCR ttbcr[2];

and not use the BANKED_REG_SET/GET macros here...

>          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 896b40d..27eaf9c 100644
> --- a/target-arm/helper.c
> +++ b/target-arm/helper.c
> @@ -1584,8 +1584,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));

... so this turns into:

    TTBCR t = env->cp15.ttbcr[ri->secure];

    t->raw_ttbcr = value;
    t->mask = ~(((uint32_t)0xffffffffu) >> maskshift);
    t->base_mask = ~((uint32_t)0x3fffu >> maskshift);

(XXX did we make ri->secure be a 0/1 or is it 1/2 ? anyway you get the idea.)

>  }
>
>  static void vmsa_ttbcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
> @@ -1604,9 +1610,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;

Similarly this will be much cleaner.

>  }
>
>  static void vmsa_tcr_el1_write(CPUARMState *env, const ARMCPRegInfo *ri,
> @@ -4440,7 +4452,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;
> @@ -4452,7 +4464,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);
>      }

and again here you can get a pointer to the correct TTBCR
struct and just reference it.

>      *table |= (address >> 18) & 0x3ffc;
>      return true;
> --

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v8 19/27] target-arm: make DACR banked
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 19/27] target-arm: make DACR banked Greg Bellows
@ 2014-10-31 15:38   ` Peter Maydell
  2014-11-03 21:23     ` Greg Bellows
  0 siblings, 1 reply; 81+ messages in thread
From: Peter Maydell @ 2014-10-31 15:38 UTC (permalink / raw)
  To: Greg Bellows
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler,
	Edgar E. Iglesias

On 30 October 2014 21:28, Greg Bellows <greg.bellows@linaro.org> wrote:
> 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 641b148..ac13d0b 100644
> --- a/hw/arm/pxa2xx.c
> +++ b/hw/arm/pxa2xx.c
> @@ -276,7 +276,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 6e9f1c3..6d39af1 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;
> +            };

If we're going to define a dacr32_el2 field here we should
actually implement the reginfo for it (it just has to be a
simple reads-as-written PL2_RW register). It's also going to
have to be uint64_t, which means the dacr_ns/dacr_s fields
also should be 64 bit.

Someday we should split out the MPU use of this encoding
properly into its own field because it isn't anything to
do with the DACR. I guess not today, though.

-- PMM

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

* Re: [Qemu-devel] [PATCH v8 20/27] target-arm: make IFSR banked
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 20/27] target-arm: make IFSR banked Greg Bellows
@ 2014-10-31 16:18   ` Peter Maydell
  2014-11-05 22:19     ` Greg Bellows
  0 siblings, 1 reply; 81+ messages in thread
From: Peter Maydell @ 2014-10-31 16:18 UTC (permalink / raw)
  To: Greg Bellows
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler,
	Edgar E. Iglesias

On 30 October 2014 21:28, Greg Bellows <greg.bellows@linaro.org> wrote:
> 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 6d39af1..c44649e 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;
> +            };
> +        };

Again, if we have the struct field we should have the reginfo.

>          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 eaae534..de355f5 100644
> --- a/target-arm/helper.c
> +++ b/target-arm/helper.c
> @@ -1653,8 +1653,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,
> @@ -4297,11 +4298,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;

This will work OK for now; if we want to implement SCR.EA to
allow routing of external aborts to Monitor mode we're going
to have to come up with something cleverer, because that
affects whether we want to write to the secure or nonsecure
copy of the IFSR/IFAR. But at the moment you can only get
a prefetch abort or data abort to the Secure world if you
were already in the Secure world.

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v8 21/27] target-arm: make DFSR banked
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 21/27] target-arm: make DFSR banked Greg Bellows
@ 2014-10-31 16:19   ` Peter Maydell
  0 siblings, 0 replies; 81+ messages in thread
From: Peter Maydell @ 2014-10-31 16:19 UTC (permalink / raw)
  To: Greg Bellows
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler,
	Edgar E. Iglesias

On 30 October 2014 21:28, Greg Bellows <greg.bellows@linaro.org> wrote:
> 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>

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

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v8 06/27] target-arm: add secure state bit to CPREG hash
  2014-10-31 12:31     ` Peter Maydell
@ 2014-10-31 16:20       ` Greg Bellows
  0 siblings, 0 replies; 81+ messages in thread
From: Greg Bellows @ 2014-10-31 16:20 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler,
	Edgar E. Iglesias

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

Fixed in v9.

On 31 October 2014 07:31, Peter Maydell <peter.maydell@linaro.org> wrote:

> On 31 October 2014 12:28, Peter Maydell <peter.maydell@linaro.org> wrote:
> > On 30 October 2014 21:28, Greg Bellows <greg.bellows@linaro.org> wrote:
>
> >>  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)
> >
> > Again, I think I'd rather we put 'nsbit' after 'state' rather than at
> the end.
> > Also you probably want 'bool ns' rather than 'int nsbit'.
>
> ...actually, what you want here is "int secstate" and pass in either
> ARM_CP_SECSTATE_S or ARM_CP_SECSTATE_NS. (This matches the way the
> 'state' parameter takes one of the ARM_CP_STATE_* values.)
>
> -- PMM
>

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

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

* Re: [Qemu-devel] [PATCH v8 22/27] target-arm: make IFAR/DFAR banked
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 22/27] target-arm: make IFAR/DFAR banked Greg Bellows
@ 2014-10-31 16:24   ` Peter Maydell
  2014-11-03 22:59     ` Greg Bellows
  0 siblings, 1 reply; 81+ messages in thread
From: Peter Maydell @ 2014-10-31 16:24 UTC (permalink / raw)
  To: Greg Bellows
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler,
	Edgar E. Iglesias

On 30 October 2014 21:28, Greg Bellows <greg.bellows@linaro.org> wrote:
> 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
> ---
>  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 18f4726..a711834 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 29bf273..10985d4 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

This is pretty ugly but I guess I can live with it.

> +                uint64_t _unused_far3;;

Stray extra semicolon.

> +            };
> +            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 c5948f7..c4d0db4 100644
> --- a/target-arm/helper.c
> +++ b/target-arm/helper.c
> @@ -554,7 +554,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.
> @@ -1681,11 +1682,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]) },

This change just seems to be rearranging the fields for no particular reason?

>      REGINFO_SENTINEL
>  };
>
> @@ -4300,8 +4304,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;
> @@ -4311,8 +4314,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);

Otherwise has my reviewed-by.

-- PMM

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

* Re: [Qemu-devel] [PATCH v8 03/27] target-arm: add banked register accessors
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 03/27] target-arm: add banked register accessors Greg Bellows
@ 2014-10-31 16:50   ` Peter Maydell
  0 siblings, 0 replies; 81+ messages in thread
From: Peter Maydell @ 2014-10-31 16:50 UTC (permalink / raw)
  To: Greg Bellows
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler,
	Edgar E. Iglesias

On 30 October 2014 21:28, 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>
> Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
>
> ---
>
> v7 -> v8
> - Move use_secure_reg() function to the TBFLAG patch.
>
> 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.
> ---
>  target-arm/cpu.h | 27 +++++++++++++++++++++++++++
>  1 file changed, 27 insertions(+)
>
> diff --git a/target-arm/cpu.h b/target-arm/cpu.h
> index be5d022..5117d4d 100644
> --- a/target-arm/cpu.h
> +++ b/target-arm/cpu.h
> @@ -817,6 +817,33 @@ static inline bool arm_el_is_aa64(CPUARMState *env, int el)
>      return arm_feature(env, ARM_FEATURE_AARCH64);
>  }
>
> +/* 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)

It's just occurred to me that this probably needs to be doing
a deposit32(), because where an AArch32 register is architecturally
mapped to an AArch64 register then only the appropriate 32 bits
of the AArch64 reg get modified by setting the 32 bit value.

> +/* 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);

-- PMM

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

* Re: [Qemu-devel] [PATCH v8 23/27] target-arm: make PAR banked
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 23/27] target-arm: make PAR banked Greg Bellows
@ 2014-10-31 17:21   ` Peter Maydell
  2014-11-03 22:58     ` Greg Bellows
  0 siblings, 1 reply; 81+ messages in thread
From: Peter Maydell @ 2014-10-31 17:21 UTC (permalink / raw)
  To: Greg Bellows
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler,
	Edgar E. Iglesias

On 30 October 2014 21:28, Greg Bellows <greg.bellows@linaro.org> wrote:
> 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
>
> v3 -> v4
> - Fix par union/structure definition
> ---
>  target-arm/cpu.h    | 10 +++++++++-
>  target-arm/helper.c | 25 ++++++++++++++-----------
>  2 files changed, 23 insertions(+), 12 deletions(-)
>
> diff --git a/target-arm/cpu.h b/target-arm/cpu.h
> index 10985d4..3c6ff4a 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 */
> diff --git a/target-arm/helper.c b/target-arm/helper.c
> index c4d0db4..ec957fb 100644
> --- a/target-arm/helper.c
> +++ b/target-arm/helper.c
> @@ -1419,7 +1419,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).
> @@ -1429,14 +1429,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);
>          }

Pull the "uint64_t par64" out to the top level of this function, and
set it in all the branches of the if() that currently set cp15.par_el1,
and then just use the big fat A32_BANKED_CURRENT_REG_SET macro once.

>      }
>  }
> @@ -1444,9 +1446,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) } },

Why move the .writefn setting around?

>  #ifndef CONFIG_USER_ONLY
>      { .name = "ATS", .cp = 15, .crn = 7, .crm = 8, .opc1 = 0, .opc2 = CP_ANY,
>        .access = PL1_W, .accessfn = ats_access,
> @@ -1902,8 +1904,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),
> --
> 1.8.3.2

Looks OK otherwise.

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v8 24/27] target-arm: make VBAR banked
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 24/27] target-arm: make VBAR banked Greg Bellows
@ 2014-10-31 17:22   ` Peter Maydell
  2014-11-03 22:06     ` Greg Bellows
  0 siblings, 1 reply; 81+ messages in thread
From: Peter Maydell @ 2014-10-31 17:22 UTC (permalink / raw)
  To: Greg Bellows
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler,
	Edgar E. Iglesias

On 30 October 2014 21:28, Greg Bellows <greg.bellows@linaro.org> wrote:
> When EL3 is running in Aarch32 (or ARMv7 with Security Extensions)
> VBAR has a secure and a non-secure instance, which are mapped to
> VBAR_EL1 and VBAR_EL3.
>
> 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 vbar union/structure definition
> - Revert back to array-based vbar definition combined with v7 naming
> ---
>  target-arm/cpu.h    | 10 +++++++++-
>  target-arm/helper.c |  8 ++++----
>  2 files changed, 13 insertions(+), 5 deletions(-)
>
> diff --git a/target-arm/cpu.h b/target-arm/cpu.h
> index 3c6ff4a..e0954c7 100644
> --- a/target-arm/cpu.h
> +++ b/target-arm/cpu.h
> @@ -306,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];
> +        };
>          uint32_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 ec957fb..fb040d4 100644
> --- a/target-arm/helper.c
> +++ b/target-arm/helper.c
> @@ -905,9 +905,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) } },

This is unnecessarily moving the .resetvalue setting around again.
Otherwise
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v8 25/27] target-arm: make c13 cp regs banked (FCSEIDR, ...)
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 25/27] target-arm: make c13 cp regs banked (FCSEIDR, ...) Greg Bellows
@ 2014-10-31 17:27   ` Peter Maydell
  2014-11-03 22:57     ` Greg Bellows
  0 siblings, 1 reply; 81+ messages in thread
From: Peter Maydell @ 2014-10-31 17:27 UTC (permalink / raw)
  To: Greg Bellows
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler,
	Edgar E. Iglesias

On 30 October 2014 21:28, Greg Bellows <greg.bellows@linaro.org> wrote:
> 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
> ---
>  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) {

Stray whitespace change.

> @@ -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;

??? whitespace changes I guess? This patch shouldn't be touching
CRIS specific code... There's a bunch more whitespace changes
below too, please get rid of them all.

> @@ -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 e0954c7..348ce73 100644
> --- a/target-arm/cpu.h
> +++ b/target-arm/cpu.h
> @@ -316,11 +316,36 @@ typedef struct CPUARMState {
>              uint64_t vbar_el[4];
>          };
>          uint32_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 of three uint64_t fields with an array with only 2
entries? That looks fishy.

> +        };
> +        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];

A one-element array??

> +        };
>          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 fb040d4..d782897 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,

Lost .opc3 again, and you don't need to specify .cp = 15 for a BOTH entry.

>        .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
>  };
> @@ -1025,23 +1028,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) } },

This diff is hard to read because you've moved .resetvalue around in the
struct, so the changed lines are more than have actually changed semantically.

> +    { .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
>  };
>
> @@ -5045,7 +5052,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);

Add braces while you're changing this line.

>      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

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v8 26/27] target-arm: make MAIR0/1 banked
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 26/27] target-arm: make MAIR0/1 banked Greg Bellows
@ 2014-10-31 17:31   ` Peter Maydell
  2014-11-03 23:00     ` Greg Bellows
  0 siblings, 1 reply; 81+ messages in thread
From: Peter Maydell @ 2014-10-31 17:31 UTC (permalink / raw)
  To: Greg Bellows
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler,
	Edgar E. Iglesias

On 30 October 2014 21:28, Greg Bellows <greg.bellows@linaro.org> wrote:
> 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
> ---
>  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 348ce73..1a76fc6 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;

Surely these need the big-endian ifdefs too if we're unioning
uint32_ts with a uint64_t array?

(Can you check the other patches for this too, please? I might
have missed it when reviewing some of them, but a quick scan through
the cpu.h file in your tree ought to catch any other cases.)

> +            };
> +            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 d782897..fd5f074 100644
> --- a/target-arm/helper.c
> +++ b/target-arm/helper.c
> @@ -939,7 +939,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.
> @@ -948,11 +948,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
>

Otherwise you can add my reviewed-by tag.

-- PMM

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

* Re: [Qemu-devel] [PATCH v8 01/27] target-arm: extend async excp masking
  2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 01/27] target-arm: extend async excp masking Greg Bellows
@ 2014-10-31 19:00   ` Peter Maydell
  2014-11-05 21:12     ` Greg Bellows
  0 siblings, 1 reply; 81+ messages in thread
From: Peter Maydell @ 2014-10-31 19:00 UTC (permalink / raw)
  To: Greg Bellows
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler,
	Edgar E. Iglesias

On 30 October 2014 21:28, Greg Bellows <greg.bellows@linaro.org> wrote:
> This patch extends arm_excp_unmasked() to use lookup tables for determining
> whether IRQ and FIQ exceptions are masked.  The lookup tables are based on the
> ARMv8 and ARMv7 specification physical interrupt masking tables.
>
> 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: Greg Bellows <greg.bellows@linaro.org>
>
> ---
>
> v7 -> v8
> - Add IRQ and FIQ exeception masking lookup tables.
> - Rewrite patch to use lookup tables for determining whether an excpetion is
>   masked or not.
>
> v5 -> v6
> - Globally change Aarch# to AArch#
> - Fixed comment termination
>
> v4 -> v5
> - Merge with v4 patch 10
> ---
>  target-arm/cpu.h | 218 ++++++++++++++++++++++++++++++++++++++++++++++++-------
>  1 file changed, 190 insertions(+), 28 deletions(-)

Having got through the rest of the series I'm coming back
to this one, which I skipped because it needed checking
against the ARM ARM.

I definitely don't like the use of tables here -- it is in almost
all of the cases simply repeating the routing calculations.
All you actually need here is:

    if (target_el < current_el) {
        /* Don't take exception */
        return false;
    }
    if (target_el > current_el && target_el != 1) {
        if (target_el == 3 && !arm_el_is_aa64(env, 3)) {
            /* In a 32 bit EL3 there are some awkward special cases where we
             * must honour the PSTATE/CPSR mask bits even when taking the
             * exception to EL3.
             */
            if (arm_is_secure(env)) {
                goto honour_masking;
            }
            /* (We know at this point that SCR.FIQ/IRQ must be set.) */
            if (excp_idx == EXCP_FIQ && HCR.FMO == 0 && SCR.FW == 1) {
                goto honour_masking;
            }
            /* If we supported SError then the async external abort routing
             * would have a similar case for SCR.AW here. There is no
SCR.IW for IRQs.
             */
            if (excp_idx == EXCP_IRQ && HCR.IMO == 0) {
                goto honour_masking;
            }
       }
       /* Take the exception unconditionally. */
       return true;
    }
honour_masking:
    /* If we get here then we check the PSTATE flags. */

(I think the 'gotos' here are clearer than turning the if statement inside out
to avoid them...)

> -    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;
> -    /* ARMv7-M interrupt return works by loading a magic value
> -     * into the PC.  On real hardware the load causes the
> -     * return to occur.  The qemu implementation performs the
> -     * jump normally, then does the exception return when the
> -     * CPU tries to execute code at the magic address.
> -     * This will cause the magic PC value to be pushed to
> -     * the stack if an interrupt occurred at the wrong time.
> -     * We avoid this by disabling interrupts when
> -     * pc contains a magic address.

You'll probably find it easier to base on top of the patches
I sent out that split out the M profile code from this
function (I'm planning to put those into target-arm.next soon
so they get in before hardfreeze).

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v8 07/27] target-arm: insert AArch32 cpregs twice into hashtable
  2014-10-31 12:44   ` Peter Maydell
@ 2014-10-31 19:01     ` Greg Bellows
  2014-11-04 22:20       ` Greg Bellows
  0 siblings, 1 reply; 81+ messages in thread
From: Greg Bellows @ 2014-10-31 19:01 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler,
	Edgar E. Iglesias

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

On 31 October 2014 07:44, Peter Maydell <peter.maydell@linaro.org> wrote:

> On 30 October 2014 21:28, Greg Bellows <greg.bellows@linaro.org> wrote:
> > 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>
> >
> > ---
> >
> > v7 -> v8
> > - Updated define registers asserts to allow either a non-zero
> fieldoffset or
> >   non-zero bank_fieldoffsets.
> > - Updated CP register hashing to always set the register fieldoffset when
> >   banked register offsets are specified.
> >
> > 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.
> > ---
> >  target-arm/helper.c | 98
> ++++++++++++++++++++++++++++++++++++++++++++---------
> >  1 file changed, 82 insertions(+), 16 deletions(-)
> >
> > diff --git a/target-arm/helper.c b/target-arm/helper.c
> > index 959a46e..c1c6303 100644
> > --- a/target-arm/helper.c
> > +++ b/target-arm/helper.c
> > @@ -3296,22 +3296,62 @@ 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 (r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1]) {
> > +        /* Register is banked (using both entries in array).
> > +         * Overwriting fieldoffset as the array is only used to define
> > +         * banked registers but later only fieldoffset is used.
> >           */
> > -        if (r2->cp == 0) {
> > -            r2->cp = 15;
> > +        r2->fieldoffset = r->bank_fieldoffsets[nsbit];
> > +    }
> > +
> > +    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;
>
> This bitmanipulation looks like leftover from when these were in 'state';
>    r2->secure = secstate;
> should be sufficient (and you might as well put this down below the
> 'r2->state = state' assignment, since it's harmless to do it for all
> regdefs including 64 bit ones).
>
>
It was in the previous code, but it is still necessary for marking whether
the given register is secure or not.


> > +
> > +        if (r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1]) {
> > +            /* If the register is banked and 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.
> > +             */
>
> I'm not sure what this paragraph is trying to say. The AArch64 equivalent
> of CONTEXTIDR(NS) is CONTEXTIDR_EL1. In v8 FCSEIDR is a constant RAZ/WI
> register, so migration and reset aren't relevant anyway.
>
> In any case, if we only have a couple of special case registers where
> this bank handling doesn't work, I suggest that we should handle them
> by having two separate reginfo structs for the S and NS versions,
> rather than special casing a specific crn value here.
>

It does not sound like the comment was clear.  The point of this code was
to disable migration and reset of one or both banks.  If we know there is
an aarch64 version (BOTH) then we know we can disable the ns bank
instance.  If we are ARMv8 then we know that we can also disable the sec
bank instance.  However, there was an exception in that neither CONTEXTIDR
nor FCSEIDR actually have an ARMv8/AArch64 secure counterparts, so we still
have to allow migration and reset even if ARMv8 is supported.

You are correct that FCSEIDR is RAZ/WI in ARMv8, which is the exact issue
as this is not the case in ARMv7.  I'll work through it to see if adding
separate entries alleviates the need for the ugly conditional.  BTW, I
didn't like this either, but at the time I hadn't found a more elegant
approach.


>
> > +            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
> > @@ -3460,10 +3500,14 @@ void define_one_arm_cp_reg_with_opaque(ARMCPU
> *cpu,
> >       */
> >      if (!(r->type & (ARM_CP_SPECIAL|ARM_CP_CONST))) {
> >          if (r->access & PL3_R) {
> > -            assert(r->fieldoffset || r->readfn);
> > +            assert((r->fieldoffset ||
> > +                   (r->bank_fieldoffsets[0] &&
> r->bank_fieldoffsets[1])) ||
> > +                   r->readfn);
> >          }
> >          if (r->access & PL3_W) {
> > -            assert(r->fieldoffset || r->writefn);
> > +            assert((r->fieldoffset ||
> > +                   (r->bank_fieldoffsets[0] &&
> r->bank_fieldoffsets[1])) ||
> > +                   r->writefn);
> >          }
> >      }
> >      /* Bad type field probably means missing sentinel at end of reg
> list */
> > @@ -3476,8 +3520,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) {
>
> As a general remark, don't use this sort of "yoda conditional" with the
> constant on the LHS of the ==, please.
>

Fixed in v9.


>
> > +                            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);
> > +                        }
>
> Given the change to make add_cpreg_to_hashtable() take an ARM_CP_SECSTATE*
> constant that I suggested in the previous patch, you can simplify this to
>
>     switch (r->secure) {
>         case ARM_CP_SECSTATE_S:
>         case ARM_CP_SECSTATE_NS:
>             add_cpreg_to_hashtable(cpu, r, opaque, state, r->secure,
> crm, opc1, opc2);
>             break;
>         default:
>             add_cpreg_to_hashtable(cpu, r, opaque, state,
> ARM_CP_SECSTATE_S, crm, opc1, opc2);
>             add_cpreg_to_hashtable(cpu, r, opaque, state,
> ARM_CP_SECSTATE_NS, crm, opc1, opc2);
>             break;
>     }
>

> > +                    } 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
>
> thanks
> -- PMM
>

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

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

* Re: [Qemu-devel] [PATCH v8 10/27] target-arm: add NSACR register
  2014-10-31 13:24   ` Peter Maydell
@ 2014-10-31 21:09     ` Greg Bellows
  0 siblings, 0 replies; 81+ messages in thread
From: Greg Bellows @ 2014-10-31 21:09 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler,
	Edgar E. Iglesias

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

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

> On 30 October 2014 21:28, Greg Bellows <greg.bellows@linaro.org> wrote:
> > 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>
> >
> > ---
> >
> > v7 -> v8
> > - Update naming from c1_nsacr to nsacr to match other registers being
> changed.
> > - Remove NSACR read/write functions
> >
> > v4 -> v5
> > - Changed to use renamed arm_current_el()
> > ---
> >  target-arm/cpu.h    | 6 ++++++
> >  target-arm/helper.c | 3 +++
> >  2 files changed, 9 insertions(+)
> >
> > diff --git a/target-arm/cpu.h b/target-arm/cpu.h
> > index 6bb7d39..88e22fb 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 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)
>
> Not sure there's much point defining bit constants we don't use
> (these don't match the v8 bits anyway).
>
>
Agree (was using them before).  Removed in v9.


> > +
> >  /* 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 e73756d..3c12eb3 100644
> > --- a/target-arm/helper.c
> > +++ b/target-arm/helper.c
> > @@ -2344,6 +2344,9 @@ static const ARMCPRegInfo el3_cp_reginfo[] = {
> >        .cp = 15, .crn = 1, .crm = 1, .opc1 = 0, .opc2 = 0,
> >        .access = PL3_RW, .resetvalue = 0, .writefn = scr_write,
> >        .fieldoffset = offsetoflow32(CPUARMState, cp15.scr_el3) },
> > +    { .name = "NSACR", .cp = 15, .crn = 1, .crm = 1, .opc1 = 0, .opc2 =
> 2,
> > +      .access = PL3_RW | PL1_R, .resetvalue = 0,
> > +      .fieldoffset = offsetof(CPUARMState, cp15.nsacr) },
>
> PL1_R implies PL3_R, so you can write the access value as
> PL3_W | PL1_R.
>
> Updated in v9.


> It would be good to have a comment
>    /* TODO: implement trapping of secure EL1 reads and writes to EL3. */
>
>
Added in v9.


> >      REGINFO_SENTINEL
> >  };
> >
> > --
> > 1.8.3.2
>
> Otherwise
> Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
>
> thanks
> -- PMM
>

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

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

* Re: [Qemu-devel] [PATCH v8 11/27] target-arm: add SDER definition
  2014-10-31 13:30   ` Peter Maydell
@ 2014-10-31 21:17     ` Greg Bellows
  0 siblings, 0 replies; 81+ messages in thread
From: Greg Bellows @ 2014-10-31 21:17 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler,
	Edgar E. Iglesias

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

On 31 October 2014 08:30, Peter Maydell <peter.maydell@linaro.org> wrote:

> On 30 October 2014 21:28, Greg Bellows <greg.bellows@linaro.org> wrote:
> > From: Sergey Fedorov <s.fedorov@samsung.com>
> >
> > Added CP register defintions for SDER and SDER32_EL3 as well as
> cp15.sder for
> > register storage.
> >
> > 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>
> >
> > ---
> >
> > v7 -> v8
> > - Added SDER32_EL3 register definition
> > - Changed sder name from c1_sder to sder
> > - Changed sder from uint32_t to uint64_t.
> > ---
> >  target-arm/cpu.h    | 1 +
> >  target-arm/helper.c | 8 ++++++++
> >  2 files changed, 9 insertions(+)
> >
> > diff --git a/target-arm/cpu.h b/target-arm/cpu.h
> > index 88e22fb..62cf48a 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.
> */
> > +        uint64_t sder; /* Secure debug enable register. */
> >          uint32_t 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 3c12eb3..0be19f3 100644
> > --- a/target-arm/helper.c
> > +++ b/target-arm/helper.c
> > @@ -2344,6 +2344,14 @@ static const ARMCPRegInfo el3_cp_reginfo[] = {
> >        .cp = 15, .crn = 1, .crm = 1, .opc1 = 0, .opc2 = 0,
> >        .access = PL3_RW, .resetvalue = 0, .writefn = scr_write,
> >        .fieldoffset = offsetoflow32(CPUARMState, cp15.scr_el3) },
> > +    { .name = "SDER32_EL3", .state = ARM_CP_STATE_AA64,
> > +      .opc0 = 3, .opc1 = 6, .crn = 1, .crm = 1, .opc2 = 1,
> > +      .access = PL3_RW, .resetvalue = 0,
> > +      .fieldoffset = offsetof(CPUARMState, cp15.sder) },
> > +    { .name = "SDER",
> > +      .cp = 15, .crn = 1, .crm = 1, .opc1 = 0, .opc2 = 1,
>
> Can you keep the ordering in reginfo fields to
>  .cp [if needed], .opc0 [if needed], .opc1, .crn, .crm, .opc2
> please? I know we have some existing reginfo structs which don't
> follow that, but for new ones we're trying to follow the ordering
> used in the v8 ARM ARM (which in turn matches the order used
> in MRC/MCR instructions).
>
>
:-) I inherited the misordered definition, should have fixed when I added
SDER32_EL3.  Fixed in v9.


> > +      .access = PL3_RW, .resetvalue = 0,
> > +      .fieldoffset = offsetoflow32(CPUARMState, cp15.sder) },
> >      { .name = "NSACR", .cp = 15, .crn = 1, .crm = 1, .opc1 = 0, .opc2 =
> 2,
> >        .access = PL3_RW | PL1_R, .resetvalue = 0,
> >        .fieldoffset = offsetof(CPUARMState, cp15.nsacr) },
> > --
> > 1.8.3.2
> >
>
> Otherwise
> Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
>
> thanks
> -- PMM
>

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

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

* Re: [Qemu-devel] [PATCH v8 12/27] target-arm: add MVBAR support
  2014-10-31 13:35   ` Peter Maydell
@ 2014-10-31 21:19     ` Greg Bellows
  0 siblings, 0 replies; 81+ messages in thread
From: Greg Bellows @ 2014-10-31 21:19 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler,
	Edgar E. Iglesias

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

Fixed in v9 as well as all other misordered instances added.

On 31 October 2014 08:35, Peter Maydell <peter.maydell@linaro.org> wrote:

> On 30 October 2014 21:28, Greg Bellows <greg.bellows@linaro.org> wrote:
> > 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>
>
> If you put the cp/opc fields in the right order, then
> Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
>
> (I shan't mention field ordering again but you can assume
> it applies to all the other patches in this series too.)
>
> thanks
> -- PMM
>

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

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

* Re: [Qemu-devel] [PATCH v8 13/27] target-arm: add SCTLR_EL3 and make SCTLR banked
  2014-10-31 14:07   ` Peter Maydell
@ 2014-10-31 21:51     ` Greg Bellows
  2014-10-31 23:26       ` Peter Maydell
  0 siblings, 1 reply; 81+ messages in thread
From: Greg Bellows @ 2014-10-31 21:51 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler,
	Edgar E. Iglesias

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

Not sure of the exact reasoning as I inherited the change.  However, when I
went through this code before I took it that the change was needed to
filter out the case where SCTLR may be either of the ARMv8 variants
(SCTLR_EL1 or SCTLR_EL3) as neither of them have a SCTLR_V bits.  In fact,
looking quickly through the ARMv8 ARM, I don't see any mention of hivec
support for AArch64.

I think the more appropriate check in this case is to check whether the
current EL is 32-bit instead of ARMv8.   Made this change in v9 along with
a comment.

I'll leave your review-by off until you okay this.

Greg


On 31 October 2014 09:07, Peter Maydell <peter.maydell@linaro.org> wrote:

> On 30 October 2014 21:28, Greg Bellows <greg.bellows@linaro.org> wrote:
> > 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>
>
> > diff --git a/target-arm/cpu.c b/target-arm/cpu.c
> > index e0b82a6..18f4726 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 DC ZVA, CTL_EL0 and the cache
> ops */
> > -        env->cp15.c1_sys |= SCTLR_UCT | SCTLR_UCI | SCTLR_DZE;
> > +        env->cp15.sctlr_el[1] |= SCTLR_UCT | SCTLR_UCI | SCTLR_DZE;
> >          /* 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;
>
> Why has this condition had an "if not v8" added to it? The v8
> spec doesn't drop support for hivecs as far as I can tell...
>
> Patch looks good otherwise.
>
> -- PMM
>

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

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

* Re: [Qemu-devel] [PATCH v8 13/27] target-arm: add SCTLR_EL3 and make SCTLR banked
  2014-10-31 21:51     ` Greg Bellows
@ 2014-10-31 23:26       ` Peter Maydell
  0 siblings, 0 replies; 81+ messages in thread
From: Peter Maydell @ 2014-10-31 23:26 UTC (permalink / raw)
  To: Greg Bellows
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler,
	Edgar E. Iglesias

On 31 October 2014 21:51, Greg Bellows <greg.bellows@linaro.org> wrote:
> Not sure of the exact reasoning as I inherited the change.  However, when I
> went through this code before I took it that the change was needed to filter
> out the case where SCTLR may be either of the ARMv8 variants (SCTLR_EL1 or
> SCTLR_EL3) as neither of them have a SCTLR_V bits.  In fact, looking quickly
> through the ARMv8 ARM, I don't see any mention of hivec support for AArch64.
>
> I think the more appropriate check in this case is to check whether the
> current EL is 32-bit instead of ARMv8.   Made this change in v9 along with a
> comment.

You don't need any extra check, for two reasons:
 (1) if our EL out of reset is 64 bit then this is SCTLR_EL3 or
 SCTLR_EL1, and in either case the V bit is RES0 so it will always
 be zero
 (2) setting env->regs[15] is harmless anyway because the AArch64
 PC is stored elsewhere

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v8 14/27] target-arm: respect SCR.FW, SCR.AW and SCTLR.NMFI
  2014-10-31 14:18   ` Peter Maydell
@ 2014-11-03 14:57     ` Greg Bellows
  0 siblings, 0 replies; 81+ messages in thread
From: Greg Bellows @ 2014-11-03 14:57 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler,
	Edgar E. Iglesias

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

On 31 October 2014 09:18, Peter Maydell <peter.maydell@linaro.org> wrote:

> On 30 October 2014 21:28, Greg Bellows <greg.bellows@linaro.org> wrote:
> > From: Fabian Aggeler <aggelerf@ethz.ch>
> >
> > bits when modifying CPSR.
>
> I prefer it if we don't continue sentences from the subject
> line into the main commit message body like this, it makes
> them rather odd to read.
>
>
I agree and I thought I fixed this with the other one you pointed out.
Fixed in v9.


> >
> > Signed-off-by: Fabian Aggeler <aggelerf@ethz.ch>
> > Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
> >
> > ---
> >
> > v7 -> v8
> > - Fixed incorrect use of env->uncached_cpsr A/I/F to use env->daif
> instead.
> > - Removed incorrect statement about SPSR to CPSR copies being affected by
> >   SCR.AW/FW.
> > - Fix typo in comment.
> > - Simpified cpsr_write logic
> >
> > 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.
> > ---
> >  target-arm/helper.c | 47 ++++++++++++++++++++++++++++++++++++++++++++---
> >  1 file changed, 44 insertions(+), 3 deletions(-)
> >
> > diff --git a/target-arm/helper.c b/target-arm/helper.c
> > index 466459b..03e6b62 100644
> > --- a/target-arm/helper.c
> > +++ b/target-arm/helper.c
> > @@ -3666,9 +3666,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.
> > @@ -3680,6 +3677,50 @@ void cpsr_write(CPUARMState *env, uint32_t val,
> uint32_t mask)
> >              switch_mode(env, val & CPSR_M);
> >          }
> >      }
> > +
>
> You've put this code hunk below the section of this function
> which updates the mode bits in the CPU state. That means we'll
> do the arm_is_secure() and BANKED_CURRENT_REG_GET below as
> if from the mode we're going to, not the mode we started out in.
> This is wrong -- compare the CPSRWriteByInstr pseudocode function,
> which updates the mode field as the last thing it does.
>

Good catch.  I moved the AIF masking logic above the mode switch
conditional in v9.


>
> > +    /* In a V7 implementation that includes 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.
> > +     */
> > +    if (!arm_feature(env, ARM_FEATURE_V8) &&
> > +        arm_feature(env, ARM_FEATURE_EL3) &&
> > +        !arm_feature(env, ARM_FEATURE_EL2) &&
> > +        !arm_is_secure(env)) {
> > +        if (!(env->cp15.scr_el3 & SCR_AW)) {
> > +            qemu_log_mask(LOG_GUEST_ERROR,
> > +                          "Ignoring attempt to switch CPSR_A flag from "
> > +                          "non-secure world with SCR.AW bit clear\n");
>
> This logging is now incorrect, because it will trigger even if the
> guest wasn't attempting to change the value of CPSR.A. You could
> either just drop the logging or alternatively only log
> if ((env->daif ^ val) & mask & CPSR_A)
> I guess.
>

True.  So the change to take out what we thought was pre-optimization was
somewhat needed.  Adding the check back in as you suggested basically puts
the code back where it was.   As you mentioned before, this is not a
bottleneck path, so I'll add back in the conditionals and add comments in
v9.


>
> > +            mask &= ~CPSR_A;
> > +        }
> > +
> > +        if (!(env->cp15.scr_el3 & SCR_FW)) {
> > +            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
>
> thanks
> -- PMM
>

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

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

* Re: [Qemu-devel] [PATCH v8 19/27] target-arm: make DACR banked
  2014-10-31 15:38   ` Peter Maydell
@ 2014-11-03 21:23     ` Greg Bellows
  0 siblings, 0 replies; 81+ messages in thread
From: Greg Bellows @ 2014-11-03 21:23 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler,
	Edgar E. Iglesias

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

Added DACR32_EL2 definition and converted dacr fields to uint64_t in v9.

On 31 October 2014 10:38, Peter Maydell <peter.maydell@linaro.org> wrote:

> On 30 October 2014 21:28, Greg Bellows <greg.bellows@linaro.org> wrote:
> > 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 641b148..ac13d0b 100644
> > --- a/hw/arm/pxa2xx.c
> > +++ b/hw/arm/pxa2xx.c
> > @@ -276,7 +276,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 6e9f1c3..6d39af1 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;
> > +            };
>
> If we're going to define a dacr32_el2 field here we should
> actually implement the reginfo for it (it just has to be a
> simple reads-as-written PL2_RW register). It's also going to
> have to be uint64_t, which means the dacr_ns/dacr_s fields
> also should be 64 bit.
>
> Someday we should split out the MPU use of this encoding
> properly into its own field because it isn't anything to
> do with the DACR. I guess not today, though.
>
> -- PMM
>

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

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

* Re: [Qemu-devel] [PATCH v8 24/27] target-arm: make VBAR banked
  2014-10-31 17:22   ` Peter Maydell
@ 2014-11-03 22:06     ` Greg Bellows
  2014-11-03 22:49       ` Peter Maydell
  0 siblings, 1 reply; 81+ messages in thread
From: Greg Bellows @ 2014-11-03 22:06 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler,
	Edgar E. Iglesias

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

You seem to not be a fan of the fields setting moved around and Fabian
appears to have done this in a number of places.  I left them as is because
I found the changes to add consistency and compactness.

Would you like me to undo any such changes?

Greg

On 31 October 2014 12:22, Peter Maydell <peter.maydell@linaro.org> wrote:

> On 30 October 2014 21:28, Greg Bellows <greg.bellows@linaro.org> wrote:
> > When EL3 is running in Aarch32 (or ARMv7 with Security Extensions)
> > VBAR has a secure and a non-secure instance, which are mapped to
> > VBAR_EL1 and VBAR_EL3.
> >
> > 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 vbar union/structure definition
> > - Revert back to array-based vbar definition combined with v7 naming
> > ---
> >  target-arm/cpu.h    | 10 +++++++++-
> >  target-arm/helper.c |  8 ++++----
> >  2 files changed, 13 insertions(+), 5 deletions(-)
> >
> > diff --git a/target-arm/cpu.h b/target-arm/cpu.h
> > index 3c6ff4a..e0954c7 100644
> > --- a/target-arm/cpu.h
> > +++ b/target-arm/cpu.h
> > @@ -306,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];
> > +        };
> >          uint32_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 ec957fb..fb040d4 100644
> > --- a/target-arm/helper.c
> > +++ b/target-arm/helper.c
> > @@ -905,9 +905,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) } },
>
> This is unnecessarily moving the .resetvalue setting around again.
> Otherwise
> Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
>
> thanks
> -- PMM
>

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

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

* Re: [Qemu-devel] [PATCH v8 24/27] target-arm: make VBAR banked
  2014-11-03 22:06     ` Greg Bellows
@ 2014-11-03 22:49       ` Peter Maydell
  0 siblings, 0 replies; 81+ messages in thread
From: Peter Maydell @ 2014-11-03 22:49 UTC (permalink / raw)
  To: Greg Bellows
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler,
	Edgar E. Iglesias

On 3 November 2014 22:06, Greg Bellows <greg.bellows@linaro.org> wrote:
> You seem to not be a fan of the fields setting moved around and Fabian
> appears to have done this in a number of places.  I left them as is because
> I found the changes to add consistency and compactness.

I particularly dislike it where it makes the diffs harder
to read (as in this instance where it disguises the fact
that there's only actually been one field that's changed).

> Would you like me to undo any such changes?

I wouldn't bother except for the patches where I
specifically mentioned it.

-- PMM

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

* Re: [Qemu-devel] [PATCH v8 25/27] target-arm: make c13 cp regs banked (FCSEIDR, ...)
  2014-10-31 17:27   ` Peter Maydell
@ 2014-11-03 22:57     ` Greg Bellows
  0 siblings, 0 replies; 81+ messages in thread
From: Greg Bellows @ 2014-11-03 22:57 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler,
	Edgar E. Iglesias

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

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

> On 30 October 2014 21:28, Greg Bellows <greg.bellows@linaro.org> wrote:
> > 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
> > ---
> >  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) {
>
> Stray whitespace change.
>
> > @@ -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;
>
> ??? whitespace changes I guess? This patch shouldn't be touching
> CRIS specific code... There's a bunch more whitespace changes
> below too, please get rid of them all.
>
>
Yeah, my bad.  I have a filter on my editor that fixes white space
anomalies such as what checkpatch catches.  Undid changes in v9.


> > @@ -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 e0954c7..348ce73 100644
> > --- a/target-arm/cpu.h
> > +++ b/target-arm/cpu.h
> > @@ -316,11 +316,36 @@ typedef struct CPUARMState {
> >              uint64_t vbar_el[4];
> >          };
> >          uint32_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 of three uint64_t fields with an array with only 2
> entries? That looks fishy.
>

I actually did this on purpose because there is no contextidr_el[2 or 3].
This is inconsistent with how I did it elsewhere though.  Fixed it in v9.


>
> > +        };
> > +        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];
>
> A one-element array??
>

This was done to remain consistent with how all the other _el[n] fields
worked. Not my favorite either, but it keeps with the pattern.

Change it?


>
> > +        };
> >          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 fb040d4..d782897 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,
>
> Lost .opc3 again, and you don't need to specify .cp = 15 for a BOTH entry.
>
> >        .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
> >  };
> > @@ -1025,23 +1028,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) } },
>
> This diff is hard to read because you've moved .resetvalue around in the
> struct, so the changed lines are more than have actually changed
> semantically.
>

Undid authors field rearranging in v9.


>
> > +    { .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
> >  };
> >
> > @@ -5045,7 +5052,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);
>
> Add braces while you're changing this line.
>

Done in v9.


>
> >      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
>
> thanks
> -- PMM
>

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

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

* Re: [Qemu-devel] [PATCH v8 23/27] target-arm: make PAR banked
  2014-10-31 17:21   ` Peter Maydell
@ 2014-11-03 22:58     ` Greg Bellows
  0 siblings, 0 replies; 81+ messages in thread
From: Greg Bellows @ 2014-11-03 22:58 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler,
	Edgar E. Iglesias

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

On 31 October 2014 12:21, Peter Maydell <peter.maydell@linaro.org> wrote:

> On 30 October 2014 21:28, Greg Bellows <greg.bellows@linaro.org> wrote:
> > 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
> >
> > v3 -> v4
> > - Fix par union/structure definition
> > ---
> >  target-arm/cpu.h    | 10 +++++++++-
> >  target-arm/helper.c | 25 ++++++++++++++-----------
> >  2 files changed, 23 insertions(+), 12 deletions(-)
> >
> > diff --git a/target-arm/cpu.h b/target-arm/cpu.h
> > index 10985d4..3c6ff4a 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 */
> > diff --git a/target-arm/helper.c b/target-arm/helper.c
> > index c4d0db4..ec957fb 100644
> > --- a/target-arm/helper.c
> > +++ b/target-arm/helper.c
> > @@ -1419,7 +1419,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).
> > @@ -1429,14 +1429,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);
> >          }
>
> Pull the "uint64_t par64" out to the top level of this function, and
> set it in all the branches of the if() that currently set cp15.par_el1,
> and then just use the big fat A32_BANKED_CURRENT_REG_SET macro once.
>
>
Done in v9


> >      }
> >  }
> > @@ -1444,9 +1446,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) }
> },
>
> Why move the .writefn setting around?
>

I'm guessing Fabian is like me and likes things to be more orderly and
consistent.  He appears to have tidied certain things he touched and I
likely did as well.  The register definitions could use a clean-up to make
them more readable.  Perhaps something to attack after the TZ stuff is in.


>
> >  #ifndef CONFIG_USER_ONLY
> >      { .name = "ATS", .cp = 15, .crn = 7, .crm = 8, .opc1 = 0, .opc2 =
> CP_ANY,
> >        .access = PL1_W, .accessfn = ats_access,
> > @@ -1902,8 +1904,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),
> > --
> > 1.8.3.2
>
> Looks OK otherwise.
>
> thanks
> -- PMM
>

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

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

* Re: [Qemu-devel] [PATCH v8 22/27] target-arm: make IFAR/DFAR banked
  2014-10-31 16:24   ` Peter Maydell
@ 2014-11-03 22:59     ` Greg Bellows
  0 siblings, 0 replies; 81+ messages in thread
From: Greg Bellows @ 2014-11-03 22:59 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler,
	Edgar E. Iglesias

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

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

> On 30 October 2014 21:28, Greg Bellows <greg.bellows@linaro.org> wrote:
> > 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
> > ---
> >  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 18f4726..a711834 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 29bf273..10985d4 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
>
> This is pretty ugly but I guess I can live with it.
>
> > +                uint64_t _unused_far3;;
>
> Stray extra semicolon.
>
>
Fixed in v9.


> > +            };
> > +            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 c5948f7..c4d0db4 100644
> > --- a/target-arm/helper.c
> > +++ b/target-arm/helper.c
> > @@ -554,7 +554,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.
> > @@ -1681,11 +1682,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]) },
>
> This change just seems to be rearranging the fields for no particular
> reason?
>

Will fix in v9.


>
> >      REGINFO_SENTINEL
> >  };
> >
> > @@ -4300,8 +4304,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;
> > @@ -4311,8 +4314,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);
>
> Otherwise has my reviewed-by.
>
> -- PMM
>

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

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

* Re: [Qemu-devel] [PATCH v8 26/27] target-arm: make MAIR0/1 banked
  2014-10-31 17:31   ` Peter Maydell
@ 2014-11-03 23:00     ` Greg Bellows
  2014-11-04 14:13       ` Greg Bellows
  0 siblings, 1 reply; 81+ messages in thread
From: Greg Bellows @ 2014-11-03 23:00 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler,
	Edgar E. Iglesias

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

On 31 October 2014 12:31, Peter Maydell <peter.maydell@linaro.org> wrote:

> On 30 October 2014 21:28, Greg Bellows <greg.bellows@linaro.org> wrote:
> > 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
> > ---
> >  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 348ce73..1a76fc6 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;
>
> Surely these need the big-endian ifdefs too if we're unioning
> uint32_ts with a uint64_t array?
>

Fixed in v9.


>
> (Can you check the other patches for this too, please? I might
> have missed it when reviewing some of them, but a quick scan through
> the cpu.h file in your tree ought to catch any other cases.)
>

Will do, but I think there were only two places where I had to mix uint32
and uint64.

Looking closer, I am thinking that this breaks with the ifdef in
add_cpreg_to_hash as it seems it will reverse the structure logic.  The
function ifdef is really only designed to handle a single uint32 overlaying
a uint64.  I have to look into this more before we move forward with it.


>
> > +            };
> > +            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 d782897..fd5f074 100644
> > --- a/target-arm/helper.c
> > +++ b/target-arm/helper.c
> > @@ -939,7 +939,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.
> > @@ -948,11 +948,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
> >
>
> Otherwise you can add my reviewed-by tag.
>
> -- PMM
>

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

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

* Re: [Qemu-devel] [PATCH v8 26/27] target-arm: make MAIR0/1 banked
  2014-11-03 23:00     ` Greg Bellows
@ 2014-11-04 14:13       ` Greg Bellows
  0 siblings, 0 replies; 81+ messages in thread
From: Greg Bellows @ 2014-11-04 14:13 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler,
	Edgar E. Iglesias

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

On 3 November 2014 17:00, Greg Bellows <greg.bellows@linaro.org> wrote:

>
>
> On 31 October 2014 12:31, Peter Maydell <peter.maydell@linaro.org> wrote:
>
>> On 30 October 2014 21:28, Greg Bellows <greg.bellows@linaro.org> wrote:
>> > 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
>> > ---
>> >  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 348ce73..1a76fc6 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;
>>
>> Surely these need the big-endian ifdefs too if we're unioning
>> uint32_ts with a uint64_t array?
>>
>
> Fixed in v9.
>
>
>>
>> (Can you check the other patches for this too, please? I might
>> have missed it when reviewing some of them, but a quick scan through
>> the cpu.h file in your tree ought to catch any other cases.)
>>
>
> Will do, but I think there were only two places where I had to mix uint32
> and uint64.
>
> Looking closer, I am thinking that this breaks with the ifdef in
> add_cpreg_to_hash as it seems it will reverse the structure logic.  The
> function ifdef is really only designed to handle a single uint32 overlaying
> a uint64.  I have to look into this more before we move forward with it.
>
>

Looked further into this and all is good.  The special registers where two
32-bit registers map to separate halves simply need to be defined
separately along with the endian ifdef and all should work out fine.


>
>> > +            };
>> > +            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 d782897..fd5f074 100644
>> > --- a/target-arm/helper.c
>> > +++ b/target-arm/helper.c
>> > @@ -939,7 +939,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.
>> > @@ -948,11 +948,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
>> >
>>
>> Otherwise you can add my reviewed-by tag.
>>
>> -- PMM
>>
>
>

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

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

* Re: [Qemu-devel] [PATCH v8 07/27] target-arm: insert AArch32 cpregs twice into hashtable
  2014-10-31 19:01     ` Greg Bellows
@ 2014-11-04 22:20       ` Greg Bellows
  0 siblings, 0 replies; 81+ messages in thread
From: Greg Bellows @ 2014-11-04 22:20 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler,
	Edgar E. Iglesias

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

I have fixed the code to properly handle the CONTEXTIDR/FCSEIDR registers.
This is done in two parts:
1) I broke the FCSEIDR and CONTEXTIDR into separate secure/non-secure
definitions.
2) I updated the check that filters the secure duplicate instance caused by
registering unbanked register twice.










On 31 October 2014 14:01, Greg Bellows <greg.bellows@linaro.org> wrote:

>
>
> On 31 October 2014 07:44, Peter Maydell <peter.maydell@linaro.org> wrote:
>
>> On 30 October 2014 21:28, Greg Bellows <greg.bellows@linaro.org> wrote:
>> > 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>
>> >
>> > ---
>> >
>> > v7 -> v8
>> > - Updated define registers asserts to allow either a non-zero
>> fieldoffset or
>> >   non-zero bank_fieldoffsets.
>> > - Updated CP register hashing to always set the register fieldoffset
>> when
>> >   banked register offsets are specified.
>> >
>> > 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.
>> > ---
>> >  target-arm/helper.c | 98
>> ++++++++++++++++++++++++++++++++++++++++++++---------
>> >  1 file changed, 82 insertions(+), 16 deletions(-)
>> >
>> > diff --git a/target-arm/helper.c b/target-arm/helper.c
>> > index 959a46e..c1c6303 100644
>> > --- a/target-arm/helper.c
>> > +++ b/target-arm/helper.c
>> > @@ -3296,22 +3296,62 @@ 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 (r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1]) {
>> > +        /* Register is banked (using both entries in array).
>> > +         * Overwriting fieldoffset as the array is only used to define
>> > +         * banked registers but later only fieldoffset is used.
>> >           */
>> > -        if (r2->cp == 0) {
>> > -            r2->cp = 15;
>> > +        r2->fieldoffset = r->bank_fieldoffsets[nsbit];
>> > +    }
>> > +
>> > +    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;
>>
>> This bitmanipulation looks like leftover from when these were in 'state';
>>    r2->secure = secstate;
>> should be sufficient (and you might as well put this down below the
>> 'r2->state = state' assignment, since it's harmless to do it for all
>> regdefs including 64 bit ones).
>>
>>
> It was in the previous code, but it is still necessary for marking whether
> the given register is secure or not.
>
>
>> > +
>> > +        if (r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1]) {
>> > +            /* If the register is banked and 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.
>> > +             */
>>
>> I'm not sure what this paragraph is trying to say. The AArch64 equivalent
>> of CONTEXTIDR(NS) is CONTEXTIDR_EL1. In v8 FCSEIDR is a constant RAZ/WI
>> register, so migration and reset aren't relevant anyway.
>>
>> In any case, if we only have a couple of special case registers where
>> this bank handling doesn't work, I suggest that we should handle them
>> by having two separate reginfo structs for the S and NS versions,
>> rather than special casing a specific crn value here.
>>
>
> It does not sound like the comment was clear.  The point of this code was
> to disable migration and reset of one or both banks.  If we know there is
> an aarch64 version (BOTH) then we know we can disable the ns bank
> instance.  If we are ARMv8 then we know that we can also disable the sec
> bank instance.  However, there was an exception in that neither CONTEXTIDR
> nor FCSEIDR actually have an ARMv8/AArch64 secure counterparts, so we still
> have to allow migration and reset even if ARMv8 is supported.
>
> You are correct that FCSEIDR is RAZ/WI in ARMv8, which is the exact issue
> as this is not the case in ARMv7.  I'll work through it to see if adding
> separate entries alleviates the need for the ugly conditional.  BTW, I
> didn't like this either, but at the time I hadn't found a more elegant
> approach.
>
>
>>
>> > +            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
>> > @@ -3460,10 +3500,14 @@ void define_one_arm_cp_reg_with_opaque(ARMCPU
>> *cpu,
>> >       */
>> >      if (!(r->type & (ARM_CP_SPECIAL|ARM_CP_CONST))) {
>> >          if (r->access & PL3_R) {
>> > -            assert(r->fieldoffset || r->readfn);
>> > +            assert((r->fieldoffset ||
>> > +                   (r->bank_fieldoffsets[0] &&
>> r->bank_fieldoffsets[1])) ||
>> > +                   r->readfn);
>> >          }
>> >          if (r->access & PL3_W) {
>> > -            assert(r->fieldoffset || r->writefn);
>> > +            assert((r->fieldoffset ||
>> > +                   (r->bank_fieldoffsets[0] &&
>> r->bank_fieldoffsets[1])) ||
>> > +                   r->writefn);
>> >          }
>> >      }
>> >      /* Bad type field probably means missing sentinel at end of reg
>> list */
>> > @@ -3476,8 +3520,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) {
>>
>> As a general remark, don't use this sort of "yoda conditional" with the
>> constant on the LHS of the ==, please.
>>
>
> Fixed in v9.
>
>
>>
>> > +                            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);
>> > +                        }
>>
>> Given the change to make add_cpreg_to_hashtable() take an ARM_CP_SECSTATE*
>> constant that I suggested in the previous patch, you can simplify this to
>>
>>     switch (r->secure) {
>>         case ARM_CP_SECSTATE_S:
>>         case ARM_CP_SECSTATE_NS:
>>             add_cpreg_to_hashtable(cpu, r, opaque, state, r->secure,
>> crm, opc1, opc2);
>>             break;
>>         default:
>>             add_cpreg_to_hashtable(cpu, r, opaque, state,
>> ARM_CP_SECSTATE_S, crm, opc1, opc2);
>>             add_cpreg_to_hashtable(cpu, r, opaque, state,
>> ARM_CP_SECSTATE_NS, crm, opc1, opc2);
>>             break;
>>     }
>>
>
>> > +                    } 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
>>
>> thanks
>> -- PMM
>>
>
>

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

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

* Re: [Qemu-devel] [PATCH v8 16/27] target-arm: add TTBR0_EL3 and make TTBR0/1 banked
  2014-10-31 15:04   ` Peter Maydell
@ 2014-11-04 22:44     ` Greg Bellows
  0 siblings, 0 replies; 81+ messages in thread
From: Greg Bellows @ 2014-11-04 22:44 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler,
	Edgar E. Iglesias

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

On 31 October 2014 10:04, Peter Maydell <peter.maydell@linaro.org> wrote:

> On 30 October 2014 21:28, Greg Bellows <greg.bellows@linaro.org> wrote:
> > From: Fabian Aggeler <aggelerf@ethz.ch>
> >
> > Add TTBR0 and maps secure/non-secure instance of ttbr0 and ttbr1
>
> Is "maps" a typo for something, or have we lost a word here?
>
>
It is just not clear.  It should say something similar to the title.  I'll
update the comment in v9.


> > 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#
> > ---
> >  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 11d51af..641b148 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.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 */
> > @@ -2047,7 +2047,7 @@ PXA2xxState *pxa270_init(MemoryRegion
> *address_space,
> >      }
> >      if (!revision)
> >          revision = "pxa270";
> > -
> > +
>
> Stray whitespace change.
>
>
Fixed in v9


> >      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 3b776a1..fe96869 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.
> */
> >          uint64_t sder; /* Secure debug enable register. */
> >          uint32_t 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 f6a9b66..598f0d1 100644
> > --- a/target-arm/helper.c
> > +++ b/target-arm/helper.c
> > @@ -1645,14 +1645,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,
>
> You seem to have lost the .opc0 setting; surely this breaks AArch64?
> Also you don't need to specify .cp = 15 explicitly for a STATE_BOTH
> register. This whole hunk should just be changing the .fieldoffset
> spec to .bank_fieldoffsets, really.
>

You are correct, this would break AArch64.  Fixed in v9.


>
> > +      .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,
> > @@ -1883,11 +1885,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
> >  };
> > @@ -2341,6 +2345,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]) },
>
> ...isn't this migrated twice (since ttbr0_el[3] is in a
> union with ttbr0_s)? In any case, see my comment below.
>

No.  This is what the ARMv8 check in add_cpreg_to_hash() is intended to
catch.  If a banked register is being hashed and ARMv8 is enabled then it
is assumed that there is an ARMv8 instance (EL3) that will take care of
both reset and migration, so the AA32 instance has them disabled.


> >      { .name = "ELR_EL3", .state = ARM_CP_STATE_AA64,
> >        .type = ARM_CP_NO_MIGRATE,
> >        .opc0 = 3, .opc1 = 6, .crn = 4, .crm = 0, .opc2 = 1,
> > @@ -4422,18 +4430,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;
> > @@ -4687,6 +4700,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;
> > @@ -4738,7 +4752,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;
> >
> > @@ -4750,7 +4776,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;
>
> This logic isn't actually sufficient to handle AArch64 EL3:
> there is no TTBR1_EL3, and so the code that sets ttbr_select
> also needs to change to not try to select TTBR1 if we're
> not in EL0/EL1. We're also missing EL2 support (or at
> least an assertion that the EL isn't 2.)
>

Right, the patchset was not intended to fully handle AArch64.  Fabian's
intent (as well as mine) was to only add the support where obvious or
overlapping with AArch32.  I believe the lack of support is benign as long
as EL3 is not enabled for A57 because it will always access the NS bank.


>
> What I suggest is that you take most of these changes,
> plus the definition of TTBR0_EL3, out of this patch and
> put them in a separate patch. (So just leave both halves
> of this if() with using BANKED_CURRENT_REG_GET, so that
> AArch32 TZ works ok and AArch64 with just EL0/EL1 still
> works.) Then put that patch at the end of your stack
> of patches and don't actually send it out as part of this
> series. Basically, put it on the shelf til we've got
> through this lot and we can come back and address the
> required code changes to support AArch64 EL3 in the
> VA-to-PA translation as a set of self-standing patches.
>
>
I have removed the lpae EL3 conditional code.

As mentioned above, if I remove the TTBR0_EL3 definition then would break
migration and reset of the secure TTBR0 bank.  As it is somewhat related, I
suggest that we leave the register definition in to allow things to work
properly.  If not, then I have to add separate defs for the secure and
non-secure just to undo the change when we add the EL3 version back in.


thanks
> -- PMM
>

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

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

* Re: [Qemu-devel] [PATCH v8 17/27] target-arm: add TCR_EL3 and make TTBCR banked
  2014-10-31 15:07   ` Peter Maydell
@ 2014-11-04 22:45     ` Greg Bellows
  0 siblings, 0 replies; 81+ messages in thread
From: Greg Bellows @ 2014-11-04 22:45 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler,
	Edgar E. Iglesias

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

Changes made in v9, but as with TTBR0_EL3 I have left the definition for
TCR_EL3 in.

On 31 October 2014 10:07, Peter Maydell <peter.maydell@linaro.org> wrote:

> On 30 October 2014 21:28, Greg Bellows <greg.bellows@linaro.org> wrote:
> > 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.
> > ---
> >  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 fe96869..f125bdd 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 598f0d1..896b40d 100644
> > --- a/target-arm/helper.c
> > +++ b/target-arm/helper.c
> > @@ -1659,11 +1659,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,
> > @@ -2349,6 +2350,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,
> > @@ -4435,13 +4441,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;
> >          }
> > @@ -4701,13 +4707,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);
> > +    }
>
> Again, I would pull out the TCR_EL3 definition and attempts
> at handling the 64 bit EL3 into their own patch and stick
> them on the shelf for later.
>
> thanks
> -- PMM
>

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

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

* Re: [Qemu-devel] [PATCH v8 18/27] target-arm: make c2_mask and c2_base_mask banked
  2014-10-31 15:26   ` Peter Maydell
@ 2014-11-04 22:46     ` Greg Bellows
  2014-11-04 23:27       ` Peter Maydell
  0 siblings, 1 reply; 81+ messages in thread
From: Greg Bellows @ 2014-11-04 22:46 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler,
	Edgar E. Iglesias

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

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

> On 30 October 2014 21:28, Greg Bellows <greg.bellows@linaro.org> wrote:
> > 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.
>
> These fields are part of our TTBCR internal representation; we
> should bank the whole TTBCR in one patch, not split over two.
>

Squashed the TTBCR and C2 mask patches in v9.


>
> > 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.
> > ---
> >  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 f125bdd..6e9f1c3 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;
> > +        };
>
> I think we should actually have:
>     typedef struct {
>         uint64_t raw_ttbcr;
>         uint32_t mask;
>         uint32_t base_mask;
>     } TTBCR;
>
>     and then have TTBCR ttbcr[2];
>
> and not use the BANKED_REG_SET/GET macros here...
>

I like the cleanliness of this approach but it does not take into
consideration the tcr_el[] fields.  I have instead changed the naming to
TCR/tcr_el and have added 4 entries instead of 2.  This is more consistent
with the other changes in the patch set.


>
> >          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 896b40d..27eaf9c 100644
> > --- a/target-arm/helper.c
> > +++ b/target-arm/helper.c
> > @@ -1584,8 +1584,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));
>
> ... so this turns into:
>
>     TTBCR t = env->cp15.ttbcr[ri->secure];
>
>     t->raw_ttbcr = value;
>     t->mask = ~(((uint32_t)0xffffffffu) >> maskshift);
>     t->base_mask = ~((uint32_t)0x3fffu >> maskshift);
>
> (XXX did we make ri->secure be a 0/1 or is it 1/2 ? anyway you get the
> idea.)
>
>
Changed in v9.  ri->secure is 1/2 as both bitsor neither may be set at
definition time.


> >  }
> >
> >  static void vmsa_ttbcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
> > @@ -1604,9 +1610,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;
>
> Similarly this will be much cleaner.
>

Changed in v9.  Question on reset.  We call raw_write() which also sets the
masks, but we set the masks separately here too, but different values.  It
seems we should only need to set them in raw_write() is this true?


>
> >  }
> >
> >  static void vmsa_tcr_el1_write(CPUARMState *env, const ARMCPRegInfo *ri,
> > @@ -4440,7 +4452,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;
> > @@ -4452,7 +4464,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);
> >      }
>
> and again here you can get a pointer to the correct TTBCR
> struct and just reference it.
>


Yes.  Changed all accesses in v9.


>
> >      *table |= (address >> 18) & 0x3ffc;
> >      return true;
> > --
>
> thanks
> -- PMM
>

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

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

* Re: [Qemu-devel] [PATCH v8 18/27] target-arm: make c2_mask and c2_base_mask banked
  2014-11-04 22:46     ` Greg Bellows
@ 2014-11-04 23:27       ` Peter Maydell
  2014-11-05 15:09         ` Greg Bellows
  0 siblings, 1 reply; 81+ messages in thread
From: Peter Maydell @ 2014-11-04 23:27 UTC (permalink / raw)
  To: Greg Bellows
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler,
	Edgar E. Iglesias

On 4 November 2014 22:46, Greg Bellows <greg.bellows@linaro.org> wrote:
>
>
> On 31 October 2014 10:26, Peter Maydell <peter.maydell@linaro.org> wrote:
>>
>> On 30 October 2014 21:28, Greg Bellows <greg.bellows@linaro.org> wrote:
>> >  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;
>>
>> Similarly this will be much cleaner.
>
>
> Changed in v9.  Question on reset.  We call raw_write() which also sets the
> masks, but we set the masks separately here too, but different values.  It
> seems we should only need to set them in raw_write() is this true?

No, raw_write() won't set the masks -- it just writes 32 or 64 bits
to the field pointed to by fieldoffset. Which makes it a pretty
obfuscated way of saying env->cp15.c2_control = 0; and I don't
know why we do it this way currently. If we go to having a TTBCR
struct we should just set all the fields directly here I think.

-- PMM

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

* Re: [Qemu-devel] [PATCH v8 18/27] target-arm: make c2_mask and c2_base_mask banked
  2014-11-04 23:27       ` Peter Maydell
@ 2014-11-05 15:09         ` Greg Bellows
  2014-11-05 15:15           ` Peter Maydell
  0 siblings, 1 reply; 81+ messages in thread
From: Greg Bellows @ 2014-11-05 15:09 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler,
	Edgar E. Iglesias

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

Ah... I was confused and thinking of ttbcr_raw_write.  Yes, raw_write does
not actually touch the masks.

The reason we used raw_write is that it updates the correct ri offset.  We
could be calling with the secure or non-secure ri so it was necessary to
make sure the correct offset gets updated.

Staying with this pattern, I introduced a new utility function raw_ptr()
that gives back the pointer calculation based on the ri fieldoffset.  For
TCR, this will be the base of the TCR struct which we can then update.

On 4 November 2014 17:27, Peter Maydell <peter.maydell@linaro.org> wrote:

> On 4 November 2014 22:46, Greg Bellows <greg.bellows@linaro.org> wrote:
> >
> >
> > On 31 October 2014 10:26, Peter Maydell <peter.maydell@linaro.org>
> wrote:
> >>
> >> On 30 October 2014 21:28, Greg Bellows <greg.bellows@linaro.org> wrote:
> >> >  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;
> >>
> >> Similarly this will be much cleaner.
> >
> >
> > Changed in v9.  Question on reset.  We call raw_write() which also sets
> the
> > masks, but we set the masks separately here too, but different values.
> It
> > seems we should only need to set them in raw_write() is this true?
>
> No, raw_write() won't set the masks -- it just writes 32 or 64 bits
> to the field pointed to by fieldoffset. Which makes it a pretty
> obfuscated way of saying env->cp15.c2_control = 0; and I don't
> know why we do it this way currently. If we go to having a TTBCR
> struct we should just set all the fields directly here I think.
>
> -- PMM
>

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

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

* Re: [Qemu-devel] [PATCH v8 18/27] target-arm: make c2_mask and c2_base_mask banked
  2014-11-05 15:09         ` Greg Bellows
@ 2014-11-05 15:15           ` Peter Maydell
  2014-11-05 15:18             ` Greg Bellows
  0 siblings, 1 reply; 81+ messages in thread
From: Peter Maydell @ 2014-11-05 15:15 UTC (permalink / raw)
  To: Greg Bellows
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler,
	Edgar E. Iglesias

On 5 November 2014 15:09, Greg Bellows <greg.bellows@linaro.org> wrote:
> Ah... I was confused and thinking of ttbcr_raw_write.  Yes, raw_write does
> not actually touch the masks.
>
> The reason we used raw_write is that it updates the correct ri offset.  We
> could be calling with the secure or non-secure ri so it was necessary to
> make sure the correct offset gets updated.

...but this doesn't help if you need to also update the mask etc.

> Staying with this pattern, I introduced a new utility function raw_ptr()
> that gives back the pointer calculation based on the ri fieldoffset.  For
> TCR, this will be the base of the TCR struct which we can then update.

Seems like overkill for one register, compared to just doing
 if (ri->secure == ...)

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v8 18/27] target-arm: make c2_mask and c2_base_mask banked
  2014-11-05 15:15           ` Peter Maydell
@ 2014-11-05 15:18             ` Greg Bellows
  0 siblings, 0 replies; 81+ messages in thread
From: Greg Bellows @ 2014-11-05 15:18 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler,
	Edgar E. Iglesias

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

Maybe, but it is cleaner and works later on down the road when we add EL2
registers that use the same write functions.

I'm fine either way if you feel strongly about it.

On 5 November 2014 09:15, Peter Maydell <peter.maydell@linaro.org> wrote:

> On 5 November 2014 15:09, Greg Bellows <greg.bellows@linaro.org> wrote:
> > Ah... I was confused and thinking of ttbcr_raw_write.  Yes, raw_write
> does
> > not actually touch the masks.
> >
> > The reason we used raw_write is that it updates the correct ri offset.
> We
> > could be calling with the secure or non-secure ri so it was necessary to
> > make sure the correct offset gets updated.
>
> ...but this doesn't help if you need to also update the mask etc.
>
> > Staying with this pattern, I introduced a new utility function raw_ptr()
> > that gives back the pointer calculation based on the ri fieldoffset.  For
> > TCR, this will be the base of the TCR struct which we can then update.
>
> Seems like overkill for one register, compared to just doing
>  if (ri->secure == ...)
>
> thanks
> -- PMM
>

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

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

* Re: [Qemu-devel] [PATCH v8 01/27] target-arm: extend async excp masking
  2014-10-31 19:00   ` Peter Maydell
@ 2014-11-05 21:12     ` Greg Bellows
  0 siblings, 0 replies; 81+ messages in thread
From: Greg Bellows @ 2014-11-05 21:12 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler,
	Edgar E. Iglesias

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

Actually it is possible to make it simpler and avoid the gotos altogether
with the changes I have made using the following conditional:

+    /* Use the target EL, current execution state and SCR/HCR settings to
+     * determine whether the corresponding CPSR bit is used to mask the
+     * interrupt.
+     */
+    if ((tar_el > cur_el) && (tar_el != 1) && (scr || hcr)) {
+        if (arm_el_is_aa64(env, 3) || !secure) {
+            unmasked = 1;
+        }
+    }
+
+    /* The PSTATE bits only mask the interrupt if we have not overriden the
+     * ability above.
+     */
+    return unmasked || pstate_unmasked;

scr and hcr are set depending on the exception type so both EXCP_IRQ and
EXCP_FIQ fall through to this check.  The conditional basically weeds out
all the cases where we can ignore/override the CPSR masking bits.

Removed table and reworked function in v9.

On 31 October 2014 14:00, Peter Maydell <peter.maydell@linaro.org> wrote:

> On 30 October 2014 21:28, Greg Bellows <greg.bellows@linaro.org> wrote:
> > This patch extends arm_excp_unmasked() to use lookup tables for
> determining
> > whether IRQ and FIQ exceptions are masked.  The lookup tables are based
> on the
> > ARMv8 and ARMv7 specification physical interrupt masking tables.
> >
> > 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: Greg Bellows <greg.bellows@linaro.org>
> >
> > ---
> >
> > v7 -> v8
> > - Add IRQ and FIQ exeception masking lookup tables.
> > - Rewrite patch to use lookup tables for determining whether an
> excpetion is
> >   masked or not.
> >
> > v5 -> v6
> > - Globally change Aarch# to AArch#
> > - Fixed comment termination
> >
> > v4 -> v5
> > - Merge with v4 patch 10
> > ---
> >  target-arm/cpu.h | 218
> ++++++++++++++++++++++++++++++++++++++++++++++++-------
> >  1 file changed, 190 insertions(+), 28 deletions(-)
>
> Having got through the rest of the series I'm coming back
> to this one, which I skipped because it needed checking
> against the ARM ARM.
>
> I definitely don't like the use of tables here -- it is in almost
> all of the cases simply repeating the routing calculations.
> All you actually need here is:
>
>     if (target_el < current_el) {
>         /* Don't take exception */
>         return false;
>     }
>     if (target_el > current_el && target_el != 1) {
>         if (target_el == 3 && !arm_el_is_aa64(env, 3)) {
>             /* In a 32 bit EL3 there are some awkward special cases where
> we
>              * must honour the PSTATE/CPSR mask bits even when taking the
>              * exception to EL3.
>              */
>             if (arm_is_secure(env)) {
>                 goto honour_masking;
>             }
>             /* (We know at this point that SCR.FIQ/IRQ must be set.) */
>             if (excp_idx == EXCP_FIQ && HCR.FMO == 0 && SCR.FW == 1) {
>                 goto honour_masking;
>             }
>             /* If we supported SError then the async external abort routing
>              * would have a similar case for SCR.AW here. There is no
> SCR.IW for IRQs.
>              */
>             if (excp_idx == EXCP_IRQ && HCR.IMO == 0) {
>                 goto honour_masking;
>             }
>        }
>        /* Take the exception unconditionally. */
>        return true;
>     }
> honour_masking:
>     /* If we get here then we check the PSTATE flags. */
>
> (I think the 'gotos' here are clearer than turning the if statement inside
> out
> to avoid them...)
>
> > -    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;
> > -    /* ARMv7-M interrupt return works by loading a magic value
> > -     * into the PC.  On real hardware the load causes the
> > -     * return to occur.  The qemu implementation performs the
> > -     * jump normally, then does the exception return when the
> > -     * CPU tries to execute code at the magic address.
> > -     * This will cause the magic PC value to be pushed to
> > -     * the stack if an interrupt occurred at the wrong time.
> > -     * We avoid this by disabling interrupts when
> > -     * pc contains a magic address.
>
> You'll probably find it easier to base on top of the patches
> I sent out that split out the M profile code from this
> function (I'm planning to put those into target-arm.next soon
> so they get in before hardfreeze).
>
> thanks
> -- PMM
>

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

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

* Re: [Qemu-devel] [PATCH v8 20/27] target-arm: make IFSR banked
  2014-10-31 16:18   ` Peter Maydell
@ 2014-11-05 22:19     ` Greg Bellows
  0 siblings, 0 replies; 81+ messages in thread
From: Greg Bellows @ 2014-11-05 22:19 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Sergey Fedorov, QEMU Developers, Fabian Aggeler,
	Edgar E. Iglesias

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

Added definition for IFSR32_EL2 and changed fields to uint64_t in v9.

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

> On 30 October 2014 21:28, Greg Bellows <greg.bellows@linaro.org> wrote:
> > 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 6d39af1..c44649e 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;
> > +            };
> > +        };
>
> Again, if we have the struct field we should have the reginfo.
>
> >          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 eaae534..de355f5 100644
> > --- a/target-arm/helper.c
> > +++ b/target-arm/helper.c
> > @@ -1653,8 +1653,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,
> > @@ -4297,11 +4298,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;
>
> This will work OK for now; if we want to implement SCR.EA to
> allow routing of external aborts to Monitor mode we're going
> to have to come up with something cleverer, because that
> affects whether we want to write to the secure or nonsecure
> copy of the IFSR/IFAR. But at the moment you can only get
> a prefetch abort or data abort to the Secure world if you
> were already in the Secure world.
>
> thanks
> -- PMM
>

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

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

end of thread, other threads:[~2014-11-05 22:19 UTC | newest]

Thread overview: 81+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-10-30 21:28 [Qemu-devel] [PATCH v8 00/27] target-arm: add Security Extensions for CPUs Greg Bellows
2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 01/27] target-arm: extend async excp masking Greg Bellows
2014-10-31 19:00   ` Peter Maydell
2014-11-05 21:12     ` Greg Bellows
2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 02/27] target-arm: add async excp target_el function Greg Bellows
2014-10-31 11:56   ` Peter Maydell
2014-10-31 14:14     ` Greg Bellows
2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 03/27] target-arm: add banked register accessors Greg Bellows
2014-10-31 16:50   ` Peter Maydell
2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 04/27] target-arm: add non-secure Translation Block flag Greg Bellows
2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 05/27] target-arm: add CPREG secure state support Greg Bellows
2014-10-31 12:15   ` Peter Maydell
2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 06/27] target-arm: add secure state bit to CPREG hash Greg Bellows
2014-10-31 12:28   ` Peter Maydell
2014-10-31 12:31     ` Peter Maydell
2014-10-31 16:20       ` Greg Bellows
2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 07/27] target-arm: insert AArch32 cpregs twice into hashtable Greg Bellows
2014-10-31 12:44   ` Peter Maydell
2014-10-31 19:01     ` Greg Bellows
2014-11-04 22:20       ` Greg Bellows
2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 08/27] target-arm: move AArch32 SCR into security reglist Greg Bellows
2014-10-31 12:06   ` Peter Maydell
2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 09/27] target-arm: implement IRQ/FIQ routing to Monitor mode Greg Bellows
2014-10-31 12:01   ` Peter Maydell
2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 10/27] target-arm: add NSACR register Greg Bellows
2014-10-31 13:24   ` Peter Maydell
2014-10-31 21:09     ` Greg Bellows
2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 11/27] target-arm: add SDER definition Greg Bellows
2014-10-31 13:30   ` Peter Maydell
2014-10-31 21:17     ` Greg Bellows
2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 12/27] target-arm: add MVBAR support Greg Bellows
2014-10-31 13:35   ` Peter Maydell
2014-10-31 21:19     ` Greg Bellows
2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 13/27] target-arm: add SCTLR_EL3 and make SCTLR banked Greg Bellows
2014-10-31 14:07   ` Peter Maydell
2014-10-31 21:51     ` Greg Bellows
2014-10-31 23:26       ` Peter Maydell
2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 14/27] target-arm: respect SCR.FW, SCR.AW and SCTLR.NMFI Greg Bellows
2014-10-31 14:18   ` Peter Maydell
2014-11-03 14:57     ` Greg Bellows
2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 15/27] target-arm: make CSSELR banked Greg Bellows
2014-10-31 14:23   ` Peter Maydell
2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 16/27] target-arm: add TTBR0_EL3 and make TTBR0/1 banked Greg Bellows
2014-10-31 15:04   ` Peter Maydell
2014-11-04 22:44     ` Greg Bellows
2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 17/27] target-arm: add TCR_EL3 and make TTBCR banked Greg Bellows
2014-10-31 15:07   ` Peter Maydell
2014-11-04 22:45     ` Greg Bellows
2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 18/27] target-arm: make c2_mask and c2_base_mask banked Greg Bellows
2014-10-31 15:26   ` Peter Maydell
2014-11-04 22:46     ` Greg Bellows
2014-11-04 23:27       ` Peter Maydell
2014-11-05 15:09         ` Greg Bellows
2014-11-05 15:15           ` Peter Maydell
2014-11-05 15:18             ` Greg Bellows
2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 19/27] target-arm: make DACR banked Greg Bellows
2014-10-31 15:38   ` Peter Maydell
2014-11-03 21:23     ` Greg Bellows
2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 20/27] target-arm: make IFSR banked Greg Bellows
2014-10-31 16:18   ` Peter Maydell
2014-11-05 22:19     ` Greg Bellows
2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 21/27] target-arm: make DFSR banked Greg Bellows
2014-10-31 16:19   ` Peter Maydell
2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 22/27] target-arm: make IFAR/DFAR banked Greg Bellows
2014-10-31 16:24   ` Peter Maydell
2014-11-03 22:59     ` Greg Bellows
2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 23/27] target-arm: make PAR banked Greg Bellows
2014-10-31 17:21   ` Peter Maydell
2014-11-03 22:58     ` Greg Bellows
2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 24/27] target-arm: make VBAR banked Greg Bellows
2014-10-31 17:22   ` Peter Maydell
2014-11-03 22:06     ` Greg Bellows
2014-11-03 22:49       ` Peter Maydell
2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 25/27] target-arm: make c13 cp regs banked (FCSEIDR, ...) Greg Bellows
2014-10-31 17:27   ` Peter Maydell
2014-11-03 22:57     ` Greg Bellows
2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 26/27] target-arm: make MAIR0/1 banked Greg Bellows
2014-10-31 17:31   ` Peter Maydell
2014-11-03 23:00     ` Greg Bellows
2014-11-04 14:13       ` Greg Bellows
2014-10-30 21:28 ` [Qemu-devel] [PATCH v8 27/27] target-arm: add cpu feature EL3 to CPUs with Security Extensions Greg Bellows

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