Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b2c3e38a authored by Russell King's avatar Russell King
Browse files

ARM: redo TTBR setup code for LPAE



Re-engineer the LPAE TTBR setup code.  Rather than passing some shifted
address in order to fit in a CPU register, pass either a full physical
address (in the case of r4, r5 for TTBR0) or a PFN (for TTBR1).

This removes the ARCH_PGD_SHIFT hack, and the last dangerous user of
cpu_set_ttbr() in the secondary CPU startup code path (which was there
to re-set TTBR1 to the appropriate high physical address space on
Keystone2.)

Tested-by: default avatarMurali Karicheri <m-karicheri2@ti.com>
Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent 1221ed10
Loading
Loading
Loading
Loading
+0 −16
Original line number Diff line number Diff line
@@ -18,8 +18,6 @@
#include <linux/types.h>
#include <linux/sizes.h>

#include <asm/cache.h>

#ifdef CONFIG_NEED_MACH_MEMORY_H
#include <mach/memory.h>
#endif
@@ -132,20 +130,6 @@
#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)

/*
 * PLAT_PHYS_OFFSET is the offset (from zero) of the start of physical
 * memory.  This is used for XIP and NoMMU kernels, and on platforms that don't
+0 −7
Original line number Diff line number Diff line
@@ -125,13 +125,6 @@ extern void cpu_resume(void);
		ttbr;						\
	})

#define cpu_set_ttbr(nr, val)					\
	do {							\
		u64 ttbr = val;					\
		__asm__("mcrr	p15, " #nr ", %Q0, %R0, c2"	\
			: : "r" (ttbr));			\
	} while (0)

#define cpu_get_pgd()	\
	({						\
		u64 pg = cpu_get_ttbr(0);		\
+1 −1
Original line number Diff line number Diff line
@@ -61,7 +61,7 @@ asmlinkage void secondary_start_kernel(void);
struct secondary_data {
	union {
		unsigned long mpu_rgn_szr;
		unsigned long pgdir;
		u64 pgdir;
	};
	unsigned long swapper_pg_dir;
	void *stack;
+1 −1
Original line number Diff line number Diff line
@@ -123,7 +123,7 @@ ENTRY(secondary_startup)
ENDPROC(secondary_startup)

ENTRY(__secondary_switched)
	ldr	sp, [r7, #8]			@ set up the stack pointer
	ldr	sp, [r7, #12]			@ set up the stack pointer
	mov	fp, #0
	b	secondary_start_kernel
ENDPROC(__secondary_switched)
+31 −11
Original line number Diff line number Diff line
@@ -131,13 +131,30 @@ ENTRY(stext)
	 * The following calls CPU specific code in a position independent
	 * manner.  See arch/arm/mm/proc-*.S for details.  r10 = base of
	 * xxx_proc_info structure selected by __lookup_processor_type
	 * above.  On return, the CPU will be ready for the MMU to be
	 * turned on, and r0 will hold the CPU control register value.
	 * above.
	 *
	 * The processor init function will be called with:
	 *  r1 - machine type
	 *  r2 - boot data (atags/dt) pointer
	 *  r4 - translation table base (low word)
	 *  r5 - translation table base (high word, if LPAE)
	 *  r8 - translation table base 1 (pfn if LPAE)
	 *  r9 - cpuid
	 *  r13 - virtual address for __enable_mmu -> __turn_mmu_on
	 *
	 * On return, the CPU will be ready for the MMU to be turned on,
	 * r0 will hold the CPU control register value, r1, r2, r4, and
	 * r9 will be preserved.  r5 will also be preserved if LPAE.
	 */
	ldr	r13, =__mmap_switched		@ address to jump to after
						@ mmu has been enabled
	adr	lr, BSYM(1f)			@ return (PIC) address
#ifdef CONFIG_ARM_LPAE
	mov	r5, #0				@ high TTBR0
	mov	r8, r4, lsr #12			@ TTBR1 is swapper_pg_dir pfn
#else
	mov	r8, r4				@ set TTBR1 to swapper_pg_dir
#endif
	ldr	r12, [r10, #PROCINFO_INITFUNC]
	add	r12, r12, r10
	ret	r12
@@ -158,7 +175,7 @@ ENDPROC(stext)
 *
 * Returns:
 *  r0, r3, r5-r7 corrupted
 *  r4 = page table (see ARCH_PGD_SHIFT in asm/memory.h)
 *  r4 = physical page table address
 */
__create_page_tables:
	pgtbl	r4, r8				@ page table address
@@ -333,7 +350,6 @@ __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
	ret	lr
ENDPROC(__create_page_tables)
@@ -381,9 +397,9 @@ ENTRY(secondary_startup)
	adr	r4, __secondary_data
	ldmia	r4, {r5, r7, r12}		@ address to jump to after
	sub	lr, r4, r5			@ mmu has been enabled
	ldr	r4, [r7, lr]			@ get secondary_data.pgdir
	add	r7, r7, #4
	ldr	r8, [r7, lr]			@ get secondary_data.swapper_pg_dir
	add	r3, r7, lr
	ldrd	r4, [r3, #0]			@ get secondary_data.pgdir
	ldr	r8, [r3, #8]			@ get secondary_data.swapper_pg_dir
	adr	lr, BSYM(__enable_mmu)		@ return address
	mov	r13, r12			@ __secondary_switched address
	ldr	r12, [r10, #PROCINFO_INITFUNC]
@@ -397,7 +413,7 @@ ENDPROC(secondary_startup_arm)
	 * r6  = &secondary_data
	 */
ENTRY(__secondary_switched)
	ldr	sp, [r7, #4]			@ get secondary_data.stack
	ldr	sp, [r7, #12]			@ get secondary_data.stack
	mov	fp, #0
	b	secondary_start_kernel
ENDPROC(__secondary_switched)
@@ -416,12 +432,14 @@ __secondary_data:
/*
 * Setup common bits before finally enabling the MMU.  Essentially
 * this is just loading the page table pointer and domain access
 * registers.
 * registers.  All these registers need to be preserved by the
 * processor setup function (or set in the case of r0)
 *
 *  r0  = cp#15 control register
 *  r1  = machine ID
 *  r2  = atags or dtb pointer
 *  r4  = page table (see ARCH_PGD_SHIFT in asm/memory.h)
 *  r4  = TTBR pointer (low word)
 *  r5  = TTBR pointer (high word if LPAE)
 *  r9  = processor ID
 *  r13 = *virtual* address to jump to upon completion
 */
@@ -440,7 +458,9 @@ __enable_mmu:
#ifdef CONFIG_CPU_ICACHE_DISABLE
	bic	r0, r0, #CR_I
#endif
#ifndef CONFIG_ARM_LPAE
#ifdef CONFIG_ARM_LPAE
	mcrr	p15, 0, r4, r5, c2		@ load TTBR0
#else
	mov	r5, #(domain_val(DOMAIN_USER, DOMAIN_MANAGER) | \
		      domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) | \
		      domain_val(DOMAIN_TABLE, DOMAIN_MANAGER) | \
Loading