Commit 4756dcbfd37819a8359d3c69a22be2ee41666d0f

Authored by Cyril Chemparathy
Committed by Will Deacon
1 parent a7fbc0d62a

ARM: LPAE: accomodate >32-bit addresses for page table base

This patch redefines the early boot time use of the R4 register to steal a few
low order bits (ARCH_PGD_SHIFT bits) on LPAE systems.  This allows for up to
38-bit physical addresses.

Signed-off-by: Cyril Chemparathy <cyril@ti.com>
Signed-off-by: Vitaly Andrianov <vitalya@ti.com>
Acked-by: Nicolas Pitre <nico@linaro.org>
Tested-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Tested-by: Subash Patel <subash.rp@samsung.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>

Showing 4 changed files with 37 additions and 8 deletions Side-by-side Diff

arch/arm/include/asm/memory.h
... ... @@ -18,6 +18,8 @@
18 18 #include <linux/types.h>
19 19 #include <linux/sizes.h>
20 20  
  21 +#include <asm/cache.h>
  22 +
21 23 #ifdef CONFIG_NEED_MACH_MEMORY_H
22 24 #include <mach/memory.h>
23 25 #endif
... ... @@ -140,6 +142,20 @@
140 142 */
141 143 #define page_to_phys(page) (__pfn_to_phys(page_to_pfn(page)))
142 144 #define phys_to_page(phys) (pfn_to_page(__phys_to_pfn(phys)))
  145 +
  146 +/*
  147 + * Minimum guaranted alignment in pgd_alloc(). The page table pointers passed
  148 + * around in head.S and proc-*.S are shifted by this amount, in order to
  149 + * leave spare high bits for systems with physical address extension. This
  150 + * does not fully accomodate the 40-bit addressing capability of ARM LPAE, but
  151 + * gives us about 38-bits or so.
  152 + */
  153 +#ifdef CONFIG_ARM_LPAE
  154 +#define ARCH_PGD_SHIFT L1_CACHE_SHIFT
  155 +#else
  156 +#define ARCH_PGD_SHIFT 0
  157 +#endif
  158 +#define ARCH_PGD_MASK ((1 << ARCH_PGD_SHIFT) - 1)
143 159  
144 160 #ifndef __ASSEMBLY__
145 161  
arch/arm/kernel/head.S
... ... @@ -156,7 +156,7 @@
156 156 *
157 157 * Returns:
158 158 * r0, r3, r5-r7 corrupted
159   - * r4 = physical page table address
  159 + * r4 = page table (see ARCH_PGD_SHIFT in asm/memory.h)
160 160 */
161 161 __create_page_tables:
162 162 pgtbl r4, r8 @ page table address
... ... @@ -331,6 +331,7 @@
331 331 #endif
332 332 #ifdef CONFIG_ARM_LPAE
333 333 sub r4, r4, #0x1000 @ point to the PGD table
  334 + mov r4, r4, lsr #ARCH_PGD_SHIFT
334 335 #endif
335 336 mov pc, lr
336 337 ENDPROC(__create_page_tables)
... ... @@ -408,7 +409,7 @@
408 409 * r0 = cp#15 control register
409 410 * r1 = machine ID
410 411 * r2 = atags or dtb pointer
411   - * r4 = page table pointer
  412 + * r4 = page table (see ARCH_PGD_SHIFT in asm/memory.h)
412 413 * r9 = processor ID
413 414 * r13 = *virtual* address to jump to upon completion
414 415 */
... ... @@ -427,10 +428,7 @@
427 428 #ifdef CONFIG_CPU_ICACHE_DISABLE
428 429 bic r0, r0, #CR_I
429 430 #endif
430   -#ifdef CONFIG_ARM_LPAE
431   - mov r5, #0
432   - mcrr p15, 0, r4, r5, c2 @ load TTBR0
433   -#else
  431 +#ifndef CONFIG_ARM_LPAE
434 432 mov r5, #(domain_val(DOMAIN_USER, DOMAIN_MANAGER) | \
435 433 domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) | \
436 434 domain_val(DOMAIN_TABLE, DOMAIN_MANAGER) | \
arch/arm/kernel/smp.c
... ... @@ -78,6 +78,13 @@
78 78 smp_ops = *ops;
79 79 };
80 80  
  81 +static unsigned long get_arch_pgd(pgd_t *pgd)
  82 +{
  83 + phys_addr_t pgdir = virt_to_phys(pgd);
  84 + BUG_ON(pgdir & ARCH_PGD_MASK);
  85 + return pgdir >> ARCH_PGD_SHIFT;
  86 +}
  87 +
81 88 int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *idle)
82 89 {
83 90 int ret;
... ... @@ -87,8 +94,8 @@
87 94 * its stack and the page tables.
88 95 */
89 96 secondary_data.stack = task_stack_page(idle) + THREAD_START_SP;
90   - secondary_data.pgdir = virt_to_phys(idmap_pgd);
91   - secondary_data.swapper_pg_dir = virt_to_phys(swapper_pg_dir);
  97 + secondary_data.pgdir = get_arch_pgd(idmap_pgd);
  98 + secondary_data.swapper_pg_dir = get_arch_pgd(swapper_pg_dir);
92 99 __cpuc_flush_dcache_area(&secondary_data, sizeof(secondary_data));
93 100 outer_clean_range(__pa(&secondary_data), __pa(&secondary_data + 1));
94 101  
arch/arm/mm/proc-v7-3level.S
... ... @@ -114,6 +114,7 @@
114 114 */
115 115 .macro v7_ttb_setup, zero, ttbr0, ttbr1, tmp
116 116 ldr \tmp, =swapper_pg_dir @ swapper_pg_dir virtual address
  117 + mov \tmp, \tmp, lsr #ARCH_PGD_SHIFT
117 118 cmp \ttbr1, \tmp @ PHYS_OFFSET > PAGE_OFFSET?
118 119 mrc p15, 0, \tmp, c2, c0, 2 @ TTB control register
119 120 orr \tmp, \tmp, #TTB_EAE
120 121  
... ... @@ -128,8 +129,15 @@
128 129 */
129 130 orrls \tmp, \tmp, #TTBR1_SIZE @ TTBCR.T1SZ
130 131 mcr p15, 0, \tmp, c2, c0, 2 @ TTBCR
  132 + mov \tmp, \ttbr1, lsr #(32 - ARCH_PGD_SHIFT) @ upper bits
  133 + mov \ttbr1, \ttbr1, lsl #ARCH_PGD_SHIFT @ lower bits
131 134 addls \ttbr1, \ttbr1, #TTBR1_OFFSET
132 135 mcrr p15, 1, \ttbr1, \zero, c2 @ load TTBR1
  136 + mov \tmp, \ttbr0, lsr #(32 - ARCH_PGD_SHIFT) @ upper bits
  137 + mov \ttbr0, \ttbr0, lsl #ARCH_PGD_SHIFT @ lower bits
  138 + mcrr p15, 0, \ttbr0, \zero, c2 @ load TTBR0
  139 + mcrr p15, 1, \ttbr1, \zero, c2 @ load TTBR1
  140 + mcrr p15, 0, \ttbr0, \zero, c2 @ load TTBR0
133 141 .endm
134 142  
135 143 __CPUINIT