aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2022-03-01 11:59:51 -1000
committerPeter Maydell <peter.maydell@linaro.org>2022-03-02 19:27:37 +0000
commit13e481c9335582fc7eed12e24e8d4d7068b24ff8 (patch)
tree9f3067dfc1fc44e07a7af082acc3c6d0185f89c8
parent7a928f43d8724bdf0777d7fc67a5ad973a0bf4bf (diff)
target/arm: Extend arm_fi_to_lfsc to level -1
With FEAT_LPA2, rather than introducing translation level 4, we introduce level -1, below the current level 0. Extend arm_fi_to_lfsc to handle these faults. Assert that this new translation level does not leak into fault types for which it is not defined, which allows some masking of fi->level to be removed. Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20220301215958.157011-12-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--target/arm/internals.h35
1 files changed, 29 insertions, 6 deletions
diff --git a/target/arm/internals.h b/target/arm/internals.h
index 3d3d41ba2b..00af41d792 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -462,28 +462,51 @@ static inline uint32_t arm_fi_to_lfsc(ARMMMUFaultInfo *fi)
case ARMFault_None:
return 0;
case ARMFault_AddressSize:
- fsc = fi->level & 3;
+ assert(fi->level >= -1 && fi->level <= 3);
+ if (fi->level < 0) {
+ fsc = 0b101001;
+ } else {
+ fsc = fi->level;
+ }
break;
case ARMFault_AccessFlag:
- fsc = (fi->level & 3) | (0x2 << 2);
+ assert(fi->level >= 0 && fi->level <= 3);
+ fsc = 0b001000 | fi->level;
break;
case ARMFault_Permission:
- fsc = (fi->level & 3) | (0x3 << 2);
+ assert(fi->level >= 0 && fi->level <= 3);
+ fsc = 0b001100 | fi->level;
break;
case ARMFault_Translation:
- fsc = (fi->level & 3) | (0x1 << 2);
+ assert(fi->level >= -1 && fi->level <= 3);
+ if (fi->level < 0) {
+ fsc = 0b101011;
+ } else {
+ fsc = 0b000100 | fi->level;
+ }
break;
case ARMFault_SyncExternal:
fsc = 0x10 | (fi->ea << 12);
break;
case ARMFault_SyncExternalOnWalk:
- fsc = (fi->level & 3) | (0x5 << 2) | (fi->ea << 12);
+ assert(fi->level >= -1 && fi->level <= 3);
+ if (fi->level < 0) {
+ fsc = 0b010011;
+ } else {
+ fsc = 0b010100 | fi->level;
+ }
+ fsc |= fi->ea << 12;
break;
case ARMFault_SyncParity:
fsc = 0x18;
break;
case ARMFault_SyncParityOnWalk:
- fsc = (fi->level & 3) | (0x7 << 2);
+ assert(fi->level >= -1 && fi->level <= 3);
+ if (fi->level < 0) {
+ fsc = 0b011011;
+ } else {
+ fsc = 0b011100 | fi->level;
+ }
break;
case ARMFault_AsyncParity:
fsc = 0x19;