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 <will@kernel.org>
Bug: 209580772
Change-Id: I3e0ec8907f46b17d74623b84a029a5b50aeaf14f
Signed-off-by: Will Deacon <willdeacon@google.com>
This commit is contained in:
Will Deacon
2021-12-09 13:04:18 +00:00
committed by Will Deacon
parent c144439fa9
commit 003b19bae8
4 changed files with 13 additions and 16 deletions

View File

@@ -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;
};

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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;
}