[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH] Add more vmxassist opcodes for Ubuntu 7.0.4support



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@xxxxxxxxxxxxxxxxxxx [mailto:xen-devel-bounces@xxxxxxxxxxxxxxxxxxx] On Behalf Of Ben Guthro
Sent: 2007
1025 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@xxxxxxxxxxxxxx>
Signed-off-by: Gary Grebus <ggrebus@xxxxxxxxxxxxxxx>


 



 
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel

 


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
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.