Skip to content

Commit b5d4e23

Browse files
bibo-maochenhuacai
authored andcommitted
LoongArch: KVM: Delay secondary mmu tlb flush until guest entry
With hardware assisted virtualization, there are two level HW mmu, one is GVA to GPA mapping, the other is GPA to HPA mapping which is called secondary mmu in generic. If there is page fault for secondary mmu, there needs tlb flush operation indexed with fault GPA address and VMID. VMID is stored at register CSR.GSTAT and will be reload or recalculated before guest entry. Currently CSR.GSTAT is not saved and restored during VCPU context switch, instead it is recalculated during guest entry. So CSR.GSTAT is effective only when a VCPU runs in guest mode, however it may not be effective if the VCPU exits to host mode. Since register CSR.GSTAT may be stale, it may records the VMID of the last schedule-out VCPU, rather than the current VCPU. Function kvm_flush_tlb_gpa() should be called with its real VMID, so here move it to the guest entrance. Also an arch-specific request id KVM_REQ_TLB_FLUSH_GPA is added to flush tlb for secondary mmu, and it can be optimized if VMID is updated, since all guest tlb entries will be invalid if VMID is updated. Signed-off-by: Bibo Mao <[email protected]> Signed-off-by: Huacai Chen <[email protected]>
1 parent e306e51 commit b5d4e23

File tree

5 files changed

+24
-5
lines changed

5 files changed

+24
-5
lines changed

arch/loongarch/include/asm/kvm_host.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#define KVM_PRIVATE_MEM_SLOTS 0
3131

3232
#define KVM_HALT_POLL_NS_DEFAULT 500000
33+
#define KVM_REQ_TLB_FLUSH_GPA KVM_ARCH_REQ(0)
3334

3435
#define KVM_GUESTDBG_SW_BP_MASK \
3536
(KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP)
@@ -190,6 +191,7 @@ struct kvm_vcpu_arch {
190191

191192
/* vcpu's vpid */
192193
u64 vpid;
194+
gpa_t flush_gpa;
193195

194196
/* Frequency of stable timer in Hz */
195197
u64 timer_mhz;

arch/loongarch/kvm/main.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,7 @@ void kvm_check_vpid(struct kvm_vcpu *vcpu)
242242
kvm_update_vpid(vcpu, cpu);
243243
trace_kvm_vpid_change(vcpu, vcpu->arch.vpid);
244244
vcpu->cpu = cpu;
245+
kvm_clear_request(KVM_REQ_TLB_FLUSH_GPA, vcpu);
245246
}
246247

247248
/* Restore GSTAT(0x50).vpid */

arch/loongarch/kvm/mmu.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -908,7 +908,8 @@ int kvm_handle_mm_fault(struct kvm_vcpu *vcpu, unsigned long gpa, bool write)
908908
return ret;
909909

910910
/* Invalidate this entry in the TLB */
911-
kvm_flush_tlb_gpa(vcpu, gpa);
911+
vcpu->arch.flush_gpa = gpa;
912+
kvm_make_request(KVM_REQ_TLB_FLUSH_GPA, vcpu);
912913

913914
return 0;
914915
}

arch/loongarch/kvm/tlb.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,7 @@ void kvm_flush_tlb_all(void)
2323

2424
void kvm_flush_tlb_gpa(struct kvm_vcpu *vcpu, unsigned long gpa)
2525
{
26-
unsigned long flags;
27-
28-
local_irq_save(flags);
26+
lockdep_assert_irqs_disabled();
2927
gpa &= (PAGE_MASK << 1);
3028
invtlb(INVTLB_GID_ADDR, read_csr_gstat() & CSR_GSTAT_GID, gpa);
31-
local_irq_restore(flags);
3229
}

arch/loongarch/kvm/vcpu.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,16 @@ static int kvm_check_requests(struct kvm_vcpu *vcpu)
5151
return RESUME_GUEST;
5252
}
5353

54+
static void kvm_late_check_requests(struct kvm_vcpu *vcpu)
55+
{
56+
lockdep_assert_irqs_disabled();
57+
if (kvm_check_request(KVM_REQ_TLB_FLUSH_GPA, vcpu))
58+
if (vcpu->arch.flush_gpa != INVALID_GPA) {
59+
kvm_flush_tlb_gpa(vcpu, vcpu->arch.flush_gpa);
60+
vcpu->arch.flush_gpa = INVALID_GPA;
61+
}
62+
}
63+
5464
/*
5565
* Check and handle pending signal and vCPU requests etc
5666
* Run with irq enabled and preempt enabled
@@ -101,6 +111,13 @@ static int kvm_pre_enter_guest(struct kvm_vcpu *vcpu)
101111
/* Make sure the vcpu mode has been written */
102112
smp_store_mb(vcpu->mode, IN_GUEST_MODE);
103113
kvm_check_vpid(vcpu);
114+
115+
/*
116+
* Called after function kvm_check_vpid()
117+
* Since it updates CSR.GSTAT used by kvm_flush_tlb_gpa(),
118+
* and it may also clear KVM_REQ_TLB_FLUSH_GPA pending bit
119+
*/
120+
kvm_late_check_requests(vcpu);
104121
vcpu->arch.host_eentry = csr_read64(LOONGARCH_CSR_EENTRY);
105122
/* Clear KVM_LARCH_SWCSR_LATEST as CSR will change when enter guest */
106123
vcpu->arch.aux_inuse &= ~KVM_LARCH_SWCSR_LATEST;
@@ -1005,6 +1022,7 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
10051022
struct loongarch_csrs *csr;
10061023

10071024
vcpu->arch.vpid = 0;
1025+
vcpu->arch.flush_gpa = INVALID_GPA;
10081026

10091027
hrtimer_init(&vcpu->arch.swtimer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS_PINNED);
10101028
vcpu->arch.swtimer.function = kvm_swtimer_wakeup;

0 commit comments

Comments
 (0)