diff mbox

[v2,1/2] target-arm: Fix handling of SDCR for 32-bit code

Message ID 1455892784-11328-2-git-send-email-peter.maydell@linaro.org (mailing list archive)
State New, archived
Headers show

Commit Message

Peter Maydell Feb. 19, 2016, 2:39 p.m. UTC
Fix two issues with our implementation of the SDCR:
 * it is only present from ARMv8 onwards
 * it does not contain several of the trap bits present in its 64-bit
   counterpart the MDCR_EL3

Put the register description in the right place so that it does not
get enabled for ARMv7 and earlier, and give it a write function so that
we can mask out the bits which should not be allowed to have an effect
if EL3 is 32-bit.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target-arm/cpu.h    |  4 ++++
 target-arm/helper.c | 23 +++++++++++++++--------
 2 files changed, 19 insertions(+), 8 deletions(-)

Comments

Sergey Fedorov Feb. 19, 2016, 4:31 p.m. UTC | #1
On 19.02.2016 17:39, Peter Maydell wrote:
> Fix two issues with our implementation of the SDCR:
>  * it is only present from ARMv8 onwards
>  * it does not contain several of the trap bits present in its 64-bit
>    counterpart the MDCR_EL3
>
> Put the register description in the right place so that it does not
> get enabled for ARMv7 and earlier, and give it a write function so that
> we can mask out the bits which should not be allowed to have an effect
> if EL3 is 32-bit.
>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  target-arm/cpu.h    |  4 ++++
>  target-arm/helper.c | 23 +++++++++++++++--------
>  2 files changed, 19 insertions(+), 8 deletions(-)
>
> diff --git a/target-arm/cpu.h b/target-arm/cpu.h
> index e72e33b..a729ae0 100644
> --- a/target-arm/cpu.h
> +++ b/target-arm/cpu.h
> @@ -599,6 +599,7 @@ void pmccntr_sync(CPUARMState *env);
>  #define MDCR_EDAD     (1U << 20)
>  #define MDCR_SPME     (1U << 17)
>  #define MDCR_SDD      (1U << 16)
> +#define MDCR_SPD      (3U << 14)
>  #define MDCR_TDRA     (1U << 11)
>  #define MDCR_TDOSA    (1U << 10)
>  #define MDCR_TDA      (1U << 9)
> @@ -607,6 +608,9 @@ void pmccntr_sync(CPUARMState *env);
>  #define MDCR_TPM      (1U << 6)
>  #define MDCR_TPMCR    (1U << 5)
>  
> +/* Not all of the MDCR_EL3 bits are present in the 32-bit SDCR */
> +#define SDCR_VALID_MASK (MDCR_EPMAD | MDCR_EDAD | MDCR_SPME | MDCR_SPD)
> +
>  #define CPSR_M (0x1fU)
>  #define CPSR_T (1U << 5)
>  #define CPSR_F (1U << 6)
> diff --git a/target-arm/helper.c b/target-arm/helper.c
> index 3d7fda1..e9b89e6 100644
> --- a/target-arm/helper.c
> +++ b/target-arm/helper.c
> @@ -3037,6 +3037,12 @@ static CPAccessResult fpexc32_access(CPUARMState *env, const ARMCPRegInfo *ri,
>      return CP_ACCESS_OK;
>  }
>  
> +static void sdcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
> +                       uint64_t value)
> +{
> +    env->cp15.mdcr_el3 = value & SDCR_VALID_MASK;
> +}
> +

Just one comment. As soon as we cannot have both of MDCR_EL3 in SDCR in
a specific CPU configuration (EL3 is either AArch64 or AArch32), the
RES0 bitfields of SDCR are "RES0 in all contexts". Thus we can choose
"The bit is hardwired to 0" behaviour as we do here. We could also
choose another behaviour "The bit can be written" and check for "EL3 is
AArch64" case before trying to interpret those bits. Anyway:

Reviewed-by: Sergey Fedorov <serge.fdrv@gmai.com>

>  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.
> @@ -3331,6 +3337,15 @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
>        .opc0 = 3, .opc1 = 4, .crn = 4, .crm = 3, .opc2 = 3,
>        .access = PL2_RW,
>        .fieldoffset = offsetof(CPUARMState, banked_spsr[BANK_FIQ]) },
> +    { .name = "MDCR_EL3", .state = ARM_CP_STATE_AA64,
> +      .opc0 = 3, .opc1 = 6, .crn = 1, .crm = 3, .opc2 = 1,
> +      .resetvalue = 0,
> +      .access = PL3_RW, .fieldoffset = offsetof(CPUARMState, cp15.mdcr_el3) },
> +    { .name = "SDCR", .type = ARM_CP_ALIAS,
> +      .cp = 15, .opc1 = 0, .crn = 1, .crm = 3, .opc2 = 1,
> +      .access = PL1_RW, .accessfn = access_trap_aa32s_el1,
> +      .writefn = sdcr_write,
> +      .fieldoffset = offsetoflow32(CPUARMState, cp15.mdcr_el3) },
>      REGINFO_SENTINEL
>  };
>  
> @@ -3688,14 +3703,6 @@ static const ARMCPRegInfo el3_cp_reginfo[] = {
>        .access = PL1_RW, .accessfn = access_trap_aa32s_el1,
>        .fieldoffset = offsetoflow32(CPUARMState, cp15.scr_el3),
>        .writefn = scr_write },
> -    { .name = "MDCR_EL3", .state = ARM_CP_STATE_AA64,
> -      .opc0 = 3, .opc1 = 6, .crn = 1, .crm = 3, .opc2 = 1,
> -      .resetvalue = 0,
> -      .access = PL3_RW, .fieldoffset = offsetof(CPUARMState, cp15.mdcr_el3) },
> -    { .name = "SDCR", .type = ARM_CP_ALIAS,
> -      .cp = 15, .opc1 = 0, .crn = 1, .crm = 3, .opc2 = 1,
> -      .access = PL1_RW, .accessfn = access_trap_aa32s_el1,
> -      .fieldoffset = offsetoflow32(CPUARMState, cp15.mdcr_el3) },
>      { .name = "SDER32_EL3", .state = ARM_CP_STATE_AA64,
>        .opc0 = 3, .opc1 = 6, .crn = 1, .crm = 1, .opc2 = 1,
>        .access = PL3_RW, .resetvalue = 0,
Peter Maydell Feb. 19, 2016, 4:38 p.m. UTC | #2
On 19 February 2016 at 16:31, Sergey Fedorov <serge.fdrv@gmail.com> wrote:
> On 19.02.2016 17:39, Peter Maydell wrote:
>> +static void sdcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
>> +                       uint64_t value)
>> +{
>> +    env->cp15.mdcr_el3 = value & SDCR_VALID_MASK;
>> +}
>> +
>
> Just one comment. As soon as we cannot have both of MDCR_EL3 in SDCR in
> a specific CPU configuration (EL3 is either AArch64 or AArch32), the
> RES0 bitfields of SDCR are "RES0 in all contexts". Thus we can choose
> "The bit is hardwired to 0" behaviour as we do here. We could also
> choose another behaviour "The bit can be written" and check for "EL3 is
> AArch64" case before trying to interpret those bits.

Yes, as you say we could do either (and we have examples of both in
QEMU currently, as well as examples of "we don't do either and if
the guest writes in a bit it should not it will get a feature it
shouldn't in theory have"). Masking on write seemed simpler here.

thanks
-- PMM
Alistair Francis Feb. 22, 2016, 6:08 p.m. UTC | #3
On Fri, Feb 19, 2016 at 6:39 AM, Peter Maydell <peter.maydell@linaro.org> wrote:
> Fix two issues with our implementation of the SDCR:
>  * it is only present from ARMv8 onwards
>  * it does not contain several of the trap bits present in its 64-bit
>    counterpart the MDCR_EL3
>
> Put the register description in the right place so that it does not
> get enabled for ARMv7 and earlier, and give it a write function so that
> we can mask out the bits which should not be allowed to have an effect
> if EL3 is 32-bit.
>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

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

Thanks,

Alistair

> ---
>  target-arm/cpu.h    |  4 ++++
>  target-arm/helper.c | 23 +++++++++++++++--------
>  2 files changed, 19 insertions(+), 8 deletions(-)
>
diff mbox

Patch

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index e72e33b..a729ae0 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -599,6 +599,7 @@  void pmccntr_sync(CPUARMState *env);
 #define MDCR_EDAD     (1U << 20)
 #define MDCR_SPME     (1U << 17)
 #define MDCR_SDD      (1U << 16)
+#define MDCR_SPD      (3U << 14)
 #define MDCR_TDRA     (1U << 11)
 #define MDCR_TDOSA    (1U << 10)
 #define MDCR_TDA      (1U << 9)
@@ -607,6 +608,9 @@  void pmccntr_sync(CPUARMState *env);
 #define MDCR_TPM      (1U << 6)
 #define MDCR_TPMCR    (1U << 5)
 
+/* Not all of the MDCR_EL3 bits are present in the 32-bit SDCR */
+#define SDCR_VALID_MASK (MDCR_EPMAD | MDCR_EDAD | MDCR_SPME | MDCR_SPD)
+
 #define CPSR_M (0x1fU)
 #define CPSR_T (1U << 5)
 #define CPSR_F (1U << 6)
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 3d7fda1..e9b89e6 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -3037,6 +3037,12 @@  static CPAccessResult fpexc32_access(CPUARMState *env, const ARMCPRegInfo *ri,
     return CP_ACCESS_OK;
 }
 
+static void sdcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
+                       uint64_t value)
+{
+    env->cp15.mdcr_el3 = value & SDCR_VALID_MASK;
+}
+
 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.
@@ -3331,6 +3337,15 @@  static const ARMCPRegInfo v8_cp_reginfo[] = {
       .opc0 = 3, .opc1 = 4, .crn = 4, .crm = 3, .opc2 = 3,
       .access = PL2_RW,
       .fieldoffset = offsetof(CPUARMState, banked_spsr[BANK_FIQ]) },
+    { .name = "MDCR_EL3", .state = ARM_CP_STATE_AA64,
+      .opc0 = 3, .opc1 = 6, .crn = 1, .crm = 3, .opc2 = 1,
+      .resetvalue = 0,
+      .access = PL3_RW, .fieldoffset = offsetof(CPUARMState, cp15.mdcr_el3) },
+    { .name = "SDCR", .type = ARM_CP_ALIAS,
+      .cp = 15, .opc1 = 0, .crn = 1, .crm = 3, .opc2 = 1,
+      .access = PL1_RW, .accessfn = access_trap_aa32s_el1,
+      .writefn = sdcr_write,
+      .fieldoffset = offsetoflow32(CPUARMState, cp15.mdcr_el3) },
     REGINFO_SENTINEL
 };
 
@@ -3688,14 +3703,6 @@  static const ARMCPRegInfo el3_cp_reginfo[] = {
       .access = PL1_RW, .accessfn = access_trap_aa32s_el1,
       .fieldoffset = offsetoflow32(CPUARMState, cp15.scr_el3),
       .writefn = scr_write },
-    { .name = "MDCR_EL3", .state = ARM_CP_STATE_AA64,
-      .opc0 = 3, .opc1 = 6, .crn = 1, .crm = 3, .opc2 = 1,
-      .resetvalue = 0,
-      .access = PL3_RW, .fieldoffset = offsetof(CPUARMState, cp15.mdcr_el3) },
-    { .name = "SDCR", .type = ARM_CP_ALIAS,
-      .cp = 15, .opc1 = 0, .crn = 1, .crm = 3, .opc2 = 1,
-      .access = PL1_RW, .accessfn = access_trap_aa32s_el1,
-      .fieldoffset = offsetoflow32(CPUARMState, cp15.mdcr_el3) },
     { .name = "SDER32_EL3", .state = ARM_CP_STATE_AA64,
       .opc0 = 3, .opc1 = 6, .crn = 1, .crm = 1, .opc2 = 1,
       .access = PL3_RW, .resetvalue = 0,