diff --git a/arch/arm64/kvm/hyp/nvhe/pkvm.c b/arch/arm64/kvm/hyp/nvhe/pkvm.c index 34fc9039110f..1f4d38d67dec 100644 --- a/arch/arm64/kvm/hyp/nvhe/pkvm.c +++ b/arch/arm64/kvm/hyp/nvhe/pkvm.c @@ -312,10 +312,21 @@ static void copy_features(struct kvm_vcpu *shadow_vcpu, struct kvm_vcpu *host_vc allowed_features, KVM_VCPU_MAX_FEATURES); } -static void init_shadow_structs(struct kvm *kvm, struct kvm_shadow_vm *vm, int nr_vcpus) +static void unpin_host_vcpus(struct kvm_shadow_vm *vm) { int i; + for (i = 0; i < vm->created_vcpus; i++) { + struct kvm_vcpu *vcpu = vm->vcpus[i]->arch.pkvm.host_vcpu; + hyp_unpin_shared_mem(vcpu, vcpu + 1); + } +} + +static int init_shadow_structs(struct kvm *kvm, struct kvm_shadow_vm *vm, int nr_vcpus) +{ + int i; + int ret; + /* TODO: initialize the protected MMU. For now, use the host's. */ vm->mmu = &kvm->arch.mmu; vm->host_kvm = kvm; @@ -326,6 +337,12 @@ static void init_shadow_structs(struct kvm *kvm, struct kvm_shadow_vm *vm, int n struct shadow_vcpu_state *shadow_state = &vm->shadow_vcpus[i]; struct kvm_vcpu *shadow_vcpu = &shadow_state->vcpu; + ret = hyp_pin_shared_mem(host_vcpu, host_vcpu + 1); + if (ret) + return -EBUSY; + + vm->created_vcpus++; + shadow_vcpu->kvm = kvm; shadow_vcpu->vcpu_id = host_vcpu->vcpu_id; shadow_vcpu->vcpu_idx = i; @@ -347,9 +364,9 @@ static void init_shadow_structs(struct kvm *kvm, struct kvm_shadow_vm *vm, int n shadow_vcpu->arch.pkvm.shadow_handle = vm->shadow_handle; shadow_vcpu->arch.pkvm.host_vcpu = host_vcpu; shadow_vcpu->arch.pkvm.shadow_vm = vm; - - vm->created_vcpus++; } + + return 0; } static bool exists_shadow(struct kvm *host_kvm) @@ -486,6 +503,10 @@ int __pkvm_init_shadow(struct kvm *kvm, kvm = kern_hyp_va(kvm); + ret = hyp_pin_shared_mem(kvm, kvm + 1); + if (ret) + return ret; + /* Ensure the host has donated enough memory for the shadow structs. */ nr_vcpus = kvm->created_vcpus; ret = check_shadow_size(nr_vcpus, shadow_size); @@ -504,16 +525,20 @@ int __pkvm_init_shadow(struct kvm *kvm, if (ret < 0) goto err_clear_shadow; - init_shadow_structs(kvm, vm, nr_vcpus); + ret = init_shadow_structs(kvm, vm, nr_vcpus); + if (ret < 0) + goto err_clear_shadow; return vm->shadow_handle; err_clear_shadow: + unpin_host_vcpus(vm); /* Clear the donated shadow memory on failure to avoid data leaks. */ memset(vm, 0, shadow_size); WARN_ON(__pkvm_hyp_donate_host(pfn, nr_pages)); err: + hyp_unpin_shared_mem(kvm, kvm + 1); return ret; } @@ -536,6 +561,8 @@ int __pkvm_teardown_shadow(struct kvm *kvm) shadow_size = vm->shadow_area_size; + unpin_host_vcpus(vm); + hyp_unpin_shared_mem(vm->host_kvm, vm->host_kvm + 1); remove_shadow_table(shadow_handle); /* Clear the shadow memory since hyp is releasing it back to host. */