@@ -2896,10 +2896,8 @@ static int mmu_set_spte(struct kvm_vcpu *vcpu, struct kvm_memory_slot *slot,
2896
2896
trace_kvm_mmu_set_spte (level , gfn , sptep );
2897
2897
}
2898
2898
2899
- if (wrprot ) {
2900
- if (write_fault )
2901
- ret = RET_PF_EMULATE ;
2902
- }
2899
+ if (wrprot && write_fault )
2900
+ ret = RET_PF_WRITE_PROTECTED ;
2903
2901
2904
2902
if (flush )
2905
2903
kvm_flush_remote_tlbs_gfn (vcpu -> kvm , gfn , level );
@@ -4531,7 +4529,7 @@ static int direct_page_fault(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault
4531
4529
return RET_PF_RETRY ;
4532
4530
4533
4531
if (page_fault_handle_page_track (vcpu , fault ))
4534
- return RET_PF_EMULATE ;
4532
+ return RET_PF_WRITE_PROTECTED ;
4535
4533
4536
4534
r = fast_page_fault (vcpu , fault );
4537
4535
if (r != RET_PF_INVALID )
@@ -4624,7 +4622,7 @@ static int kvm_tdp_mmu_page_fault(struct kvm_vcpu *vcpu,
4624
4622
int r ;
4625
4623
4626
4624
if (page_fault_handle_page_track (vcpu , fault ))
4627
- return RET_PF_EMULATE ;
4625
+ return RET_PF_WRITE_PROTECTED ;
4628
4626
4629
4627
r = fast_page_fault (vcpu , fault );
4630
4628
if (r != RET_PF_INVALID )
@@ -4703,6 +4701,7 @@ static int kvm_tdp_map_page(struct kvm_vcpu *vcpu, gpa_t gpa, u64 error_code,
4703
4701
switch (r ) {
4704
4702
case RET_PF_FIXED :
4705
4703
case RET_PF_SPURIOUS :
4704
+ case RET_PF_WRITE_PROTECTED :
4706
4705
return 0 ;
4707
4706
4708
4707
case RET_PF_EMULATE :
@@ -5952,6 +5951,40 @@ static bool is_write_to_guest_page_table(u64 error_code)
5952
5951
return (error_code & mask ) == mask ;
5953
5952
}
5954
5953
5954
+ static int kvm_mmu_write_protect_fault (struct kvm_vcpu * vcpu , gpa_t cr2_or_gpa ,
5955
+ u64 error_code , int * emulation_type )
5956
+ {
5957
+ bool direct = vcpu -> arch .mmu -> root_role .direct ;
5958
+
5959
+ /*
5960
+ * Before emulating the instruction, check if the error code
5961
+ * was due to a RO violation while translating the guest page.
5962
+ * This can occur when using nested virtualization with nested
5963
+ * paging in both guests. If true, we simply unprotect the page
5964
+ * and resume the guest.
5965
+ */
5966
+ if (direct && is_write_to_guest_page_table (error_code )) {
5967
+ kvm_mmu_unprotect_page (vcpu -> kvm , gpa_to_gfn (cr2_or_gpa ));
5968
+ return RET_PF_RETRY ;
5969
+ }
5970
+
5971
+ /*
5972
+ * The gfn is write-protected, but if emulation fails we can still
5973
+ * optimistically try to just unprotect the page and let the processor
5974
+ * re-execute the instruction that caused the page fault. Do not allow
5975
+ * retrying MMIO emulation, as it's not only pointless but could also
5976
+ * cause us to enter an infinite loop because the processor will keep
5977
+ * faulting on the non-existent MMIO address. Retrying an instruction
5978
+ * from a nested guest is also pointless and dangerous as we are only
5979
+ * explicitly shadowing L1's page tables, i.e. unprotecting something
5980
+ * for L1 isn't going to magically fix whatever issue cause L2 to fail.
5981
+ */
5982
+ if (!mmio_info_in_cache (vcpu , cr2_or_gpa , direct ) && !is_guest_mode (vcpu ))
5983
+ * emulation_type |= EMULTYPE_ALLOW_RETRY_PF ;
5984
+
5985
+ return RET_PF_EMULATE ;
5986
+ }
5987
+
5955
5988
int noinline kvm_mmu_page_fault (struct kvm_vcpu * vcpu , gpa_t cr2_or_gpa , u64 error_code ,
5956
5989
void * insn , int insn_len )
5957
5990
{
@@ -5997,6 +6030,10 @@ int noinline kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, u64 err
5997
6030
if (r < 0 )
5998
6031
return r ;
5999
6032
6033
+ if (r == RET_PF_WRITE_PROTECTED )
6034
+ r = kvm_mmu_write_protect_fault (vcpu , cr2_or_gpa , error_code ,
6035
+ & emulation_type );
6036
+
6000
6037
if (r == RET_PF_FIXED )
6001
6038
vcpu -> stat .pf_fixed ++ ;
6002
6039
else if (r == RET_PF_EMULATE )
@@ -6007,32 +6044,6 @@ int noinline kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, u64 err
6007
6044
if (r != RET_PF_EMULATE )
6008
6045
return 1 ;
6009
6046
6010
- /*
6011
- * Before emulating the instruction, check if the error code
6012
- * was due to a RO violation while translating the guest page.
6013
- * This can occur when using nested virtualization with nested
6014
- * paging in both guests. If true, we simply unprotect the page
6015
- * and resume the guest.
6016
- */
6017
- if (vcpu -> arch .mmu -> root_role .direct &&
6018
- is_write_to_guest_page_table (error_code )) {
6019
- kvm_mmu_unprotect_page (vcpu -> kvm , gpa_to_gfn (cr2_or_gpa ));
6020
- return 1 ;
6021
- }
6022
-
6023
- /*
6024
- * vcpu->arch.mmu.page_fault returned RET_PF_EMULATE, but we can still
6025
- * optimistically try to just unprotect the page and let the processor
6026
- * re-execute the instruction that caused the page fault. Do not allow
6027
- * retrying MMIO emulation, as it's not only pointless but could also
6028
- * cause us to enter an infinite loop because the processor will keep
6029
- * faulting on the non-existent MMIO address. Retrying an instruction
6030
- * from a nested guest is also pointless and dangerous as we are only
6031
- * explicitly shadowing L1's page tables, i.e. unprotecting something
6032
- * for L1 isn't going to magically fix whatever issue cause L2 to fail.
6033
- */
6034
- if (!mmio_info_in_cache (vcpu , cr2_or_gpa , direct ) && !is_guest_mode (vcpu ))
6035
- emulation_type |= EMULTYPE_ALLOW_RETRY_PF ;
6036
6047
emulate :
6037
6048
return x86_emulate_instruction (vcpu , cr2_or_gpa , emulation_type , insn ,
6038
6049
insn_len );
0 commit comments