ANDROID: KVM: arm64: pkvm: Wire MMIO guard hypercalls
Plumb in the hypercall interface to allow a guest to discover, enroll, map and unmap MMIO regions. Bug: 357781595 Change-Id: I0390456ffde8ceca351d3d8e82fd1dddeb747fac Signed-off-by: Marc Zyngier <maz@kernel.org> Signed-off-by: Fuad Tabba <tabba@google.com>
This commit is contained in:
committed by
Keir Fraser
parent
18eceabfb8
commit
a0923f4678
@@ -30,6 +30,17 @@ DEFINE_PER_CPU(struct kvm_nvhe_init_params, kvm_init_params);
|
||||
|
||||
void __kvm_hyp_host_forward_smc(struct kvm_cpu_context *host_ctxt);
|
||||
|
||||
static int pkvm_refill_memcache(struct pkvm_hyp_vcpu *hyp_vcpu)
|
||||
{
|
||||
struct pkvm_hyp_vm *hyp_vm = pkvm_hyp_vcpu_to_hyp_vm(hyp_vcpu);
|
||||
struct kvm_s2_mmu *mmu = &hyp_vm->kvm.arch.mmu;
|
||||
u64 nr_pages = VTCR_EL2_LVLS(mmu->vtcr) - 1;
|
||||
struct kvm_vcpu *host_vcpu = hyp_vcpu->host_vcpu;
|
||||
|
||||
return refill_memcache(&hyp_vcpu->vcpu.arch.pkvm_memcache, nr_pages,
|
||||
&host_vcpu->arch.pkvm_memcache);
|
||||
}
|
||||
|
||||
typedef void (*hyp_entry_exit_handler_fn)(struct pkvm_hyp_vcpu *);
|
||||
|
||||
static void handle_pvm_entry_wfx(struct pkvm_hyp_vcpu *hyp_vcpu)
|
||||
@@ -82,6 +93,9 @@ static void handle_pvm_entry_hvc64(struct pkvm_hyp_vcpu *hyp_vcpu)
|
||||
u32 fn = smccc_get_function(&hyp_vcpu->vcpu);
|
||||
|
||||
switch (fn) {
|
||||
case ARM_SMCCC_VENDOR_HYP_KVM_MMIO_GUARD_MAP_FUNC_ID:
|
||||
pkvm_refill_memcache(hyp_vcpu);
|
||||
break;
|
||||
case ARM_SMCCC_VENDOR_HYP_KVM_MEM_SHARE_FUNC_ID:
|
||||
fallthrough;
|
||||
case ARM_SMCCC_VENDOR_HYP_KVM_MEM_UNSHARE_FUNC_ID:
|
||||
@@ -256,6 +270,10 @@ static void handle_pvm_exit_hvc64(struct pkvm_hyp_vcpu *hyp_vcpu)
|
||||
n = 4;
|
||||
break;
|
||||
|
||||
case ARM_SMCCC_VENDOR_HYP_KVM_MMIO_GUARD_MAP_FUNC_ID:
|
||||
n = 3;
|
||||
break;
|
||||
|
||||
case PSCI_1_1_FN_SYSTEM_RESET2:
|
||||
case PSCI_1_1_FN64_SYSTEM_RESET2:
|
||||
n = 3;
|
||||
@@ -893,17 +911,6 @@ out:
|
||||
cpu_reg(host_ctxt, 1) = ret;
|
||||
}
|
||||
|
||||
static int pkvm_refill_memcache(struct pkvm_hyp_vcpu *hyp_vcpu)
|
||||
{
|
||||
struct pkvm_hyp_vm *hyp_vm = pkvm_hyp_vcpu_to_hyp_vm(hyp_vcpu);
|
||||
struct kvm_s2_mmu *mmu = &hyp_vm->kvm.arch.mmu;
|
||||
u64 nr_pages = VTCR_EL2_LVLS(mmu->vtcr) - 1;
|
||||
struct kvm_vcpu *host_vcpu = hyp_vcpu->host_vcpu;
|
||||
|
||||
return refill_memcache(&hyp_vcpu->vcpu.arch.pkvm_memcache, nr_pages,
|
||||
&host_vcpu->arch.pkvm_memcache);
|
||||
}
|
||||
|
||||
static void handle___pkvm_host_map_guest(struct kvm_cpu_context *host_ctxt)
|
||||
{
|
||||
DECLARE_REG(u64, pfn, host_ctxt, 1);
|
||||
|
||||
@@ -1374,6 +1374,31 @@ out_guest_err:
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool pkvm_install_ioguard_page(struct pkvm_hyp_vcpu *hyp_vcpu, u64 *exit_code)
|
||||
{
|
||||
u64 retval = SMCCC_RET_SUCCESS;
|
||||
u64 ipa = smccc_get_arg1(&hyp_vcpu->vcpu);
|
||||
int ret;
|
||||
|
||||
ret = __pkvm_install_ioguard_page(hyp_vcpu, ipa);
|
||||
if (ret == -ENOMEM) {
|
||||
/*
|
||||
* We ran out of memcache, let's ask for more. Cancel
|
||||
* the effects of the HVC that took us here, and
|
||||
* forward the hypercall to the host for page donation
|
||||
* purposes.
|
||||
*/
|
||||
write_sysreg_el2(read_sysreg_el2(SYS_ELR) - 4, SYS_ELR);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ret)
|
||||
retval = SMCCC_RET_INVALID_PARAMETER;
|
||||
|
||||
smccc_set_retval(&hyp_vcpu->vcpu, retval, 0, 0, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handler for protected VM HVC calls.
|
||||
*
|
||||
@@ -1404,7 +1429,24 @@ bool kvm_handle_pvm_hvc64(struct kvm_vcpu *vcpu, u64 *exit_code)
|
||||
val[0] |= BIT(ARM_SMCCC_KVM_FUNC_HYP_MEMINFO);
|
||||
val[0] |= BIT(ARM_SMCCC_KVM_FUNC_MEM_SHARE);
|
||||
val[0] |= BIT(ARM_SMCCC_KVM_FUNC_MEM_UNSHARE);
|
||||
val[0] |= BIT(ARM_SMCCC_KVM_FUNC_MMIO_GUARD_INFO);
|
||||
val[0] |= BIT(ARM_SMCCC_KVM_FUNC_MMIO_GUARD_ENROLL);
|
||||
val[0] |= BIT(ARM_SMCCC_KVM_FUNC_MMIO_GUARD_MAP);
|
||||
val[0] |= BIT(ARM_SMCCC_KVM_FUNC_MMIO_GUARD_UNMAP);
|
||||
break;
|
||||
case ARM_SMCCC_VENDOR_HYP_KVM_MMIO_GUARD_ENROLL_FUNC_ID:
|
||||
set_bit(KVM_ARCH_FLAG_MMIO_GUARD, &vcpu->kvm->arch.flags);
|
||||
val[0] = SMCCC_RET_SUCCESS;
|
||||
break;
|
||||
case ARM_SMCCC_VENDOR_HYP_KVM_MMIO_GUARD_MAP_FUNC_ID:
|
||||
return pkvm_install_ioguard_page(hyp_vcpu, exit_code);
|
||||
case ARM_SMCCC_VENDOR_HYP_KVM_MMIO_GUARD_UNMAP_FUNC_ID:
|
||||
if (__pkvm_remove_ioguard_page(hyp_vcpu, vcpu_get_reg(vcpu, 1)))
|
||||
val[0] = SMCCC_RET_INVALID_PARAMETER;
|
||||
else
|
||||
val[0] = SMCCC_RET_SUCCESS;
|
||||
break;
|
||||
case ARM_SMCCC_VENDOR_HYP_KVM_MMIO_GUARD_INFO_FUNC_ID:
|
||||
case ARM_SMCCC_VENDOR_HYP_KVM_HYP_MEMINFO_FUNC_ID:
|
||||
if (smccc_get_arg1(vcpu) ||
|
||||
smccc_get_arg2(vcpu) ||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <linux/kvm_host.h>
|
||||
|
||||
#include <asm/kvm_emulate.h>
|
||||
#include <asm/stage2_pgtable.h>
|
||||
|
||||
#include <kvm/arm_hypercalls.h>
|
||||
#include <kvm/arm_psci.h>
|
||||
@@ -75,6 +76,7 @@ static bool kvm_smccc_default_allowed(u32 func_id)
|
||||
*/
|
||||
case ARM_SMCCC_VERSION_FUNC_ID:
|
||||
case ARM_SMCCC_ARCH_FEATURES_FUNC_ID:
|
||||
case ARM_SMCCC_VENDOR_HYP_KVM_MMIO_GUARD_MAP_FUNC_ID:
|
||||
return true;
|
||||
default:
|
||||
/* PSCI 0.2 and up is in the 0:0x1f range */
|
||||
@@ -364,6 +366,10 @@ int kvm_smccc_call_handler(struct kvm_vcpu *vcpu)
|
||||
case ARM_SMCCC_VENDOR_HYP_KVM_PTP_FUNC_ID:
|
||||
kvm_ptp_get_time(vcpu, val);
|
||||
break;
|
||||
case ARM_SMCCC_VENDOR_HYP_KVM_MMIO_GUARD_MAP_FUNC_ID:
|
||||
if (kvm_vm_is_protected(vcpu->kvm) && !topup_hyp_memcache(vcpu))
|
||||
val[0] = SMCCC_RET_SUCCESS;
|
||||
break;
|
||||
case ARM_SMCCC_TRNG_VERSION:
|
||||
case ARM_SMCCC_TRNG_FEATURES:
|
||||
case ARM_SMCCC_TRNG_GET_UUID:
|
||||
|
||||
Reference in New Issue
Block a user