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.
@@ -560,10 +560,9 @@ 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;
@@ -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);
