hv: instr_emul: use cs segment when fetching instructions

In non-64-bit mode, CS segment base address should be considered when
determining the linear address of the vcpu's instruction pointer. Use
vie_calculate_gla() for instruction address translation which also takes
care of 64-bit mode.

Tracked-On: #4064
Signed-off-by: Peter Fang <peter.fang@intel.com>
This commit is contained in:
Peter Fang 2019-10-21 04:15:50 -07:00 committed by wenlingz
parent 05bb56291b
commit b7329f10a5

View File

@ -560,14 +560,13 @@ static bool is_desc_valid(const struct seg_desc *desc, uint32_t prot)
*@pre prot must be PROT_READ or PROT_WRITE
*/
static void vie_calculate_gla(enum vm_cpu_mode cpu_mode, enum cpu_reg_name seg,
const struct seg_desc *desc, uint64_t offset_arg, uint8_t addrsize, uint64_t *gla)
const struct seg_desc *desc, uint64_t offset, uint8_t addrsize, uint64_t *gla)
{
uint64_t firstoff, segbase;
uint64_t offset = offset_arg;
uint8_t glasize;
firstoff = offset;
glasize = (cpu_mode == CPU_MODE_64BIT) ? 8U: 4U;
glasize = (cpu_mode == CPU_MODE_64BIT) ? 8U : 4U;
/*
* In 64-bit mode all segments except %fs and %gs have a segment
@ -1643,8 +1642,10 @@ static int32_t emulate_bittest(struct acrn_vcpu *vcpu, const struct instr_emul_v
static int32_t vie_init(struct instr_emul_vie *vie, struct acrn_vcpu *vcpu)
{
uint64_t guest_rip_gva = vcpu_get_rip(vcpu);
uint32_t inst_len = vcpu->arch.inst_len;
enum vm_cpu_mode cpu_mode;
struct seg_desc desc;
uint64_t guest_rip_gva;
uint32_t err_code;
uint64_t fault_addr;
int32_t ret;
@ -1660,6 +1661,13 @@ static int32_t vie_init(struct instr_emul_vie *vie, struct acrn_vcpu *vcpu)
vie->index_register = CPU_REG_LAST;
vie->segment_register = CPU_REG_LAST;
cpu_mode = get_vcpu_mode(vcpu);
vm_get_seg_desc(CPU_REG_CS, &desc);
/* VMX_GUEST_RIP is a natural-width field */
vie_calculate_gla(cpu_mode, CPU_REG_CS, &desc, vcpu_get_rip(vcpu),
8U, &guest_rip_gva);
err_code = PAGE_FAULT_ID_FLAG;
ret = copy_from_gva(vcpu, vie->inst, guest_rip_gva, inst_len, &err_code, &fault_addr);
if (ret < 0) {
@ -2301,12 +2309,12 @@ int32_t decode_instruction(struct acrn_vcpu *vcpu)
emul_ctxt = &vcpu->inst_ctxt;
retval = vie_init(&emul_ctxt->vie, vcpu);
if (retval < 0) {
if (retval != -EFAULT) {
pr_err("init vie failed @ 0x%016lx:", vcpu_get_rip(vcpu));
}
} else {
csar = exec_vmread32(VMX_GUEST_CS_ATTR);
cpu_mode = get_vcpu_mode(vcpu);