summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/arm/Booting1
-rw-r--r--arch/arm/Kconfig3
-rw-r--r--arch/arm/boot/compressed/Makefile1
-rw-r--r--arch/arm/boot/compressed/head.S49
-rw-r--r--arch/arm/include/asm/memory.h5
-rw-r--r--arch/arm/kernel/head.S31
-rw-r--r--arch/arm/kernel/setup.c10
7 files changed, 91 insertions, 9 deletions
diff --git a/Documentation/arm/Booting b/Documentation/arm/Booting
index 76850295af8f..ec228a472bec 100644
--- a/Documentation/arm/Booting
+++ b/Documentation/arm/Booting
@@ -126,6 +126,7 @@ In either case, the following conditions must be met:
r0 = 0,
r1 = machine type number discovered in (3) above.
r2 = physical address of tagged list in system RAM.
+ r3 = PHYS_OFFSET
- CPU mode
All forms of interrupts must be disabled (IRQs and FIQs)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 62ec97f5928c..fa492c2e051a 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1166,6 +1166,9 @@ config UACCESS_WITH_MEMCPY
However, if the CPU data cache is using a write-allocate mode,
this option is unlikely to provide any performance gain.
+config RUNTIME_PHYS_OFFSET
+ bool
+
endmenu
menu "Boot options"
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
index ce39dc540085..b0bba0911f22 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -4,6 +4,7 @@
# create a compressed vmlinuz image from the original vmlinux
#
+AFLAGS_head.o += -DTEXT_OFFSET=$(TEXT_OFFSET)
HEAD = head.o
OBJS = misc.o
FONTC = $(srctree)/drivers/video/console/font_acorn_8x8.c
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index 4515728c5345..4a7649025228 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -112,6 +112,16 @@
#endif
.endm
+ .macro debug_passed_physoffset
+#ifdef DEBUG
+ bleq 1f
+ kputc #'!'
+ kphex r9, 8
+ kputc #'\n'
+1:
+#endif
+ .endm
+
.section ".start", #alloc, #execinstr
/*
* sort out different calling conventions
@@ -129,6 +139,7 @@ start:
.word _edata @ zImage end address
1: mov r7, r1 @ save architecture ID
mov r8, r2 @ save atags pointer
+ mov r9, r3 @ save phys_offset
#ifndef __ARM_ARCH_2__
/*
@@ -222,6 +233,43 @@ not_relocated: mov r0, #0
cmp r2, r3
blo 1b
+#ifdef CONFIG_RUNTIME_PHYS_OFFSET
+ /*
+ * assert physoffset passed by bootloader is properly
+ * 2MiB-aligned, ...
+ */
+ ldr r10, =0x001fffff
+
+ tst r9, r10
+ debug_passed_physoffset
+ tst r9, r10
+
+ /*
+ * ... if not guess it based on sp.
+ * sp & 0xf8000000 should work for most machines. The needed
+ * preconditions are:
+ * - physoffset is aligned to a 128MiB boundary
+ * (As of Jan 2010 all but s3c2400, u300 and at91 have it.
+ * For the latter it depends on configuration.)
+ * - sp < physoffset + 128MiB (which is definitely true if you
+ * only have 128MiB of RAM or less)
+ */
+ andne r9, sp, #0xf8000000
+#ifdef DEBUG
+ kputc #'P'
+ kphex r9, 8
+ kputc #'\n'
+#endif
+
+ add r4, r9, #TEXT_OFFSET
+#else /* ifdef CONFIG_RUNTIME_PHYS_OFFSET */
+ /* warn on r4(ZRELADDR) != r9 + TEXT_OFFSET */
+ add r10, r9, #TEXT_OFFSET
+ cmp r10, r4
+ debug_passed_physoffset
+
+#endif /* ifdef CONFIG_RUNTIME_PHYS_OFFSET / else */
+
/*
* The C runtime environment should now be setup
* sufficiently. Turn the cache on, set up some
@@ -545,6 +593,7 @@ call_kernel: bl cache_clean_flush
mov r0, #0 @ must be zero
mov r1, r7 @ restore architecture number
mov r2, r8 @ restore atags pointer
+ sub r3, r4, #TEXT_OFFSET @ physoffset
mov pc, r4 @ call kernel
/*
diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h
index 85763db87449..b325f46a6ad3 100644
--- a/arch/arm/include/asm/memory.h
+++ b/arch/arm/include/asm/memory.h
@@ -24,6 +24,11 @@
*/
#define UL(x) _AC(x, UL)
+#if defined(CONFIG_RUNTIME_PHYS_OFFSET) && !defined(__ASSEMBLY__)
+extern unsigned long phys_offset;
+#define PHYS_OFFSET phys_offset
+#endif
+
#ifdef CONFIG_MMU
/*
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