From: Marcelo Tosatti <mtosatti@redhat.com>
To: Guillaume Thouvenin <guillaume.thouvenin@ext.bull.net>
Cc: kvm-devel@lists.sourceforge.net,
Mohammed Gamal <m.gamal005@gmail.com>,
Avi Kivity <avi@qumranet.com>
Subject: Re: Protected mode transitions and big real mode... still an issue
Date: Wed, 14 May 2008 18:29:53 -0300 [thread overview]
Message-ID: <20080514212953.GA17705@dmt> (raw)
In-Reply-To: <20080514092911.561872d4@frecb000711.frec.bull.fr>
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" <m.gamal005@gmail.com> 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/
next prev parent reply other threads:[~2008-05-14 21:29 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-04-29 13:02 Protected mode transitions and big real mode... still an issue Guillaume Thouvenin
2008-04-29 16:41 ` Anthony Liguori
2008-04-29 17:09 ` Laurent Vivier
2008-04-29 17:22 ` Laurent Vivier
2008-04-29 23:20 ` Avi Kivity
2008-04-29 18:17 ` Anthony Liguori
2008-04-29 16:56 ` David Mair
2008-04-29 18:16 ` Anthony Liguori
2008-05-01 19:13 ` Marcelo Tosatti
2008-05-03 8:26 ` Balaji Rao
2008-05-05 12:40 ` Guillaume Thouvenin
2008-05-05 12:44 ` Balaji Rao
2008-05-05 12:57 ` Anthony Liguori
2008-05-05 13:29 ` Mohammed Gamal
2008-05-06 13:38 ` Guillaume Thouvenin
2008-05-06 14:30 ` Anthony Liguori
2008-05-06 17:05 ` Mohammed Gamal
2008-05-14 7:29 ` Guillaume Thouvenin
2008-05-14 21:29 ` Marcelo Tosatti [this message]
2008-05-15 7:33 ` Avi Kivity
2008-05-15 7:49 ` Guillaume Thouvenin
2008-05-15 18:07 ` Mohammed Gamal
2008-05-07 5:57 ` Guillaume Thouvenin
2008-05-05 6:27 ` Guillaume Thouvenin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20080514212953.GA17705@dmt \
--to=mtosatti@redhat.com \
--cc=avi@qumranet.com \
--cc=guillaume.thouvenin@ext.bull.net \
--cc=kvm-devel@lists.sourceforge.net \
--cc=m.gamal005@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.