Commit e69f202d authored by Vivek Goyal's avatar Vivek Goyal Committed by Andi Kleen

[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: default avatarVivek Goyal <vgoyal@in.ibm.com>
Signed-off-by: default avatarAndi Kleen <ak@suse.de>
parent 6a044b3a
...@@ -785,23 +785,26 @@ config RELOCATABLE ...@@ -785,23 +785,26 @@ config RELOCATABLE
must live at a different physical address than the primary must live at a different physical address than the primary
kernel. kernel.
config PHYSICAL_START config PHYSICAL_ALIGN
hex "Physical address where the kernel is loaded" if (EMBEDDED || CRASH_DUMP) hex "Alignment value to which kernel should be aligned"
default "0x1000000" if CRASH_DUMP
default "0x100000" default "0x100000"
range 0x2000 0x400000
help help
This gives the physical address where the kernel is loaded. Normally This value puts the alignment restrictions on physical address
for regular kernels this value is 0x100000 (1MB). But in the case where kernel is loaded and run from. Kernel is compiled for an
of kexec on panic the fail safe kernel needs to run at a different address which meets above alignment restriction.
address than the panic-ed kernel. This option is used to set the load
address for kernels used to capture crash dump on being kexec'ed If bootloader loads the kernel at a non-aligned address and
after panic. The default value for crash dump kernels is CONFIG_RELOCATABLE is set, kernel will move itself to nearest
0x1000000 (16MB). This can also be set based on the "X" value as address aligned to above value and run from there.
specified in the "crashkernel=YM@XM" command line boot parameter
passed to the panic-ed kernel. Typically this parameter is set as If bootloader loads the kernel at a non-aligned address and
crashkernel=64M@16M. Please take a look at CONFIG_RELOCATABLE is not set, kernel will ignore the run time
Documentation/kdump/kdump.txt for more details about crash dumps. load address and decompress itself to the address it has been
compiled for and run from there. The address for which kernel is
compiled already meets above alignment restrictions. Hence the
end result is that kernel runs from a physical address meeting
above alignment restrictions.
Don't change this unless you know what you are doing. Don't change this unless you know what you are doing.
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <linux/linkage.h> #include <linux/linkage.h>
#include <asm/segment.h> #include <asm/segment.h>
#include <asm/page.h> #include <asm/page.h>
#include <asm/boot.h>
.section ".text.head" .section ".text.head"
.globl startup_32 .globl startup_32
...@@ -52,17 +53,17 @@ startup_32: ...@@ -52,17 +53,17 @@ startup_32:
1: popl %ebp 1: popl %ebp
subl $1b, %ebp subl $1b, %ebp
/* Compute the delta between where we were compiled to run at /* %ebp contains the address we are loaded at by the boot loader and %ebx
* and where the code will actually run at. * contains the address where we should move the kernel image temporarily
* for safe in-place decompression.
*/ */
/* Start with the delta to where the kernel will run at. If we are
* a relocatable kernel this is the delta to our load address otherwise
* this is the delta to CONFIG_PHYSICAL start.
*/
#ifdef CONFIG_RELOCATABLE #ifdef CONFIG_RELOCATABLE
movl %ebp, %ebx movl %ebp, %ebx
addl $(CONFIG_PHYSICAL_ALIGN - 1), %ebx
andl $(~(CONFIG_PHYSICAL_ALIGN - 1)), %ebx
#else #else
movl $(CONFIG_PHYSICAL_START - startup_32), %ebx movl $LOAD_PHYSICAL_ADDR, %ebx
#endif #endif
/* Replace the compressed data size with the uncompressed size */ /* Replace the compressed data size with the uncompressed size */
...@@ -94,9 +95,10 @@ startup_32: ...@@ -94,9 +95,10 @@ startup_32:
/* Compute the kernel start address. /* Compute the kernel start address.
*/ */
#ifdef CONFIG_RELOCATABLE #ifdef CONFIG_RELOCATABLE
leal startup_32(%ebp), %ebp addl $(CONFIG_PHYSICAL_ALIGN - 1), %ebp
andl $(~(CONFIG_PHYSICAL_ALIGN - 1)), %ebp
#else #else
movl $CONFIG_PHYSICAL_START, %ebp movl $LOAD_PHYSICAL_ADDR, %ebp
#endif #endif
/* /*
...@@ -150,8 +152,8 @@ relocated: ...@@ -150,8 +152,8 @@ relocated:
* and where it was actually loaded. * and where it was actually loaded.
*/ */
movl %ebp, %ebx movl %ebp, %ebx
subl $CONFIG_PHYSICAL_START, %ebx subl $LOAD_PHYSICAL_ADDR, %ebx
jz 2f /* Nothing to be done if loaded at compiled addr. */
/* /*
* Process relocations. * Process relocations.
*/ */
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <linux/screen_info.h> #include <linux/screen_info.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/page.h> #include <asm/page.h>
#include <asm/boot.h>
/* WARNING!! /* WARNING!!
* This code is compiled with -fPIC and it is relocated dynamically * 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,12 +361,12 @@ asmlinkage void decompress_kernel(void *rmode, unsigned long end,
insize = input_len; insize = input_len;
inptr = 0; inptr = 0;
if (((u32)output - CONFIG_PHYSICAL_START) & 0x3fffff) if ((u32)output & (CONFIG_PHYSICAL_ALIGN -1))
error("Destination address not 4M aligned"); error("Destination address not CONFIG_PHYSICAL_ALIGN aligned");
if (end > ((-__PAGE_OFFSET-(512 <<20)-1) & 0x7fffffff)) if (end > ((-__PAGE_OFFSET-(512 <<20)-1) & 0x7fffffff))
error("Destination address too large"); error("Destination address too large");
#ifndef CONFIG_RELOCATABLE #ifndef CONFIG_RELOCATABLE
if ((u32)output != CONFIG_PHYSICAL_START) if ((u32)output != LOAD_PHYSICAL_ADDR)
error("Wrong destination address"); error("Wrong destination address");
#endif #endif
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <asm/thread_info.h> #include <asm/thread_info.h>
#include <asm/page.h> #include <asm/page.h>
#include <asm/cache.h> #include <asm/cache.h>
#include <asm/boot.h>
OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
OUTPUT_ARCH(i386) OUTPUT_ARCH(i386)
...@@ -27,7 +28,7 @@ PHDRS { ...@@ -27,7 +28,7 @@ PHDRS {
} }
SECTIONS SECTIONS
{ {
. = LOAD_OFFSET + CONFIG_PHYSICAL_START; . = LOAD_OFFSET + LOAD_PHYSICAL_ADDR;
phys_startup_32 = startup_32 - LOAD_OFFSET; phys_startup_32 = startup_32 - LOAD_OFFSET;
/* read-only */ /* read-only */
.text : AT(ADDR(.text) - LOAD_OFFSET) { .text : AT(ADDR(.text) - LOAD_OFFSET) {
......
...@@ -12,4 +12,8 @@ ...@@ -12,4 +12,8 @@
#define EXTENDED_VGA 0xfffe /* 80x50 mode */ #define EXTENDED_VGA 0xfffe /* 80x50 mode */
#define ASK_VGA 0xfffd /* ask for it at bootup */ #define ASK_VGA 0xfffd /* ask for it at bootup */
#endif /* Physical address where kenrel should be loaded. */
#define LOAD_PHYSICAL_ADDR ((0x100000 + CONFIG_PHYSICAL_ALIGN - 1) \
& ~(CONFIG_PHYSICAL_ALIGN - 1))
#endif /* _LINUX_BOOT_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment