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

      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.