aboutsummaryrefslogtreecommitdiff
path: root/target/ppc/mmu-radix64.c
diff options
context:
space:
mode:
authorLeandro Lupori <leandro.lupori@eldorado.org.br>2022-06-28 10:39:59 -0300
committerDaniel Henrique Barboza <danielhb413@gmail.com>2022-07-18 13:59:43 -0300
commitd2066bc50d690a6605307eaf0e72a9cf51e6fc25 (patch)
treeab23c55d87b7e6c9ccf17692b830ca2548a1fc1b /target/ppc/mmu-radix64.c
parent47e83d9107887c867bad8900ed39e83b79110b66 (diff)
downloadqemu-d2066bc50d690a6605307eaf0e72a9cf51e6fc25.zip
qemu-d2066bc50d690a6605307eaf0e72a9cf51e6fc25.tar.gz
qemu-d2066bc50d690a6605307eaf0e72a9cf51e6fc25.tar.bz2
target/ppc: Check page dir/table base alignment
According to PowerISA 3.1B, Book III 6.7.6 programming note, the page directory base addresses are expected to be aligned to their size. Real hardware seems to rely on that and will access the wrong address if they are misaligned. This results in a translation failure even if the page tables seem to be properly populated. Signed-off-by: Leandro Lupori <leandro.lupori@eldorado.org.br> Reviewed-by: Daniel Henrique Barboza <danielhb413@gmail.com> Message-Id: <20220628133959.15131-4-leandro.lupori@eldorado.org.br> Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com>
Diffstat (limited to 'target/ppc/mmu-radix64.c')
-rw-r--r--target/ppc/mmu-radix64.c28
1 files changed, 24 insertions, 4 deletions
diff --git a/target/ppc/mmu-radix64.c b/target/ppc/mmu-radix64.c
index 705bff7..00f2e9f 100644
--- a/target/ppc/mmu-radix64.c
+++ b/target/ppc/mmu-radix64.c
@@ -265,7 +265,7 @@ static int ppc_radix64_next_level(AddressSpace *as, vaddr eaddr,
uint64_t *pte_addr, uint64_t *nls,
int *psize, uint64_t *pte, int *fault_cause)
{
- uint64_t index, pde;
+ uint64_t index, mask, nlb, pde;
/* Read page <directory/table> entry from guest address space */
pde = ldq_phys(as, *pte_addr);
@@ -280,7 +280,17 @@ static int ppc_radix64_next_level(AddressSpace *as, vaddr eaddr,
*nls = pde & R_PDE_NLS;
index = eaddr >> (*psize - *nls); /* Shift */
index &= ((1UL << *nls) - 1); /* Mask */
- *pte_addr = (pde & R_PDE_NLB) + (index * sizeof(pde));
+ nlb = pde & R_PDE_NLB;
+ mask = MAKE_64BIT_MASK(0, *nls + 3);
+
+ if (nlb & mask) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: misaligned page dir/table base: 0x"TARGET_FMT_lx
+ " page dir size: 0x"TARGET_FMT_lx"\n",
+ __func__, nlb, mask + 1);
+ nlb &= ~mask;
+ }
+ *pte_addr = nlb + index * sizeof(pde);
}
return 0;
}
@@ -294,8 +304,18 @@ static int ppc_radix64_walk_tree(AddressSpace *as, vaddr eaddr,
int level = 0;
index = eaddr >> (*psize - nls); /* Shift */
- index &= ((1UL << nls) - 1); /* Mask */
- *pte_addr = base_addr + (index * sizeof(pde));
+ index &= ((1UL << nls) - 1); /* Mask */
+ mask = MAKE_64BIT_MASK(0, nls + 3);
+
+ if (base_addr & mask) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: misaligned page dir base: 0x"TARGET_FMT_lx
+ " page dir size: 0x"TARGET_FMT_lx"\n",
+ __func__, base_addr, mask + 1);
+ base_addr &= ~mask;
+ }
+ *pte_addr = base_addr + index * sizeof(pde);
+
do {
int ret;