diff options
author | Uwe Kleine-König <u.kleine-koenig@pengutronix.de> | 2010-03-18 09:07:08 -0500 |
---|---|---|
committer | Alejandro Gonzalez <alex.gonzalez@digi.com> | 2010-05-25 11:20:14 +0200 |
commit | 8513c72819be22b22d044424eff0fd4183ea8ca2 (patch) | |
tree | 61ec023cba96fabbb23e1bf6d4ff9c68d54c6ac3 /arch/arm/kernel | |
parent | 73f8a055cfa54399eb612964301b2e06f5aa3e16 (diff) |
Allow PHYS_OFFSET to be runtime determined
This bases on work done earlier by Lennert Buytenhek and Mark A. Greer.
Compared to their approach zreladdr isn't guessed based on the pc
register but the bootloader is expected to pass PHYS_OFFSET in r3. If
that value doesn't look right (e.g. isn't aligned) it is guessed based
on the value of sp. This should work for CONFIG_ZBOOT_ROM, too.
To use it for your machine removing the definition of PHYS_OFFSET from
<mach/memory.h> and selecting CONFIG_RUNTIME_PHYS_OFFSET should be
enough.
Cc: Lennert Buytenhek <buytenh@wantstofly.org>
Cc: Steve Chen <schen@mvista.com>
Cc: Mark A. Greer <mgreer@mvista.com>
Cc: Kevin Hilman <khilman@deeprootsystems.com>
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Signed-off-by: Alejandro Gonzalez <alex.gonzalez@digi.com>
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r-- | arch/arm/kernel/head.S | 31 | ||||
-rw-r--r-- | arch/arm/kernel/setup.c | 10 |
2 files changed, 32 insertions, 9 deletions
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index 21e17dc94cb5..7d8d4b0ce66e 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S @@ -22,12 +22,14 @@ #include <asm/thread_info.h> #include <asm/system.h> +#if !defined(CONFIG_RUNTIME_PHYS_OFFSET) #if (PHYS_OFFSET & 0x001fffff) #error "PHYS_OFFSET must be at an even 2MiB boundary!" #endif +#define KERNEL_RAM_PADDR (PHYS_OFFSET + TEXT_OFFSET) +#endif #define KERNEL_RAM_VADDR (PAGE_OFFSET + TEXT_OFFSET) -#define KERNEL_RAM_PADDR (PHYS_OFFSET + TEXT_OFFSET) /* @@ -44,8 +46,8 @@ .globl swapper_pg_dir .equ swapper_pg_dir, KERNEL_RAM_VADDR - 0x4000 - .macro pgtbl, rd - ldr \rd, =(KERNEL_RAM_PADDR - 0x4000) + .macro pgtbl, rd, phys_offset + add \rd, \phys_offset, #(TEXT_OFFSET - 0x4000) .endm #ifdef CONFIG_XIP_KERNEL @@ -210,9 +212,25 @@ ENDPROC(__turn_mmu_on) * Returns: * r0, r3, r6, r7 corrupted * r4 = physical page table address + * r5 = physical start address of (the first bank of) RAM (PHYS_OFFSET) */ __create_page_tables: - pgtbl r4 @ page table address +#if defined(CONFIG_RUNTIME_PHYS_OFFSET) + @ stext is at PHYS_OFFSET + TEXT_OFFSET. As PHYS_OFFSET has to be + @ 2MiB-aligned and assuming that TEXT_OFFSET < 2MiB + @ stext & 0xffe00000 yields PHYS_OFFSET + adr r5, stext + ldr r4, =0xffe00000 + and r5, r5, r4 + + @ save phys_offset + ldr r4, =(phys_offset - PAGE_OFFSET) + str r5, [r4, r5] +#else + ldr r5, =PHYS_OFFSET +#endif + + pgtbl r4, r5 @ r4 = page table address /* * Clear the 16K level 1 swapper page table @@ -276,10 +294,7 @@ __create_page_tables: * Then map first 1MB of ram in case it contains our boot params. */ add r0, r4, #PAGE_OFFSET >> 18 - orr r6, r7, #(PHYS_OFFSET & 0xff000000) - .if (PHYS_OFFSET & 0x00f00000) - orr r6, r6, #(PHYS_OFFSET & 0x00f00000) - .endif + orr r6, r7, r5 str r6, [r0] #ifdef CONFIG_DEBUG_LL diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index bc5e4128f9f3..f17193b64f57 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -64,6 +64,12 @@ __setup("fpe=", fpe_setup); extern void paging_init(struct machine_desc *desc); extern void reboot_setup(char *str); +#if defined(CONFIG_RUNTIME_PHYS_OFFSET) +/* assign a value to prevent phys_offset from ending in up bss */ +unsigned long phys_offset = 0xdeadbeef; +EXPORT_SYMBOL(phys_offset); +#endif + unsigned int processor_id; EXPORT_SYMBOL(processor_id); unsigned int __machine_arch_type; @@ -665,7 +671,7 @@ static struct init_tags { { tag_size(tag_core), ATAG_CORE }, { 1, PAGE_SIZE, 0xff }, { tag_size(tag_mem32), ATAG_MEM }, - { MEM_SIZE, PHYS_OFFSET }, + { MEM_SIZE, }, { 0, ATAG_NONE } }; @@ -699,6 +705,8 @@ void __init setup_arch(char **cmdline_p) tags = phys_to_virt(__atags_pointer); else if (mdesc->boot_params) tags = phys_to_virt(mdesc->boot_params); + else + init_tags.mem.start = PHYS_OFFSET; /* * If we have the old style parameters, convert them to |