Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F106107270
D20755.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
3 KB
Referenced Files
None
Subscribers
None
D20755.diff
View Options
Index: head/sys/amd64/vmm/vmm_instruction_emul.c
===================================================================
--- head/sys/amd64/vmm/vmm_instruction_emul.c
+++ head/sys/amd64/vmm/vmm_instruction_emul.c
@@ -78,6 +78,7 @@
VIE_OP_TYPE_BITTEST,
VIE_OP_TYPE_TWOB_GRP15,
VIE_OP_TYPE_ADD,
+ VIE_OP_TYPE_TEST,
VIE_OP_TYPE_LAST
};
@@ -221,6 +222,12 @@
.op_byte = 0x8F,
.op_type = VIE_OP_TYPE_POP,
},
+ [0xF7] = {
+ /* XXX Group 3 extended opcode - not just TEST */
+ .op_byte = 0xF7,
+ .op_type = VIE_OP_TYPE_TEST,
+ .op_flags = VIE_OP_F_IMM,
+ },
[0xFF] = {
/* XXX Group 5 extended opcode - not just PUSH */
.op_byte = 0xFF,
@@ -450,6 +457,41 @@
return (getaddflags64(x, y));
}
+/*
+ * Return the status flags that would result from doing (x & y).
+ */
+#define GETANDFLAGS(sz) \
+static u_long \
+getandflags##sz(uint##sz##_t x, uint##sz##_t y) \
+{ \
+ u_long rflags; \
+ \
+ __asm __volatile("and %2,%1; pushfq; popq %0" : \
+ "=r" (rflags), "+r" (x) : "m" (y)); \
+ return (rflags); \
+} struct __hack
+
+GETANDFLAGS(8);
+GETANDFLAGS(16);
+GETANDFLAGS(32);
+GETANDFLAGS(64);
+
+static u_long
+getandflags(int opsize, uint64_t x, uint64_t y)
+{
+ KASSERT(opsize == 1 || opsize == 2 || opsize == 4 || opsize == 8,
+ ("getandflags: invalid operand size %d", opsize));
+
+ if (opsize == 1)
+ return (getandflags8(x, y));
+ else if (opsize == 2)
+ return (getandflags16(x, y));
+ else if (opsize == 4)
+ return (getandflags32(x, y));
+ else
+ return (getandflags64(x, y));
+}
+
static int
emulate_mov(void *vm, int vcpuid, uint64_t gpa, struct vie *vie,
mem_region_read_t memread, mem_region_write_t memwrite, void *arg)
@@ -1219,6 +1261,55 @@
}
static int
+emulate_test(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 op1, rflags, rflags2;
+
+ size = vie->opsize;
+ error = EINVAL;
+
+ switch (vie->op.op_byte) {
+ case 0xF7:
+ /*
+ * F7 /0 test r/m16, imm16
+ * F7 /0 test r/m32, imm32
+ * REX.W + F7 /0 test r/m64, imm32 sign-extended to 64
+ *
+ * Test mem (ModRM:r/m) with immediate and set status
+ * flags according to the results. The comparison is
+ * performed by anding the immediate from the first
+ * operand and then setting the status flags.
+ */
+ if ((vie->reg & 7) != 0)
+ return (EINVAL);
+
+ error = memread(vm, vcpuid, gpa, &op1, size, arg);
+ if (error)
+ return (error);
+
+ rflags2 = getandflags(size, op1, vie->immediate);
+ break;
+ default:
+ return (EINVAL);
+ }
+ error = vie_read_register(vm, vcpuid, VM_REG_GUEST_RFLAGS, &rflags);
+ if (error)
+ return (error);
+
+ /*
+ * OF and CF are cleared; the SF, ZF and PF flags are set according
+ * to the result; AF is undefined.
+ */
+ rflags &= ~RFLAGS_STATUS_BITS;
+ rflags |= rflags2 & (PSL_PF | PSL_Z | PSL_N);
+
+ error = vie_update_register(vm, vcpuid, VM_REG_GUEST_RFLAGS, rflags, 8);
+ return (error);
+}
+
+static int
emulate_add(void *vm, int vcpuid, uint64_t gpa, struct vie *vie,
mem_region_read_t memread, mem_region_write_t memwrite, void *arg)
{
@@ -1642,6 +1733,10 @@
case VIE_OP_TYPE_ADD:
error = emulate_add(vm, vcpuid, gpa, vie, memread,
memwrite, memarg);
+ break;
+ case VIE_OP_TYPE_TEST:
+ error = emulate_test(vm, vcpuid, gpa, vie,
+ memread, memwrite, memarg);
break;
default:
error = EINVAL;
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Dec 26, 12:42 PM (11 h, 34 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15604824
Default Alt Text
D20755.diff (3 KB)
Attached To
Mode
D20755: Emulate the TEST instruction with opcode F7 /0.
Attached
Detach File
Event Timeline
Log In to Comment