Hi Guillaume,

On Wed, May 14, 2008 at 09:29:11AM +0200, Guillaume Thouvenin wrote:
> On Tue, 6 May 2008 20:05:39 +0300
> "Mohammed Gamal" <[EMAIL PROTECTED]> wrote:
> 
> 
> > > > > WinXP fails with the patch applied too. Ubuntu 7.10 live CD and
> > > > > FreeDOS don't boot but complain about instruction mov 0x11,sreg not
> > > > > being emulated.
> 
> Mohammed, can you try the patch at the end of this mail? Here it's
> working with FreeDOS now (I added the emulation of 0x90 that is an xchg
> instruction). I can also boot winXP Professional X64 edition. I still
> have a weird issue with Ubuntu 7.10 that crashes sometimes with the
> error:
> 
> kvm_run: failed entry, reason 5
> kvm_run returned -8
> 
> It's a little bit strange because this error appears very often with
> the wmii window manager but never with XFCE. And with wmii, it only
> occurs when I move the mouse above the Qemu/KVM window. If I wait 30s
> until the automatic boot it works... 

This appears to be due to the vmport save/load bug:
https://bugs.launchpad.net/ubuntu/+source/kvm/+bug/219165 

I'll look into it if nobody beats me to it.

Regarding FreeDOS, it necessary to emulate software interrupts and NOP
to get the "HIMEM XMS-memory driver" version to boot (with the FreeOSZOO
image).

The "maximum RAM free, using EMM86" version is more complicated, requiring 
ldt, ltr and a few other things.

There are two problems remaining:

1) add is storing the result in the wrong register

    6486:       66 64 89 3e 72 01       mov    %edi,%fs:0x172
    648c:       66 be 8d 03 00 00       mov    $0x38d,%esi
    6492:       66 c1 e6 04             shl    $0x4,%esi
    6496:       66 b8 98 0a 00 00       mov    $0xa98,%eax
    649c:       66 03 f0                add    %eax,%esi

The destination for the add is "%esi", but the emulation stores the 
result in eax, because:

                if ((c->d & ModRM) && c->modrm_mod == 3) {
                        u8 reg;
                        c->dst.bytes = (c->d & ByteOp) ? 1 : c->op_bytes;
                        c->dst.ptr = decode_register(c->modrm_rm, c->regs, c->d 
& ByteOp);
                }

modrm_reg contains "6", which is the correct register index, but
modrm_rm contains 0, so the result is stored in "eax" (see hack).

2) iretl generates pagefaults

  1226df:       0f 06                   clts
  1226e1:       b8 14 00                mov    $0x14,%ax
  1226e4:       8e e0                   mov    %ax,%fs
  1226e6:       66 64 a1 50 01          mov    %fs:0x150,%eax
  1226eb:       0f 22 d8                mov    %eax,%cr3
  1226ee:       0f 20 c0                mov    %cr0,%eax
  1226f1:       66 0d 00 00 00 80       or     $0x80000000,%eax
  1226f7:       0f 22 c0                mov    %eax,%cr0
  1226fa:       66 cf                   iretl

The iretl which happens after enabling paging faults in different ways:

kvm_inject_page_fault: EIP=1226fa
kvm_inject_page_fault: ADDR=1226fa

kvm_inject_page_fault: EIP=1226fa
kvm_inject_page_fault: ADDR=1237d1
kvm: inject_page_fault: double fault 0x1237d1


Index: kvm.tip/arch/x86/kvm/vmx.c
===================================================================
--- kvm.tip.orig/arch/x86/kvm/vmx.c
+++ kvm.tip/arch/x86/kvm/vmx.c
@@ -194,6 +194,12 @@ static inline int is_external_interrupt(
                == (INTR_TYPE_EXT_INTR | INTR_INFO_VALID_MASK);
 }
 
+static inline int is_software_interrupt(u32 intr_info)
+{
+       return (intr_info & (INTR_TYPE_SOFT_INTR | INTR_INFO_VALID_MASK))
+               == (INTR_TYPE_SOFT_INTR | INTR_INFO_VALID_MASK);
+}
+
 static inline int cpu_has_vmx_msr_bitmap(void)
 {
        return (vmcs_config.cpu_based_exec_ctrl & CPU_BASED_USE_MSR_BITMAPS);
@@ -2190,8 +2196,10 @@ static void kvm_guest_debug_pre(struct k
 }
 
 static int handle_rmode_exception(struct kvm_vcpu *vcpu,
-                                 int vec, u32 err_code)
+                                 u32 intr_info, u32 err_code)
 {
+       int vec = intr_info & INTR_INFO_VECTOR_MASK;
+
        if (!vcpu->arch.rmode.active)
                return 0;
 
@@ -2202,6 +2210,10 @@ static int handle_rmode_exception(struct
        if (((vec == GP_VECTOR) || (vec == SS_VECTOR)) && err_code == 0)
                if (emulate_instruction(vcpu, NULL, 0, 0, 0) == EMULATE_DONE)
                        return 1;
+       if (is_software_interrupt(intr_info) && err_code == 0) {
+               if (emulate_instruction(vcpu, NULL, 0, 0, 0) == EMULATE_DONE)
+                       return 1;
+               }
        return 0;
 }
 
@@ -2257,8 +2269,7 @@ static int handle_exception(struct kvm_v
        }
 
        if (vcpu->arch.rmode.active &&
-           handle_rmode_exception(vcpu, intr_info & INTR_INFO_VECTOR_MASK,
-                                                               error_code)) {
+           handle_rmode_exception(vcpu, intr_info, error_code)) {
                if (vcpu->arch.halt_request) {
                        vcpu->arch.halt_request = 0;
                        return kvm_emulate_halt(vcpu);
Index: kvm.tip/arch/x86/kvm/x86.c
===================================================================
--- kvm.tip.orig/arch/x86/kvm/x86.c
+++ kvm.tip/arch/x86/kvm/x86.c
@@ -3294,13 +3294,21 @@ int load_segment_descriptor(struct kvm_v
 
        if (load_segment_descriptor_to_kvm_desct(vcpu, selector, &kvm_seg))
                return 1;
-       kvm_seg.type |= type_bits;
 
        if (seg != VCPU_SREG_SS && seg != VCPU_SREG_CS &&
            seg != VCPU_SREG_LDTR)
                if (!kvm_seg.s)
                        kvm_seg.unusable = 1;
 
+       if (seg == VCPU_SREG_CS && !kvm_seg.s) {
+               switch (kvm_seg.type) {
+               case 9: /* TSS */
+                       return kvm_task_switch(vcpu, selector, TASK_SWITCH_JMP);
+               default:
+               }
+       }
+
+       kvm_seg.type |= type_bits;
        set_segment(vcpu, &kvm_seg, seg);
        return 0;
 }
Index: kvm.tip/arch/x86/kvm/x86_emulate.c
===================================================================
--- kvm.tip.orig/arch/x86/kvm/x86_emulate.c
+++ kvm.tip/arch/x86/kvm/x86_emulate.c
@@ -99,7 +99,7 @@ static u16 opcode_table[256] = {
        /* 0x28 - 0x2F */
        ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM,
        ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM,
-       0, 0, 0, 0,
+       DstReg | SrcImm, DstReg | SrcImm, 0, 0,
        /* 0x30 - 0x37 */
        ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM,
        ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM,
@@ -107,7 +107,7 @@ static u16 opcode_table[256] = {
        /* 0x38 - 0x3F */
        ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM,
        ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM,
-       0, 0, 0, 0,
+       0, ByteOp | DstReg | SrcImm, 0, 0,
        /* 0x40 - 0x47 */
        DstReg, DstReg, DstReg, DstReg, DstReg, DstReg, DstReg, DstReg,
        /* 0x48 - 0x4F */
@@ -154,8 +154,10 @@ static u16 opcode_table[256] = {
        ByteOp | ImplicitOps | Mov | String, ImplicitOps | Mov | String,
        ByteOp | ImplicitOps | String, ImplicitOps | String,
        /* 0xB0 - 0xBF */
-       0, 0, 0, 0, 0, 0, 0, 0,
        DstReg | SrcImm | Mov, 0, 0, 0, 0, 0, 0, 0,
+       DstReg | SrcImm | Mov, DstReg | SrcImm | Mov, DstReg | SrcImm | Mov,
+       DstReg | SrcImm | Mov, DstReg | SrcImm | Mov, DstReg | SrcImm | Mov,
+       DstReg | SrcImm | Mov, DstReg | SrcImm | Mov,
        /* 0xC0 - 0xC7 */
        ByteOp | DstMem | SrcImm | ModRM, DstMem | SrcImmByte | ModRM,
        0, ImplicitOps | Stack, 0, 0,
@@ -169,7 +171,7 @@ static u16 opcode_table[256] = {
        /* 0xD8 - 0xDF */
        0, 0, 0, 0, 0, 0, 0, 0,
        /* 0xE0 - 0xE7 */
-       0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, SrcImmByte, 0, 0, 0, 0, 0,
        /* 0xE8 - 0xEF */
        ImplicitOps | Stack, SrcImm | ImplicitOps, ImplicitOps, SrcImmByte | 
ImplicitOps,
        0, 0, 0, 0,
@@ -183,7 +185,8 @@ static u16 opcode_table[256] = {
 
 static u16 twobyte_table[256] = {
        /* 0x00 - 0x0F */
-       0, Group | GroupDual | Group7, 0, 0, 0, 0, ImplicitOps, 0,
+       SrcReg|SrcMem16|ModRM,
+       Group | GroupDual | Group7, 0, 0, 0, 0, ImplicitOps, 0,
        ImplicitOps, ImplicitOps, 0, 0, 0, ImplicitOps | ModRM, 0, 0,
        /* 0x10 - 0x1F */
        0, 0, 0, 0, 0, 0, 0, 0, ImplicitOps | ModRM, 0, 0, 0, 0, 0, 0, 0,
@@ -275,7 +278,8 @@ static u16 group_table[] = {
        0, 0, 0, 0, 0, 0,
        [Group5*8] =
        DstMem | SrcNone | ModRM, DstMem | SrcNone | ModRM, 0, 0,
-       SrcMem | ModRM, 0, SrcMem | ModRM | Stack, 0,
+       SrcMem | ModRM, ImplicitOps | ModRM, SrcMem | ModRM | Stack, 0,
+
        [Group7*8] =
        0, 0, ModRM | SrcMem, ModRM | SrcMem,
        SrcNone | ModRM | DstMem | Mov, 0,
@@ -951,8 +955,8 @@ done_prefixes:
        }
 
        /* Unrecognised? */
-       if (c->d == 0) {
-               DPRINTF("Cannot emulate %02x\n", c->b);
+       if (c->d == 0 && (c->b != 0xcc) && (c->b != 0x90) && (c->b != 0xf)) {
+               DPRINTF("Cannot emulate %02x %x\n", c->b, c->eip);
                return -1;
        }
 
@@ -1359,8 +1363,15 @@ special_insn:
        case 0x00 ... 0x05:
              add:              /* add */
                if ((c->d & ModRM) && c->modrm_mod == 3) {
+                       u8 reg;
                        c->dst.bytes = (c->d & ByteOp) ? 1 : c->op_bytes;
-                       c->dst.ptr =  decode_register(c->modrm_rm, c->regs, 
c->d & ByteOp);
+
+                       if (ctxt->cs_base + c->eip == 0x649f)
+                               reg = c->modrm_rm|c->modrm_reg;
+                       else
+                               reg = c->modrm_rm;
+
+                       c->dst.ptr =  decode_register(reg, c->regs, c->d & 
ByteOp);
                }
                emulate_2op_SrcV("add", c->src, c->dst, ctxt->eflags);
                break;
@@ -1616,8 +1627,14 @@ special_insn:
                if (rc != 0)
                        goto done;
                break;
-       case 0xb8: /* mov r, imm */
-               goto mov;
+       case 0xb8 ... 0xbf: /* mov r, imm */
+               {
+                       int reg = c->b & 0x7;
+                       c->dst.ptr = (unsigned long *)&c->regs[VCPU_REGS_RAX + 
reg];
+                       goto mov;
+               }
+       case 0x90: /* nop */
+               break;
        case 0x9c: /* pushf */
                c->src.val =  (unsigned long) ctxt->eflags;
                emulate_push(ctxt);
@@ -1732,6 +1749,11 @@ special_insn:
        mov:
                c->dst.val = c->src.val;
                break;
+       case 0xcc ... 0xcd: /* int */
+               /* FIXME: do a proper jump through idt */
+               if (ctxt->mode == X86EMUL_MODE_REAL) {
+               }
+               break;
        case 0xd0 ... 0xd1:     /* Grp2 */
                c->src.val = 1;
                emulate_grp2(ctxt);
@@ -1740,6 +1762,12 @@ special_insn:
                c->src.val = c->regs[VCPU_REGS_RCX];
                emulate_grp2(ctxt);
                break;
+       case 0xe2:              /* loop */
+               c->regs[VCPU_REGS_RCX]--;
+               if (c->regs[VCPU_REGS_RCX])
+                       c->eip = c->eip + c->src.val;
+               c->dst.type = OP_NONE;
+               break;
        case 0xe8: /* call (near) */ {
                long int rel;
                switch (c->op_bytes) {
@@ -1763,13 +1791,38 @@ special_insn:
                jmp_rel(c, c->src.val);
                c->dst.type = OP_NONE; /* Disable writeback. */
                break;
-       case 0xea: /* jmp far */ {
+       case 0xea:
+       jmpfar: /* jmp far */ {
                uint32_t eip;
                uint16_t sel;
 
                /* enable switch_perso */
                switch_perso = 1;
 
+               if (c->b == 0xff) {
+                       rc = ops->read_emulated(c->modrm_ea, &eip, 
+                                               c->op_bytes, ctxt->vcpu);
+                       if (rc != 0)
+                               goto cannot_emulate;
+
+                       c->modrm_ea += c->op_bytes;
+                       rc = ops->read_emulated(c->modrm_ea, &sel, 
+                                               2, ctxt->vcpu);
+                       if (rc != 0)
+                               goto cannot_emulate;
+
+                       c->eip = eip;
+                       if (load_segment_descriptor(ctxt->vcpu, sel, 9,
+                           VCPU_SREG_CS) < 0) {
+                               printk("failed to load cs!\n");
+                               goto cannot_emulate;
+                       }
+                       goto done;
+                       /* FIXME: if this is not a TSS jump need to
+                        * perform register writeback.
+                        * break;
+                        */
+               }
                switch (c->op_bytes) {
                case 2:
                        eip = insn_fetch(u16, 2, c->eip);
@@ -1823,6 +1876,8 @@ special_insn:
                c->dst.type = OP_NONE;  /* Disable writeback. */
                break;
        case 0xfe ... 0xff:     /* Grp4/Grp5 */
+               if (c->modrm_reg == 5)
+                       goto jmpfar;
                rc = emulate_grp45(ctxt, ops);
                if (rc != 0)
                        goto done;
@@ -1847,6 +1902,22 @@ done:
 
 twobyte_insn:
        switch (c->b) {
+       case 0x0:
+               switch (c->modrm_reg) {
+               case 2: /* ldt */
+                       if (load_segment_descriptor(ctxt->vcpu, c->src.val,
+                                                   0, VCPU_SREG_LDTR))
+                               goto cannot_emulate;
+                       break;
+               case 3: /* ltr */
+                       if (load_segment_descriptor(ctxt->vcpu, c->src.val, 
+                                                   1, VCPU_SREG_TR))
+                               goto cannot_emulate;
+                       break;
+               default:
+                       goto cannot_emulate;
+               }
+               break;
        case 0x01: /* lgdt, lidt, lmsw */
                switch (c->modrm_reg) {
                        u16 size;

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft 
Defy all challenges. Microsoft(R) Visual Studio 2008. 
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
kvm-devel mailing list
kvm-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/kvm-devel

Reply via email to