ANDROID: KVM: arm64: devices: Add request_mmio guest HVC

request_mmio is a guest HVC that is used to authenticate a device
MMIO resource, it returns a unique token, that can be used by the
guest.

Bug: 357781595
Bug: 348382247
Change-Id: I87d67ce9c14578702dda1b157411fdc622327286
Signed-off-by: Mostafa Saleh <smostafa@google.com>
This commit is contained in:
Mostafa Saleh
2023-11-10 13:45:51 +00:00
committed by Treehugger Robot
parent e0a0783241
commit 774b9063c8
6 changed files with 94 additions and 1 deletions
@@ -74,6 +74,8 @@ u64 __pkvm_ptdump_walk_range(pkvm_handle_t handle, struct pkvm_ptdump_log_hdr *l
int hyp_check_range_owned(u64 addr, u64 size);
int __pkvm_install_guest_mmio(struct pkvm_hyp_vcpu *hyp_vcpu, u64 pfn, u64 gfn);
int __pkvm_guest_get_valid_phys_page(struct pkvm_hyp_vm *vm, u64 *phys, u64 ipa);
bool addr_is_memory(phys_addr_t phys);
int host_stage2_idmap_locked(phys_addr_t addr, u64 size,
enum kvm_pgtable_prot prot,
+2
View File
@@ -162,6 +162,8 @@ int pkvm_host_hvc_pd(u64 device_id, u64 on);
int pkvm_init_scmi_pd(struct kvm_power_domain *pd,
const struct kvm_power_domain_ops *ops);
bool pkvm_device_request_mmio(struct pkvm_hyp_vcpu *hyp_vcpu, u64 *exit_code);
/*
* Register a power domain. When the hypervisor catches power requests from the
* host for this power domain, it calls the power ops with @pd as argument.
+68
View File
@@ -7,6 +7,7 @@
#include <nvhe/mm.h>
#include <nvhe/pkvm.h>
#include <kvm/arm_hypercalls.h>
#include <kvm/device.h>
struct pkvm_device *registered_devices;
@@ -234,3 +235,70 @@ out_ret:
hyp_spin_unlock(&device_spinlock);
return ret;
}
static int pkvm_get_device_pa(struct pkvm_hyp_vcpu *hyp_vcpu, u64 ipa, u64 *pa, u64 *exit_code)
{
struct kvm_hyp_req *req;
int ret;
struct pkvm_hyp_vm *vm = pkvm_hyp_vcpu_to_hyp_vm(hyp_vcpu);
ret = __pkvm_guest_get_valid_phys_page(vm, pa, ipa);
if (ret == -ENOENT) {
/* Page not mapped, create a request*/
req = pkvm_hyp_req_reserve(hyp_vcpu, KVM_HYP_REQ_TYPE_MAP);
if (!req)
return -ENOMEM;
req->map.guest_ipa = ipa;
req->map.size = PAGE_SIZE;
*exit_code = ARM_EXCEPTION_HYP_REQ;
/* Repeat next time. */
write_sysreg_el2(read_sysreg_el2(SYS_ELR) - 4, SYS_ELR);
}
return ret;
}
bool pkvm_device_request_mmio(struct pkvm_hyp_vcpu *hyp_vcpu, u64 *exit_code)
{
int i, j, ret;
struct kvm_vcpu *vcpu = &hyp_vcpu->vcpu;
struct pkvm_hyp_vm *vm = pkvm_hyp_vcpu_to_hyp_vm(hyp_vcpu);
u64 ipa = smccc_get_arg1(vcpu);
u64 token;
/* arg2 and arg3 reserved for future use. */
if (smccc_get_arg2(vcpu) || smccc_get_arg3(vcpu) || !PAGE_ALIGNED(ipa))
goto out_inval;
ret = pkvm_get_device_pa(hyp_vcpu, ipa, &token, exit_code);
if (ret == -ENOENT)
return false;
else if (ret)
goto out_inval;
hyp_spin_lock(&device_spinlock);
for (i = 0 ; i < registered_devices_nr ; ++i) {
struct pkvm_device *dev = &registered_devices[i];
if (dev->ctxt != vm)
continue;
for (j = 0 ; j < dev->nr_resources; ++j) {
struct pkvm_dev_resource *res = &dev->resources[j];
if ((token >= res->base) && (token + PAGE_SIZE <= res->base + res->size)) {
smccc_set_retval(vcpu, SMCCC_RET_SUCCESS, token, 0, 0);
goto out_ret;
}
}
}
smccc_set_retval(vcpu, SMCCC_RET_INVALID_PARAMETER, 0, 0, 0);
out_ret:
hyp_spin_unlock(&device_spinlock);
return true;
out_inval:
smccc_set_retval(vcpu, SMCCC_RET_INVALID_PARAMETER, 0, 0, 0);
return true;
}
+12
View File
@@ -1837,6 +1837,18 @@ static int guest_get_valid_pte(struct pkvm_hyp_vm *vm, u64 *phys, u64 ipa, u8 or
return 0;
}
int __pkvm_guest_get_valid_phys_page(struct pkvm_hyp_vm *vm, u64 *phys, u64 ipa)
{
kvm_pte_t pte;
int ret;
guest_lock_component(vm);
ret = guest_get_valid_pte(vm, phys, ipa, 0, &pte);
guest_unlock_component(vm);
return ret;
}
/*
* Ideally we would like to use check_unshare()... but this wouldn't let us
* restrict the unshare range to the actual guest stage-2 mapping.
+3
View File
@@ -9,6 +9,7 @@
#include <kvm/arm_hypercalls.h>
#include <kvm/arm_psci.h>
#include <kvm/device.h>
#include <asm/kvm_emulate.h>
@@ -1659,6 +1660,8 @@ bool kvm_handle_pvm_hvc64(struct kvm_vcpu *vcpu, u64 *exit_code)
if (smccc_trng_available)
return pkvm_forward_trng(vcpu);
break;
case ARM_SMCCC_VENDOR_HYP_KVM_DEV_REQ_MMIO_FUNC_ID:
return pkvm_device_request_mmio(hyp_vcpu, exit_code);
default:
return pkvm_handle_psci(hyp_vcpu);
}
+7 -1
View File
@@ -177,7 +177,7 @@
#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_60 60
#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_61 61
#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_62 62
#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_63 63
#define ARM_SMCCC_KVM_FUNC_DEV_REQ_MMIO 63
/* End of pKVM hypercall range */
#define ARM_SMCCC_KVM_FUNC_FEATURES_2 127
#define ARM_SMCCC_KVM_NUM_FUNCS 128
@@ -227,6 +227,12 @@
ARM_SMCCC_OWNER_VENDOR_HYP, \
ARM_SMCCC_KVM_FUNC_MEM_RELINQUISH)
#define ARM_SMCCC_VENDOR_HYP_KVM_DEV_REQ_MMIO_FUNC_ID \
ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
ARM_SMCCC_SMC_64, \
ARM_SMCCC_OWNER_VENDOR_HYP, \
ARM_SMCCC_KVM_FUNC_DEV_REQ_MMIO)
/* ptp_kvm counter type ID */
#define KVM_PTP_VIRT_COUNTER 0
#define KVM_PTP_PHYS_COUNTER 1