powerpc/8xx: Don't set IMMR map anymore at boot
authorChristophe Leroy <christophe.leroy@csgroup.eu>
Tue, 19 May 2020 05:49:14 +0000 (05:49 +0000)
committerMichael Ellerman <mpe@ellerman.id.au>
Tue, 26 May 2020 12:22:21 +0000 (22:22 +1000)
Only early debug requires IMMR to be mapped early.

No need to set it up and pin it in assembly. Map it
through page tables at udbg init when necessary.

If CONFIG_PIN_TLB_IMMR is selected, pin it once we
don't need the 32 Mb pinned RAM anymore.

Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/13c1e8539fdf363d3146f4884e5c3c76c6c308b5.1589866984.git.christophe.leroy@csgroup.eu
arch/powerpc/kernel/head_8xx.S
arch/powerpc/mm/mmu_decl.h
arch/powerpc/mm/nohash/8xx.c
arch/powerpc/platforms/8xx/Kconfig
arch/powerpc/sysdev/cpm_common.c

index c9e3d54e6a6f19af11b293931bb7af07a8c51152..d607f4b53e0fd051c2d251276711a5e290608933 100644 (file)
@@ -749,6 +749,23 @@ start_here:
        rfi
 /* Load up the kernel context */
 2:
+#ifdef CONFIG_PIN_TLB_IMMR
+       lis     r0, MD_TWAM@h
+       oris    r0, r0, 0x1f00
+       mtspr   SPRN_MD_CTR, r0
+       LOAD_REG_IMMEDIATE(r0, VIRT_IMMR_BASE | MD_EVALID)
+       tlbie   r0
+       mtspr   SPRN_MD_EPN, r0
+       LOAD_REG_IMMEDIATE(r0, MD_SVALID | MD_PS512K | MD_GUARDED)
+       mtspr   SPRN_MD_TWC, r0
+       mfspr   r0, SPRN_IMMR
+       rlwinm  r0, r0, 0, 0xfff80000
+       ori     r0, r0, 0xf0 | _PAGE_DIRTY | _PAGE_SPS | _PAGE_SH | \
+                       _PAGE_NO_CACHE | _PAGE_PRESENT
+       mtspr   SPRN_MD_RPN, r0
+       lis     r0, (MD_TWAM | MD_RSV4I)@h
+       mtspr   SPRN_MD_CTR, r0
+#endif
        tlbia                   /* Clear all TLB entries */
        sync                    /* wait for tlbia/tlbie to finish */
 
@@ -797,28 +814,6 @@ initial_mmu:
        ori     r8, r8, MD_APG_INIT@l
        mtspr   SPRN_MD_AP, r8
 
-       /* Map a 512k page for the IMMR to get the processor
-        * internal registers (among other things).
-        */
-#ifdef CONFIG_PIN_TLB_IMMR
-       oris    r10, r10, MD_RSV4I@h
-       ori     r10, r10, 0x1c00
-       mtspr   SPRN_MD_CTR, r10
-
-       mfspr   r9, 638                 /* Get current IMMR */
-       andis.  r9, r9, 0xfff8          /* Get 512 kbytes boundary */
-
-       lis     r8, VIRT_IMMR_BASE@h    /* Create vaddr for TLB */
-       ori     r8, r8, MD_EVALID       /* Mark it valid */
-       mtspr   SPRN_MD_EPN, r8
-       li      r8, MD_PS512K | MD_GUARDED      /* Set 512k byte page */
-       ori     r8, r8, MD_SVALID       /* Make it valid */
-       mtspr   SPRN_MD_TWC, r8
-       mr      r8, r9                  /* Create paddr for TLB */
-       ori     r8, r8, MI_BOOTINIT|0x2 /* Inhibit cache -- Cort */
-       mtspr   SPRN_MD_RPN, r8
-#endif
-
        /* Now map the lower RAM (up to 32 Mbytes) into the ITLB. */
 #ifdef CONFIG_PIN_TLB_TEXT
        lis     r8, MI_RSV4I@h
index 7097e07a209a75589f2b5f8afe25491d1e5a0f5d..1b6d39e9baed875efa52ce54a4a87ace507ca511 100644 (file)
@@ -182,6 +182,10 @@ static inline void mmu_mark_initmem_nx(void) { }
 static inline void mmu_mark_rodata_ro(void) { }
 #endif
 
+#ifdef CONFIG_PPC_8xx
+void __init mmu_mapin_immr(void);
+#endif
+
 #ifdef CONFIG_PPC_DEBUG_WX
 void ptdump_check_wx(void);
 #else
index b27017109a36adb18dc0e81972b636384e2ee7f8..44cbde7612cbdf94e218eff5d15cfaa1d0341a5f 100644 (file)
@@ -66,7 +66,7 @@ void __init MMU_init_hw(void)
        if (IS_ENABLED(CONFIG_PIN_TLB_DATA)) {
                unsigned long ctr = mfspr(SPRN_MD_CTR) & 0xfe000000;
                unsigned long flags = 0xf0 | MD_SPS16K | _PAGE_SH | _PAGE_DIRTY;
-               int i = IS_ENABLED(CONFIG_PIN_TLB_IMMR) ? 29 : 28;
+               int i = 28;
                unsigned long addr = 0;
                unsigned long mem = total_lowmem;
 
@@ -81,12 +81,19 @@ void __init MMU_init_hw(void)
        }
 }
 
-static void __init mmu_mapin_immr(void)
+static bool immr_is_mapped __initdata;
+
+void __init mmu_mapin_immr(void)
 {
        unsigned long p = PHYS_IMMR_BASE;
        unsigned long v = VIRT_IMMR_BASE;
        int offset;
 
+       if (immr_is_mapped)
+               return;
+
+       immr_is_mapped = true;
+
        for (offset = 0; offset < IMMR_SIZE; offset += PAGE_SIZE)
                map_kernel_page(v + offset, p + offset, PAGE_KERNEL_NCG);
 }
@@ -122,9 +129,10 @@ unsigned long __init mmu_mapin_ram(unsigned long base, unsigned long top)
 {
        unsigned long mapped;
 
+       mmu_mapin_immr();
+
        if (__map_without_ltlbs) {
                mapped = 0;
-               mmu_mapin_immr();
                if (!IS_ENABLED(CONFIG_PIN_TLB_IMMR))
                        patch_instruction_site(&patch__dtlbmiss_immr_jmp, ppc_inst(PPC_INST_NOP));
                if (!IS_ENABLED(CONFIG_PIN_TLB_TEXT))
@@ -143,7 +151,6 @@ unsigned long __init mmu_mapin_ram(unsigned long base, unsigned long top)
                 */
                mmu_mapin_ram_chunk(0, einittext8, PAGE_KERNEL_X);
                mmu_mapin_ram_chunk(einittext8, mapped, PAGE_KERNEL);
-               mmu_mapin_immr();
        }
 
        mmu_patch_cmp_limit(&patch__dtlbmiss_linmem_top, mapped);
index 0d036cd868ef5f202040d1d257a3c0edefe0c799..04ea1a8a0bdc8e1947eb66b27f90beb8d461968c 100644 (file)
@@ -187,7 +187,7 @@ config PIN_TLB_DATA
 
 config PIN_TLB_IMMR
        bool "Pinned TLB for IMMR"
-       depends on PIN_TLB || PPC_EARLY_DEBUG_CPM
+       depends on PIN_TLB
        default y
        help
          This pins the IMMR area with a 512kbytes page. In case
index 71660bacb264b13a6241586d5151b72d4b83803a..7dc1960f8bdb5e2267c85ac1ba7b9798a34a1b58 100644 (file)
@@ -68,6 +68,8 @@ static void udbg_putc_cpm(char c)
 void __init udbg_init_cpm(void)
 {
 #ifdef CONFIG_PPC_8xx
+       mmu_mapin_immr();
+
        cpm_udbg_txdesc = (u32 __iomem __force *)
                          (CONFIG_PPC_EARLY_DEBUG_CPM_ADDR - PHYS_IMMR_BASE +
                           VIRT_IMMR_BASE);