From: Graeme Russ <graeme.russ@gmail.com>
To: "H. Peter Anvin" <hpa@zytor.com>
Cc: linux-kernel@vger.kernel.org
Subject: Re: x86 embedded - Problem getting past 'move compressed kernel before decompression'
Date: Sat, 27 Feb 2010 16:06:45 +1100 [thread overview]
Message-ID: <4B88A865.2080009@gmail.com> (raw)
In-Reply-To: <d66caabb1002211451s5a68565fue6096e17b99402f7@mail.gmail.com>
Graeme Russ wrote:
> On Sun, Feb 21, 2010 at 4:53 PM, H. Peter Anvin <hpa@zytor.com> wrote:
>> On 02/20/2010 09:45 PM, H. Peter Anvin wrote:
>>
> Thanks Peter - I gave that a try but no luck. I am in the process of
> writing some routines which will dump the contents of the registers
> upon entering startup_32 and the relocation jump address prior to
> the jump.
>
> My assembler is a bit rusty, so it is taking a bit of time
>
Sorry for the delay - been very busy lately.
I borrowed __show_regs() from process_32.c and implemented crash dump and
break dump handlers in u-boot. So now I can int3 and dump all registers.
To give some context to what I am doing in u-boot:
#define DECLARE_INTERRUPT(x) \
".globl irq_"#x"\n" \
".hidden irq_"#x"\n" \
".type irq_"#x", @function\n" \
"irq_"#x":\n" \
"pushl $"#x"\n" \
"jmp irq_common_entry\n"
asm(".globl irq_common_entry\n" \
".hidden irq_common_entry\n" \
".type irq_common_entry, @function\n" \
"irq_common_entry:\n" \
"cld\n" \
"pushl %gs\n" \
"pushl %fs\n" \
"pushl %es\n" \
"pushl %ds\n" \
"pushl %eax\n" \
"pushl %ebp\n" \
"pushl %edi\n" \
"pushl %esi\n" \
"pushl %edx\n" \
"pushl %ecx\n" \
"pushl %ebx\n" \
"mov %esp, %eax\n" \
"pushl %ebp\n" \
"movl %esp,%ebp\n" \
"pushl %eax\n" \
"call irq_llsr\n" \
"popl %eax\n" \
"leave\n"\
"popl %ebx\n" \
"popl %ecx\n" \
"popl %edx\n" \
"popl %esi\n" \
"popl %edi\n" \
"popl %ebp\n" \
"popl %eax\n" \
"popl %ds\n" \
"popl %es\n" \
"popl %fs\n" \
"popl %gs\n" \
"add $4, %esp\n" \
"iret\n" \
DECLARE_INTERRUPT(0) \
DECLARE_INTERRUPT(1) \
DECLARE_INTERRUPT(2) \
.
.
.
DECLARE_INTERRUPT(255)
/* IRQ Low-Level Service Routine */
__isr__ irq_llsr(struct pt_regs *regs)
{
switch (regs->orig_eax) {
case 0x00:
printf("Divide Error (Division by zero)\n");
dump_regs(regs);
while(1);
break;
case 0x01:
printf("Debug Interrupt (Single step)\n");
dump_regs(regs);
break;
case 0x02:
printf("NMI Interrupt\n");
dump_regs(regs);
break;
case 0x03:
printf("Breakpoint\n");
dump_regs(regs);
break;
etc
}
dump_regs() is pretty much the same as __show_regs() in process_32.c
I've pulled the latest 6.2.33 kernel source and applied the following patch
to trace progress through the 32-bit Boot Protocol:
diff --git a/arch/x86/boot/compressed/head_32.S
b/arch/x86/boot/compressed/head_32.S
index f543b70..3535470 100644
--- a/arch/x86/boot/compressed/head_32.S
+++ b/arch/x86/boot/compressed/head_32.S
@@ -32,6 +32,7 @@
__HEAD
ENTRY(startup_32)
+ int3
cld
/*
* Test KEEP_SEGMENTS flag to see if the bootloader is asking
@@ -93,12 +94,14 @@ ENTRY(startup_32)
* Copy the compressed kernel to the end of our buffer
* where decompression in place becomes safe.
*/
+ int3
pushl %esi
leal (_bss-4)(%ebp), %esi
leal (_bss-4)(%ebx), %edi
movl $(_bss - startup_32), %ecx
shrl $2, %ecx
std
+ int3
rep movsl
cld
popl %esi
@@ -106,12 +109,15 @@ ENTRY(startup_32)
/*
* Jump to the relocated address.
*/
+ int3
leal relocated(%ebx), %eax
+ int3
jmp *%eax
ENDPROC(startup_32)
.text
relocated:
+ int3
/*
* Clear BSS (stack is currently empty)
and in u-boot, to boot the kernel, I have:
struct boot_params boot_params __attribute__((aligned(16)));
struct setup_header *hdr = (struct setup_header *)(0x90000 + 0x1f1);
void boot_zimage(void *setup_base)
{
printf("&boot_params = 0x%8.8lx\n", (ulong)&boot_params);
printf("sizeof (*hdr) = 0x%8.8lx\n", (ulong)(sizeof (*hdr)));
memset(&boot_params, 0x00, sizeof boot_params);
memcpy(&boot_params.hdr, hdr, sizeof (*hdr));
boot_params.alt_mem_k = 128 * 1024;
boot_params.e820_entries = 1;
boot_params.e820_map[0].addr = 0x00000000;
boot_params.e820_map[0].size = 128 * 1024;
boot_params.e820_map[0].type = 1;
printf("Entering Linux\n");
asm volatile(
"movl %2, %%ds\n" \
"movl %2, %%es\n" \
"movl %2, %%fs\n" \
"movl %2, %%gs\n" \
"movl %2, %%ss\n" \
"xorl %%ebp, %%ebp\n" \
"xorl %%ebx, %%ebx\n" \
"int3\n" \
"ljmpl $0x10,$0x100000"
: : "S" (&boot_params), "D" (0), "r" (0x18));
}
The result is:
&boot_params = 0x03ffb350
sizeof (*hdr) = 0x00000067
Entering Linux
Breakpoint
EIP: 0010:[<03fe3e0b>] EFLAGS: 00000046
EAX: 00000018 EBX: 00000000 ECX: 000003f8 EDX: 000003f8
ESI: 03ffb350 EDI: 00000000 EBP: 00000000 ESP: 03ff42f3
DS: 0018 ES: 0018 FS: 0018 GS: 0018 SS: 01f1
CR0: 00000033 CR2: 00000000 CR3: 00000000 CR4: 00080099
DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000
DR6: ffff0ff0 DR7: 00000400
Breakpoint
EIP: 0010:[<00100001>] EFLAGS: 00000046
EAX: 00000018 EBX: 00000000 ECX: 000003f8 EDX: 000003f8
ESI: 03ffb350 EDI: 00000000 EBP: 00000000 ESP: 03ff42f3
DS: 0018 ES: 0018 FS: 0018 GS: 0018 SS: 01f1
CR0: 00000033 CR2: 00000000 CR3: 00000000 CR4: 00080099
DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000
DR6: ffff0ff0 DR7: 00000400
Breakpoint
EIP: 0010:[<00100042>] EFLAGS: 00000002
EAX: 00000018 EBX: 00377000 ECX: 000003f8 EDX: 000003f8
ESI: 03ffb350 EDI: 00000000 EBP: 00100000 ESP: 00000000
DS: 0018 ES: 0018 FS: 0018 GS: 0018 SS: 0000
CR0: 00000033 CR2: 00000000 CR3: 00000000 CR4: 00080099
DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000
DR6: ffff0ff0 DR7: 00000400
Breakpoint
EIP: 0010:[<00100059>] EFLAGS: 00000416
EAX: 00000018 EBX: 00377000 ECX: 00070828 EDX: 000003f8
ESI: 002c209c EDI: 0053909c EBP: 00100000 ESP: 03ffb350
DS: 0018 ES: 0018 FS: 0018 GS: 0018 SS: 0000
CR0: 00000033 CR2: 00000000 CR3: 00000000 CR4: 00080099
DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000
DR6: ffff0ff0 DR7: 00000400
Breakpoint
EIP: 0010:[<0010005e>] EFLAGS: 00000016
EAX: 00000018 EBX: 00377000 ECX: 00000000 EDX: 000003f8
ESI: 03ffb350 EDI: 00376ffc EBP: 00100000 ESP: 00000000
DS: 0018 ES: 0018 FS: 0018 GS: 0018 SS: 0000
CR0: 00000033 CR2: 00000000 CR3: 00000000 CR4: 00080099
DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000
DR6: ffff0ff0 DR7: 00000400
Breakpoint
EIP: 0010:[<00100065>] EFLAGS: 00000016
EAX: 005379c4 EBX: 00377000 ECX: 00000000 EDX: 000003f8
ESI: 03ffb350 EDI: 00376ffc EBP: 00100000 ESP: 00000000
DS: 0018 ES: 0018 FS: 0018 GS: 0018 SS: 0000
CR0: 00000033 CR2: 00000000 CR3: 00000000 CR4: 00080099
DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000
DR6: ffff0ff0 DR7: 00000400
Invalid Opcode (UnDefined Opcode)
EIP: 0010:[<dd013ea8>] EFLAGS: 00010016
EAX: 005379c4 EBX: 00377000 ECX: 00000000 EDX: 873d0328
ESI: 03ffb350 EDI: 00376ffc EBP: 00100000 ESP: 00000018
DS: 0018 ES: 0018 FS: 0018 GS: 0018 SS: 0000
CR0: 00000033 CR2: 00000000 CR3: 00000000 CR4: 00080099
DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000
DR6: ffff0ff0 DR7: 00000400
I don't understand what is going on with SS and ESP, but everything else is
looking good up until:
jmp *%eax
At which point, eax appears to hold a reasonably value. But:
boot > md 5379c4
005379c4: c11c0e7f b0c2ea61 2d43c068 f02e6fa0 ....a...h.C-.o..
005379d4: 3d0328ba 76651e87 c4c6e98e 26fddcad .(.=..ev.......&
005379e4: 1983b874 c9edece7 793c2ce4 a8de5f50 t........,<yP_..
005379f4: a29afa5b e7b42f13 c4233d0a bc6e8424 [..../...=#.$.n.
00537a04: cb90001b dcea7bb4 969601e8 707fbe4a .....{......J..p
00537a14: dfead2ec b8e62d5b fd7d2b53 b8ad16ef ....[-..S+}.....
00537a24: e0252df2 28044367 9c80c800 beec457e .-%.gC.(....~E..
00537a34: 22d27b84 4f32a8cc 9d1eb9b3 aac36b6a .{."..2O....jk..
00537a44: f7f79e53 54af3ec6 f32eebe6 5a89fe1d S....>.T.......Z
00537a54: 3e3aadfa 63e0b27f 5086cadd b438532e ..:>...c...P.S8.
00537a64: 0a4daef6 f68fb9fc b525a3f1 c0cd58e7 ..M.......%..X..
00537a74: 3f727ad6 061e1199 793d150a 5fd8a267 .zr?......=yg.._
00537a84: fca2d658 4f1e392c dbdd62d3 4fed04dd X...,9.O.b.....O
00537a94: 07caba83 1274f371 e18ef1f5 e1c32aef ....q.t......*..
00537aa4: 964ff812 f214be9d a59e8b2c 281d0dd6 ..O.....,......(
00537ab4: 0d5a95fc 818d59e7 11d33442 73b99e6b ..Z..Y..B4..k..s
(Note: each of the above longs is in reverse byte order, so 0x005379c4 is
actually 0x7f
I would have expected a 0xcc at 0x005379c4.
>From u-boot, if I jump straight to 0x005379c4 I get pretty much the same
crash. So it looks like a problem with the calculation of the copy source
or target address, or the calculation of the relocated jump address.
Any ideas?
Regards
Graeme
next prev parent reply other threads:[~2010-02-27 5:06 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-02-21 2:03 x86 embedded - Problem getting past 'move compressed kernel before decompression' Graeme Russ
2010-02-21 5:45 ` H. Peter Anvin
2010-02-21 5:53 ` H. Peter Anvin
2010-02-21 9:11 ` Yuhong Bao
2010-02-21 22:51 ` Graeme Russ
2010-02-27 5:06 ` Graeme Russ [this message]
2010-03-01 11:56 ` Graeme Russ
2010-03-01 16:46 ` H. Peter Anvin
2010-03-01 19:41 ` Graeme Russ
2010-03-01 19:43 ` H. Peter Anvin
2010-03-01 19:59 ` Graeme Russ
2010-03-05 13:02 ` Graeme Russ
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=4B88A865.2080009@gmail.com \
--to=graeme.russ@gmail.com \
--cc=hpa@zytor.com \
--cc=linux-kernel@vger.kernel.org \
/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.