From: Yinghai Lu <yinghai@kernel.org>
To: Simon Horman <horms@verge.net.au>,
"H. Peter Anvin" <hpa@zytor.com>, Vivek Goyal <vgoyal@redhat.com>,
Haren Myneni <hbabu@us.ibm.com>,
"Eric W. Biederman" <ebiederm@xmission.com>
Cc: Yinghai Lu <yinghai@kernel.org>, kexec@lists.infradead.org
Subject: [PATCH v6 3/6] kexec, x86: Fix bzImage real-mode booting
Date: Thu, 13 Dec 2012 14:18:29 -0800 [thread overview]
Message-ID: <1355437112-9250-4-git-send-email-yinghai@kernel.org> (raw)
In-Reply-To: <1355437112-9250-1-git-send-email-yinghai@kernel.org>
We need to keep space for bss, heap/stack before command line.
otherwise command_line will be cleared by kernel 16bit init code.
also need to set 32bit start in real_mode header, kernel 16bit code
need to jump there.
Also don't touch regs16 if --real-mode is not specified.
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
kexec/arch/i386/kexec-bzImage.c | 65 +++++++++++++++++++++++++++++++--------
1 file changed, 52 insertions(+), 13 deletions(-)
diff --git a/kexec/arch/i386/kexec-bzImage.c b/kexec/arch/i386/kexec-bzImage.c
index a5896be..da3ebd1 100644
--- a/kexec/arch/i386/kexec-bzImage.c
+++ b/kexec/arch/i386/kexec-bzImage.c
@@ -130,6 +130,8 @@ int do_bzImage_load(struct kexec_info *info,
unsigned long kernel32_load_addr;
char *modified_cmdline;
unsigned long cmdline_end;
+ unsigned long kern16_size_needed;
+ unsigned long heap_size = 0;
/*
* Find out about the file I am about to load.
@@ -221,9 +223,31 @@ int do_bzImage_load(struct kexec_info *info,
elf_rel_build_load(info, &info->rhdr, purgatory, purgatory_size,
0x3000, 640*1024, -1, 0);
dbgprintf("Loaded purgatory at addr 0x%lx\n", info->rhdr.rel_addr);
+
/* The argument/parameter segment */
- setup_size = kern16_size + command_line_len + PURGATORY_CMDLINE_SIZE;
+ if (real_mode_entry) {
+ /* need to include size for bss and heap etc */
+ if (setup_header.protocol_version >= 0x0201)
+ kern16_size_needed = setup_header.heap_end_ptr;
+ else
+ kern16_size_needed = kern16_size + 8192; /* bss */
+ if (kern16_size_needed < kern16_size)
+ kern16_size_needed = kern16_size;
+ if (kern16_size_needed > 0xfffc)
+ die("kern16_size_needed is more then 64k\n");
+ heap_size = 0xfffc - kern16_size_needed; /* less 64k */
+ heap_size &= ~(0x200 - 1);
+ kern16_size_needed += heap_size;
+ } else {
+ kern16_size_needed = kern16_size;
+ /* need to bigger than size of struct bootparams */
+ if (kern16_size_needed < 4096)
+ kern16_size_needed = 4096;
+ }
+ setup_size = kern16_size_needed + command_line_len +
+ PURGATORY_CMDLINE_SIZE;
real_mode = xmalloc(setup_size);
+ memset(real_mode, 0, setup_size);
memcpy(real_mode, kernel, kern16_size);
if (!real_mode_entry)
clean_boot_params((unsigned char *)real_mode, kern16_size);
@@ -281,11 +305,20 @@ int do_bzImage_load(struct kexec_info *info,
/* Tell the kernel what is going on */
setup_linux_bootloader_parameters(info, real_mode, setup_base,
- kern16_size, command_line, command_line_len,
+ kern16_size_needed, command_line, command_line_len,
initrd, initrd_len);
+ if (real_mode_entry) {
+ /* restore can use heap and load high */
+ real_mode->loader_flags = 0x81;
+ if (real_mode->protocol_version >= 0x0201)
+ real_mode->heap_end_ptr += heap_size - 0x200; /*stack*/
+ }
+
/* Get the initial register values */
- elf_rel_get_symbol(&info->rhdr, "entry16_regs", ®s16, sizeof(regs16));
+ if (real_mode_entry)
+ elf_rel_get_symbol(&info->rhdr, "entry16_regs",
+ ®s16, sizeof(regs16));
elf_rel_get_symbol(&info->rhdr, "entry32_regs", ®s32, sizeof(regs32));
/*
@@ -304,16 +337,18 @@ int do_bzImage_load(struct kexec_info *info,
/*
* Initialize the 16bit start information.
*/
- regs16.ds = regs16.es = regs16.fs = regs16.gs = setup_base >> 4;
- regs16.cs = regs16.ds + 0x20;
- regs16.ip = 0;
- /* XXX: Documentation/i386/boot.txt says 'ss' must equal 'ds' */
- regs16.ss = (elf_rel_get_addr(&info->rhdr, "stack_end") - 64*1024) >> 4;
- /* XXX: Documentation/i386/boot.txt says 'sp' must equal heap_end */
- regs16.esp = 0xFFFC;
if (real_mode_entry) {
+ regs16.ds = regs16.es = regs16.fs = regs16.gs = setup_base >> 4;
+ regs16.cs = regs16.ds + 0x20;
+ regs16.ip = 0;
+ /* XXX: Documentation/i386/boot.txt says 'ss' must equal 'ds' */
+ regs16.ss = (elf_rel_get_addr(&info->rhdr, "stack_end") - 64*1024) >> 4;
+ /* XXX: Documentation/i386/boot.txt says 'sp' must equal heap_end */
+ regs16.esp = 0xFFFC;
+
printf("Starting the kernel in real mode\n");
regs32.eip = elf_rel_get_addr(&info->rhdr, "entry16");
+ real_mode->kernel_start = kernel32_load_addr;
}
if (real_mode_entry && kexec_debug) {
unsigned long entry16_debug, pre32, first32;
@@ -333,10 +368,14 @@ int do_bzImage_load(struct kexec_info *info,
regs32.eip = entry16_debug;
}
- elf_rel_set_symbol(&info->rhdr, "entry16_regs", ®s16, sizeof(regs16));
- elf_rel_set_symbol(&info->rhdr, "entry16_debug_regs", ®s16, sizeof(regs16));
+ if (real_mode_entry) {
+ elf_rel_set_symbol(&info->rhdr, "entry16_regs",
+ ®s16, sizeof(regs16));
+ elf_rel_set_symbol(&info->rhdr, "entry16_debug_regs",
+ ®s16, sizeof(regs16));
+ }
elf_rel_set_symbol(&info->rhdr, "entry32_regs", ®s32, sizeof(regs32));
- cmdline_end = setup_base + kern16_size + command_line_len - 1;
+ cmdline_end = setup_base + kern16_size_needed + command_line_len - 1;
elf_rel_set_symbol(&info->rhdr, "cmdline_end", &cmdline_end,
sizeof(unsigned long));
--
1.7.10.4
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
next prev parent reply other threads:[~2012-12-13 22:18 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-12-13 22:18 [PATCH v6 0/6] kexec: put bzImage and ramdisk above 4G for x86 64bit Yinghai Lu
2012-12-13 22:18 ` [PATCH v6 1/6] kexec, x86: add boot header member for version 2.12 Yinghai Lu
2012-12-13 22:18 ` [PATCH v6 2/6] kexec, x86: clean boot_params area for entry-32bit path Yinghai Lu
2012-12-13 22:18 ` Yinghai Lu [this message]
2012-12-13 23:42 ` [PATCH v6 3/6] kexec, x86: Fix bzImage real-mode booting H. Peter Anvin
2012-12-14 0:06 ` Yinghai Lu
2012-12-13 22:18 ` [PATCH v6 4/6] kexec, x86: put ramdisk/cmd_line above 4G for 64bit bzImage Yinghai Lu
2012-12-13 22:18 ` [PATCH v6 5/6] kexec, x86_64: Load bzImage64 above 4G Yinghai Lu
2012-12-13 22:18 ` [PATCH v6 6/6] kexec, x86: handle Crash low kernel range Yinghai Lu
2012-12-14 0:41 ` [PATCH v6 0/6] kexec: put bzImage and ramdisk above 4G for x86 64bit H. Peter Anvin
2012-12-14 0:47 ` Yinghai Lu
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1355437112-9250-4-git-send-email-yinghai@kernel.org \
--to=yinghai@kernel.org \
--cc=ebiederm@xmission.com \
--cc=hbabu@us.ibm.com \
--cc=horms@verge.net.au \
--cc=hpa@zytor.com \
--cc=kexec@lists.infradead.org \
--cc=vgoyal@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.