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