summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortychon <tychon@FreeBSD.org>2015-03-24 17:12:36 +0000
committertychon <tychon@FreeBSD.org>2015-03-24 17:12:36 +0000
commitb925086de0c55cdfbaf91ed147f66c84d02b82b3 (patch)
tree781c2f05d97aef978b92a7a4fa2c321ae3694302
parentbaf4ea8ca8f540542e799c44517f022c9c73d448 (diff)
downloadFreeBSD-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.h1
-rw-r--r--sys/amd64/vmm/amd/svm.c6
-rw-r--r--sys/amd64/vmm/intel/vmx.c6
-rw-r--r--sys/amd64/vmm/vmm.c7
-rw-r--r--sys/amd64/vmm/vmm_instruction_emul.c6
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);
OpenPOWER on IntegriCloud