target/arm: Fix fault reporting in get_phys_addr_lpae

Always overriding fi->type was incorrect, as we would not properly
propagate the fault type from S1_ptw_translate, or arm_ldq_ptw.
Simplify things by providing a new label for a translation fault.
For other faults, store into fi directly.

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Message-id: 20221024051851.3074715-9-richard.henderson@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Richard Henderson 2022-10-24 15:18:45 +10:00 committed by Peter Maydell
parent fe4ddc151b
commit 27c1b81d61
1 changed files with 13 additions and 18 deletions

View File

@ -1044,8 +1044,6 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
ARMCPU *cpu = env_archcpu(env); ARMCPU *cpu = env_archcpu(env);
ARMMMUIdx mmu_idx = ptw->in_mmu_idx; ARMMMUIdx mmu_idx = ptw->in_mmu_idx;
bool is_secure = ptw->in_secure; bool is_secure = ptw->in_secure;
/* Read an LPAE long-descriptor translation table. */
ARMFaultType fault_type = ARMFault_Translation;
uint32_t level; uint32_t level;
ARMVAParameters param; ARMVAParameters param;
uint64_t ttbr; uint64_t ttbr;
@ -1082,8 +1080,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
* so our choice is to always raise the fault. * so our choice is to always raise the fault.
*/ */
if (param.tsz_oob) { if (param.tsz_oob) {
fault_type = ARMFault_Translation; goto do_translation_fault;
goto do_fault;
} }
addrsize = 64 - 8 * param.tbi; addrsize = 64 - 8 * param.tbi;
@ -1120,8 +1117,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
addrsize - inputsize); addrsize - inputsize);
if (-top_bits != param.select) { if (-top_bits != param.select) {
/* The gap between the two regions is a Translation fault */ /* The gap between the two regions is a Translation fault */
fault_type = ARMFault_Translation; goto do_translation_fault;
goto do_fault;
} }
} }
@ -1147,7 +1143,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
* Translation table walk disabled => Translation fault on TLB miss * Translation table walk disabled => Translation fault on TLB miss
* Note: This is always 0 on 64-bit EL2 and EL3. * Note: This is always 0 on 64-bit EL2 and EL3.
*/ */
goto do_fault; goto do_translation_fault;
} }
if (!regime_is_stage2(mmu_idx)) { if (!regime_is_stage2(mmu_idx)) {
@ -1178,8 +1174,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
if (param.ds && stride == 9 && sl2) { if (param.ds && stride == 9 && sl2) {
if (sl0 != 0) { if (sl0 != 0) {
level = 0; level = 0;
fault_type = ARMFault_Translation; goto do_translation_fault;
goto do_fault;
} }
startlevel = -1; startlevel = -1;
} else if (!aarch64 || stride == 9) { } else if (!aarch64 || stride == 9) {
@ -1198,8 +1193,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
ok = check_s2_mmu_setup(cpu, aarch64, startlevel, ok = check_s2_mmu_setup(cpu, aarch64, startlevel,
inputsize, stride, outputsize); inputsize, stride, outputsize);
if (!ok) { if (!ok) {
fault_type = ARMFault_Translation; goto do_translation_fault;
goto do_fault;
} }
level = startlevel; level = startlevel;
} }
@ -1221,7 +1215,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
descaddr |= extract64(ttbr, 2, 4) << 48; descaddr |= extract64(ttbr, 2, 4) << 48;
} else if (descaddr >> outputsize) { } else if (descaddr >> outputsize) {
level = 0; level = 0;
fault_type = ARMFault_AddressSize; fi->type = ARMFault_AddressSize;
goto do_fault; goto do_fault;
} }
@ -1282,7 +1276,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
if (!(descriptor & 1) || (!(descriptor & 2) && (level == 3))) { if (!(descriptor & 1) || (!(descriptor & 2) && (level == 3))) {
/* Invalid, or the Reserved level 3 encoding */ /* Invalid, or the Reserved level 3 encoding */
goto do_fault; goto do_translation_fault;
} }
descaddr = descriptor & descaddrmask; descaddr = descriptor & descaddrmask;
@ -1300,7 +1294,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
descaddr |= extract64(descriptor, 12, 4) << 48; descaddr |= extract64(descriptor, 12, 4) << 48;
} }
} else if (descaddr >> outputsize) { } else if (descaddr >> outputsize) {
fault_type = ARMFault_AddressSize; fi->type = ARMFault_AddressSize;
goto do_fault; goto do_fault;
} }
@ -1357,9 +1351,9 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
* Here descaddr is the final physical address, and attributes * Here descaddr is the final physical address, and attributes
* are all in attrs. * are all in attrs.
*/ */
fault_type = ARMFault_AccessFlag;
if ((attrs & (1 << 8)) == 0) { if ((attrs & (1 << 8)) == 0) {
/* Access flag */ /* Access flag */
fi->type = ARMFault_AccessFlag;
goto do_fault; goto do_fault;
} }
@ -1376,8 +1370,8 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
result->f.prot = get_S1prot(env, mmu_idx, aarch64, ap, ns, xn, pxn); result->f.prot = get_S1prot(env, mmu_idx, aarch64, ap, ns, xn, pxn);
} }
fault_type = ARMFault_Permission;
if (!(result->f.prot & (1 << access_type))) { if (!(result->f.prot & (1 << access_type))) {
fi->type = ARMFault_Permission;
goto do_fault; goto do_fault;
} }
@ -1422,8 +1416,9 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
result->f.lg_page_size = ctz64(page_size); result->f.lg_page_size = ctz64(page_size);
return false; return false;
do_fault: do_translation_fault:
fi->type = fault_type; fi->type = ARMFault_Translation;
do_fault:
fi->level = level; fi->level = level;
/* Tag the error as S2 for failed S1 PTW at S2 or ordinary S2. */ /* Tag the error as S2 for failed S1 PTW at S2 or ordinary S2. */
fi->stage2 = fi->s1ptw || regime_is_stage2(mmu_idx); fi->stage2 = fi->s1ptw || regime_is_stage2(mmu_idx);