]> git.baikalelectronics.ru Git - kernel.git/commitdiff
powerpc/8xx: Fix pinned TLBs with CONFIG_STRICT_KERNEL_RWX
authorChristophe Leroy <christophe.leroy@csgroup.eu>
Mon, 15 Nov 2021 08:08:36 +0000 (09:08 +0100)
committerMichael Ellerman <mpe@ellerman.id.au>
Tue, 16 Nov 2021 10:37:10 +0000 (21:37 +1100)
As spotted and explained in commit 44cb53b7f213 ("powerpc/8xx: Fix
Oops with STRICT_KERNEL_RWX without DEBUG_RODATA_TEST"), the selection
of STRICT_KERNEL_RWX without selecting DEBUG_RODATA_TEST has spotted
the lack of the DIRTY bit in the pinned kernel data TLBs.

This problem should have been detected a lot earlier if things had
been working as expected. But due to an incredible level of chance or
mishap, this went undetected because of a set of bugs: In fact the
DTLBs were not pinned, because instead of setting the reserve bit
in MD_CTR, it was set in MI_CTR that is the register for ITLBs.

But then, another huge bug was there: the physical address was
reset to 0 at the boundary between RO and RW areas, leading to the
same physical space being mapped at both 0xc0000000 and 0xc8000000.
This had by miracle no consequence until now because the entry was
not really pinned so it was overwritten soon enough to go undetected.

Of course, now that we really pin the DTLBs, it must be fixed as well.

Fixes: 31dab2289ab5 ("powerpc/8xx: Add function to set pinned TLBs")
Cc: stable@vger.kernel.org # v5.8+
Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
Depends-on: 44cb53b7f213 ("powerpc/8xx: Fix Oops with STRICT_KERNEL_RWX without DEBUG_RODATA_TEST")
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/a21e9a057fe2d247a535aff0d157a54eefee017a.1636963688.git.christophe.leroy@csgroup.eu
arch/powerpc/kernel/head_8xx.S

index 2d596881b70e70c24627020ee3a31f36680ec945..0d073b9fd52c5b5ef0988fe4cdce4a8270113844 100644 (file)
@@ -733,6 +733,7 @@ _GLOBAL(mmu_pin_tlb)
 #ifdef CONFIG_PIN_TLB_DATA
        LOAD_REG_IMMEDIATE(r6, PAGE_OFFSET)
        LOAD_REG_IMMEDIATE(r7, MI_SVALID | MI_PS8MEG | _PMD_ACCESSED)
+       li      r8, 0
 #ifdef CONFIG_PIN_TLB_IMMR
        li      r0, 3
 #else
@@ -741,26 +742,26 @@ _GLOBAL(mmu_pin_tlb)
        mtctr   r0
        cmpwi   r4, 0
        beq     4f
-       LOAD_REG_IMMEDIATE(r8, 0xf0 | _PAGE_RO | _PAGE_SPS | _PAGE_SH | _PAGE_PRESENT)
        LOAD_REG_ADDR(r9, _sinittext)
 
 2:     ori     r0, r6, MD_EVALID
+       ori     r12, r8, 0xf0 | _PAGE_RO | _PAGE_SPS | _PAGE_SH | _PAGE_PRESENT
        mtspr   SPRN_MD_CTR, r5
        mtspr   SPRN_MD_EPN, r0
        mtspr   SPRN_MD_TWC, r7
-       mtspr   SPRN_MD_RPN, r8
+       mtspr   SPRN_MD_RPN, r12
        addi    r5, r5, 0x100
        addis   r6, r6, SZ_8M@h
        addis   r8, r8, SZ_8M@h
        cmplw   r6, r9
        bdnzt   lt, 2b
-
-4:     LOAD_REG_IMMEDIATE(r8, 0xf0 | _PAGE_DIRTY | _PAGE_SPS | _PAGE_SH | _PAGE_PRESENT)
+4:
 2:     ori     r0, r6, MD_EVALID
+       ori     r12, r8, 0xf0 | _PAGE_DIRTY | _PAGE_SPS | _PAGE_SH | _PAGE_PRESENT
        mtspr   SPRN_MD_CTR, r5
        mtspr   SPRN_MD_EPN, r0
        mtspr   SPRN_MD_TWC, r7
-       mtspr   SPRN_MD_RPN, r8
+       mtspr   SPRN_MD_RPN, r12
        addi    r5, r5, 0x100
        addis   r6, r6, SZ_8M@h
        addis   r8, r8, SZ_8M@h
@@ -781,7 +782,7 @@ _GLOBAL(mmu_pin_tlb)
 #endif
 #if defined(CONFIG_PIN_TLB_IMMR) || defined(CONFIG_PIN_TLB_DATA)
        lis     r0, (MD_RSV4I | MD_TWAM)@h
-       mtspr   SPRN_MI_CTR, r0
+       mtspr   SPRN_MD_CTR, r0
 #endif
        mtspr   SPRN_SRR1, r10
        mtspr   SPRN_SRR0, r11