From: Yinghai Lu <yinghai@kernel.org>
To: Simon Horman <horms@verge.net.au>,
"H. Peter Anvin" <hpa@zytor.com>, Vivek Goyal <vgoyal@redhat.com>,
"Eric W. Biederman" <ebiederm@xmission.com>
Cc: Yinghai Lu <yinghai@kernel.org>, kexec@lists.infradead.org
Subject: [PATCH v9 4/7] kexec, x86: Fix bzImage real-mode booting
Date: Thu, 21 Feb 2013 20:07:53 -0800 [thread overview]
Message-ID: <1361506076-13112-5-git-send-email-yinghai@kernel.org> (raw)
In-Reply-To: <1361506076-13112-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 | 62 +++++++++++++++++++++++++++++++--------
1 file changed, 49 insertions(+), 13 deletions(-)
diff --git a/kexec/arch/i386/kexec-bzImage.c b/kexec/arch/i386/kexec-bzImage.c
index 35005c7..0756f23 100644
--- a/kexec/arch/i386/kexec-bzImage.c
+++ b/kexec/arch/i386/kexec-bzImage.c
@@ -117,6 +117,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.
@@ -208,8 +210,29 @@ 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);
if (!real_mode_entry) {
@@ -275,11 +298,18 @@ 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 && real_mode->protocol_version >= 0x0201) {
+ real_mode->loader_flags |= 0x80; /* CAN_USE_HEAP */
+ 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));
/*
@@ -298,16 +328,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;
@@ -327,10 +359,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:[~2013-02-22 4:08 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-02-22 4:07 [PATCH v9 0/7] kexec: put bzImage and ramdisk above 4G for x86 64bit Yinghai Lu
2013-02-22 4:07 ` [PATCH v9 1/7] kexec, x86: set booloader id in setup_header Yinghai Lu
2013-02-22 4:07 ` [PATCH v9 2/7] kexec, x86: add boot header member for version 2.12 Yinghai Lu
2013-02-22 4:07 ` [PATCH v9 3/7] kexec, x86: clean boot_params area for entry-32bit path Yinghai Lu
2013-02-22 4:07 ` Yinghai Lu [this message]
2013-02-22 4:07 ` [PATCH v9 5/7] kexec, x86: put ramdisk/cmd_line above 4G for 64bit bzImage Yinghai Lu
2013-02-22 4:07 ` [PATCH v9 6/7] kexec, x86_64: Load bzImage64 above 4G Yinghai Lu
2013-02-22 4:07 ` [PATCH v9 7/7] kexec, x86: handle Crash low kernel range Yinghai Lu
2013-02-26 9:18 ` [PATCH v9 0/7] kexec: put bzImage and ramdisk above 4G for x86 64bit Dave Young
2013-03-05 1:34 ` Simon Horman
2013-03-05 1:39 ` Simon Horman
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=1361506076-13112-5-git-send-email-yinghai@kernel.org \
--to=yinghai@kernel.org \
--cc=ebiederm@xmission.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.