LoongArch: KVM: Do not flush tlb if HW PTW supported
authorBibo Mao <maobibo@loongson.cn>
Tue, 20 May 2025 12:20:18 +0000 (20:20 +0800)
committerHuacai Chen <chenhuacai@loongson.cn>
Tue, 20 May 2025 12:20:18 +0000 (20:20 +0800)
With HW PTW supported, invalid TLB is not added when page fault happens.
But for EXCCODE_TLBM exception, stale TLB may exist because of the last
read access. Thus TLB flush operation is necessary for the EXCCODE_TLBM
exception, but not necessary for other tyeps of page fault exceptions.

With SW PTW supported, invalid TLB is added in the TLB refill exception.
TLB flush operation is necessary for all types of page fault exceptions.

Here remove unnecessary TLB flush opereation with HW PTW supported.

Signed-off-by: Bibo Mao <maobibo@loongson.cn>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
arch/loongarch/include/asm/kvm_host.h
arch/loongarch/kvm/exit.c
arch/loongarch/kvm/mmu.c

index f457c2662e2f2b91b5ee90682fd2009abbd9b887..a3c4cc46c892242ae0f89fbc9e3326aae2cecad0 100644 (file)
@@ -301,7 +301,7 @@ int kvm_arch_vcpu_dump_regs(struct kvm_vcpu *vcpu);
 /* MMU handling */
 void kvm_flush_tlb_all(void);
 void kvm_flush_tlb_gpa(struct kvm_vcpu *vcpu, unsigned long gpa);
-int kvm_handle_mm_fault(struct kvm_vcpu *vcpu, unsigned long badv, bool write);
+int kvm_handle_mm_fault(struct kvm_vcpu *vcpu, unsigned long badv, bool write, int ecode);
 
 int kvm_unmap_hva_range(struct kvm *kvm, unsigned long start, unsigned long end, bool blockable);
 int kvm_age_hva(struct kvm *kvm, unsigned long start, unsigned long end);
index e143fa3d21d4af1101053379908ae55e8b481ca8..fa52251b3bf1c889e27a055fe8b126ac4ae50563 100644 (file)
@@ -661,7 +661,7 @@ int kvm_emu_mmio_write(struct kvm_vcpu *vcpu, larch_inst inst)
        return ret;
 }
 
-static int kvm_handle_rdwr_fault(struct kvm_vcpu *vcpu, bool write)
+static int kvm_handle_rdwr_fault(struct kvm_vcpu *vcpu, bool write, int ecode)
 {
        int ret;
        larch_inst inst;
@@ -675,7 +675,7 @@ static int kvm_handle_rdwr_fault(struct kvm_vcpu *vcpu, bool write)
                return RESUME_GUEST;
        }
 
-       ret = kvm_handle_mm_fault(vcpu, badv, write);
+       ret = kvm_handle_mm_fault(vcpu, badv, write, ecode);
        if (ret) {
                /* Treat as MMIO */
                inst.word = vcpu->arch.badi;
@@ -707,12 +707,12 @@ static int kvm_handle_rdwr_fault(struct kvm_vcpu *vcpu, bool write)
 
 static int kvm_handle_read_fault(struct kvm_vcpu *vcpu, int ecode)
 {
-       return kvm_handle_rdwr_fault(vcpu, false);
+       return kvm_handle_rdwr_fault(vcpu, false, ecode);
 }
 
 static int kvm_handle_write_fault(struct kvm_vcpu *vcpu, int ecode)
 {
-       return kvm_handle_rdwr_fault(vcpu, true);
+       return kvm_handle_rdwr_fault(vcpu, true, ecode);
 }
 
 int kvm_complete_user_service(struct kvm_vcpu *vcpu, struct kvm_run *run)
index 4d203294767c5a2f72946b17fb793470a2672ed9..ed956c5cf2cc043ef16d7839af4522e9929d0ec3 100644 (file)
@@ -912,7 +912,7 @@ out:
        return err;
 }
 
-int kvm_handle_mm_fault(struct kvm_vcpu *vcpu, unsigned long gpa, bool write)
+int kvm_handle_mm_fault(struct kvm_vcpu *vcpu, unsigned long gpa, bool write, int ecode)
 {
        int ret;
 
@@ -921,8 +921,17 @@ int kvm_handle_mm_fault(struct kvm_vcpu *vcpu, unsigned long gpa, bool write)
                return ret;
 
        /* Invalidate this entry in the TLB */
-       vcpu->arch.flush_gpa = gpa;
-       kvm_make_request(KVM_REQ_TLB_FLUSH_GPA, vcpu);
+       if (!cpu_has_ptw || (ecode == EXCCODE_TLBM)) {
+               /*
+                * With HW PTW, invalid TLB is not added when page fault. But
+                * for EXCCODE_TLBM exception, stale TLB may exist because of
+                * the last read access.
+                *
+                * With SW PTW, invalid TLB is added in TLB refill exception.
+                */
+               vcpu->arch.flush_gpa = gpa;
+               kvm_make_request(KVM_REQ_TLB_FLUSH_GPA, vcpu);
+       }
 
        return 0;
 }