On Thu, Jan 3, 2013 at 2:31 PM, Alex Williamson alex.williamson@redhat.com wrote:
Hi,
I was playing a bit with vfio-based PCI device assignment of VGA in qemu and I seem to be hitting a wall just trying to jump into the VGA BIOS. I'm booting qemu with -vga none and assigning a radeon hd5450 via vfio-pci with some extra code to handle passing legacy accesses through to the host. Legacy access hardly seems to matter though as the experiment quickly dies when the vcpu starts executing zero'd memory. gdb shows me something like this:
0x000f257c <__callrom+72>: 66 c7 44 24 16 ff ff movw $0xffff,0x16(%esp) 0x000f2583 <__callrom+79>: 66 c7 44 24 1a ff ff movw $0xffff,0x1a(%esp) 0x000f258a <__callrom+86>: 66 c7 44 24 08 00 f0 movw $0xf000,0x8(%esp) 0x000f2591 <__callrom+93>: b8 80 d1 0f 00 mov $0xfd180,%eax 0x000f2596 <__callrom+98>: 66 89 44 24 0a mov %ax,0xa(%esp) 0x000f259b <__callrom+103>: c1 e5 10 shl $0x10,%ebp 0x000f259e <__callrom+106>: 0f b7 d7 movzwl %di,%edx 0x000f25a1 <__callrom+109>: 09 ea or %ebp,%edx 0x000f25a3 <__callrom+111>: 89 54 24 26 mov %edx,0x26(%esp) 0x000f25a7 <__callrom+115>: 89 e0 mov %esp,%eax 0x000f25a9 <__callrom+117>: 3d 00 70 00 00 cmp $0x7000,%eax 0x000f25ae <__callrom+122>: 76 0a jbe 0xf25ba <__callrom+134> 0x000f25ba <__callrom+134>: 89 f0 mov %esi,%eax 0x000f25bc <__callrom+136>: bb 58 68 00 00 mov $0x6858,%ebx 0x000f25c1 <__callrom+141>: e8 31 98 00 00 call 0xfbdf7 0x000fbdf7: ba 01 be 00 00 mov $0xbe01,%edx 0x000fbdfc: e9 0e ff ff ff jmp 0xfbd0f 0x000fbd0f: 89 c1 mov %eax,%ecx 0x000fbd11: b8 30 00 00 00 mov $0x30,%eax 0x000fbd16: 8e d8 mov %eax,%ds 0x000fbd18: 8e c0 mov %eax,%es 0x000fbd1a: 8e d0 mov %eax,%ss 0x000fbd1c: 8e e0 mov %eax,%fs 0x000fbd1e: 8e e8 mov %eax,%gs 0x000fbd20: 66 ea 26 bd 28 00 ljmpw $0x28,$0xbd26 0x0000bd26: 00 00 add %al,(%eax)
I think GDB is probably getting lost at the far jump (ljmpw). To my knowledge, GDB does not understand the x86 segmented real-mode memory model.
The trace above is __callrom() -> farcall16big() -> call16big() -> __call16big() -> transition16big in romlayout.S, which contains the ljmpw in question.
Trying to follow the code into __callrom(), I'm really confused how the option rom init vector is actually used since callrom() passes the option rom header offset to the init vector rather than anything actually resembling the value of the init vector. I really don't know x86 though, so maybe I'm missing something.
The far address of the ROM initialization vector (seg:offset) is being loaded into br.code, which will get used later on in the farcall helper functions noted above. The offset is set to OPTION_ROM_INITVECTOR by callrom(), which is 3; this is relative to the segment of the ROM header (hence the FLATPTR_TO_SEG in __callrom). The ROM header should have a jump at that location to the real initialization code.
I don't have any real tips on how to make this work - hopefully someone else will know the magic incantation to clue in GDB to the new code segment.
This blog post also looks relevant: http://crustynation.net/wiki/doku.php?id=blog:gdb_real_mode
-- Daniel