mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 03:40:35 +09:00
BACKPORT: KVM: arm64: Introduce kvm_share_hyp()
The create_hyp_mappings() function can currently be called at any point in time. However, its behaviour in protected mode changes widely depending on when it is being called. Prior to KVM init, it is used to create the temporary page-table used to bring-up the hypervisor, and later on it is transparently turned into a 'share' hypercall when the kernel has lost control over the hypervisor stage-1. In order to prepare the ground for also unsharing pages with the hypervisor during guest teardown, introduce a kvm_share_hyp() function to make it clear in which places a share hypercall should be expected, as we will soon need a matching unshare hypercall in all those places. Signed-off-by: Quentin Perret <qperret@google.com> Signed-off-by: Marc Zyngier <maz@kernel.org> Link: https://lore.kernel.org/r/20211215161232.1480836-7-qperret@google.com (cherry picked from commit3f868e142c) [willdeacon@: Fix conflict in kvm_arch_vcpu_run_map_fp() in same way as upstream merge commit2d761dbf7f("Merge branch kvm-arm64/fpsimd-tracking into kvmarm-master/next")] Signed-off-by: Will Deacon <willdeacon@google.com> Bug: 233587962 Bug: 233588291 Change-Id: Id3ba033a51550e5aada862d6af06773d0be833fb
This commit is contained in:
committed by
Will Deacon
parent
a95e22e27f
commit
9b19221dbb
@@ -150,6 +150,7 @@ static __always_inline unsigned long __kern_hyp_va(unsigned long v)
|
||||
#include <asm/kvm_pgtable.h>
|
||||
#include <asm/stage2_pgtable.h>
|
||||
|
||||
int kvm_share_hyp(void *from, void *to);
|
||||
int create_hyp_mappings(void *from, void *to, enum kvm_pgtable_prot prot);
|
||||
int create_hyp_io_mappings(phys_addr_t phys_addr, size_t size,
|
||||
void __iomem **kaddr,
|
||||
|
||||
@@ -146,7 +146,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = create_hyp_mappings(kvm, kvm + 1, PAGE_HYP);
|
||||
ret = kvm_share_hyp(kvm, kvm + 1);
|
||||
if (ret)
|
||||
goto out_free_stage2_pgd;
|
||||
|
||||
@@ -350,7 +350,7 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return create_hyp_mappings(vcpu, vcpu + 1, PAGE_HYP);
|
||||
return kvm_share_hyp(vcpu, vcpu + 1);
|
||||
}
|
||||
|
||||
void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)
|
||||
|
||||
@@ -30,12 +30,10 @@ int kvm_arch_vcpu_run_map_fp(struct kvm_vcpu *vcpu)
|
||||
struct user_fpsimd_state *fpsimd = ¤t->thread.uw.fpsimd_state;
|
||||
|
||||
/* Make sure the host task fpsimd state is visible to hyp: */
|
||||
ret = create_hyp_mappings(fpsimd, fpsimd + 1, PAGE_HYP);
|
||||
if (ret)
|
||||
goto error;
|
||||
ret = kvm_share_hyp(fpsimd, fpsimd + 1);
|
||||
if (!ret)
|
||||
vcpu->arch.host_fpsimd_state = kern_hyp_va(fpsimd);
|
||||
|
||||
vcpu->arch.host_fpsimd_state = kern_hyp_va(fpsimd);
|
||||
error:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -299,6 +299,25 @@ static int pkvm_share_hyp(phys_addr_t start, phys_addr_t end)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kvm_share_hyp(void *from, void *to)
|
||||
{
|
||||
if (is_kernel_in_hyp_mode())
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* The share hcall maps things in the 'fixed-offset' region of the hyp
|
||||
* VA space, so we can only share physically contiguous data-structures
|
||||
* for now.
|
||||
*/
|
||||
if (is_vmalloc_or_module_addr(from) || is_vmalloc_or_module_addr(to))
|
||||
return -EINVAL;
|
||||
|
||||
if (kvm_host_owns_hyp_mappings())
|
||||
return create_hyp_mappings(from, to, PAGE_HYP);
|
||||
|
||||
return pkvm_share_hyp(__pa(from), __pa(to));
|
||||
}
|
||||
|
||||
/**
|
||||
* create_hyp_mappings - duplicate a kernel virtual address range in Hyp mode
|
||||
* @from: The virtual kernel start address of the range
|
||||
@@ -319,12 +338,8 @@ int create_hyp_mappings(void *from, void *to, enum kvm_pgtable_prot prot)
|
||||
if (is_kernel_in_hyp_mode())
|
||||
return 0;
|
||||
|
||||
if (!kvm_host_owns_hyp_mappings()) {
|
||||
if (WARN_ON(prot != PAGE_HYP))
|
||||
return -EPERM;
|
||||
return pkvm_share_hyp(kvm_kaddr_to_phys(from),
|
||||
kvm_kaddr_to_phys(to));
|
||||
}
|
||||
if (!kvm_host_owns_hyp_mappings())
|
||||
return -EPERM;
|
||||
|
||||
start = start & PAGE_MASK;
|
||||
end = PAGE_ALIGN(end);
|
||||
|
||||
@@ -113,7 +113,7 @@ static int kvm_vcpu_finalize_sve(struct kvm_vcpu *vcpu)
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = create_hyp_mappings(buf, buf + reg_sz, PAGE_HYP);
|
||||
ret = kvm_share_hyp(buf, buf + reg_sz);
|
||||
if (ret) {
|
||||
kfree(buf);
|
||||
return ret;
|
||||
|
||||
Reference in New Issue
Block a user