@@ -454,7 +454,6 @@ static int vie_calculate_gla(enum vm_cpu_mode cpu_mode, enum cpu_reg_name seg,
454
454
uint64_t firstoff , segbase ;
455
455
uint64_t offset = offset_arg ;
456
456
uint8_t glasize ;
457
- uint32_t type ;
458
457
459
458
firstoff = offset ;
460
459
glasize = (cpu_mode == CPU_MODE_64BIT ) ? 8U : 4U ;
@@ -860,52 +859,97 @@ static int emulate_movx(struct vcpu *vcpu, struct instr_emul_vie *vie)
860
859
return error ;
861
860
}
862
861
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
+
863
888
/*
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
865
895
*/
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 )
870
899
{
871
900
int ret ;
901
+ uint32_t err_code ;
872
902
struct seg_desc desc ;
873
- uint64_t cr0 , val , rflags ;
903
+ enum vm_cpu_mode cpu_mode ;
904
+ uint64_t val , gpa ;
874
905
875
- cr0 = vm_get_register (vcpu , CPU_REG_CR0 );
876
- rflags = vm_get_register (vcpu , CPU_REG_RFLAGS );
877
906
val = vm_get_register (vcpu , gpr );
878
907
vm_get_seg_desc (seg , & desc );
908
+ cpu_mode = get_vcpu_mode (vcpu );
879
909
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 ;
886
921
}
887
- goto guest_fault ;
888
922
}
889
923
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 );
895
937
}
896
- goto guest_fault ;
938
+ return ret ;
897
939
}
898
940
899
- * fault = 0 ;
900
941
return 0 ;
901
942
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 ;
905
950
}
906
951
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 )
909
953
{
910
954
uint64_t dstaddr , srcaddr ;
911
955
uint64_t rcx , rdi , rsi , rflags ;
@@ -939,18 +983,10 @@ static int emulate_movs(struct vcpu *vcpu, struct instr_emul_vie *vie,
939
983
}
940
984
941
985
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
- }
947
986
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 );
954
990
955
991
(void )memcpy_s ((void * )dstaddr , 16U , (void * )srcaddr , opsize );
956
992
@@ -1520,7 +1556,7 @@ static int vmm_emulate_instruction(struct instr_emul_ctxt *ctxt)
1520
1556
error = emulate_movx (vcpu , vie );
1521
1557
break ;
1522
1558
case VIE_OP_TYPE_MOVS :
1523
- error = emulate_movs (vcpu , vie , paging );
1559
+ error = emulate_movs (vcpu , vie );
1524
1560
break ;
1525
1561
case VIE_OP_TYPE_STOS :
1526
1562
error = emulate_stos (vcpu , vie );
0 commit comments