Leandro Lupori <leandro.lup...@eldorado.org.br> writes: > Check if each page dir/table base address is properly aligned and > log a guest error if not, as real hardware behave incorrectly in > this case.
I think the commit message could be clearer, something like: 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. Let's make sure we capture this assumption in the code to help anyone implementing page tables. > > Signed-off-by: Leandro Lupori <leandro.lup...@eldorado.org.br> > --- > target/ppc/mmu-radix64.c | 15 +++++++++++++++ > 1 file changed, 15 insertions(+) > > diff --git a/target/ppc/mmu-radix64.c b/target/ppc/mmu-radix64.c > index 339cf5b4d8..1e7d932893 100644 > --- a/target/ppc/mmu-radix64.c > +++ b/target/ppc/mmu-radix64.c > @@ -280,6 +280,14 @@ static int ppc_radix64_next_level(AddressSpace *as, > vaddr eaddr, > *psize -= *nls; > if (!(pde & R_PTE_LEAF)) { /* Prepare for next iteration */ > *nls = pde & R_PDE_NLS; > + > + if ((pde & R_PDE_NLB) & MAKE_64BIT_MASK(0, *nls + 3)) { > + qemu_log_mask(LOG_GUEST_ERROR, > + "%s: misaligned page dir/table base: 0x%"VADDR_PRIx > + " page dir size: 0x"TARGET_FMT_lx"\n", > + __func__, (pde & R_PDE_NLB), BIT(*nls + 3)); > + } > + > index = eaddr >> (*psize - *nls); /* Shift */ > index &= ((1UL << *nls) - 1); /* Mask */ > *pte_addr = (pde & R_PDE_NLB) + (index * sizeof(pde)); > @@ -295,6 +303,13 @@ static int ppc_radix64_walk_tree(AddressSpace *as, vaddr > eaddr, > uint64_t index, pde, rpn, mask; > int level = 0; > > + if (base_addr & MAKE_64BIT_MASK(0, nls + 3)) { > + qemu_log_mask(LOG_GUEST_ERROR, > + "%s: misaligned page dir base: 0x%"VADDR_PRIx > + " page dir size: 0x"TARGET_FMT_lx"\n", > + __func__, base_addr, BIT(nls + 3)); > + } > + > index = eaddr >> (*psize - nls); /* Shift */ > index &= ((1UL << nls) - 1); /* Mask */ > *pte_addr = base_addr + (index * sizeof(pde));