aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVivek Goyal <vgoyal@in.ibm.com>2006-12-06 20:14:04 -0500
committerAndi Kleen <andi@basil.nowhere.org>2006-12-06 20:14:04 -0500
commite69f202d0a1419219198566e1c22218a5c71a9a6 (patch)
tree16bb59505500797e1ea7e09ee9c3b495ce65b76a
parent6a044b3a0a1829ef19bb29548ffe553f48e8d80c (diff)
[PATCH] i386: Implement CONFIG_PHYSICAL_ALIGN
o Now CONFIG_PHYSICAL_START is being replaced with CONFIG_PHYSICAL_ALIGN. Hardcoding the kernel physical start value creates a problem in relocatable kernel context due to boot loader limitations. For ex, if somebody compiles a relocatable kernel to be run from address 4MB, but this kernel will run from location 1MB as grub loads the kernel at physical address 1MB. Kernel thinks that I am a relocatable kernel and I should run from the address I have been loaded at. So somebody wanting to run kernel from 4MB alignment location (for improved performance regions) can't do that. o Hence, Eric proposed that probably CONFIG_PHYSICAL_ALIGN will make more sense in relocatable kernel context. At run time kernel will move itself to a physical addr location which meets user specified alignment restrictions. Signed-off-by: Vivek Goyal <vgoyal@in.ibm.com> Signed-off-by: Andi Kleen <ak@suse.de>
-rw-r--r--arch/i386/Kconfig33
-rw-r--r--arch/i386/boot/compressed/head.S26
-rw-r--r--arch/i386/boot/compressed/misc.c7
-rw-r--r--arch/i386/kernel/vmlinux.lds.S3
-rw-r--r--include/asm-i386/boot.h6
5 files changed, 43 insertions, 32 deletions
diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig
index d588ca874bb4..fd2fa7a7ec52 100644
--- a/arch/i386/Kconfig
+++ b/arch/i386/Kconfig
@@ -785,23 +785,26 @@ config RELOCATABLE
785 must live at a different physical address than the primary 785 must live at a different physical address than the primary
786 kernel. 786 kernel.
787 787
788config PHYSICAL_START 788config PHYSICAL_ALIGN
789 hex "Physical address where the kernel is loaded" if (EMBEDDED || CRASH_DUMP) 789 hex "Alignment value to which kernel should be aligned"
790
791 default "0x1000000" if CRASH_DUMP
792 default "0x100000" 790 default "0x100000"
791 range 0x2000 0x400000
793 help 792 help
794 This gives the physical address where the kernel is loaded. Normally 793 This value puts the alignment restrictions on physical address
795 for regular kernels this value is 0x100000 (1MB). But in the case 794 where kernel is loaded and run from. Kernel is compiled for an
796 of kexec on panic the fail safe kernel needs to run at a different 795 address which meets above alignment restriction.
797 address than the panic-ed kernel. This option is used to set the load 796
798 address for kernels used to capture crash dump on being kexec'ed 797 If bootloader loads the kernel at a non-aligned address and
799 after panic. The default value for crash dump kernels is 798 CONFIG_RELOCATABLE is set, kernel will move itself to nearest
800 0x1000000 (16MB). This can also be set based on the "X" value as 799 address aligned to above value and run from there.
801 specified in the "crashkernel=YM@XM" command line boot parameter 800
802 passed to the panic-ed kernel. Typically this parameter is set as 801 If bootloader loads the kernel at a non-aligned address and
803 crashkernel=64M@16M. Please take a look at 802 CONFIG_RELOCATABLE is not set, kernel will ignore the run time
804 Documentation/kdump/kdump.txt for more details about crash dumps. 803 load address and decompress itself to the address it has been
804 compiled for and run from there. The address for which kernel is
805 compiled already meets above alignment restrictions. Hence the
806 end result is that kernel runs from a physical address meeting
807 above alignment restrictions.
805 808
806 Don't change this unless you know what you are doing. 809 Don't change this unless you know what you are doing.
807 810
diff --git a/arch/i386/boot/compressed/head.S b/arch/i386/boot/compressed/head.S
index e4dd7a6b9b0f..f395a4bb38bb 100644
--- a/arch/i386/boot/compressed/head.S
+++ b/arch/i386/boot/compressed/head.S
@@ -26,6 +26,7 @@
26#include <linux/linkage.h> 26#include <linux/linkage.h>
27#include <asm/segment.h> 27#include <asm/segment.h>
28#include <asm/page.h> 28#include <asm/page.h>
29#include <asm/boot.h>
29 30
30.section ".text.head" 31.section ".text.head"
31 .globl startup_32 32 .globl startup_32
@@ -52,17 +53,17 @@ startup_32:
521: popl %ebp 531: popl %ebp
53 subl $1b, %ebp 54 subl $1b, %ebp
54 55
55/* Compute the delta between where we were compiled to run at 56/* %ebp contains the address we are loaded at by the boot loader and %ebx
56 * and where the code will actually run at. 57 * contains the address where we should move the kernel image temporarily
58 * for safe in-place decompression.
57 */ 59 */
58 /* Start with the delta to where the kernel will run at. If we are 60
59 * a relocatable kernel this is the delta to our load address otherwise
60 * this is the delta to CONFIG_PHYSICAL start.
61 */
62#ifdef CONFIG_RELOCATABLE 61#ifdef CONFIG_RELOCATABLE
63 movl %ebp, %ebx 62 movl %ebp, %ebx
63 addl $(CONFIG_PHYSICAL_ALIGN - 1), %ebx
64 andl $(~(CONFIG_PHYSICAL_ALIGN - 1)), %ebx
64#else 65#else
65 movl $(CONFIG_PHYSICAL_START - startup_32), %ebx 66 movl $LOAD_PHYSICAL_ADDR, %ebx
66#endif 67#endif
67 68
68 /* Replace the compressed data size with the uncompressed size */ 69 /* Replace the compressed data size with the uncompressed size */
@@ -94,9 +95,10 @@ startup_32:
94/* Compute the kernel start address. 95/* Compute the kernel start address.
95 */ 96 */
96#ifdef CONFIG_RELOCATABLE 97#ifdef CONFIG_RELOCATABLE
97 leal startup_32(%ebp), %ebp 98 addl $(CONFIG_PHYSICAL_ALIGN - 1), %ebp
99 andl $(~(CONFIG_PHYSICAL_ALIGN - 1)), %ebp
98#else 100#else
99 movl $CONFIG_PHYSICAL_START, %ebp 101 movl $LOAD_PHYSICAL_ADDR, %ebp
100#endif 102#endif
101 103
102/* 104/*
@@ -150,8 +152,8 @@ relocated:
150 * and where it was actually loaded. 152 * and where it was actually loaded.
151 */ 153 */
152 movl %ebp, %ebx 154 movl %ebp, %ebx
153 subl $CONFIG_PHYSICAL_START, %ebx 155 subl $LOAD_PHYSICAL_ADDR, %ebx
154 156 jz 2f /* Nothing to be done if loaded at compiled addr. */
155/* 157/*
156 * Process relocations. 158 * Process relocations.
157 */ 159 */
diff --git a/arch/i386/boot/compressed/misc.c b/arch/i386/boot/compressed/misc.c
index 4eac24e95a10..dc1538931555 100644
--- a/arch/i386/boot/compressed/misc.c
+++ b/arch/i386/boot/compressed/misc.c
@@ -14,6 +14,7 @@
14#include <linux/screen_info.h> 14#include <linux/screen_info.h>
15#include <asm/io.h> 15#include <asm/io.h>
16#include <asm/page.h> 16#include <asm/page.h>
17#include <asm/boot.h>
17 18
18/* WARNING!! 19/* WARNING!!
19 * This code is compiled with -fPIC and it is relocated dynamically 20 * This code is compiled with -fPIC and it is relocated dynamically
@@ -360,12 +361,12 @@ asmlinkage void decompress_kernel(void *rmode, unsigned long end,
360 insize = input_len; 361 insize = input_len;
361 inptr = 0; 362 inptr = 0;
362 363
363 if (((u32)output - CONFIG_PHYSICAL_START) & 0x3fffff) 364 if ((u32)output & (CONFIG_PHYSICAL_ALIGN -1))
364 error("Destination address not 4M aligned"); 365 error("Destination address not CONFIG_PHYSICAL_ALIGN aligned");
365 if (end > ((-__PAGE_OFFSET-(512 <<20)-1) & 0x7fffffff)) 366 if (end > ((-__PAGE_OFFSET-(512 <<20)-1) & 0x7fffffff))
366 error("Destination address too large"); 367 error("Destination address too large");
367#ifndef CONFIG_RELOCATABLE 368#ifndef CONFIG_RELOCATABLE
368 if ((u32)output != CONFIG_PHYSICAL_START) 369 if ((u32)output != LOAD_PHYSICAL_ADDR)
369 error("Wrong destination address"); 370 error("Wrong destination address");
370#endif 371#endif
371 372
diff --git a/arch/i386/kernel/vmlinux.lds.S b/arch/i386/kernel/vmlinux.lds.S
index f8d61ec4c8cb..6860f20aa579 100644
--- a/arch/i386/kernel/vmlinux.lds.S
+++ b/arch/i386/kernel/vmlinux.lds.S
@@ -14,6 +14,7 @@
14#include <asm/thread_info.h> 14#include <asm/thread_info.h>
15#include <asm/page.h> 15#include <asm/page.h>
16#include <asm/cache.h> 16#include <asm/cache.h>
17#include <asm/boot.h>
17 18
18OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") 19OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
19OUTPUT_ARCH(i386) 20OUTPUT_ARCH(i386)
@@ -27,7 +28,7 @@ PHDRS {
27} 28}
28SECTIONS 29SECTIONS
29{ 30{
30 . = LOAD_OFFSET + CONFIG_PHYSICAL_START; 31 . = LOAD_OFFSET + LOAD_PHYSICAL_ADDR;
31 phys_startup_32 = startup_32 - LOAD_OFFSET; 32 phys_startup_32 = startup_32 - LOAD_OFFSET;
32 /* read-only */ 33 /* read-only */
33 .text : AT(ADDR(.text) - LOAD_OFFSET) { 34 .text : AT(ADDR(.text) - LOAD_OFFSET) {
diff --git a/include/asm-i386/boot.h b/include/asm-i386/boot.h
index 96b228e6e79c..8ce79a6fa891 100644
--- a/include/asm-i386/boot.h
+++ b/include/asm-i386/boot.h
@@ -12,4 +12,8 @@
12#define EXTENDED_VGA 0xfffe /* 80x50 mode */ 12#define EXTENDED_VGA 0xfffe /* 80x50 mode */
13#define ASK_VGA 0xfffd /* ask for it at bootup */ 13#define ASK_VGA 0xfffd /* ask for it at bootup */
14 14
15#endif 15/* Physical address where kenrel should be loaded. */
16#define LOAD_PHYSICAL_ADDR ((0x100000 + CONFIG_PHYSICAL_ALIGN - 1) \
17 & ~(CONFIG_PHYSICAL_ALIGN - 1))
18
19#endif /* _LINUX_BOOT_H */