diff options
author | tychon <tychon@FreeBSD.org> | 2015-03-24 17:12:36 +0000 |
---|---|---|
committer | tychon <tychon@FreeBSD.org> | 2015-03-24 17:12:36 +0000 |
commit | b925086de0c55cdfbaf91ed147f66c84d02b82b3 (patch) | |
tree | 781c2f05d97aef978b92a7a4fa2c321ae3694302 | |
parent | baf4ea8ca8f540542e799c44517f022c9c73d448 (diff) | |
download | FreeBSD-src-b925086de0c55cdfbaf91ed147f66c84d02b82b3.zip FreeBSD-src-b925086de0c55cdfbaf91ed147f66c84d02b82b3.tar.gz |
When fetching an instruction in non-64bit mode, consider the value of the
code segment base address.
Also if an instruction doesn't support a mod R/M (modRM) byte, don't
be concerned if the CPU is in real mode.
Reviewed by: neel
-rw-r--r-- | sys/amd64/include/vmm.h | 1 | ||||
-rw-r--r-- | sys/amd64/vmm/amd/svm.c | 6 | ||||
-rw-r--r-- | sys/amd64/vmm/intel/vmx.c | 6 | ||||
-rw-r--r-- | sys/amd64/vmm/vmm.c | 7 | ||||
-rw-r--r-- | sys/amd64/vmm/vmm_instruction_emul.c | 6 |
5 files changed, 20 insertions, 6 deletions
diff --git a/sys/amd64/include/vmm.h b/sys/amd64/include/vmm.h index cf7f5bc..52294bd 100644 --- a/sys/amd64/include/vmm.h +++ b/sys/amd64/include/vmm.h @@ -551,6 +551,7 @@ struct vm_exit { struct { uint64_t gpa; uint64_t gla; + uint64_t cs_base; int cs_d; /* CS.D */ struct vm_guest_paging paging; struct vie vie; diff --git a/sys/amd64/vmm/amd/svm.c b/sys/amd64/vmm/amd/svm.c index 88a846d..18871d0 100644 --- a/sys/amd64/vmm/amd/svm.c +++ b/sys/amd64/vmm/amd/svm.c @@ -799,8 +799,13 @@ svm_handle_inst_emul(struct vmcb *vmcb, uint64_t gpa, struct vm_exit *vmexit) KASSERT(error == 0, ("%s: vmcb_seg(CS) error %d", __func__, error)); switch(paging->cpu_mode) { + case CPU_MODE_REAL: + vmexit->u.inst_emul.cs_base = seg.base; + vmexit->u.inst_emul.cs_d = 0; case CPU_MODE_PROTECTED: case CPU_MODE_COMPATIBILITY: + vmexit->u.inst_emul.cs_base = seg.base; + /* * Section 4.8.1 of APM2, Default Operand Size or D bit. */ @@ -808,6 +813,7 @@ svm_handle_inst_emul(struct vmcb *vmcb, uint64_t gpa, struct vm_exit *vmexit) 1 : 0; break; default: + vmexit->u.inst_emul.cs_base = 0; vmexit->u.inst_emul.cs_d = 0; break; } diff --git a/sys/amd64/vmm/intel/vmx.c b/sys/amd64/vmm/intel/vmx.c index 6dbf38a..03d755c 100644 --- a/sys/amd64/vmm/intel/vmx.c +++ b/sys/amd64/vmm/intel/vmx.c @@ -1784,12 +1784,18 @@ vmexit_inst_emul(struct vm_exit *vmexit, uint64_t gpa, uint64_t gla) vmexit->u.inst_emul.gla = gla; vmx_paging_info(paging); switch (paging->cpu_mode) { + case CPU_MODE_REAL: + vmexit->u.inst_emul.cs_base = vmcs_read(VMCS_GUEST_CS_BASE); + vmexit->u.inst_emul.cs_d = 0; + break; case CPU_MODE_PROTECTED: case CPU_MODE_COMPATIBILITY: + vmexit->u.inst_emul.cs_base = vmcs_read(VMCS_GUEST_CS_BASE); csar = vmcs_read(VMCS_GUEST_CS_ACCESS_RIGHTS); vmexit->u.inst_emul.cs_d = SEG_DESC_DEF32(csar); break; default: + vmexit->u.inst_emul.cs_base = 0; vmexit->u.inst_emul.cs_d = 0; break; } diff --git a/sys/amd64/vmm/vmm.c b/sys/amd64/vmm/vmm.c index 7e72b02..42a275b 100644 --- a/sys/amd64/vmm/vmm.c +++ b/sys/amd64/vmm/vmm.c @@ -1251,7 +1251,7 @@ vm_handle_inst_emul(struct vm *vm, int vcpuid, bool *retu) struct vie *vie; struct vcpu *vcpu; struct vm_exit *vme; - uint64_t gla, gpa; + uint64_t gla, gpa, cs_base; struct vm_guest_paging *paging; mem_region_read_t mread; mem_region_write_t mwrite; @@ -1263,6 +1263,7 @@ vm_handle_inst_emul(struct vm *vm, int vcpuid, bool *retu) gla = vme->u.inst_emul.gla; gpa = vme->u.inst_emul.gpa; + cs_base = vme->u.inst_emul.cs_base; cs_d = vme->u.inst_emul.cs_d; vie = &vme->u.inst_emul.vie; paging = &vme->u.inst_emul.paging; @@ -1277,8 +1278,8 @@ vm_handle_inst_emul(struct vm *vm, int vcpuid, bool *retu) * maximum size instruction. */ length = vme->inst_length ? vme->inst_length : VIE_INST_SIZE; - error = vmm_fetch_instruction(vm, vcpuid, paging, vme->rip, - length, vie); + error = vmm_fetch_instruction(vm, vcpuid, paging, vme->rip + + cs_base, length, vie); } else { /* * The instruction bytes have already been copied into 'vie' diff --git a/sys/amd64/vmm/vmm_instruction_emul.c b/sys/amd64/vmm/vmm_instruction_emul.c index 3db890e..2dfbe8b 100644 --- a/sys/amd64/vmm/vmm_instruction_emul.c +++ b/sys/amd64/vmm/vmm_instruction_emul.c @@ -1825,12 +1825,12 @@ decode_modrm(struct vie *vie, enum vm_cpu_mode cpu_mode) { uint8_t x; - if (cpu_mode == CPU_MODE_REAL) - return (-1); - if (vie->op.op_flags & VIE_OP_F_NO_MODRM) return (0); + if (cpu_mode == CPU_MODE_REAL) + return (-1); + if (vie_peek(vie, &x)) return (-1); |