diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index 93dd0a11f76e..b1ef14d8c57e 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -228,6 +228,9 @@ struct kvm_protected_vcpu { * PSCI_0_2_AFFINITY_LEVEL_PENDING */ int power_state; + + /* True if this vcpu is currently loaded on a cpu. */ + bool loaded_on_cpu; }; struct kvm_vcpu_fault_info { diff --git a/arch/arm64/kvm/hyp/nvhe/pkvm.c b/arch/arm64/kvm/hyp/nvhe/pkvm.c index c77baf1c8347..dd4ad41dc5cc 100644 --- a/arch/arm64/kvm/hyp/nvhe/pkvm.c +++ b/arch/arm64/kvm/hyp/nvhe/pkvm.c @@ -264,6 +264,14 @@ struct kvm_vcpu *get_shadow_vcpu(int shadow_handle, int vcpu_idx) if (!vm || vcpu_idx < 0 || vm->created_vcpus <= vcpu_idx) goto unlock; vcpu = &vm->shadow_vcpus[vcpu_idx].vcpu; + + /* Ensure vcpu isn't loaded on more than one cpu simultaneously. */ + if (unlikely(vcpu->arch.pkvm.loaded_on_cpu)) { + vcpu = NULL; + goto unlock; + } + vcpu->arch.pkvm.loaded_on_cpu = true; + hyp_page_ref_inc(hyp_virt_to_page(vm)); unlock: hyp_spin_unlock(&shadow_lock); @@ -276,6 +284,7 @@ void put_shadow_vcpu(struct kvm_vcpu *vcpu) struct kvm_shadow_vm *vm = vcpu->arch.pkvm.shadow_vm; hyp_spin_lock(&shadow_lock); + vcpu->arch.pkvm.loaded_on_cpu = false; hyp_page_ref_dec(hyp_virt_to_page(vm)); hyp_spin_unlock(&shadow_lock); }