svn commit: r246108 - in head/sys/amd64: include vmm

Neel Natu neel at FreeBSD.org
Wed Jan 30 04:09:10 UTC 2013


Author: neel
Date: Wed Jan 30 04:09:09 2013
New Revision: 246108
URL: http://svnweb.freebsd.org/changeset/base/246108

Log:
  Add emulation support for instruction "88/r: mov r/m8, r8".
  
  This instruction moves a byte from a register to a memory location.
  
  Tested by: tycho nightingale at pluribusnetworks com

Modified:
  head/sys/amd64/include/vmm_instruction_emul.h
  head/sys/amd64/vmm/vmm_instruction_emul.c

Modified: head/sys/amd64/include/vmm_instruction_emul.h
==============================================================================
--- head/sys/amd64/include/vmm_instruction_emul.h	Wed Jan 30 01:43:00 2013	(r246107)
+++ head/sys/amd64/include/vmm_instruction_emul.h	Wed Jan 30 04:09:09 2013	(r246108)
@@ -49,7 +49,8 @@ struct vie {
 	uint8_t		rex_w:1,		/* REX prefix */
 			rex_r:1,
 			rex_x:1,
-			rex_b:1;
+			rex_b:1,
+			rex_present:1;
 
 	uint8_t		mod:2,			/* ModRM byte */
 			reg:4,

Modified: head/sys/amd64/vmm/vmm_instruction_emul.c
==============================================================================
--- head/sys/amd64/vmm/vmm_instruction_emul.c	Wed Jan 30 01:43:00 2013	(r246107)
+++ head/sys/amd64/vmm/vmm_instruction_emul.c	Wed Jan 30 04:09:09 2013	(r246108)
@@ -65,6 +65,10 @@ enum {
 #define	VIE_OP_F_IMM8		(1 << 1)	/* 8-bit immediate operand */
 
 static const struct vie_op one_byte_opcodes[256] = {
+	[0x88] = {
+		.op_byte = 0x88,
+		.op_type = VIE_OP_TYPE_MOV,
+	},
 	[0x89] = {
 		.op_byte = 0x89,
 		.op_type = VIE_OP_TYPE_MOV,
@@ -161,6 +165,46 @@ vie_read_register(void *vm, int vcpuid, 
 }
 
 static int
+vie_read_bytereg(void *vm, int vcpuid, struct vie *vie, uint8_t *rval)
+{
+	uint64_t val;
+	int error, rshift;
+	enum vm_reg_name reg;
+
+	rshift = 0;
+	reg = gpr_map[vie->reg];
+
+	/*
+	 * 64-bit mode imposes limitations on accessing legacy byte registers.
+	 *
+	 * The legacy high-byte registers cannot be addressed if the REX
+	 * prefix is present. In this case the values 4, 5, 6 and 7 of the
+	 * 'ModRM:reg' field address %spl, %bpl, %sil and %dil respectively.
+	 *
+	 * If the REX prefix is not present then the values 4, 5, 6 and 7
+	 * of the 'ModRM:reg' field address the legacy high-byte registers,
+	 * %ah, %ch, %dh and %bh respectively.
+	 */
+	if (!vie->rex_present) {
+		if (vie->reg & 0x4) {
+			/*
+			 * Obtain the value of %ah by reading %rax and shifting
+			 * right by 8 bits (same for %bh, %ch and %dh).
+			 */
+			rshift = 8;
+			reg = gpr_map[vie->reg & 0x3];
+		}
+	}
+
+	if (!vie_valid_register(reg))
+		return (EINVAL);
+
+	error = vm_get_register(vm, vcpuid, reg, &val);
+	*rval = val >> rshift;
+	return (error);
+}
+
+static int
 vie_update_register(void *vm, int vcpuid, enum vm_reg_name reg,
 		    uint64_t val, int size)
 {
@@ -209,12 +253,24 @@ emulate_mov(void *vm, int vcpuid, uint64
 {
 	int error, size;
 	enum vm_reg_name reg;
+	uint8_t byte;
 	uint64_t val;
 
 	size = 4;
 	error = EINVAL;
 
 	switch (vie->op.op_byte) {
+	case 0x88:
+		/*
+		 * MOV byte from reg (ModRM:reg) to mem (ModRM:r/m)
+		 * 88/r:	mov r/m8, r8
+		 * REX + 88/r:	mov r/m8, r8 (%ah, %ch, %dh, %bh not available)
+		 */
+		size = 1;
+		error = vie_read_bytereg(vm, vcpuid, vie, &byte);
+		if (error == 0)
+			error = memwrite(vm, vcpuid, gpa, byte, size, arg);
+		break;
 	case 0x89:
 		/*
 		 * MOV from reg (ModRM:reg) to mem (ModRM:r/m)
@@ -497,6 +553,8 @@ decode_rex(struct vie *vie)
 		return (-1);
 
 	if (x >= 0x40 && x <= 0x4F) {
+		vie->rex_present = 1;
+
 		vie->rex_w = x & 0x8 ? 1 : 0;
 		vie->rex_r = x & 0x4 ? 1 : 0;
 		vie->rex_x = x & 0x2 ? 1 : 0;


More information about the svn-src-head mailing list