Skip to content

Commit 92e4505

Browse files
committed
RISC-V: KVM: Cleanup stale TLB entries when host CPU changes
On RISC-V platforms with hardware VMID support, we share same VMID for all VCPUs of a particular Guest/VM. This means we might have stale G-stage TLB entries on the current Host CPU due to some other VCPU of the same Guest which ran previously on the current Host CPU. To cleanup stale TLB entries, we simply flush all G-stage TLB entries by VMID whenever underlying Host CPU changes for a VCPU. Signed-off-by: Anup Patel <apatel@ventanamicro.com> Reviewed-by: Atish Patra <atishp@rivosinc.com> Signed-off-by: Anup Patel <anup@brainfault.org>
1 parent 13acfec commit 92e4505

3 files changed

Lines changed: 39 additions & 0 deletions

File tree

arch/riscv/include/asm/kvm_host.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,9 @@ struct kvm_vcpu_arch {
166166
/* VCPU ran at least once */
167167
bool ran_atleast_once;
168168

169+
/* Last Host CPU on which Guest VCPU exited */
170+
int last_exit_cpu;
171+
169172
/* ISA feature bits (similar to MISA) */
170173
unsigned long isa;
171174

@@ -253,6 +256,8 @@ void kvm_riscv_local_hfence_vvma_gva(unsigned long vmid,
253256
unsigned long order);
254257
void kvm_riscv_local_hfence_vvma_all(unsigned long vmid);
255258

259+
void kvm_riscv_local_tlb_sanitize(struct kvm_vcpu *vcpu);
260+
256261
void kvm_riscv_fence_i_process(struct kvm_vcpu *vcpu);
257262
void kvm_riscv_hfence_gvma_vmid_all_process(struct kvm_vcpu *vcpu);
258263
void kvm_riscv_hfence_vvma_all_process(struct kvm_vcpu *vcpu);

arch/riscv/kvm/tlb.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,29 @@ void kvm_riscv_local_hfence_vvma_all(unsigned long vmid)
215215
csr_write(CSR_HGATP, hgatp);
216216
}
217217

218+
void kvm_riscv_local_tlb_sanitize(struct kvm_vcpu *vcpu)
219+
{
220+
unsigned long vmid;
221+
222+
if (!kvm_riscv_gstage_vmid_bits() ||
223+
vcpu->arch.last_exit_cpu == vcpu->cpu)
224+
return;
225+
226+
/*
227+
* On RISC-V platforms with hardware VMID support, we share same
228+
* VMID for all VCPUs of a particular Guest/VM. This means we might
229+
* have stale G-stage TLB entries on the current Host CPU due to
230+
* some other VCPU of the same Guest which ran previously on the
231+
* current Host CPU.
232+
*
233+
* To cleanup stale TLB entries, we simply flush all G-stage TLB
234+
* entries by VMID whenever underlying Host CPU changes for a VCPU.
235+
*/
236+
237+
vmid = READ_ONCE(vcpu->kvm->arch.vmid.vmid);
238+
kvm_riscv_local_hfence_gvma_vmid_all(vmid);
239+
}
240+
218241
void kvm_riscv_fence_i_process(struct kvm_vcpu *vcpu)
219242
{
220243
local_flush_icache_all();

arch/riscv/kvm/vcpu.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ static void kvm_riscv_reset_vcpu(struct kvm_vcpu *vcpu)
6767
if (loaded)
6868
kvm_arch_vcpu_put(vcpu);
6969

70+
vcpu->arch.last_exit_cpu = -1;
71+
7072
memcpy(csr, reset_csr, sizeof(*csr));
7173

7274
memcpy(cntx, reset_cntx, sizeof(*cntx));
@@ -735,6 +737,7 @@ static void noinstr kvm_riscv_vcpu_enter_exit(struct kvm_vcpu *vcpu)
735737
{
736738
guest_state_enter_irqoff();
737739
__kvm_riscv_switch_to(&vcpu->arch);
740+
vcpu->arch.last_exit_cpu = vcpu->cpu;
738741
guest_state_exit_irqoff();
739742
}
740743

@@ -829,6 +832,14 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
829832
continue;
830833
}
831834

835+
/*
836+
* Cleanup stale TLB enteries
837+
*
838+
* Note: This should be done after G-stage VMID has been
839+
* updated using kvm_riscv_gstage_vmid_ver_changed()
840+
*/
841+
kvm_riscv_local_tlb_sanitize(vcpu);
842+
832843
guest_timing_enter_irqoff();
833844

834845
kvm_riscv_vcpu_enter_exit(vcpu);

0 commit comments

Comments
 (0)