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: 209580772
Change-Id: I0390456ffde8ceca351d3d8e82fd1dddeb747fac
Signed-off-by: Marc Zyngier <maz@kernel.org>
Signed-off-by: Quentin Perret <qperret@google.com>
[tabba@:
- use the new pkvm_hyp_* infrastructure
- move pkvm_refill_memcache() up in file to expose it to
handle_pvm_entry_hvc64()
- include asm/stage2_pgtable.h in hypercalls.c for
topup_hyp_memcache()
- fix pkvm_install_ioguard_page() retval to u64, reported in
b/253586500 and fixed in a separate patch before
- fix smccc to return success, reported in b/251426790 and fixed
in a separate patch before
]
Signed-off-by: Fuad Tabba <tabba@google.com>
Signed-off-by: Quentin Perret <qperret@google.com>
This commit is contained in:
Marc Zyngier
2021-06-21 19:49:45 +01:00
committed by Quentin Perret
parent 0e40cc466b
commit 1ac4d8a25d
3 changed files with 63 additions and 10 deletions

View File

@@ -37,6 +37,16 @@ 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);
u64 nr_pages = VTCR_EL2_LVLS(hyp_vm->kvm.arch.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)
@@ -89,6 +99,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:
@@ -267,6 +280,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;
@@ -825,16 +842,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);
u64 nr_pages = VTCR_EL2_LVLS(hyp_vm->kvm.arch.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);

View File

@@ -1317,6 +1317,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;
}
bool smccc_trng_available;
static bool pkvm_forward_trng(struct kvm_vcpu *vcpu)
@@ -1377,7 +1402,24 @@ bool kvm_handle_pvm_hvc64(struct kvm_vcpu *vcpu, u64 *exit_code)
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_MEM_RELINQUISH);
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:
return pkvm_meminfo_call(hyp_vcpu);
case ARM_SMCCC_VENDOR_HYP_KVM_MEM_SHARE_FUNC_ID:

View File

@@ -228,6 +228,10 @@ int kvm_hvc_call_handler(struct kvm_vcpu *vcpu)
pkvm_host_reclaim_page(vcpu->kvm, smccc_get_arg1(vcpu));
val[0] = SMCCC_RET_SUCCESS;
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: