[SeaBIOS] vgabios testing

Julian Pidancet julian.pidancet at gmail.com
Sun Mar 4 04:03:49 CET 2012


On 03/04/12 00:21, Julian Pidancet wrote:
> On 03/02/12 09:09, Gerd Hoffmann wrote:
>>   Hi,
>>
>> Did some more testing of the vgabios today, two issues popped up:
>>
>>   (1) screen isn't cleared in some cases.  Visible with grub1 in text
>>       mode.  When it displays the menu a few stray chars are visible.
>>       Even more obvious it becomes when hitting 'c' then to get a
>>       prompt, then alot of the menu is still visible.
>>
>>   (2) The Xorg Server has trouble, the VESA driver doesn't work.
>>
>> There are also some good news:  linux kernel with vesafb active works
>> fine, likewise winxp guests.
> 
> Hi Gerd.
> 
> I took a look at the issue with Xorg. According to my diagnostic, x86emu
> (the real-mode emulator that the X server uses) seems to have problems
> emulating mov instructions that uses segment selectors other than DS and SS.
> 
> In lots of places in the vga bios code, we use instructions like
> mov %cs:(%eax), %ebp to access global variables (mostly when we
> use the GET_GLOBAL macro). We also might have a problem we use the
> SET_FARVAR macro because it uses ES.
> 
> This issue with segment selector seems to be confirmed by some comments
> I found in x86emu's code while doing my research:
> http://cgit.freedesktop.org/xorg/xserver/tree/hw/xfree86/x86emu/decode.c
> The comment describing the decode_rm00_address function (line 838) seems
> to imply that only DS or SS can be used.
> 
> Kevin, would you see a problem modifying the READx_SEG macros in
> src/farptr.h to only dereference memory using the DS selector, in the
> vgabios case ?
> 
> For example:
> 
> #define READ8_SEG(prefix, SEG, value, var)                      \
>     __asm__(prefix "push %%ds\n"                                \
>                    "movw %%" #SEG " , %%ax\n"                   \
>                    "movw %%ax, %%ds\n"                          \
>                    "movb %1, %b0\n"                             \
>                    "pop %%ds" : "=Qi"(value)                    \
>             : "m"(var), "m"(__segment_ ## SEG))
> 
> instead of:
> 
> #define READ8_SEG(prefix, SEG, value, var)                      \
>     __asm__(prefix "movb %%" #SEG ":%1, %b0" : "=Qi"(value)     \
> 
> 

Hi again,

I've done further debugging, and you can ignore all of the crap above.
x86emu badly handles the retl instruction and only pops a 16bit wide
value from the stack, whereas the corresponding calll pushes a 32bit
return address. leavel suffers from the same problem.

I've applied the following patch to x86emu and it seems to work better:

diff --git a/hw/xfree86/x86emu/ops.c b/hw/xfree86/x86emu/ops.c
index 5d3cac1..dd15387 100644
--- a/hw/xfree86/x86emu/ops.c
+++ b/hw/xfree86/x86emu/ops.c
@@ -8503,7 +8503,11 @@ static void x86emuOp_ret_near(u8 X86EMU_UNUSED(op1))
     DECODE_PRINTF("RET\n");
        RETURN_TRACE("RET",M.x86.saved_cs,M.x86.saved_ip);
        TRACE_AND_STEP();
-    M.x86.R_IP = pop_word();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+       M.x86.R_EIP = pop_long();
+    } else {
+       M.x86.R_IP = pop_word();
+    }
     DECODE_CLEAR_SEGOVR();
     END_OF_INSTR();
 }
@@ -8807,8 +8811,13 @@ static void x86emuOp_leave(u8 X86EMU_UNUSED(op1))
     START_OF_INSTR();
     DECODE_PRINTF("LEAVE\n");
     TRACE_AND_STEP();
-    M.x86.R_SP = M.x86.R_BP;
-    M.x86.R_BP = pop_word();
+    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+       M.x86.R_ESP = M.x86.R_EBP;
+       M.x86.R_EBP = pop_long();
+    } else {
+       M.x86.R_SP = M.x86.R_BP;
+       M.x86.R_BP = pop_word();
+    }
     DECODE_CLEAR_SEGOVR();
     END_OF_INSTR();
 }

I am now wondering why Xorg calls VBE function 4f01 on the ROM so many
times. It might be another bug.
Also, in my test environment, Xorg still reports a bad checksum.

-- 
Julian






More information about the SeaBIOS mailing list