All of lore.kernel.org
 help / color / mirror / Atom feed
* [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.