From: Ben Guthro <bguthro@virtualiron.com>
To: "Li, Xin B" <xin.b.li@intel.com>
Cc: Gary Grebus <ggrebus@virtualiron.com>,
xen-devel <xen-devel@lists.xensource.com>
Subject: Re: [PATCH] Add more vmxassist opcodes for Ubuntu 7.0.4support
Date: Thu, 25 Oct 2007 07:40:38 -0400 [thread overview]
Message-ID: <472080B6.5090201@virtualiron.com> (raw)
In-Reply-To: <B30DA1341B0CFA4893EF8A36B40B5C5D01CE3B74@pdsmsx411.ccr.corp.intel.com>
[-- 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
prev parent reply other threads:[~2007-10-25 11:40 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
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 message]
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=472080B6.5090201@virtualiron.com \
--to=bguthro@virtualiron.com \
--cc=ggrebus@virtualiron.com \
--cc=xen-devel@lists.xensource.com \
--cc=xin.b.li@intel.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.