Commit c5b367835cfc ("MIPS: Add support for XPA.") changed build_pte_present() and build_pte_writable() to assume a constant offset of _PAGE_READ and _PAGE_WRITE relative to _PAGE_PRESENT, however this is no longer true for some MIPS32R2 builds since commit be0c37c985ed ("MIPS: Rearrange PTE bits into fixed positions.") which moved the _PAGE_READ PTE bit away from the _PAGE_PRESENT bit, with the _PAGE_WRITE bit falling into its place. Make use of the _PAGE_READ and _PAGE_WRITE definitions to calculate the correct mask to apply instead of hard coding 3 (for _PAGE_PRESENT | _PAGE_READ) or 5 (for _PAGE_PRESENT | _PAGE_WRITE). Fixes: c5b367835cfc ("MIPS: Add support for XPA.") Signed-off-by: James Hogan <james.hogan@xxxxxxxxxx> Cc: Ralf Baechle <ralf@xxxxxxxxxxxxxx> Cc: Steven J. Hill <Steven.Hill@xxxxxxxxxx> Cc: linux-mips@xxxxxxxxxxxxxx --- I hit a hang during boot on v4.1-rc1 KVM guest kernels, where its continuously trying to service a TLB miss for a page which is apparently _PAGE_READ but not _PAGE_WRITE, but since the TLBL handler (build_pte_present()) ends up incorrectly testing _PAGE_WRITE, it just keeps calling into C code instead of making the PTE valid and updating the TLB entry. The build_pte_present() part of this patch fixes it, but its still not entirely clear to me why I cannot reproduce the problem in other MIPS R2 environments without RIXI. --- arch/mips/mm/tlbex.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index 97c87027c17f..d998fea7fc93 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -1623,8 +1623,10 @@ build_pte_present(u32 **p, struct uasm_reloc **r, } } else { uasm_i_srl(p, t, pte, _PAGE_PRESENT_SHIFT); - uasm_i_andi(p, t, t, 3); - uasm_i_xori(p, t, t, 3); + uasm_i_andi(p, t, t, + (_PAGE_PRESENT | _PAGE_READ) >> _PAGE_PRESENT_SHIFT); + uasm_i_xori(p, t, t, + (_PAGE_PRESENT | _PAGE_READ) >> _PAGE_PRESENT_SHIFT); uasm_il_bnez(p, r, t, lid); if (pte == t) /* You lose the SMP race :-(*/ @@ -1654,8 +1656,10 @@ build_pte_writable(u32 **p, struct uasm_reloc **r, int t = scratch >= 0 ? scratch : pte; uasm_i_srl(p, t, pte, _PAGE_PRESENT_SHIFT); - uasm_i_andi(p, t, t, 5); - uasm_i_xori(p, t, t, 5); + uasm_i_andi(p, t, t, + (_PAGE_PRESENT | _PAGE_WRITE) >> _PAGE_PRESENT_SHIFT); + uasm_i_xori(p, t, t, + (_PAGE_PRESENT | _PAGE_WRITE) >> _PAGE_PRESENT_SHIFT); uasm_il_bnez(p, r, t, lid); if (pte == t) /* You lose the SMP race :-(*/ -- 2.0.5