diff options
author | Vivek Goyal <vgoyal@in.ibm.com> | 2006-12-06 20:14:04 -0500 |
---|---|---|
committer | Andi Kleen <andi@basil.nowhere.org> | 2006-12-06 20:14:04 -0500 |
commit | e69f202d0a1419219198566e1c22218a5c71a9a6 (patch) | |
tree | 16bb59505500797e1ea7e09ee9c3b495ce65b76a | |
parent | 6a044b3a0a1829ef19bb29548ffe553f48e8d80c (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/Kconfig | 33 | ||||
-rw-r--r-- | arch/i386/boot/compressed/head.S | 26 | ||||
-rw-r--r-- | arch/i386/boot/compressed/misc.c | 7 | ||||
-rw-r--r-- | arch/i386/kernel/vmlinux.lds.S | 3 | ||||
-rw-r--r-- | include/asm-i386/boot.h | 6 |
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 | ||
788 | config PHYSICAL_START | 788 | config 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: | |||
52 | 1: popl %ebp | 53 | 1: 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 | ||
18 | OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") | 19 | OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") |
19 | OUTPUT_ARCH(i386) | 20 | OUTPUT_ARCH(i386) |
@@ -27,7 +28,7 @@ PHDRS { | |||
27 | } | 28 | } |
28 | SECTIONS | 29 | SECTIONS |
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 */ | ||