When there is contention on faulting in a particular page table entry at stage 2, the break-before-make requirement of the architecture can lead to additional refaulting due to TLB invalidation. Avoid this by skipping a page table update if the new value of the PTE matches the previous value.
Unified · Split
| @@ -1147,6 +1147,10 @@ static int stage2_set_pte(struct kvm *kvm, struct kvm_mmu_memory_cache *cache, · 1146 unmodified lines | |||
| 1147 | /* Create 2nd stage page table mapping - Level 3 */ | 1147 | /* Create 2nd stage page table mapping - Level 3 */ |
| 1148 | old_pte = *pte; | 1148 | old_pte = *pte; |
| 1149 | if (pte_present(old_pte)) { | 1149 | if (pte_present(old_pte)) { |
| 1150 | /* Skip page table update if there is no change */ | ||
| 1151 | if (pte_val(old_pte) == pte_val(*new_pte)) | ||
| 1152 | return 0; | ||
| 1153 | |||
| 1150 | kvm_set_pte(pte, __pte(0)); | 1154 | kvm_set_pte(pte, __pte(0)); |
| 1151 | kvm_tlb_flush_vmid_ipa(kvm, addr); | 1155 | kvm_tlb_flush_vmid_ipa(kvm, addr); |
| 1152 | } else { | 1156 | } else { |