[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 12/14] target/arm/ptw: Check for block descriptors at invalid lev
From: |
Peter Maydell |
Subject: |
[PATCH 12/14] target/arm/ptw: Check for block descriptors at invalid levels |
Date: |
Fri, 14 Jul 2023 16:46:46 +0100 |
The architecture doesn't permit block descriptors at any arbitrary
level of the page table walk; it depends on the granule size which
levels are permitted. We implemented only a partial version of this
check which assumes that block descriptors are valid at all levels
except level 3, which meant that we wouldn't deliver the Translation
fault for all cases of this sort of guest page table error.
Implement the logic corresponding to the pseudocode
AArch64.DecodeDescriptorType() and AArch64.BlockDescSupported().
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
target/arm/ptw.c | 25 +++++++++++++++++++++++--
1 file changed, 23 insertions(+), 2 deletions(-)
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
index e4210abc148..ed46bb82a75 100644
--- a/target/arm/ptw.c
+++ b/target/arm/ptw.c
@@ -1549,6 +1549,25 @@ static int check_s2_mmu_setup(ARMCPU *cpu, bool is_aa64,
uint64_t tcr,
return INT_MIN;
}
+static bool lpae_block_desc_valid(ARMCPU *cpu, bool ds,
+ ARMGranuleSize gran, int level)
+{
+ /*
+ * See pseudocode AArch46.BlockDescSupported(): block descriptors
+ * are not valid at all levels, depending on the page size.
+ */
+ switch (gran) {
+ case Gran4K:
+ return (level == 0 && ds) || level == 1 || level == 2;
+ case Gran16K:
+ return (level == 1 && ds) || level == 2;
+ case Gran64K:
+ return (level == 1 && arm_pamax(cpu) == 52) || level == 2;
+ default:
+ g_assert_not_reached();
+ }
+}
+
/**
* get_phys_addr_lpae: perform one stage of page table walk, LPAE format
*
@@ -1784,8 +1803,10 @@ static bool get_phys_addr_lpae(CPUARMState *env,
S1Translate *ptw,
new_descriptor = descriptor;
restart_atomic_update:
- if (!(descriptor & 1) || (!(descriptor & 2) && (level == 3))) {
- /* Invalid, or the Reserved level 3 encoding */
+ if (!(descriptor & 1) ||
+ (!(descriptor & 2) &&
+ !lpae_block_desc_valid(cpu, param.ds, param.gran, level))) {
+ /* Invalid, or a block descriptor at an invalid level */
goto do_translation_fault;
}
--
2.34.1
- Re: [PATCH 06/14] target/arm/ptw: Pass an ARMSecuritySpace to arm_hcr_el2_eff_secstate(), (continued)
[PATCH 11/14] target/arm/ptw: Set attributes correctly for MMU disabled data accesses, Peter Maydell, 2023/07/14
[PATCH 10/14] target/arm/ptw: Drop S1Translate::out_secure, Peter Maydell, 2023/07/14
[PATCH 13/14] target/arm/ptw: Report stage 2 fault level for stage 2 faults on stage 1 ptw, Peter Maydell, 2023/07/14
[PATCH 14/14] target/arm: Adjust PAR_EL1.SH for Device and Normal-NC memory types, Peter Maydell, 2023/07/14
[PATCH 12/14] target/arm/ptw: Check for block descriptors at invalid levels,
Peter Maydell <=
[PATCH 03/14] target/arm/ptw: Set s1ns bit in fault info more consistently, Peter Maydell, 2023/07/14