[PATCH 4/6] LoongArch: KVM: implement vmid updating logic
From: Bibo Mao
Date: Mon Jul 27 2026 - 03:32:35 EST
For every physical CPU, there is one vmid calculation method. For
vCPUs on the same VM, vmid is the same. However for vCPUs on
different VM, vmid is different. When vCPU is scheduled on the
physical CPU, it checked vmid of this VM and the global cached
vmid, and judge whether it is valid or not.
Signed-off-by: Bibo Mao <maobibo@xxxxxxxxxxx>
---
arch/loongarch/include/asm/kvm_host.h | 2 ++
arch/loongarch/kvm/main.c | 42 ++++++++++++++++++++++++++-
2 files changed, 43 insertions(+), 1 deletion(-)
diff --git a/arch/loongarch/include/asm/kvm_host.h b/arch/loongarch/include/asm/kvm_host.h
index e93307cbe740..a01623c42c7a 100644
--- a/arch/loongarch/include/asm/kvm_host.h
+++ b/arch/loongarch/include/asm/kvm_host.h
@@ -79,6 +79,7 @@ struct kvm_arch_memory_slot {
#define HOST_MAX_PMNUM 16
struct kvm_context {
unsigned long vpid_cache;
+ unsigned long vmid_cache;
struct kvm_vcpu *last_vcpu;
/* Host PMU CSR */
u64 perf_ctrl[HOST_MAX_PMNUM];
@@ -132,6 +133,7 @@ struct kvm_arch {
unsigned long kvm_features;
s64 time_offset;
+ unsigned long vmid[NR_CPUS];
struct kvm_context __percpu *vmcs;
struct loongarch_ipi *ipi;
struct loongarch_dmsintc *dmsintc;
diff --git a/arch/loongarch/kvm/main.c b/arch/loongarch/kvm/main.c
index 3df46e02594f..7b3661da8958 100644
--- a/arch/loongarch/kvm/main.c
+++ b/arch/loongarch/kvm/main.c
@@ -281,9 +281,33 @@ static void kvm_check_vcpuid(struct kvm_vcpu *vcpu)
}
}
-static void kvm_check_vmid(struct kvm_vcpu *vcpu)
+static void kvm_update_vmid(struct kvm_vcpu *vcpu, int cpu)
{
unsigned long vmid;
+ struct kvm_context *context;
+
+ context = per_cpu_ptr(vcpu->kvm->arch.vmcs, cpu);
+ vmid = context->vmid_cache + 1;
+ if (!(vmid & vpid_mask)) {
+ /* finish round of vmid loop */
+ if (unlikely(!vmid))
+ vmid = vpid_mask + 1;
+
+ ++vmid; /* vmid 0 reserved for root */
+
+ /* start new vmid cycle */
+ kvm_flush_tlb_all_stage2();
+ }
+
+ context->vmid_cache = vmid;
+ vcpu->kvm->arch.vmid[cpu] = vmid;
+}
+
+static void kvm_check_vmid(struct kvm_vcpu *vcpu)
+{
+ int cpu;
+ unsigned long ver, old, vmid;
+ struct kvm_context *context;
/* On some machines like 3A5000, vmid needs the same with vpid */
if (!cpu_has_guestid) {
@@ -295,6 +319,21 @@ static void kvm_check_vmid(struct kvm_vcpu *vcpu)
return;
}
+
+ cpu = smp_processor_id();
+ context = per_cpu_ptr(vcpu->kvm->arch.vmcs, cpu);
+
+ /*
+ * Check if our vmid is of an older version
+ */
+ ver = vcpu->kvm->arch.vmid[cpu] & ~vpid_mask;
+ old = context->vmid_cache & ~vpid_mask;
+ if (ver != old) {
+ kvm_update_vmid(vcpu, cpu);
+ kvm_clear_request(KVM_REQ_TLB_FLUSH_GPA, vcpu);
+ }
+
+ vcpu->arch.vmid = vcpu->kvm->arch.vmid[cpu] & vpid_mask;
}
void kvm_check_vpid(struct kvm_vcpu *vcpu)
@@ -400,6 +439,7 @@ static int kvm_loongarch_env_init(void)
for_each_possible_cpu(cpu) {
context = per_cpu_ptr(vmcs, cpu);
context->vpid_cache = vpid_mask + 1;
+ context->vmid_cache = vpid_mask + 1;
context->last_vcpu = NULL;
}
--
2.39.3