Patchwork [PULL,7/8] target-arm: avoid undefined behaviour when writing TTBCR

login
register
mail settings
Submitter Peter Maydell
Date July 15, 2013, 4:17 p.m.
Message ID <1373905022-27735-8-git-send-email-peter.maydell@linaro.org>
Download mbox | patch
Permalink /patch/259109/
State New
Headers show

Comments

Peter Maydell - July 15, 2013, 4:17 p.m.
LPAE CPUs have more potentially valid bits in the TTBCR, and so the
simple masking out of invalid bits is no longer sufficient to obtain
the base address width field of the register, which is what we use to
precalculate c2_mask and c2_base_mask.  Explicitly extract the
relevant register field rather than simply shifting by the register
value.

This bug would have had no ill effects in practice, since if the
EAE bit (TTBCR bit 31) is set then we don't use the precalculated
masks, and if EAE is zero then bits 30..3 are all UNK/SBZP, so
well-behaved guests won't set them. However the shift is undefined
behaviour, so we should avoid it.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 1372347527-4428-1-git-send-email-peter.maydell@linaro.org
---
 target-arm/helper.c |    6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

Patch

diff --git a/target-arm/helper.c b/target-arm/helper.c
index b7c926d..57fa8c8 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -891,6 +891,8 @@  static const ARMCPRegInfo pmsav5_cp_reginfo[] = {
 static int vmsa_ttbcr_raw_write(CPUARMState *env, const ARMCPRegInfo *ri,
                                 uint64_t value)
 {
+    int maskshift = extract32(value, 0, 3);
+
     if (arm_feature(env, ARM_FEATURE_LPAE)) {
         value &= ~((7 << 19) | (3 << 14) | (0xf << 3));
     } else {
@@ -902,8 +904,8 @@  static int vmsa_ttbcr_raw_write(CPUARMState *env, const ARMCPRegInfo *ri,
      * and the c2_mask and c2_base_mask values are meaningless.
      */
     env->cp15.c2_control = value;
-    env->cp15.c2_mask = ~(((uint32_t)0xffffffffu) >> value);
-    env->cp15.c2_base_mask = ~((uint32_t)0x3fffu >> value);
+    env->cp15.c2_mask = ~(((uint32_t)0xffffffffu) >> maskshift);
+    env->cp15.c2_base_mask = ~((uint32_t)0x3fffu >> maskshift);
     return 0;
 }