* [PATCH] Add more vmxassist opcodes for Ubuntu 7.0.4 support
@ 2007-10-24 21:17 Ben Guthro
2007-10-24 22:21 ` Ben Guthro
0 siblings, 1 reply; 4+ messages in thread
From: Ben Guthro @ 2007-10-24 21:17 UTC (permalink / raw)
To: xen-devel; +Cc: Gary Grebus
[-- Attachment #1: Type: text/plain, Size: 182 bytes --]
Add more opcodes to the vmxassist emulation sufficient to boot Ubuntu 7.04.
Signed-off-by: Ben Guthro <bguthro@virtualron.com>
Signed-off-by: Gary Grebus <ggrebus@virtualiron.com>
[-- Attachment #2: xen-vmxassist-ubuntu.txt --]
[-- Type: text/plain, Size: 181 bytes --]
Add more opcodes to the vmxassist emulation sufficient to boot Ubuntu
7.04.
Signed-off-by: Ben Guthro <bguthro@virtualron.com>
Signed-off-by: Gary Grebus <ggrebus@virtualiron.com>
[-- Attachment #3: Type: text/plain, Size: 138 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] Add more vmxassist opcodes for Ubuntu 7.0.4 support
2007-10-24 21:17 [PATCH] Add more vmxassist opcodes for Ubuntu 7.0.4 support Ben Guthro
@ 2007-10-24 22:21 ` Ben Guthro
2007-10-25 1:44 ` [PATCH] Add more vmxassist opcodes for Ubuntu 7.0.4support Li, Xin B
0 siblings, 1 reply; 4+ messages in thread
From: Ben Guthro @ 2007-10-24 22:21 UTC (permalink / raw)
To: xen-devel; +Cc: Gary Grebus
[-- Attachment #1.1: Type: text/plain, Size: 503 bytes --]
Attached description instead of patch. please find patch attached.
Ben Guthro wrote:
> Add more opcodes to the vmxassist emulation sufficient to boot Ubuntu
> 7.04.
>
> Signed-off-by: Ben Guthro <bguthro@virtualron.com>
> Signed-off-by: Gary Grebus <ggrebus@virtualiron.com>
>
> ------------------------------------------------------------------------
>
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@lists.xensource.com
> http://lists.xensource.com/xen-devel
[-- Attachment #1.2: Type: text/html, Size: 1144 bytes --]
[-- Attachment #2: xen-vmxassist-ubuntu.patch --]
[-- Type: text/x-patch, Size: 10111 bytes --]
diff -r 30d246cbc009 tools/firmware/vmxassist/machine.h
--- a/tools/firmware/vmxassist/machine.h Wed Oct 10 08:44:32 2007 -0400
+++ b/tools/firmware/vmxassist/machine.h Wed Oct 10 08:44:32 2007 -0400
@@ -38,10 +38,15 @@
#define CR4_PSE (1 << 4)
#define CR4_PAE (1 << 5)
+#define EFLAGS_CF (1 << 0)
+#define EFLAGS_PF (1 << 2)
+#define EFLAGS_AF (1 << 4)
#define EFLAGS_ZF (1 << 6)
+#define EFLAGS_SF (1 << 7)
#define EFLAGS_TF (1 << 8)
#define EFLAGS_IF (1 << 9)
#define EFLAGS_DF (1 << 10)
+#define EFLAGS_OF (1 << 11)
#define EFLAGS_IOPL (3 << 12)
#define EFLAGS_VM ((1 << 17) | EFLAGS_IOPL)
#define EFLAGS_VIF (1 << 19)
diff -r 30d246cbc009 tools/firmware/vmxassist/vm86.c
--- a/tools/firmware/vmxassist/vm86.c Wed Oct 10 08:44:32 2007 -0400
+++ b/tools/firmware/vmxassist/vm86.c Wed Oct 10 08:44:32 2007 -0400
@@ -33,6 +33,7 @@
#define SEG_SS 0x0020
#define SEG_FS 0x0040
#define SEG_GS 0x0080
+#define REP 0x0100
static unsigned prev_eip = 0;
enum vm86_mode mode = 0;
@@ -656,6 +657,108 @@ movr(struct regs *regs, unsigned prefix,
}
/*
+ * We need to handle string moves that address memory beyond the 64KB segment
+ * limit that VM8086 mode enforces.
+ */
+static inline int
+movs(struct regs *regs, unsigned prefix, unsigned opc)
+{
+ unsigned eip = regs->eip - 1;
+ unsigned sseg = segment(prefix, regs, regs->vds);
+ unsigned dseg = regs->ves;
+ unsigned saddr, daddr;
+ unsigned count = 1;
+ int incr = ((regs->eflags & EFLAGS_DF) == 0) ? 1 : -1;
+
+ saddr = address(regs, sseg, regs->esi);
+ daddr = address(regs, dseg, regs->edi);
+
+ if ((prefix & REP) != 0) {
+ count = regs->ecx;
+ regs->ecx = 0;
+ }
+
+ switch (opc) {
+ case 0xA4: /* movsb */
+ regs->esi += (incr * count);
+ regs->edi += (incr * count);
+
+ while (count-- != 0) {
+ write8(daddr, read8(saddr));
+ daddr += incr;
+ saddr += incr;
+ }
+ TRACE((regs, regs->eip - eip, "movsb (%%esi),%%es:(%%edi)"));
+ break;
+
+ case 0xA5: /* movsw */
+ if ((prefix & DATA32) == 0) {
+ incr = 2 * incr;
+ regs->esi += (incr * count);
+ regs->edi += (incr * count);
+
+ while (count-- != 0) {
+ write16(daddr, read16(saddr));
+ daddr += incr;
+ saddr += incr;
+ }
+ } else {
+ incr = 4 * incr;
+ regs->esi += (incr * count);
+ regs->edi += (incr * count);
+
+ while (count-- != 0) {
+ write32(daddr, read32(saddr));
+ daddr += incr;
+ saddr += incr;
+ }
+ }
+ TRACE((regs, regs->eip - eip, "movsw %s(%%esi),%%es:(%%edi)"));
+ break;
+ }
+
+ return 1;
+}
+
+static inline int
+lods(struct regs *regs, unsigned prefix, unsigned opc)
+{
+ unsigned eip = regs->eip - 1;
+ unsigned seg = segment(prefix, regs, regs->vds);
+ unsigned addr = address(regs, seg, regs->esi);
+ unsigned count = 1;
+ int incr = ((regs->eflags & EFLAGS_DF) == 0) ? 1 : -1;
+
+ if ((prefix & REP) != 0) {
+ count = regs->ecx;
+ regs->ecx = 0;
+ }
+
+ switch (opc) {
+ case 0xAD: /* lodsw */
+ if ((prefix & DATA32) == 0) {
+ incr = 2 * incr;
+ regs->esi += (incr * count);
+ while (count-- != 0) {
+ setreg16(regs, 0, read16(addr));
+ addr += incr;
+ }
+
+ TRACE((regs, regs->eip - eip, "lodsw (%%esi),%%ax"));
+ } else {
+ incr = 4 * incr;
+ regs->esi += (incr * count);
+ while (count-- != 0) {
+ setreg32(regs, 0, read32(addr));
+ addr += incr;
+ }
+ TRACE((regs, regs->eip - eip, "lodsw (%%esi),%%eax"));
+ }
+ break;
+ }
+ return 1;
+}
+/*
* Move to and from a control register.
*/
static int
@@ -718,6 +821,55 @@ static inline void set_eflags_ZF(unsigne
regs->eflags &= ~EFLAGS_ZF;
}
+static void set_eflags_add(unsigned hi_bit_mask, unsigned v1, unsigned v2,
+ unsigned result, struct regs *regs)
+{
+ int bit_count;
+ unsigned tmp;
+ unsigned full_mask;
+ unsigned nonsign_mask;
+
+ /* Carry out of high order bit? */
+ if ( v1 & v2 & hi_bit_mask )
+ regs->eflags |= EFLAGS_CF;
+ else
+ regs->eflags &= ~EFLAGS_CF;
+
+ /* Even parity in least significant byte? */
+ tmp = result & 0xff;
+ for (bit_count = 0; tmp != 0; bit_count++)
+ tmp &= (tmp - 1);
+
+ if (bit_count & 1)
+ regs->eflags &= ~EFLAGS_PF;
+ else
+ regs->eflags |= EFLAGS_PF;
+
+ /* Carry out of least significant BCD digit? */
+ if ( v1 & v2 & (1<<3) )
+ regs->eflags |= EFLAGS_AF;
+ else
+ regs->eflags &= ~EFLAGS_AF;
+
+ /* Result is zero? */
+ full_mask = (hi_bit_mask - 1) | hi_bit_mask;
+ set_eflags_ZF(full_mask, result, regs);
+
+ /* Sign of result? */
+ if ( result & hi_bit_mask )
+ regs->eflags |= EFLAGS_SF;
+ else
+ regs->eflags &= ~EFLAGS_SF;
+
+ /* Carry out of highest non-sign bit? */
+ nonsign_mask = (hi_bit_mask >> 1) & ~hi_bit_mask;
+ if ( v1 & v2 & hi_bit_mask )
+ regs->eflags |= EFLAGS_OF;
+ else
+ regs->eflags &= ~EFLAGS_OF;
+
+}
+
/*
* We need to handle cmp opcodes that address memory beyond the 64KB
* segment limit that VM8086 mode enforces.
@@ -787,6 +939,82 @@ test(struct regs *regs, unsigned prefix,
/* other test opcodes ... */
}
+
+ return 1;
+}
+
+/*
+ * We need to handle add opcodes that address memory beyond the 64KB
+ * segment limit that VM8086 mode enforces.
+ */
+static int
+add(struct regs *regs, unsigned prefix, unsigned opc)
+{
+ unsigned eip = regs->eip - 1;
+ unsigned modrm = fetch8(regs);
+ unsigned addr = operand(prefix, regs, modrm);
+ unsigned r = (modrm >> 3) & 7;
+
+ unsigned val1 = 0;
+ unsigned val2 = 0;
+ unsigned result = 0;
+ unsigned hi_bit;
+
+ if ((modrm & 0xC0) == 0xC0) /* no registers */
+ return 0;
+
+ switch (opc) {
+ case 0x00: /* addr32 add r8, r/m8 */
+ val1 = getreg8(regs, r);
+ val2 = read8(addr);
+ result = val1 + val2;
+ write8(addr, result);
+ TRACE((regs, regs->eip - eip,
+ "addb %%e%s, *0x%x", rnames[r], addr));
+ break;
+
+ case 0x01: /* addr32 add r16, r/m16 */
+ if (prefix & DATA32) {
+ val1 = getreg32(regs, r);
+ val2 = read32(addr);
+ result = val1 + val2;
+ write32(addr, result);
+ TRACE((regs, regs->eip - eip,
+ "addl %%e%s, *0x%x", rnames[r], addr));
+ } else {
+ val1 = getreg16(regs, r);
+ val2 = read16(addr);
+ result = val1 + val2;
+ write16(addr, result);
+ TRACE((regs, regs->eip - eip,
+ "addw %%e%s, *0x%x", rnames[r], addr));
+ }
+ break;
+
+ case 0x03: /* addr32 add r/m16, r16 */
+ if (prefix & DATA32) {
+ val1 = getreg32(regs, r);
+ val2 = read32(addr);
+ result = val1 + val2;
+ setreg32(regs, r, result);
+ TRACE((regs, regs->eip - eip,
+ "addl *0x%x, %%e%s", addr, rnames[r]));
+ } else {
+ val1 = getreg16(regs, r);
+ val2 = read16(addr);
+ result = val1 + val2;
+ setreg16(regs, r, result);
+ TRACE((regs, regs->eip - eip,
+ "addw *0x%x, %%%s", addr, rnames[r]));
+ }
+ break;
+ }
+
+ if (opc == 0x00)
+ hi_bit = (1<<7);
+ else
+ hi_bit = (prefix & DATA32) ? (1<<31) : (1<<15);
+ set_eflags_add(hi_bit, val1, val2, result, regs);
return 1;
}
@@ -1314,6 +1542,18 @@ opcode(struct regs *regs)
for (;;) {
switch ((opc = fetch8(regs))) {
+
+ case 0x00: /* addr32 add r8, r/m8 */
+ case 0x01: /* addr32 add r16, r/m16 */
+ case 0x03: /* addr32 add r/m16, r16 */
+ if (mode != VM86_REAL && mode != VM86_REAL_TO_PROTECTED)
+ goto invalid;
+ if ((prefix & ADDR32) == 0)
+ goto invalid;
+ if (!add(regs, prefix, opc))
+ goto invalid;
+ return OPC_EMULATED;
+
case 0x07: /* pop %es */
regs->ves = (prefix & DATA32) ?
pop32(regs) : pop16(regs);
@@ -1510,6 +1750,21 @@ opcode(struct regs *regs)
return OPC_EMULATED;
}
+ case 0xA4: /* movsb */
+ case 0xA5: /* movsw */
+ if ((prefix & ADDR32) == 0)
+ goto invalid;
+ if (!movs(regs, prefix, opc))
+ goto invalid;
+ return OPC_EMULATED;
+
+ case 0xAD: /* lodsw */
+ if ((prefix & ADDR32) == 0)
+ goto invalid;
+ if (!lods(regs, prefix, opc))
+ goto invalid;
+ return OPC_EMULATED;
+
case 0xBB: /* mov bx, imm16 */
{
int data;
@@ -1627,6 +1882,11 @@ opcode(struct regs *regs)
/* Do something power-saving here! */
return OPC_EMULATED;
+ case 0xF3: /* rep/repe/repz */
+ TRACE((regs, regs->eip - eip, "rep"));
+ prefix |= REP;
+ continue;
+
case 0xF6: /* addr32 testb $imm, r/m8 */
if (!(prefix & ADDR32))
goto invalid;
@@ -1660,6 +1920,7 @@ emulate(struct regs *regs)
{
unsigned flteip;
int nemul = 0;
+ unsigned ip;
/* emulate as many instructions as possible */
while (opcode(regs) != OPC_INVALID)
@@ -1668,6 +1929,12 @@ emulate(struct regs *regs)
/* detect the case where we are not making progress */
if (nemul == 0 && prev_eip == regs->eip) {
flteip = address(regs, MASK16(regs->cs), regs->eip);
+
+ printf("Undecoded sequence: \n");
+ for (ip=flteip; ip < flteip+16; ip++)
+ printf("0x%02x ", read8(ip));
+ printf("\n");
+
panic("Unknown opcode at %04x:%04x=0x%x",
MASK16(regs->cs), regs->eip, flteip);
} else
[-- Attachment #3: Type: text/plain, Size: 138 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel
^ permalink raw reply [flat|nested] 4+ messages in thread
* RE: [PATCH] Add more vmxassist opcodes for Ubuntu 7.0.4support
2007-10-24 22:21 ` Ben Guthro
@ 2007-10-25 1:44 ` Li, Xin B
2007-10-25 11:40 ` Ben Guthro
0 siblings, 1 reply; 4+ messages in thread
From: Li, Xin B @ 2007-10-25 1:44 UTC (permalink / raw)
To: Ben Guthro, xen-devel; +Cc: Gary Grebus
[-- Attachment #1.1: Type: text/plain, Size: 957 bytes --]
This patch does not follow VMX Assist coding style, we use tab instead of spaces.
-Xin
________________________________
From: xen-devel-bounces@lists.xensource.com [mailto:xen-devel-bounces@lists.xensource.com] On Behalf Of Ben Guthro
Sent: 2007年10月25日 6:22
To: xen-devel
Cc: Gary Grebus
Subject: Re: [Xen-devel] [PATCH] Add more vmxassist opcodes for Ubuntu 7.0.4support
Attached description instead of patch. please find patch attached.
Ben Guthro wrote:
Add more opcodes to the vmxassist emulation sufficient to boot Ubuntu 7.04.
Signed-off-by: Ben Guthro <bguthro@virtualron.com> <mailto:bguthro@virtualron.com>
Signed-off-by: Gary Grebus <ggrebus@virtualiron.com> <mailto:ggrebus@virtualiron.com>
________________________________
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel
[-- Attachment #1.2: Type: text/html, Size: 6491 bytes --]
[-- Attachment #2: Type: text/plain, Size: 138 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] Add more vmxassist opcodes for Ubuntu 7.0.4support
2007-10-25 1:44 ` [PATCH] Add more vmxassist opcodes for Ubuntu 7.0.4support Li, Xin B
@ 2007-10-25 11:40 ` Ben Guthro
0 siblings, 0 replies; 4+ messages in thread
From: Ben Guthro @ 2007-10-25 11:40 UTC (permalink / raw)
To: Li, Xin B; +Cc: Gary Grebus, xen-devel
[-- Attachment #1.1: Type: text/plain, Size: 1370 bytes --]
I have reformatted the patch to use tabs instead of spaces.
Please find the revised version of this patch attached.
Please note that I have only changed formatting of this patch, and no
contents have changed.
Ben
Li, Xin B wrote:
>
> This patch does not follow VMX Assist coding style, we use tab instead
> of spaces.
>
> -Xin
>
> ------------------------------------------------------------------------
>
> *From:* xen-devel-bounces@lists.xensource.com
> [mailto:xen-devel-bounces@lists.xensource.com] *On Behalf Of *Ben Guthro
> *Sent:* 2007年10月25日 6:22
> *To:* xen-devel
> *Cc:* Gary Grebus
> *Subject:* Re: [Xen-devel] [PATCH] Add more vmxassist opcodes for
> Ubuntu 7.0.4support
>
> Attached description instead of patch. please find patch attached.
>
> Ben Guthro wrote:
>
> Add more opcodes to the vmxassist emulation sufficient to boot Ubuntu
> 7.04.
>
> Signed-off-by: Ben Guthro <bguthro@virtualron.com>
> <mailto:bguthro@virtualron.com>
> Signed-off-by: Gary Grebus <ggrebus@virtualiron.com>
> <mailto:ggrebus@virtualiron.com>
>
>
>
>
> ------------------------------------------------------------------------
>
>
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@lists.xensource.com <mailto:Xen-devel@lists.xensource.com>
> http://lists.xensource.com/xen-devel
>
[-- Attachment #1.2: Type: text/html, Size: 7405 bytes --]
[-- Attachment #2: xen-vmxassist-ubuntu.patch --]
[-- Type: text/x-patch, Size: 8746 bytes --]
diff -r 30d246cbc009 tools/firmware/vmxassist/machine.h
--- a/tools/firmware/vmxassist/machine.h Wed Oct 10 08:44:32 2007 -0400
+++ b/tools/firmware/vmxassist/machine.h Wed Oct 10 08:44:32 2007 -0400
@@ -38,10 +38,15 @@
#define CR4_PSE (1 << 4)
#define CR4_PAE (1 << 5)
+#define EFLAGS_CF (1 << 0)
+#define EFLAGS_PF (1 << 2)
+#define EFLAGS_AF (1 << 4)
#define EFLAGS_ZF (1 << 6)
+#define EFLAGS_SF (1 << 7)
#define EFLAGS_TF (1 << 8)
#define EFLAGS_IF (1 << 9)
#define EFLAGS_DF (1 << 10)
+#define EFLAGS_OF (1 << 11)
#define EFLAGS_IOPL (3 << 12)
#define EFLAGS_VM ((1 << 17) | EFLAGS_IOPL)
#define EFLAGS_VIF (1 << 19)
diff -r 30d246cbc009 tools/firmware/vmxassist/vm86.c
--- a/tools/firmware/vmxassist/vm86.c Wed Oct 10 08:44:32 2007 -0400
+++ b/tools/firmware/vmxassist/vm86.c Wed Oct 10 08:44:32 2007 -0400
@@ -33,6 +33,7 @@
#define SEG_SS 0x0020
#define SEG_FS 0x0040
#define SEG_GS 0x0080
+#define REP 0x0100
static unsigned prev_eip = 0;
enum vm86_mode mode = 0;
@@ -656,6 +657,108 @@ movr(struct regs *regs, unsigned prefix,
}
/*
+ * We need to handle string moves that address memory beyond the 64KB segment
+ * limit that VM8086 mode enforces.
+ */
+static inline int
+movs(struct regs *regs, unsigned prefix, unsigned opc)
+{
+ unsigned eip = regs->eip - 1;
+ unsigned sseg = segment(prefix, regs, regs->vds);
+ unsigned dseg = regs->ves;
+ unsigned saddr, daddr;
+ unsigned count = 1;
+ int incr = ((regs->eflags & EFLAGS_DF) == 0) ? 1 : -1;
+
+ saddr = address(regs, sseg, regs->esi);
+ daddr = address(regs, dseg, regs->edi);
+
+ if ((prefix & REP) != 0) {
+ count = regs->ecx;
+ regs->ecx = 0;
+ }
+
+ switch (opc) {
+ case 0xA4: /* movsb */
+ regs->esi += (incr * count);
+ regs->edi += (incr * count);
+
+ while (count-- != 0) {
+ write8(daddr, read8(saddr));
+ daddr += incr;
+ saddr += incr;
+ }
+ TRACE((regs, regs->eip - eip, "movsb (%%esi),%%es:(%%edi)"));
+ break;
+
+ case 0xA5: /* movsw */
+ if ((prefix & DATA32) == 0) {
+ incr = 2 * incr;
+ regs->esi += (incr * count);
+ regs->edi += (incr * count);
+
+ while (count-- != 0) {
+ write16(daddr, read16(saddr));
+ daddr += incr;
+ saddr += incr;
+ }
+ } else {
+ incr = 4 * incr;
+ regs->esi += (incr * count);
+ regs->edi += (incr * count);
+
+ while (count-- != 0) {
+ write32(daddr, read32(saddr));
+ daddr += incr;
+ saddr += incr;
+ }
+ }
+ TRACE((regs, regs->eip - eip, "movsw %s(%%esi),%%es:(%%edi)"));
+ break;
+ }
+
+ return 1;
+}
+
+static inline int
+lods(struct regs *regs, unsigned prefix, unsigned opc)
+{
+ unsigned eip = regs->eip - 1;
+ unsigned seg = segment(prefix, regs, regs->vds);
+ unsigned addr = address(regs, seg, regs->esi);
+ unsigned count = 1;
+ int incr = ((regs->eflags & EFLAGS_DF) == 0) ? 1 : -1;
+
+ if ((prefix & REP) != 0) {
+ count = regs->ecx;
+ regs->ecx = 0;
+ }
+
+ switch (opc) {
+ case 0xAD: /* lodsw */
+ if ((prefix & DATA32) == 0) {
+ incr = 2 * incr;
+ regs->esi += (incr * count);
+ while (count-- != 0) {
+ setreg16(regs, 0, read16(addr));
+ addr += incr;
+ }
+
+ TRACE((regs, regs->eip - eip, "lodsw (%%esi),%%ax"));
+ } else {
+ incr = 4 * incr;
+ regs->esi += (incr * count);
+ while (count-- != 0) {
+ setreg32(regs, 0, read32(addr));
+ addr += incr;
+ }
+ TRACE((regs, regs->eip - eip, "lodsw (%%esi),%%eax"));
+ }
+ break;
+ }
+ return 1;
+}
+/*
* Move to and from a control register.
*/
static int
@@ -718,6 +821,55 @@ static inline void set_eflags_ZF(unsigne
regs->eflags &= ~EFLAGS_ZF;
}
+static void set_eflags_add(unsigned hi_bit_mask, unsigned v1, unsigned v2,
+ unsigned result, struct regs *regs)
+{
+ int bit_count;
+ unsigned tmp;
+ unsigned full_mask;
+ unsigned nonsign_mask;
+
+ /* Carry out of high order bit? */
+ if ( v1 & v2 & hi_bit_mask )
+ regs->eflags |= EFLAGS_CF;
+ else
+ regs->eflags &= ~EFLAGS_CF;
+
+ /* Even parity in least significant byte? */
+ tmp = result & 0xff;
+ for (bit_count = 0; tmp != 0; bit_count++)
+ tmp &= (tmp - 1);
+
+ if (bit_count & 1)
+ regs->eflags &= ~EFLAGS_PF;
+ else
+ regs->eflags |= EFLAGS_PF;
+
+ /* Carry out of least significant BCD digit? */
+ if ( v1 & v2 & (1<<3) )
+ regs->eflags |= EFLAGS_AF;
+ else
+ regs->eflags &= ~EFLAGS_AF;
+
+ /* Result is zero? */
+ full_mask = (hi_bit_mask - 1) | hi_bit_mask;
+ set_eflags_ZF(full_mask, result, regs);
+
+ /* Sign of result? */
+ if ( result & hi_bit_mask )
+ regs->eflags |= EFLAGS_SF;
+ else
+ regs->eflags &= ~EFLAGS_SF;
+
+ /* Carry out of highest non-sign bit? */
+ nonsign_mask = (hi_bit_mask >> 1) & ~hi_bit_mask;
+ if ( v1 & v2 & hi_bit_mask )
+ regs->eflags |= EFLAGS_OF;
+ else
+ regs->eflags &= ~EFLAGS_OF;
+
+}
+
/*
* We need to handle cmp opcodes that address memory beyond the 64KB
* segment limit that VM8086 mode enforces.
@@ -787,6 +939,82 @@ test(struct regs *regs, unsigned prefix,
/* other test opcodes ... */
}
+
+ return 1;
+}
+
+/*
+ * We need to handle add opcodes that address memory beyond the 64KB
+ * segment limit that VM8086 mode enforces.
+ */
+static int
+add(struct regs *regs, unsigned prefix, unsigned opc)
+{
+ unsigned eip = regs->eip - 1;
+ unsigned modrm = fetch8(regs);
+ unsigned addr = operand(prefix, regs, modrm);
+ unsigned r = (modrm >> 3) & 7;
+
+ unsigned val1 = 0;
+ unsigned val2 = 0;
+ unsigned result = 0;
+ unsigned hi_bit;
+
+ if ((modrm & 0xC0) == 0xC0) /* no registers */
+ return 0;
+
+ switch (opc) {
+ case 0x00: /* addr32 add r8, r/m8 */
+ val1 = getreg8(regs, r);
+ val2 = read8(addr);
+ result = val1 + val2;
+ write8(addr, result);
+ TRACE((regs, regs->eip - eip,
+ "addb %%e%s, *0x%x", rnames[r], addr));
+ break;
+
+ case 0x01: /* addr32 add r16, r/m16 */
+ if (prefix & DATA32) {
+ val1 = getreg32(regs, r);
+ val2 = read32(addr);
+ result = val1 + val2;
+ write32(addr, result);
+ TRACE((regs, regs->eip - eip,
+ "addl %%e%s, *0x%x", rnames[r], addr));
+ } else {
+ val1 = getreg16(regs, r);
+ val2 = read16(addr);
+ result = val1 + val2;
+ write16(addr, result);
+ TRACE((regs, regs->eip - eip,
+ "addw %%e%s, *0x%x", rnames[r], addr));
+ }
+ break;
+
+ case 0x03: /* addr32 add r/m16, r16 */
+ if (prefix & DATA32) {
+ val1 = getreg32(regs, r);
+ val2 = read32(addr);
+ result = val1 + val2;
+ setreg32(regs, r, result);
+ TRACE((regs, regs->eip - eip,
+ "addl *0x%x, %%e%s", addr, rnames[r]));
+ } else {
+ val1 = getreg16(regs, r);
+ val2 = read16(addr);
+ result = val1 + val2;
+ setreg16(regs, r, result);
+ TRACE((regs, regs->eip - eip,
+ "addw *0x%x, %%%s", addr, rnames[r]));
+ }
+ break;
+ }
+
+ if (opc == 0x00)
+ hi_bit = (1<<7);
+ else
+ hi_bit = (prefix & DATA32) ? (1<<31) : (1<<15);
+ set_eflags_add(hi_bit, val1, val2, result, regs);
return 1;
}
@@ -1314,6 +1542,18 @@ opcode(struct regs *regs)
for (;;) {
switch ((opc = fetch8(regs))) {
+
+ case 0x00: /* addr32 add r8, r/m8 */
+ case 0x01: /* addr32 add r16, r/m16 */
+ case 0x03: /* addr32 add r/m16, r16 */
+ if (mode != VM86_REAL && mode != VM86_REAL_TO_PROTECTED)
+ goto invalid;
+ if ((prefix & ADDR32) == 0)
+ goto invalid;
+ if (!add(regs, prefix, opc))
+ goto invalid;
+ return OPC_EMULATED;
+
case 0x07: /* pop %es */
regs->ves = (prefix & DATA32) ?
pop32(regs) : pop16(regs);
@@ -1510,6 +1750,21 @@ opcode(struct regs *regs)
return OPC_EMULATED;
}
+ case 0xA4: /* movsb */
+ case 0xA5: /* movsw */
+ if ((prefix & ADDR32) == 0)
+ goto invalid;
+ if (!movs(regs, prefix, opc))
+ goto invalid;
+ return OPC_EMULATED;
+
+ case 0xAD: /* lodsw */
+ if ((prefix & ADDR32) == 0)
+ goto invalid;
+ if (!lods(regs, prefix, opc))
+ goto invalid;
+ return OPC_EMULATED;
+
case 0xBB: /* mov bx, imm16 */
{
int data;
@@ -1627,6 +1882,11 @@ opcode(struct regs *regs)
/* Do something power-saving here! */
return OPC_EMULATED;
+ case 0xF3: /* rep/repe/repz */
+ TRACE((regs, regs->eip - eip, "rep"));
+ prefix |= REP;
+ continue;
+
case 0xF6: /* addr32 testb $imm, r/m8 */
if (!(prefix & ADDR32))
goto invalid;
@@ -1660,6 +1920,7 @@ emulate(struct regs *regs)
{
unsigned flteip;
int nemul = 0;
+ unsigned ip;
/* emulate as many instructions as possible */
while (opcode(regs) != OPC_INVALID)
@@ -1668,6 +1929,12 @@ emulate(struct regs *regs)
/* detect the case where we are not making progress */
if (nemul == 0 && prev_eip == regs->eip) {
flteip = address(regs, MASK16(regs->cs), regs->eip);
+
+ printf("Undecoded sequence: \n");
+ for (ip=flteip; ip < flteip+16; ip++)
+ printf("0x%02x ", read8(ip));
+ printf("\n");
+
panic("Unknown opcode at %04x:%04x=0x%x",
MASK16(regs->cs), regs->eip, flteip);
} else
[-- Attachment #3: Type: text/plain, Size: 138 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2007-10-25 11:40 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-10-24 21:17 [PATCH] Add more vmxassist opcodes for Ubuntu 7.0.4 support Ben Guthro
2007-10-24 22:21 ` Ben Guthro
2007-10-25 1:44 ` [PATCH] Add more vmxassist opcodes for Ubuntu 7.0.4support Li, Xin B
2007-10-25 11:40 ` Ben Guthro
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.