diff options
author | grehan <grehan@FreeBSD.org> | 2012-11-29 06:26:42 +0000 |
---|---|---|
committer | grehan <grehan@FreeBSD.org> | 2012-11-29 06:26:42 +0000 |
commit | ffd1f089c33d0e59c0cb85b52bc683272f7880dd (patch) | |
tree | ae1cace65dd274cdb8c7e60c5747c289e4959216 /sys/amd64/vmm/vmm_instruction_emul.c | |
parent | da4e87dfd614fffb88e5a93c988e1caec9c9efe7 (diff) | |
download | FreeBSD-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
Diffstat (limited to 'sys/amd64/vmm/vmm_instruction_emul.c')
-rw-r--r-- | sys/amd64/vmm/vmm_instruction_emul.c | 29 |
1 files changed, 29 insertions, 0 deletions
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; } |