Re: Protected mode transitions and big real mode... still an issue

Marcelo Tosatti
2008-05-01T19:13:31Z

Hi Guillaume,

On Tue, Apr 29, 2008 at 03:02:36PM +0200, Guillaume Thouvenin wrote:
> Hello,

<snip>

> -hda ~/disk_images/hd_50G.qcow2
> -cdrom /images_iso/openSUSE-10.3-GM-x86_64-mini.iso -boot d -s -m 1024
>
> exception 13 (33)
> rax 0000000000000673 rbx 0000000000800000 rcx 0000000000000000
> rdx 00000000000013ca rsi 0000000000055e1c rdi 0000000000055e1d
> rsp 00000000fffa0080 rbp 000000000000200b r8 0000000000000000
> r9 0000000000000000 r10 0000000000000000 r11 0000000000000000
> r12 0000000000000000 r13 0000000000000000 r14 0000000000000000
> r15 0000000000000000 rip 000000000000b071 rflags 00033092
> cs 4004 (00040040/0000ffff p 1 dpl 3 db 0 s 1 type 3 l 0 g 0 avl 0)
> ds 4004 (00040040/0000ffff p 1 dpl 3 db 0 s 1 type 3 l 0 g 0 avl 0)
> es 00ff (00000ff0/0000ffff p 1 dpl 3 db 0 s 1 type 3 l 0 g 0 avl 0)
> ss ff11 (000ff110/0000ffff p 1 dpl 3 db 0 s 1 type 3 l 0 g 0 avl 0)
> fs 3002 (00030020/0000ffff p 1 dpl 3 db 0 s 1 type 3 l 0 g 0 avl 0)
> gs 0000 (00000000/0000ffff p 1 dpl 3 db 0 s 1 type 3 l 0 g 0 avl 0)
> tr 0000 (fffbd000/00002088 p 1 dpl 0 db 0 s 0 type b l 0 g 0 avl 0)
> ldt 0000 (00000000/0000ffff p 1 dpl 0 db 0 s 0 type 2 l 0 g 0 avl 0)
> gdt 40920/47 idt 0/ffff cr0 10 cr2 0 cr3 0 cr4 0 cr8 0 efer 0
> code: 17 06 29 4b 01 18 eb 18 a8 25 aa 19 28 4c 01 28 4d 01 01 17 -->
> 0f 17 0f 01 17 0f 17 12 01 17 2c 25 4b 19 21 00 02 17 1a 94 0a 76 67 61
> 3d 30 78 25 78 20 Aborted
>
> It's strange because handle_vmentry_failure() is not called. I'm trying
> to see where is the problem, any comments are welcome

Not sure if this is the same problem you're seeing, but with your patch
Plan9 triggers:

exception 13 (6b)
rax 0000000000010010 rbx 0000000000000001 rcx 00000000f0012000 rdx 00000000000000a1
rsi 00000000f0101000 rdi 00000000f0009000 rsp 0000000000007bfc rbp 00000000f0001320
r8 0000000000000000 r9 0000000000000000 r10 0000000000000000 r11 0000000000000000
r12 0000000000000000 r13 0000000000000000 r14 0000000000000000 r15 0000000000000000
rip 000000000000023e rflags 00033002
cs 0000 (00000000/0000ffff p 1 dpl 3 db 0 s 1 type 3 l 0 g 0 avl 0)
ds 0000 (00000000/0000ffff p 1 dpl 3 db 0 s 1 type 3 l 0 g 0 avl 0)
es 0000 (00000000/0000ffff p 1 dpl 3 db 0 s 1 type 3 l 0 g 0 avl 0)
ss 0000 (00000000/0000ffff p 1 dpl 3 db 0 s 1 type 3 l 0 g 0 avl 0)
fs 0000 (00000000/0000ffff p 1 dpl 3 db 0 s 1 type 3 l 0 g 0 avl 0)
gs 0000 (00000000/0000ffff p 1 dpl 3 db 0 s 1 type 3 l 0 g 0 avl 0)
tr 0000 (fffbd000/00002088 p 1 dpl 0 db 0 s 0 type b l 0 g 0 avl 0)
ldt 0000 (00000000/0000ffff p 1 dpl 0 db 0 s 0 type 2 l 0 g 0 avl 0)
gdt 14000/4f
idt 0/3ff
cr0 10010 cr2 0 cr3 12000 cr4 d0 cr8 0 efer 0
code: 00 f0 53 ff 00 f0 53 ff 00 f0 53 ff 00 f0 53 ff 00 f0 53 ff -->
00 f0 53 ff 00 f0 53 ff 00 f0 53 ff 00 f0 53 ff 00 f0 53 ff 00 f0 53 ff 00 f0 53 ff 00 f0

The code sequence is:

8235: 66 data16
8236: 0f 22 c0 mov %eax,%cr0
8239: ea 3e 02 00 08 b8 00 ljmp $0xb8,$0x800023e

So it switches to realmode and then does a ljmp. Problem is that you're
using the segment selector as a GDT index, but in realmode it should be
shifted left by 4 to determine the segment base address. Following patch
makes Plan9 happy.

Other than that, load_segment_descriptor() can return a positive error
on failure, should do a proper check.

Index: kvm/arch/x86/kvm/x86_emulate.c
===================================================================
--- kvm.orig/arch/x86/kvm/x86_emulate.c
+++ kvm/arch/x86/kvm/x86_emulate.c
@@ -1755,7 +1755,10 @@ special_insn:
goto cannot_emulate;
}
sel = insn_fetch(u16, 2, c->eip);
- if (load_segment_descriptor(ctxt->vcpu, sel, 9, VCPU_SREG_CS) < 0) {
+ if (ctxt->mode == X86EMUL_MODE_REAL)
+ eip |= (sel << 4);
+ else if (load_segment_descriptor(ctxt->vcpu, sel, 9,
+ VCPU_SREG_CS) < 0) {
DPRINTF("jmp far: Failed to load CS descriptor\n");
goto cannot_emulate;
}