Skip to content

Commit b01a812

Browse files
fyin1lijinxia
authored andcommitted
hv: add new function to get gva for MOVS/STO instruction
Drop the get_gla function and add - get_gva_di_si_nocheck get gva from ES:DI and DS(other segment):SI without check faulure case - get_gva_di_si_check get gva from ES:DI and DS(other segment):SI with failure case checked TODO: - Save dst_gpa and src_gpa for instruction emulation phase use. Signed-off-by: Yin Fengwei <fengwei.yin@intel.com> Acked-by: Anthony Xu <anthony.xu@intel.com>
1 parent 8480c98 commit b01a812

File tree

1 file changed

+76
-40
lines changed

1 file changed

+76
-40
lines changed

hypervisor/arch/x86/guest/instr_emul.c

Lines changed: 76 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -454,7 +454,6 @@ static int vie_calculate_gla(enum vm_cpu_mode cpu_mode, enum cpu_reg_name seg,
454454
uint64_t firstoff, segbase;
455455
uint64_t offset = offset_arg;
456456
uint8_t glasize;
457-
uint32_t type;
458457

459458
firstoff = offset;
460459
glasize = (cpu_mode == CPU_MODE_64BIT) ? 8U: 4U;
@@ -860,52 +859,97 @@ static int emulate_movx(struct vcpu *vcpu, struct instr_emul_vie *vie)
860859
return error;
861860
}
862861

862+
/**
863+
* @pre only called by instruction emulation and check was done during
864+
* instruction decode
865+
*
866+
* @remark This function can only be called in instruction emulation and
867+
* suppose always success because the check was done during instruction
868+
* decode.
869+
*
870+
* It's only used by MOVS/STO
871+
*/
872+
static void get_gva_di_si_nocheck(struct vcpu *vcpu, uint8_t addrsize,
873+
enum cpu_reg_name seg, enum cpu_reg_name gpr, uint64_t *gva)
874+
{
875+
uint64_t val;
876+
struct seg_desc desc;
877+
enum vm_cpu_mode cpu_mode;
878+
879+
val = vm_get_register(vcpu, gpr);
880+
vm_get_seg_desc(seg, &desc);
881+
cpu_mode = get_vcpu_mode(vcpu);
882+
883+
(void)vie_calculate_gla(cpu_mode, seg, &desc, val, addrsize, gva);
884+
885+
return;
886+
}
887+
863888
/*
864-
* Helper function to calculate and validate a linear address.
889+
* @pre only called during instruction decode phase
890+
*
891+
* @remark This function get gva from ES:DI and DS(other segment):SI. And
892+
* do check the failure condition and inject exception to guest accordingly.
893+
*
894+
* It's only used by MOVS/STO
865895
*/
866-
static int get_gla(struct vcpu *vcpu, __unused struct instr_emul_vie *vie,
867-
struct vm_guest_paging *paging,
868-
uint8_t opsize, uint8_t addrsize, uint32_t prot, enum cpu_reg_name seg,
869-
enum cpu_reg_name gpr, uint64_t *gla, int *fault)
896+
static int get_gva_di_si_check(struct vcpu *vcpu, uint8_t addrsize,
897+
uint32_t prot, enum cpu_reg_name seg, enum cpu_reg_name gpr,
898+
uint64_t *gva)
870899
{
871900
int ret;
901+
uint32_t err_code;
872902
struct seg_desc desc;
873-
uint64_t cr0, val, rflags;
903+
enum vm_cpu_mode cpu_mode;
904+
uint64_t val, gpa;
874905

875-
cr0 = vm_get_register(vcpu, CPU_REG_CR0);
876-
rflags = vm_get_register(vcpu, CPU_REG_RFLAGS);
877906
val = vm_get_register(vcpu, gpr);
878907
vm_get_seg_desc(seg, &desc);
908+
cpu_mode = get_vcpu_mode(vcpu);
879909

880-
if (vie_calculate_gla(paging->cpu_mode, seg, &desc, val,
881-
addrsize, gla) != 0) {
882-
if (seg == CPU_REG_SS) {
883-
pr_err("TODO: inject ss exception");
884-
} else {
885-
pr_err("TODO: inject gp exception");
910+
if (!is_desc_valid(&desc, prot)) {
911+
goto exception_inject;
912+
}
913+
914+
if (cpu_mode == CPU_MODE_64BIT) {
915+
if ((addrsize != 4U) && (addrsize != 8U)) {
916+
goto exception_inject;
917+
}
918+
} else {
919+
if ((addrsize != 2U) && (addrsize != 4U)) {
920+
goto exception_inject;
886921
}
887-
goto guest_fault;
888922
}
889923

890-
if (vie_canonical_check(paging->cpu_mode, *gla) != 0) {
891-
if (seg == CPU_REG_SS) {
892-
pr_err("TODO: inject ss exception");
893-
} else {
894-
pr_err("TODO: inject gp exception");
924+
if (vie_calculate_gla(cpu_mode, seg, &desc, val, addrsize, gva) != 0) {
925+
goto exception_inject;
926+
}
927+
928+
if (vie_canonical_check(cpu_mode, *gva) != 0) {
929+
goto exception_inject;
930+
}
931+
932+
err_code = (prot == PROT_WRITE) ? PAGE_FAULT_WR_FLAG : 0U;
933+
ret = gva2gpa(vcpu, (uint64_t)gva, &gpa, &err_code);
934+
if (ret < 0) {
935+
if (ret == -EFAULT) {
936+
vcpu_inject_pf(vcpu, (uint64_t)gva, err_code);
895937
}
896-
goto guest_fault;
938+
return ret;
897939
}
898940

899-
*fault = 0;
900941
return 0;
901942

902-
guest_fault:
903-
*fault = 1;
904-
return ret;
943+
exception_inject:
944+
if (seg == CPU_REG_SS) {
945+
vcpu_inject_ss(vcpu);
946+
} else {
947+
vcpu_inject_gp(vcpu, 0U);
948+
}
949+
return -EFAULT;
905950
}
906951

907-
static int emulate_movs(struct vcpu *vcpu, struct instr_emul_vie *vie,
908-
struct vm_guest_paging *paging)
952+
static int emulate_movs(struct vcpu *vcpu, struct instr_emul_vie *vie)
909953
{
910954
uint64_t dstaddr, srcaddr;
911955
uint64_t rcx, rdi, rsi, rflags;
@@ -939,18 +983,10 @@ static int emulate_movs(struct vcpu *vcpu, struct instr_emul_vie *vie,
939983
}
940984

941985
seg = (vie->seg_override != 0U) ? (vie->segment_register) : CPU_REG_DS;
942-
error = get_gla(vcpu, vie, paging, opsize, vie->addrsize,
943-
PROT_READ, seg, CPU_REG_RSI, &srcaddr, &fault);
944-
if ((error != 0) || (fault != 0)) {
945-
goto done;
946-
}
947986

948-
error = get_gla(vcpu, vie, paging, opsize, vie->addrsize,
949-
PROT_WRITE, CPU_REG_ES, CPU_REG_RDI, &dstaddr,
950-
&fault);
951-
if ((error != 0) || (fault != 0)) {
952-
goto done;
953-
}
987+
get_gva_di_si_nocheck(vcpu, vie->addrsize, seg, CPU_REG_RSI, &srcaddr);
988+
get_gva_di_si_nocheck(vcpu, vie->addrsize, CPU_REG_ES, CPU_REG_RDI,
989+
&dstaddr);
954990

955991
(void)memcpy_s((void *)dstaddr, 16U, (void *)srcaddr, opsize);
956992

@@ -1520,7 +1556,7 @@ static int vmm_emulate_instruction(struct instr_emul_ctxt *ctxt)
15201556
error = emulate_movx(vcpu, vie);
15211557
break;
15221558
case VIE_OP_TYPE_MOVS:
1523-
error = emulate_movs(vcpu, vie, paging);
1559+
error = emulate_movs(vcpu, vie);
15241560
break;
15251561
case VIE_OP_TYPE_STOS:
15261562
error = emulate_stos(vcpu, vie);

0 commit comments

Comments
 (0)