summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgrehan <grehan@FreeBSD.org>2012-11-29 06:26:42 +0000
committergrehan <grehan@FreeBSD.org>2012-11-29 06:26:42 +0000
commitffd1f089c33d0e59c0cb85b52bc683272f7880dd (patch)
treeae1cace65dd274cdb8c7e60c5747c289e4959216
parentda4e87dfd614fffb88e5a93c988e1caec9c9efe7 (diff)
downloadFreeBSD-src-ffd1f089c33d0e59c0cb85b52bc683272f7880dd.zip
FreeBSD-src-ffd1f089c33d0e59c0cb85b52bc683272f7880dd.tar.gz
Add support for the 0x81 AND instruction, now generated
by clang in the local APIC code. 0x81 is a read-modify-write instruction - the EPT check that only allowed read or write and not both has been relaxed to allow read and write. Reviewed by: neel Obtained from: NetApp
-rw-r--r--sys/amd64/vmm/intel/vmx.c9
-rw-r--r--sys/amd64/vmm/vmm_instruction_emul.c29
2 files changed, 34 insertions, 4 deletions
diff --git a/sys/amd64/vmm/intel/vmx.c b/sys/amd64/vmm/intel/vmx.c
index 2b6ef35..4f267bb 100644
--- a/sys/amd64/vmm/intel/vmx.c
+++ b/sys/amd64/vmm/intel/vmx.c
@@ -1159,15 +1159,16 @@ vmx_ept_fault(struct vm *vm, int cpu,
if (ept_qual & EPT_VIOLATION_INST_FETCH)
return (UNHANDLED);
- /* EPT violation must be a read fault or a write fault but not both */
+ /* EPT violation must be a read fault or a write fault */
read = ept_qual & EPT_VIOLATION_DATA_READ ? 1 : 0;
write = ept_qual & EPT_VIOLATION_DATA_WRITE ? 1 : 0;
- if ((read ^ write) == 0)
+ if ((read | write) == 0)
return (UNHANDLED);
/*
- * The EPT violation must have been caused by accessing a guest-physical
- * address that is a translation of a guest-linear address.
+ * The EPT violation must have been caused by accessing a
+ * guest-physical address that is a translation of a guest-linear
+ * address.
*/
if ((ept_qual & EPT_VIOLATION_GLA_VALID) == 0 ||
(ept_qual & EPT_VIOLATION_XLAT_VALID) == 0) {
diff --git a/sys/amd64/vmm/vmm_instruction_emul.c b/sys/amd64/vmm/vmm_instruction_emul.c
index 5e5399b..0a7286b 100644
--- a/sys/amd64/vmm/vmm_instruction_emul.c
+++ b/sys/amd64/vmm/vmm_instruction_emul.c
@@ -81,6 +81,11 @@ static const struct vie_op one_byte_opcodes[256] = {
[0x23] = {
.op_byte = 0x23,
.op_type = VIE_OP_TYPE_AND,
+ },
+ [0x81] = {
+ .op_byte = 0x81,
+ .op_type = VIE_OP_TYPE_AND,
+ .op_flags = VIE_OP_F_IMM,
}
};
@@ -299,6 +304,30 @@ emulate_and(void *vm, int vcpuid, uint64_t gpa, struct vie *vie,
val1 &= val2;
error = vie_update_register(vm, vcpuid, reg, val1, size);
break;
+ case 0x81:
+ printf("0x81 AND\n");
+ /*
+ * AND reg (ModRM:reg) with immediate and store the
+ * result in reg
+ *
+ * 81/ and r/m32, imm32
+ * REX.W + 81/ and r/m64, imm32 sign-extended to 64
+ */
+ if (vie->rex_w)
+ size = 8;
+
+ /* get the first operand */
+ error = memread(vm, vcpuid, gpa, &val1, size, arg);
+ if (error)
+ 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);
+ break;
default:
break;
}
OpenPOWER on IntegriCloud