This patch moves enabling TTBRx split from __v7_setup (v7_ttb_setup)
into cpu_init() which is called in init_mm context after leaving idmap.
Also it disables split in setup_mm_for_reboot() before switching mm to idmap.
After that idmap and VM split never meet, thus they no longer conflict.

Callback keystone_smp_secondary_initmem isn't required, all setup is
done in cpu_init() which is called right before smp_ops.smp_secondary_init.

Also this patch prepares code for enabling split in non-LPAE mode.

Signed-off-by: Konstantin Khlebnikov <[email protected]>
---
 arch/arm/include/asm/pgtable-2level-hwdef.h |    2 ++
 arch/arm/include/asm/pgtable-3level-hwdef.h |   12 +++++-------
 arch/arm/include/asm/proc-fns.h             |   13 +++++++++++++
 arch/arm/kernel/setup.c                     |   11 +++++++++++
 arch/arm/mach-keystone/platsmp.c            |   13 -------------
 arch/arm/mm/idmap.c                         |    6 ++++++
 arch/arm/mm/proc-v7-3level.S                |   13 -------------
 7 files changed, 37 insertions(+), 33 deletions(-)

diff --git a/arch/arm/include/asm/pgtable-2level-hwdef.h 
b/arch/arm/include/asm/pgtable-2level-hwdef.h
index 5cfba15..c2ed1fa 100644
--- a/arch/arm/include/asm/pgtable-2level-hwdef.h
+++ b/arch/arm/include/asm/pgtable-2level-hwdef.h
@@ -90,4 +90,6 @@
 
 #define PHYS_MASK              (~0UL)
 
+#define TTBR1_SIZE     0
+
 #endif
diff --git a/arch/arm/include/asm/pgtable-3level-hwdef.h 
b/arch/arm/include/asm/pgtable-3level-hwdef.h
index 9fd61c7..8bb32a0 100644
--- a/arch/arm/include/asm/pgtable-3level-hwdef.h
+++ b/arch/arm/include/asm/pgtable-3level-hwdef.h
@@ -89,19 +89,17 @@
  *   0x40000000: T0SZ = 2, T1SZ = 0 (not used)
  *   0x80000000: T0SZ = 0, T1SZ = 1
  *   0xc0000000: T0SZ = 0, T1SZ = 2
- *
- * Only use this feature if PHYS_OFFSET <= PAGE_OFFSET, otherwise
- * booting secondary CPUs would end up using TTBR1 for the identity
- * mapping set up in TTBR0.
  */
 #if defined CONFIG_VMSPLIT_2G
 #define TTBR1_OFFSET   16                      /* skip two L1 entries */
+#define TTBR1_SIZE     (1<<16)
 #elif defined CONFIG_VMSPLIT_3G
 #define TTBR1_OFFSET   (4096 * (1 + 3))        /* only L2, skip pgd + 3*pmd */
+#define TTBR1_SIZE     (2<<16)
 #else
-#define TTBR1_OFFSET   0
+#define TTBR1_OFFSET   8                       /* skip one L1 entry */
+/* Not implemented. In this mode TTBR0 points to first pmd instead of pgd. */
+#define TTBR1_SIZE     0
 #endif
 
-#define TTBR1_SIZE     (((PAGE_OFFSET >> 30) - 1) << 16)
-
 #endif
diff --git a/arch/arm/include/asm/proc-fns.h b/arch/arm/include/asm/proc-fns.h
index 5324c11..8353eb4 100644
--- a/arch/arm/include/asm/proc-fns.h
+++ b/arch/arm/include/asm/proc-fns.h
@@ -149,6 +149,19 @@ extern void cpu_resume(void);
        })
 #endif
 
+static inline u32 cpu_get_ttbcr(void)
+{
+       u32 val;
+
+       __asm__("mrc p15, 0, %0, c2, c0, 2" : "=r" (val));
+       return val;
+}
+
+static inline void cpu_set_ttbcr(u32 val)
+{
+       __asm__("mcr p15, 0, %0, c2, c0, 2" : : "r" (val));
+}
+
 #else  /*!CONFIG_MMU */
 
 #define cpu_switch_mm(pgd,mm)  { }
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index c031063..6a54a82 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -488,6 +488,17 @@ void notrace cpu_init(void)
              PLC (PSR_F_BIT | PSR_I_BIT | SVC_MODE)
            : "r14");
 #endif
+
+#ifdef CONFIG_ARM_LPAE
+       /* For short mode TTBR1 already loaded by macro v7_ttb_setup */
+       cpu_set_ttbr(1, __pa(init_mm.pgd) + TTBR1_OFFSET);
+#endif
+
+#if defined(CONFIG_MMU) && TTBR1_SIZE
+       /* Enable TTBR0/TTBR1 split */
+       cpu_set_ttbcr(cpu_get_ttbcr() | TTBR1_SIZE);
+       local_flush_tlb_all();
+#endif
 }
 
 u32 __cpu_logical_map[NR_CPUS] = { [0 ... NR_CPUS-1] = MPIDR_INVALID };
diff --git a/arch/arm/mach-keystone/platsmp.c b/arch/arm/mach-keystone/platsmp.c
index 5f46a7c..4bbb184 100644
--- a/arch/arm/mach-keystone/platsmp.c
+++ b/arch/arm/mach-keystone/platsmp.c
@@ -39,19 +39,6 @@ static int keystone_smp_boot_secondary(unsigned int cpu,
        return error;
 }
 
-#ifdef CONFIG_ARM_LPAE
-static void __cpuinit keystone_smp_secondary_initmem(unsigned int cpu)
-{
-       pgd_t *pgd0 = pgd_offset_k(0);
-       cpu_set_ttbr(1, __pa(pgd0) + TTBR1_OFFSET);
-       local_flush_tlb_all();
-}
-#else
-static inline void __cpuinit keystone_smp_secondary_initmem(unsigned int cpu)
-{}
-#endif
-
 struct smp_operations keystone_smp_ops __initdata = {
        .smp_boot_secondary     = keystone_smp_boot_secondary,
-       .smp_secondary_init     = keystone_smp_secondary_initmem,
 };
diff --git a/arch/arm/mm/idmap.c b/arch/arm/mm/idmap.c
index e7a81ceb..cc51b40 100644
--- a/arch/arm/mm/idmap.c
+++ b/arch/arm/mm/idmap.c
@@ -123,6 +123,12 @@ void setup_mm_for_reboot(void)
 {
        /* Switch to the identity mapping. */
        cpu_switch_mm(idmap_pgd, &init_mm);
+
+#if TTBR1_SIZE
+       /* Disable TTBR0/TTBR1 split, idmap might collide with TTRB1 range */
+       cpu_set_ttbcr(cpu_get_ttbcr() | ~TTBR1_SIZE);
+#endif
+
        local_flush_bp_all();
 
 #ifdef CONFIG_CPU_HAS_ASID
diff --git a/arch/arm/mm/proc-v7-3level.S b/arch/arm/mm/proc-v7-3level.S
index d3daed0..b8173cf 100644
--- a/arch/arm/mm/proc-v7-3level.S
+++ b/arch/arm/mm/proc-v7-3level.S
@@ -127,26 +127,13 @@ ENDPROC(cpu_v7_set_pte_ext)
         * - \ttbr1 updated.
         */
        .macro  v7_ttb_setup, zero, ttbr0, ttbr1, tmp
-       ldr     \tmp, =swapper_pg_dir           @ swapper_pg_dir virtual address
-       mov     \tmp, \tmp, lsr #ARCH_PGD_SHIFT
-       cmp     \ttbr1, \tmp                    @ PHYS_OFFSET > PAGE_OFFSET?
        mrc     p15, 0, \tmp, c2, c0, 2         @ TTB control register
        orr     \tmp, \tmp, #TTB_EAE
        ALT_SMP(orr     \tmp, \tmp, #TTB_FLAGS_SMP)
        ALT_UP(orr      \tmp, \tmp, #TTB_FLAGS_UP)
        ALT_SMP(orr     \tmp, \tmp, #TTB_FLAGS_SMP << 16)
        ALT_UP(orr      \tmp, \tmp, #TTB_FLAGS_UP << 16)
-       /*
-        * Only use split TTBRs if PHYS_OFFSET <= PAGE_OFFSET (cmp above),
-        * otherwise booting secondary CPUs would end up using TTBR1 for the
-        * identity mapping set up in TTBR0.
-        */
-       orrls   \tmp, \tmp, #TTBR1_SIZE                         @ TTBCR.T1SZ
        mcr     p15, 0, \tmp, c2, c0, 2                         @ TTBCR
-       mov     \tmp, \ttbr1, lsr #(32 - ARCH_PGD_SHIFT)        @ upper bits
-       mov     \ttbr1, \ttbr1, lsl #ARCH_PGD_SHIFT             @ lower bits
-       addls   \ttbr1, \ttbr1, #TTBR1_OFFSET
-       mcrr    p15, 1, \ttbr1, \tmp, c2                        @ load TTBR1
        mov     \tmp, \ttbr0, lsr #(32 - ARCH_PGD_SHIFT)        @ upper bits
        mov     \ttbr0, \ttbr0, lsl #ARCH_PGD_SHIFT             @ lower bits
        mcrr    p15, 0, \ttbr0, \tmp, c2                        @ load TTBR0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to