From 003b19bae85ac1805d7cf6c67b40bb1b16a00f1f Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Thu, 9 Dec 2021 13:04:18 +0000 Subject: [PATCH] ANDROID: KVM: arm64: Create EL2 shadow for VMs when pKVM is enabled Regardless of whether a given VM is protected or unprotected, when pKVM is enabled we must create an EL2 shadow for each VM so that the stage-2 page-tables are managed by the hypervisor instead of the host. Create the EL2 shadow for a VM on the first-run of a vCPU when a shadow is not already present. Signed-off-by: Will Deacon Bug: 209580772 Change-Id: I3e0ec8907f46b17d74623b84a029a5b50aeaf14f Signed-off-by: Will Deacon --- arch/arm64/include/asm/kvm_host.h | 1 + arch/arm64/include/asm/kvm_pkvm.h | 2 ++ arch/arm64/kvm/arm.c | 3 +++ arch/arm64/kvm/pkvm.c | 23 +++++++---------------- 4 files changed, 13 insertions(+), 16 deletions(-) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index 1499c2d54a87..c17aee87de91 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -164,6 +164,7 @@ struct kvm_pinned_page { struct kvm_protected_vm { bool enabled; int shadow_handle; + struct mutex shadow_lock; struct kvm_hyp_memcache teardown_mc; struct list_head pinned_pages; }; diff --git a/arch/arm64/include/asm/kvm_pkvm.h b/arch/arm64/include/asm/kvm_pkvm.h index efb54331fd6f..f96f8fa7059e 100644 --- a/arch/arm64/include/asm/kvm_pkvm.h +++ b/arch/arm64/include/asm/kvm_pkvm.h @@ -16,6 +16,8 @@ #define HYP_MEMBLOCK_REGIONS 128 +int create_el2_shadow(struct kvm *kvm); + /* * Definitions for features to be allowed or restricted for guest virtual * machines, depending on the mode KVM is running in and on the type of guest diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c index 97b40bd1d429..4ed14cf9ad13 100644 --- a/arch/arm64/kvm/arm.c +++ b/arch/arm64/kvm/arm.c @@ -774,6 +774,9 @@ int kvm_arch_vcpu_run_pid_change(struct kvm_vcpu *vcpu) static_branch_inc(&userspace_irqchip_in_use); } + if (is_protected_kvm_enabled()) + ret = create_el2_shadow(kvm); + return ret; } diff --git a/arch/arm64/kvm/pkvm.c b/arch/arm64/kvm/pkvm.c index 90d4a15e9cd9..431b85575dc0 100644 --- a/arch/arm64/kvm/pkvm.c +++ b/arch/arm64/kvm/pkvm.c @@ -118,16 +118,13 @@ static void update_vcpu_state(struct kvm_vcpu *vcpu, int shadow_handle) * * Return 0 on success, negative error code on failure. */ -static int create_el2_shadow(struct kvm *kvm) +static int __create_el2_shadow(struct kvm *kvm) { size_t pgd_sz, shadow_sz; void *pgd, *shadow_addr; int shadow_handle; int ret, i; - if (kvm->arch.pkvm.shadow_handle) - return -EEXIST; - if (kvm->created_vcpus < 1) return -EINVAL; @@ -174,20 +171,14 @@ free_pgd: return ret; } -int pkvm_init_el2_context(struct kvm *kvm) +int create_el2_shadow(struct kvm *kvm) { int ret = 0; - mutex_lock(&kvm->lock); - ret = create_el2_shadow(kvm); - mutex_unlock(&kvm->lock); + mutex_lock(&kvm->arch.pkvm.shadow_lock); + if (!kvm->arch.pkvm.shadow_handle) + ret = __create_el2_shadow(kvm); + mutex_unlock(&kvm->arch.pkvm.shadow_lock); - if (ret < 0) { - kvm_err("Creating shadow structures for protected VM failed: %d\n", - ret); - return ret; - } - - kvm_pr_unimpl("Stage-2 protection is a work-in-progress: civilization phase III\n"); - return 0; + return ret; }