[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <4B88A865.2080009@gmail.com>
Date: Sat, 27 Feb 2010 16:06:45 +1100
From: Graeme Russ <graeme.russ@...il.com>
To: "H. Peter Anvin" <hpa@...or.com>
CC: linux-kernel@...r.kernel.org
Subject: Re: x86 embedded - Problem getting past 'move compressed kernel
before decompression'
Graeme Russ wrote:
> On Sun, Feb 21, 2010 at 4:53 PM, H. Peter Anvin <hpa@...or.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
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists