summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSubash Patel <subash.rp@samsung.com>2012-12-03 14:51:55 +0530
committerTushar Behera <tushar.behera@linaro.org>2013-01-22 11:41:32 +0530
commit1e949956fb69091764d81cbbeba78be8494f97c5 (patch)
tree5f19acfef3b074b699824ae7b5d9efcc8d15f928
parent3ad97f2608a9b9c3a37051ac73b88a707c85f735 (diff)
downloadlinux-topics-1e949956fb69091764d81cbbeba78be8494f97c5.tar.gz
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> Hand-edited as this patch in eml format doesnt apply due to missing blob data for arch/arm/include/asm/memory.h Signed-off-by: Subash Patel <subash.rp@samsung.com>
-rw-r--r--arch/arm/include/asm/memory.h31
-rw-r--r--arch/arm/kernel/head.S10
-rw-r--r--arch/arm/kernel/smp.c11
-rw-r--r--arch/arm/mm/proc-v7-3level.S8
4 files changed, 44 insertions, 16 deletions
diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h
index a286acc01db..485c3154ba8 100644
--- a/arch/arm/include/asm/memory.h
+++ b/arch/arm/include/asm/memory.h
@@ -18,6 +18,7 @@
#include <linux/types.h>
#include <linux/sizes.h>
+#include <asm/cache.h>
#include <asm/runtime-patch.h>
#ifdef CONFIG_NEED_MACH_MEMORY_H
@@ -101,11 +102,11 @@
#endif
#ifndef PHYS_OFFSET
-#define PHYS_OFFSET UL(CONFIG_DRAM_BASE)
+#define PHYS_OFFSET UL(CONFIG_DRAM_BASE)
#endif
#ifndef END_MEM
-#define END_MEM (UL(CONFIG_DRAM_BASE) + CONFIG_DRAM_SIZE)
+#define END_MEM (UL(CONFIG_DRAM_BASE) + CONFIG_DRAM_SIZE)
#endif
#ifndef PAGE_OFFSET
@@ -143,6 +144,20 @@
#define page_to_phys(page) (__pfn_to_phys(page_to_pfn(page)))
#define phys_to_page(phys) (pfn_to_page(__phys_to_pfn(phys)))
+/*
+ * Minimum guaranted alignment in pgd_alloc(). The page table pointers passed
+ * around in head.S and proc-*.S are shifted by this amount, in order to
+ * leave spare high bits for systems with physical address extension. This
+ * does not fully accomodate the 40-bit addressing capability of ARM LPAE, but
+ * gives us about 38-bits or so.
+ */
+#ifdef CONFIG_ARM_LPAE
+#define ARCH_PGD_SHIFT L1_CACHE_SHIFT
+#else
+#define ARCH_PGD_SHIFT 0
+#endif
+#define ARCH_PGD_MASK ((1 << ARCH_PGD_SHIFT) - 1)
+
#ifndef __ASSEMBLY__
/*
@@ -188,12 +203,12 @@ static inline phys_addr_t __virt_to_phys(unsigned long x)
".long " PV_PHYS_HIGH "\n"
"mov %R[to], %[imm]\n",
/* operands */
- : [to] "=r" (t),
- [tmp] "=&r" (__tmp)
- : [from] "r" (x),
- [imm] "I" (__IMM8),
- "i" (&__pv_offset),
- "i" (&__pv_phys_offset));
+ : [to] "=r" (t),
+ [tmp] "=&r" (__tmp)
+ : [from]"r" (x),
+ [imm] "I" (__IMM8),
+ "i" (&__pv_offset),
+ "i" (&__pv_phys_offset));
#endif
return t;
}
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index 1ae52e1d896..3de7baaef44 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -156,7 +156,7 @@ ENDPROC(stext)
*
* Returns:
* r0, r3, r5-r7 corrupted
- * r4 = physical page table address
+ * r4 = page table (see ARCH_PGD_SHIFT in asm/memory.h)
*/
__create_page_tables:
pgtbl r4, r8 @ page table address
@@ -310,6 +310,7 @@ __create_page_tables:
#endif
#ifdef CONFIG_ARM_LPAE
sub r4, r4, #0x1000 @ point to the PGD table
+ mov r4, r4, lsr #ARCH_PGD_SHIFT
#endif
mov pc, lr
ENDPROC(__create_page_tables)
@@ -387,7 +388,7 @@ __secondary_data:
* r0 = cp#15 control register
* r1 = machine ID
* r2 = atags or dtb pointer
- * r4 = page table pointer
+ * r4 = page table (see ARCH_PGD_SHIFT in asm/memory.h)
* r9 = processor ID
* r13 = *virtual* address to jump to upon completion
*/
@@ -406,10 +407,7 @@ __enable_mmu:
#ifdef CONFIG_CPU_ICACHE_DISABLE
bic r0, r0, #CR_I
#endif
-#ifdef CONFIG_ARM_LPAE
- mov r5, #0
- mcrr p15, 0, r4, r5, c2 @ load TTBR0
-#else
+#ifndef CONFIG_ARM_LPAE
mov r5, #(domain_val(DOMAIN_USER, DOMAIN_MANAGER) | \
domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) | \
domain_val(DOMAIN_TABLE, DOMAIN_MANAGER) | \
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index c115ab3c27f..2477225c33c 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -71,6 +71,13 @@ enum ipi_msg_type {
static DECLARE_COMPLETION(cpu_running);
+static unsigned long get_arch_pgd(pgd_t *pgd)
+{
+ phys_addr_t pgdir = virt_to_phys(pgd);
+ BUG_ON(pgdir & ARCH_PGD_MASK);
+ return pgdir >> ARCH_PGD_SHIFT;
+}
+
static struct smp_operations smp_ops;
void __init smp_set_ops(struct smp_operations *ops)
@@ -88,8 +95,8 @@ int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *idle)
* its stack and the page tables.
*/
secondary_data.stack = task_stack_page(idle) + THREAD_START_SP;
- secondary_data.pgdir = virt_to_phys(idmap_pgd);
- secondary_data.swapper_pg_dir = virt_to_phys(swapper_pg_dir);
+ secondary_data.pgdir = get_arch_pgd(idmap_pgd);
+ secondary_data.swapper_pg_dir = get_arch_pgd(swapper_pg_dir);
__cpuc_flush_dcache_area(&secondary_data, sizeof(secondary_data));
outer_clean_range(__pa(&secondary_data), __pa(&secondary_data + 1));
diff --git a/arch/arm/mm/proc-v7-3level.S b/arch/arm/mm/proc-v7-3level.S
index ee90f8d1ce9..624ac666634 100644
--- a/arch/arm/mm/proc-v7-3level.S
+++ b/arch/arm/mm/proc-v7-3level.S
@@ -114,6 +114,7 @@ ENDPROC(cpu_v7_set_pte_ext)
*/
.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? (branch below)
mrc p15, 0, \tmp, c2, c0, 2 @ TTB control register
orr \tmp, \tmp, #TTB_EAE
@@ -133,8 +134,15 @@ ENDPROC(cpu_v7_set_pte_ext)
*/
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, \zero, 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, \zero, c2 @ load TTBR0
+ mcrr p15, 1, \ttbr1, \zero, c2 @ load TTBR1
+ mcrr p15, 0, \ttbr0, \zero, c2 @ load TTBR0
.endm
__CPUINIT