Skip to content

Commit 4756dcb

Browse files
cchemparathywildea01
authored andcommitted
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 <[email protected]> Signed-off-by: Vitaly Andrianov <[email protected]> Acked-by: Nicolas Pitre <[email protected]> Tested-by: Santosh Shilimkar <[email protected]> Tested-by: Subash Patel <[email protected]> Signed-off-by: Will Deacon <[email protected]>
1 parent a7fbc0d commit 4756dcb

File tree

4 files changed

+37
-8
lines changed

4 files changed

+37
-8
lines changed

arch/arm/include/asm/memory.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
#include <linux/types.h>
1919
#include <linux/sizes.h>
2020

21+
#include <asm/cache.h>
22+
2123
#ifdef CONFIG_NEED_MACH_MEMORY_H
2224
#include <mach/memory.h>
2325
#endif
@@ -141,6 +143,20 @@
141143
#define page_to_phys(page) (__pfn_to_phys(page_to_pfn(page)))
142144
#define phys_to_page(phys) (pfn_to_page(__phys_to_pfn(phys)))
143145

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)
159+
144160
#ifndef __ASSEMBLY__
145161

146162
/*

arch/arm/kernel/head.S

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ ENDPROC(stext)
156156
*
157157
* Returns:
158158
* r0, r3, r5-r7 corrupted
159-
* r4 = physical page table address
159+
* r4 = page table (see ARCH_PGD_SHIFT in asm/memory.h)
160160
*/
161161
__create_page_tables:
162162
pgtbl r4, r8 @ page table address
@@ -331,6 +331,7 @@ __create_page_tables:
331331
#endif
332332
#ifdef CONFIG_ARM_LPAE
333333
sub r4, r4, #0x1000 @ point to the PGD table
334+
mov r4, r4, lsr #ARCH_PGD_SHIFT
334335
#endif
335336
mov pc, lr
336337
ENDPROC(__create_page_tables)
@@ -408,7 +409,7 @@ __secondary_data:
408409
* r0 = cp#15 control register
409410
* r1 = machine ID
410411
* r2 = atags or dtb pointer
411-
* r4 = page table pointer
412+
* r4 = page table (see ARCH_PGD_SHIFT in asm/memory.h)
412413
* r9 = processor ID
413414
* r13 = *virtual* address to jump to upon completion
414415
*/
@@ -427,10 +428,7 @@ __enable_mmu:
427428
#ifdef CONFIG_CPU_ICACHE_DISABLE
428429
bic r0, r0, #CR_I
429430
#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
434432
mov r5, #(domain_val(DOMAIN_USER, DOMAIN_MANAGER) | \
435433
domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) | \
436434
domain_val(DOMAIN_TABLE, DOMAIN_MANAGER) | \

arch/arm/kernel/smp.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,13 @@ void __init smp_set_ops(struct smp_operations *ops)
7878
smp_ops = *ops;
7979
};
8080

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+
8188
int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *idle)
8289
{
8390
int ret;
@@ -87,8 +94,8 @@ int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *idle)
8794
* its stack and the page tables.
8895
*/
8996
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);
9299
__cpuc_flush_dcache_area(&secondary_data, sizeof(secondary_data));
93100
outer_clean_range(__pa(&secondary_data), __pa(&secondary_data + 1));
94101

arch/arm/mm/proc-v7-3level.S

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ ENDPROC(cpu_v7_set_pte_ext)
114114
*/
115115
.macro v7_ttb_setup, zero, ttbr0, ttbr1, tmp
116116
ldr \tmp, =swapper_pg_dir @ swapper_pg_dir virtual address
117+
mov \tmp, \tmp, lsr #ARCH_PGD_SHIFT
117118
cmp \ttbr1, \tmp @ PHYS_OFFSET > PAGE_OFFSET?
118119
mrc p15, 0, \tmp, c2, c0, 2 @ TTB control register
119120
orr \tmp, \tmp, #TTB_EAE
@@ -128,8 +129,15 @@ ENDPROC(cpu_v7_set_pte_ext)
128129
*/
129130
orrls \tmp, \tmp, #TTBR1_SIZE @ TTBCR.T1SZ
130131
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
131134
addls \ttbr1, \ttbr1, #TTBR1_OFFSET
132135
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
133141
.endm
134142

135143
__CPUINIT

0 commit comments

Comments
 (0)