svn commit: r271659 - stable/10/sys/amd64/vmm
Peter Grehan
grehan at FreeBSD.org
Tue Sep 16 01:59:20 UTC 2014
Author: grehan
Date: Tue Sep 16 01:59:19 2014
New Revision: 271659
URL: http://svnweb.freebsd.org/changeset/base/271659
Log:
MFC r270689:
Implement the 0x2B SUB instruction, and the OR variant of 0x81.
Found with local APIC accesses from bitrig/amd64 bsd.rd, 07/15-snap.
Approved by: re (rodrigc)
Modified:
stable/10/sys/amd64/vmm/vmm_instruction_emul.c
Directory Properties:
stable/10/ (props changed)
Modified: stable/10/sys/amd64/vmm/vmm_instruction_emul.c
==============================================================================
--- stable/10/sys/amd64/vmm/vmm_instruction_emul.c Tue Sep 16 01:21:47 2014 (r271658)
+++ stable/10/sys/amd64/vmm/vmm_instruction_emul.c Tue Sep 16 01:59:19 2014 (r271659)
@@ -65,6 +65,7 @@ enum {
VIE_OP_TYPE_MOVZX,
VIE_OP_TYPE_AND,
VIE_OP_TYPE_OR,
+ VIE_OP_TYPE_SUB,
VIE_OP_TYPE_TWO_BYTE,
VIE_OP_TYPE_PUSH,
VIE_OP_TYPE_CMP,
@@ -97,6 +98,10 @@ static const struct vie_op one_byte_opco
.op_byte = 0x0F,
.op_type = VIE_OP_TYPE_TWO_BYTE
},
+ [0x2B] = {
+ .op_byte = 0x2B,
+ .op_type = VIE_OP_TYPE_SUB,
+ },
[0x3B] = {
.op_byte = 0x3B,
.op_type = VIE_OP_TYPE_CMP,
@@ -597,18 +602,16 @@ emulate_and(void *vm, int vcpuid, uint64
break;
case 0x81:
/*
- * AND mem (ModRM:r/m) with immediate and store the
+ * AND/OR mem (ModRM:r/m) with immediate and store the
* result in mem.
*
- * 81 /4 and r/m16, imm16
- * 81 /4 and r/m32, imm32
- * REX.W + 81 /4 and r/m64, imm32 sign-extended to 64
+ * AND: i = 4
+ * OR: i = 1
+ * 81 /i op r/m16, imm16
+ * 81 /i op r/m32, imm32
+ * REX.W + 81 /i op r/m64, imm32 sign-extended to 64
*
- * Currently, only the AND operation of the 0x81 opcode
- * is implemented (ModRM:reg = b100).
*/
- if ((vie->reg & 7) != 4)
- break;
/* get the first operand */
error = memread(vm, vcpuid, gpa, &val1, size, arg);
@@ -616,11 +619,26 @@ emulate_and(void *vm, int vcpuid, uint64
break;
/*
- * perform the operation with the pre-fetched immediate
- * operand and write the result
- */
- val1 &= vie->immediate;
- error = memwrite(vm, vcpuid, gpa, val1, size, arg);
+ * perform the operation with the pre-fetched immediate
+ * operand and write the result
+ */
+ switch (vie->reg & 7) {
+ case 0x4:
+ /* modrm:reg == b100, AND */
+ val1 &= vie->immediate;
+ break;
+ case 0x1:
+ /* modrm:reg == b001, OR */
+ val1 |= vie->immediate;
+ break;
+ default:
+ error = EINVAL;
+ break;
+ }
+ if (error)
+ break;
+
+ error = memwrite(vm, vcpuid, gpa, val1, size, arg);
break;
default:
break;
@@ -723,6 +741,62 @@ emulate_cmp(void *vm, int vcpuid, uint64
}
static int
+emulate_sub(void *vm, int vcpuid, uint64_t gpa, struct vie *vie,
+ mem_region_read_t memread, mem_region_write_t memwrite, void *arg)
+{
+ int error, size;
+ uint64_t nval, rflags, rflags2, val1, val2;
+ enum vm_reg_name reg;
+
+ size = vie->opsize;
+ error = EINVAL;
+
+ switch (vie->op.op_byte) {
+ case 0x2B:
+ /*
+ * SUB r/m from r and store the result in r
+ *
+ * 2B/r SUB r16, r/m16
+ * 2B/r SUB r32, r/m32
+ * REX.W + 2B/r SUB r64, r/m64
+ */
+
+ /* get the first operand */
+ reg = gpr_map[vie->reg];
+ error = vie_read_register(vm, vcpuid, reg, &val1);
+ if (error)
+ break;
+
+ /* get the second operand */
+ error = memread(vm, vcpuid, gpa, &val2, size, arg);
+ if (error)
+ break;
+
+ /* perform the operation and write the result */
+ nval = val1 - val2;
+ error = vie_update_register(vm, vcpuid, reg, nval, size);
+ break;
+ default:
+ break;
+ }
+
+ if (!error) {
+ rflags2 = getcc(size, val1, val2);
+ error = vie_read_register(vm, vcpuid, VM_REG_GUEST_RFLAGS,
+ &rflags);
+ if (error)
+ return (error);
+
+ rflags &= ~RFLAGS_STATUS_BITS;
+ rflags |= rflags2 & RFLAGS_STATUS_BITS;
+ error = vie_update_register(vm, vcpuid, VM_REG_GUEST_RFLAGS,
+ rflags, 8);
+ }
+
+ return (error);
+}
+
+static int
emulate_push(void *vm, int vcpuid, uint64_t mmio_gpa, struct vie *vie,
struct vm_guest_paging *paging, mem_region_read_t memread,
mem_region_write_t memwrite, void *arg)
@@ -865,6 +939,10 @@ vmm_emulate_instruction(void *vm, int vc
error = emulate_or(vm, vcpuid, gpa, vie,
memread, memwrite, memarg);
break;
+ case VIE_OP_TYPE_SUB:
+ error = emulate_sub(vm, vcpuid, gpa, vie,
+ memread, memwrite, memarg);
+ break;
default:
error = EINVAL;
break;
More information about the svn-src-stable-10
mailing list