[PATCH 2/2] [ARM] Allow PHYS_OFFSET to be runtime determined

Eric Miao eric.miao at canonical.com
Thu Jun 3 05:43:35 EDT 2010


From: Uwe Kleine-König <u.kleine-koenig at pengutronix.de>

Original patch from: "Uwe Kleine-König" <u.kleine-koenig at pengutronix.de>

Changes to the original patch:

1. simplify the algorithm of getting phys_offset by masking PC with
   0xf000_0000, this works for most platforms, but we can possibly
   loosen this restriction to 0xf800_0000 or 0xfc00_0000 to cover
   more platforms like ARCH_MX1/ARCH_SHARK and ARCH_S3C2400. It is
   a bit more difficult to support the U300 platform though.

2. Assigning 0xdeadbeef to phys_offset might be a bit hackish,
   explicitly specify the section for it.

3. Make RUNTIME_PHYS_OFFSET a toggle-able option in case someone
   want to manually enable or disable it. And make it valid only
   when MMU is enabled and XIP_KERNEL is disabled.

Cc: Lennert Buytenhek <buytenh at wantstofly.org>
Cc: Steve Chen <schen at mvista.com>
Cc: Mark A. Greer <mgreer at mvista.com>
Cc: Kevin Hilman <khilman at deeprootsystems.com>
Signed-off-by: Uwe Kleine-König <u.kleine-koenig at pengutronix.de>
Signed-off-by: Eric Miao <eric.miao at canonical.com>
---
 arch/arm/Kconfig              |    9 +++++++++
 arch/arm/include/asm/memory.h |    6 ++++++
 arch/arm/kernel/head.S        |   14 +++++++++++++-
 arch/arm/kernel/setup.c       |   10 +++++++++-
 4 files changed, 37 insertions(+), 2 deletions(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 818f731..add2c15 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1498,6 +1498,15 @@ config TEXT_OFFSET
 	  memory start. Currently, it is expected the least significant 16
 	  bits to be 0x8000, so to leave space for the initial page table.
 
+config RUNTIME_PHYS_OFFSET
+	bool "Auto calculate the physical address of the memory start"
+	depends on MMU && !XIP_KERNEL
+	help
+	  PHYS_OFFSET can be automatically caculated at run time by
+	  masking the PC with 0xf0000000 if the memory starts at 256MB
+	  boundary (most platforms do). Do not select this option if
+	  it is not a correct assumption on your platform.
+
 config AUTO_ZRELADDR
 	bool "Auto calculation of the decompressed kernel image address"
 	depends on !ZBOOT_ROM && !(ARCH_MX1 || ARCH_SHARK || ARCH_U300)
diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h
index 4312ee5..fb18aff 100644
--- a/arch/arm/include/asm/memory.h
+++ b/arch/arm/include/asm/memory.h
@@ -147,6 +147,12 @@
 
 #ifndef __ASSEMBLY__
 
+#ifdef CONFIG_RUNTIME_PHYS_OFFSET
+extern unsigned long phys_offset;
+#undef  PHYS_OFFSET
+#define PHYS_OFFSET	phys_offset
+#endif
+
 /*
  * The DMA mask corresponding to the maximum bus address allocatable
  * using GFP_DMA.  The default here places no restriction on DMA
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index db789fb..c77db05 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -22,7 +22,7 @@
 #include <asm/thread_info.h>
 #include <asm/system.h>
 
-#if (PHYS_OFFSET & 0x001fffff)
+#if !defined(CONFIG_RUNTIME_PHYS_OFFSET) && (PHYS_OFFSET & 0x001fffff)
 #error "PHYS_OFFSET must be at an even 2MiB boundary!"
 #endif
 
@@ -48,9 +48,15 @@
 	add	\rd, \phys_offset, #(TEXT_OFFSET - 0x4000)
 	.endm
 
+#ifndef CONFIG_RUNTIME_PHYS_OFFSET
 	.macro	get_phys_offset, rd
 	ldr	\rd, =(PHYS_OFFSET & 0xfff00000)
 	.endm
+#else
+	.macro	get_phys_offset, rd
+	and	\rd, pc, #0xf0000000
+	.endm
+#endif
 
 #ifdef CONFIG_XIP_KERNEL
 #define KERNEL_START	XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR)
@@ -332,6 +338,12 @@ __create_page_tables:
 	str	r3, [r0]
 #endif
 #endif
+
+#ifdef CONFIG_RUNTIME_PHYS_OFFSET
+	@ save to __phys_to_virt(phys_offset)
+	ldr	r0, =(phys_offset - PAGE_OFFSET)
+	str	r5, [r0, r5]
+#endif
 	mov	pc, lr
 ENDPROC(__create_page_tables)
 	.ltorg
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 122d999..e11fdb7 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -105,6 +105,12 @@ struct cpu_cache_fns cpu_cache;
 struct outer_cache_fns outer_cache;
 EXPORT_SYMBOL(outer_cache);
 #endif
+#ifdef CONFIG_RUNTIME_PHYS_OFFSET
+/* prevent phys_offset from being end up in bss */
+unsigned long phys_offset __attribute__(section(".data"));
+EXPORT_SYMBOL(phys_offset);
+#endif
+
 
 struct stack {
 	u32 irq[3];
@@ -648,7 +654,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 }
 };
 
@@ -678,6 +684,8 @@ void __init setup_arch(char **cmdline_p)
 	if (mdesc->soft_reboot)
 		reboot_setup("s");
 
+	init_tags.mem.start = PHYS_OFFSET;
+
 	if (__atags_pointer)
 		tags = phys_to_virt(__atags_pointer);
 	else if (mdesc->boot_params)
-- 
1.7.0.4




More information about the linux-arm-kernel mailing list