On 08/27/14 23:17, Curt Brune wrote:
Hello Kevin -
On Mon Aug 18 14:56, Kevin O'Connor wrote:
Unfortunately, I don't see anything in the log that looks suspicious. Since you are using qemu/kvm, you could try attaching a debugger (if you are familiar with gdb).
There's documentation online and in the SeaBIOS' README file. In a nutshell, run qemu with "-s -S" and then run "gdb" in another terminal and send it "target remote localhost:1234" along with something like "br *0x40000" to set a break point at the start of the payload.
Another option would be to try with a known working payload and verify if you can get SeaBIOS to launch it.
Thanks for your time and suggestions.
As a control I tried using the libpayload example (http://www.coreboot.org/Libpayload) as a SeaBIOS payload and that worked fine. So SeaBIOS seems fine.
I went down the gdb route and found some interesting results, but still not sure what is wrong. It has been educational :)
Using gdb I worked my way through coreboot and SeaBIOS loading and into cbfs_run_payload(). cbfs_run_payload() loads the payload OK and jumps to the trampoline @ 0x40000 fine. The trampoline does various things and eventually jumps to the kernel code @ 0x1000000. In gdb this looks like:
=> 0x1000000: cld 0x1000001: test BYTE PTR [esi+0x211],0x40 0x1000008: jne 0x1000016 0x100000a: cli 0x100000b: mov eax,0x18 0x1000010: mov ds,eax 0x1000012: mov es,eax 0x1000014: mov ss,eax <--- CPU resets executing this 0x1000016: lea esp,[esi+0x1e8] 0x100001c: call 0x1000021
The source code for this location comes from the kernel file linux/arch/x86/boot/compressed/head_64.S
I found executing the "mov ss,eax" instruction @ 0x1000014 would cause the virtual machine to reboot. I presume some kind of stack/memory exception happened and the exception handler resets the CPU.
Just before executing that instruction the CPU registers look like this (from the qemu monitor):
(qemu) info registers EAX=00000018 EBX=1ffd6610 ECX=00000000 EDX=00000000 ESI=00090000 EDI=00090334 EBP=00040070 ESP=00006fa4 EIP=01000014 EFL=00000046 [---Z-P-] CPL=0 II=0 A20=1 SMM=0 HLT=0 ES =0018 000f0000 0000ffff 00009b00 DPL=0 CS16 [-RA] CS =0008 00000000 ffffffff 00c09b00 DPL=0 CS32 [-RA] SS =0010 00000000 ffffffff 00c09300 DPL=0 DS [-WA] DS =0018 000f0000 0000ffff 00009b00 DPL=0 CS16 [-RA] FS =0010 00000000 ffffffff 00c09300 DPL=0 DS [-WA] GS =0010 00000000 ffffffff 00c09300 DPL=0 DS [-WA] LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy GDT= 000f4b78 00000037 IDT= 000f4bb6 00000000 CR0=00000011 CR2=00000000 CR3=00000000 CR4=00000000 DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000 DR6=00000000ffff0ff0 DR7=0000000000000400 EFER=0000000000000000 FCW=037f FSW=0000 [ST=0] FTW=00 MXCSR=00001f80
So setting SS from 0x10 to 0x18 caused the exception. Of note the DS and ES registers were set from 0x10 to 0x18 without any problem.
Now armed with qemu/gdb knowledge I went through my working case, where my kernel is loaded directly by coreboot. SeaBIOS is not used in this case. My kernel boots fine in this case.
Just before executing the troublesome instruction @ 0x1000014 the CPU registers look like this (from the qemu monitor) in the working case:
(qemu) info registers EAX=00000018 EBX=1ffd6610 ECX=00000000 EDX=00000000 ESI=00090000 EDI=00090334 EBP=00127ff0 ESP=1ffd0f88 EIP=01000014 EFL=00000046 [---Z-P-] CPL=0 II=0 A20=1 SMM=0 HLT=0 ES =0018 00000000 ffffffff 00c09300 DPL=0 DS [-WA] CS =0010 00000000 ffffffff 00c09b00 DPL=0 CS32 [-RA] SS =0018 00000000 ffffffff 00c09300 DPL=0 DS [-WA] DS =0018 00000000 ffffffff 00c09300 DPL=0 DS [-WA] FS =0018 00000000 ffffffff 00c09300 DPL=0 DS [-WA] GS =0018 00000000 ffffffff 00c09300 DPL=0 DS [-WA] LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy GDT= 1ffec000 00000047 IDT= 001218c4 0000009f CR0=60000011 CR2=00000000 CR3=00000000 CR4=00000000 DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000 DR6=00000000ffff0ff0 DR7=0000000000000400 EFER=0000000000000000 FCW=037f FSW=0000 [ST=0] FTW=00 MXCSR=00001f80
Here the interesting thing is that DS, ES and SS *already* contained 0x18. In the SeaBIOS case those registers contained 0x10 before the Linux kernel set them up.
That's all I got. Any clues?
I'll probably make a clown out of myself, but I'll just blurt out that the direct value of SS (0x18) is quite meaningless, it's just a segment *selector* value. What is interesting is the contents of the GDT entry, at byte offset 0x18 (which corresponds to the fourth GDT entry).
In your first register dump, you have
GDT= 000f4b78 00000037
in the 2nd register dump, you have
GDT= 1ffec000 00000047
The second value in each case means the maximum (inclusive) byte offset in the GDT, so 0x18 itself should be okay in both cases.
Can you hex-dump the guest memory too, in both cases, starting from 0xf4b78+0x18, and from 0x1ffec000+0x18, respectively, for 0x8 bytes? This would provide the segment descriptor in each case that the selector value 0x18 references.
In the resetting case, the segment descriptor referenced by selector value 0x18 is probably suitable for data segments, but inappropriate for the stack segment.
Thanks Laszlo /ducks