]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
powerpc/8xx: Inconditionally use task PGDIR in DTLB misses
authorChristophe Leroy <christophe.leroy@csgroup.eu>
Tue, 20 Aug 2024 17:23:53 +0000 (19:23 +0200)
committerMichael Ellerman <mpe@ellerman.id.au>
Fri, 30 Aug 2024 11:29:53 +0000 (21:29 +1000)
At the time being, DATA TLB miss handlers use task PGDIR for user
addresses and swapper_pg_dir for kernel addresses.

Now that kernel part of swapper_pg_dir is copied into task PGDIR
at PGD allocation, it is possible to avoid the above logic and
always use task PGDIR.

But new kernel PGD entries can still be created after init, in
which case those PGD entries may miss in task PGDIR. This can be
handled in DATA TLB error handler.

However, it needs to be done in real mode because the missing
entry might be related to the stack.

So implement copy of missing PGD entry in the prolog of DATA TLB
ERROR handler just after the fixup of DAR.

Note that this is feasible because 8xx doesn't implement vmap or
ioremap with 8Mbytes pages but only 512kbytes pages which are at
PTE level.

Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://msgid.link/7a76a923d2a111f1d843d8b20b4df0c65d2f4a7b.1724173828.git.christophe.leroy@csgroup.eu
arch/powerpc/kernel/head_8xx.S

index f9a05648a52299d9b21b2996a6ed8c09fb1a8706..811a7130505cd40e37836707da6e6bdf842da4c2 100644 (file)
 
 #include "head_32.h"
 
-.macro compare_to_kernel_boundary scratch, addr
-#if CONFIG_TASK_SIZE <= 0x80000000 && MODULES_VADDR >= 0x80000000
-/* By simply checking Address >= 0x80000000, we know if its a kernel address */
-       not.    \scratch, \addr
-#else
-       rlwinm  \scratch, \addr, 16, 0xfff8
-       cmpli   cr0, \scratch, TASK_SIZE@h
-#endif
-.endm
-
 #define PAGE_SHIFT_512K                19
 #define PAGE_SHIFT_8M          23
 
@@ -237,19 +227,12 @@ instruction_counter:
        START_EXCEPTION(INTERRUPT_DATA_TLB_MISS_8xx, DataStoreTLBMiss)
        mtspr   SPRN_SPRG_SCRATCH2, r10
        mtspr   SPRN_M_TW, r11
-       mfcr    r11
 
        /* If we are faulting a kernel address, we have to use the
         * kernel page tables.
         */
        mfspr   r10, SPRN_MD_EPN
-       compare_to_kernel_boundary r10, r10
        mfspr   r10, SPRN_M_TWB /* Get level 1 table */
-       blt+    3f
-       rlwinm  r10, r10, 0, 20, 31
-       oris    r10, r10, (swapper_pg_dir - PAGE_OFFSET)@ha
-3:
-       mtcr    r11
        lwz     r11, (swapper_pg_dir-PAGE_OFFSET)@l(r10)        /* Get level 1 entry */
 
        mtspr   SPRN_MD_TWC, r11
@@ -321,15 +304,19 @@ instruction_counter:
        cmpwi   cr1, r11, RPN_PATTERN
        beq-    cr1, FixupDAR   /* must be a buggy dcbX, icbi insn. */
 DARFixed:/* Return from dcbx instruction bug workaround */
+       mfspr   r11, SPRN_DSISR
+       rlwinm  r11, r11, 0, DSISR_NOHPTE
+       cmpwi   cr1, r11, 0
+       beq+    cr1, .Ldtlbie
+       mfspr   r11, SPRN_DAR
+       tlbie   r11
+       rlwinm  r11, r11, 16, 0xffff
+       cmplwi  cr1, r11, TASK_SIZE@h
+       bge-    cr1, FixupPGD
+.Ldtlbie:
        EXCEPTION_PROLOG_1
        /* 0x300 is DataAccess exception, needed by bad_page_fault() */
        EXCEPTION_PROLOG_2 INTERRUPT_DATA_STORAGE DataTLBError handle_dar_dsisr=1
-       lwz     r4, _DAR(r11)
-       lwz     r5, _DSISR(r11)
-       andis.  r10,r5,DSISR_NOHPTE@h
-       beq+    .Ldtlbie
-       tlbie   r4
-.Ldtlbie:
        prepare_transfer_to_handler
        bl      do_page_fault
        b       interrupt_return
@@ -383,6 +370,30 @@ DARFixed:/* Return from dcbx instruction bug workaround */
        __HEAD
        . = 0x2000
 
+FixupPGD:
+       mtspr   SPRN_M_TW, r10
+       mfspr   r10, SPRN_DAR
+       mtspr   SPRN_MD_EPN, r10
+       mfspr   r11, SPRN_M_TWB /* Get level 1 table */
+       lwz     r10, (swapper_pg_dir - PAGE_OFFSET)@l(r11)      /* Get the level 1 entry */
+       cmpwi   cr1, r10, 0
+       bne     cr1, 1f
+
+       rlwinm  r10, r11, 0, 20, 31
+       oris    r10, r10, (swapper_pg_dir - PAGE_OFFSET)@ha
+       lwz     r10, (swapper_pg_dir - PAGE_OFFSET)@l(r10)      /* Get the level 1 entry */
+       cmpwi   cr1, r10, 0
+       beq     cr1, 1f
+       stw     r10, (swapper_pg_dir - PAGE_OFFSET)@l(r11)      /* Set the level 1 entry */
+       mfspr   r10, SPRN_M_TW
+       mtcr    r10
+       mfspr   r10, SPRN_SPRG_SCRATCH0
+       mfspr   r11, SPRN_SPRG_SCRATCH1
+       rfi
+1:
+       mfspr   r10, SPRN_M_TW
+       b       .Ldtlbie
+
 /* This is the procedure to calculate the data EA for buggy dcbx,dcbi instructions
  * by decoding the registers used by the dcbx instruction and adding them.
  * DAR is set to the calculated address.