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.