aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorKeir Fraser <keir@xensource.com>2007-07-02 00:24:59 +0100
committerKeir Fraser <keir@xensource.com>2007-07-02 00:24:59 +0100
commitd0e4f15cfdad64de400ab32ab544f5434b38c9f7 (patch)
tree56b444ef1bc8b4c7d73fb83cf991cc82e98bed17 /tools
parent0cf4932910783de7126b89a4c9c6e0712ff37291 (diff)
downloadxen-d0e4f15cfdad64de400ab32ab544f5434b38c9f7.tar.gz
xen-d0e4f15cfdad64de400ab32ab544f5434b38c9f7.tar.bz2
xen-d0e4f15cfdad64de400ab32ab544f5434b38c9f7.zip
Use 32bit operand and address during VMXAssist protected to real.
Signed-off-by: Xin Li <xin.b.li@intel.com>
Diffstat (limited to 'tools')
-rw-r--r--tools/firmware/vmxassist/setup.c3
-rw-r--r--tools/firmware/vmxassist/vm86.c61
2 files changed, 52 insertions, 12 deletions
diff --git a/tools/firmware/vmxassist/setup.c b/tools/firmware/vmxassist/setup.c
index fd03e3c6cb..1e2e86c27b 100644
--- a/tools/firmware/vmxassist/setup.c
+++ b/tools/firmware/vmxassist/setup.c
@@ -198,9 +198,10 @@ enter_real_mode(struct regs *regs)
}
/* go from protected to real mode */
- regs->eflags |= EFLAGS_VM;
set_mode(regs, VM86_PROTECTED_TO_REAL);
emulate(regs);
+ if (mode != VM86_REAL)
+ panic("failed to emulate between clear PE and long jump.\n");
}
/*
diff --git a/tools/firmware/vmxassist/vm86.c b/tools/firmware/vmxassist/vm86.c
index 357a73e353..847b625e07 100644
--- a/tools/firmware/vmxassist/vm86.c
+++ b/tools/firmware/vmxassist/vm86.c
@@ -580,8 +580,13 @@ movr(struct regs *regs, unsigned prefix, unsigned opc)
unsigned addr = operand(prefix, regs, modrm);
unsigned val, r = (modrm >> 3) & 7;
- if ((modrm & 0xC0) == 0xC0) /* no registers */
- return 0;
+ if ((modrm & 0xC0) == 0xC0) {
+ /*
+ * Emulate all guest instructions in protected to real mode.
+ */
+ if (mode != VM86_PROTECTED_TO_REAL)
+ return 0;
+ }
switch (opc) {
case 0x88: /* addr32 mov r8, r/m8 */
@@ -806,8 +811,13 @@ mov_to_seg(struct regs *regs, unsigned prefix, unsigned opc)
{
unsigned modrm = fetch8(regs);
- /* Only need to emulate segment loads in real->protected mode. */
- if (mode != VM86_REAL_TO_PROTECTED)
+ /*
+ * Emulate segment loads in:
+ * 1) real->protected mode.
+ * 2) protected->real mode.
+ */
+ if ((mode != VM86_REAL_TO_PROTECTED) &&
+ (mode != VM86_PROTECTED_TO_REAL))
return 0;
/* Register source only. */
@@ -817,6 +827,8 @@ mov_to_seg(struct regs *regs, unsigned prefix, unsigned opc)
switch ((modrm & 0x38) >> 3) {
case 0: /* es */
regs->ves = getreg16(regs, modrm);
+ if (mode == VM86_PROTECTED_TO_REAL)
+ return 1;
saved_rm_regs.ves = 0;
oldctx.es_sel = regs->ves;
return 1;
@@ -825,21 +837,29 @@ mov_to_seg(struct regs *regs, unsigned prefix, unsigned opc)
case 2: /* ss */
regs->uss = getreg16(regs, modrm);
+ if (mode == VM86_PROTECTED_TO_REAL)
+ return 1;
saved_rm_regs.uss = 0;
oldctx.ss_sel = regs->uss;
return 1;
case 3: /* ds */
regs->vds = getreg16(regs, modrm);
+ if (mode == VM86_PROTECTED_TO_REAL)
+ return 1;
saved_rm_regs.vds = 0;
oldctx.ds_sel = regs->vds;
return 1;
case 4: /* fs */
regs->vfs = getreg16(regs, modrm);
+ if (mode == VM86_PROTECTED_TO_REAL)
+ return 1;
saved_rm_regs.vfs = 0;
oldctx.fs_sel = regs->vfs;
return 1;
case 5: /* gs */
regs->vgs = getreg16(regs, modrm);
+ if (mode == VM86_PROTECTED_TO_REAL)
+ return 1;
saved_rm_regs.vgs = 0;
oldctx.gs_sel = regs->vgs;
return 1;
@@ -1055,7 +1075,8 @@ set_mode(struct regs *regs, enum vm86_mode newmode)
}
mode = newmode;
- TRACE((regs, 0, states[mode]));
+ if (mode != VM86_PROTECTED)
+ TRACE((regs, 0, states[mode]));
}
static void
@@ -1269,6 +1290,12 @@ opcode(struct regs *regs)
unsigned opc, modrm, disp;
unsigned prefix = 0;
+ if (mode == VM86_PROTECTED_TO_REAL &&
+ oldctx.cs_arbytes.fields.default_ops_size) {
+ prefix |= DATA32;
+ prefix |= ADDR32;
+ }
+
for (;;) {
switch ((opc = fetch8(regs))) {
case 0x07: /* pop %es */
@@ -1379,17 +1406,29 @@ opcode(struct regs *regs)
continue;
case 0x66:
- TRACE((regs, regs->eip - eip, "data32"));
- prefix |= DATA32;
+ if (mode == VM86_PROTECTED_TO_REAL &&
+ oldctx.cs_arbytes.fields.default_ops_size) {
+ TRACE((regs, regs->eip - eip, "data16"));
+ prefix &= ~DATA32;
+ } else {
+ TRACE((regs, regs->eip - eip, "data32"));
+ prefix |= DATA32;
+ }
continue;
case 0x67:
- TRACE((regs, regs->eip - eip, "addr32"));
- prefix |= ADDR32;
+ if (mode == VM86_PROTECTED_TO_REAL &&
+ oldctx.cs_arbytes.fields.default_ops_size) {
+ TRACE((regs, regs->eip - eip, "addr16"));
+ prefix &= ~ADDR32;
+ } else {
+ TRACE((regs, regs->eip - eip, "addr32"));
+ prefix |= ADDR32;
+ }
continue;
- case 0x88: /* addr32 mov r8, r/m8 */
- case 0x8A: /* addr32 mov r/m8, r8 */
+ case 0x88: /* mov r8, r/m8 */
+ case 0x8A: /* mov r/m8, r8 */
if (mode != VM86_REAL && mode != VM86_REAL_TO_PROTECTED)
goto invalid;
if ((prefix & ADDR32) == 0)