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
This commit is contained in:
parent
a2d4a7e456
commit
e4f605ee81
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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'
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user