ANDROID: KVM: arm64: Add request_dma guest HVC

Add request_dma HVC which returns 128 bit token to authenticate a
pvIOMMU and vsid pair.

Bug: 357781595
Bug: 348382247
Bug: 236685427
Change-Id: If032cf3e14653c0114aec3595902d09d6b3fded2
Signed-off-by: Mostafa Saleh <smostafa@google.com>
This commit is contained in:
Mostafa Saleh
2023-11-21 16:41:00 +00:00
committed by Carlos Llamas
parent 3ab3693c96
commit f5ca8b1321
7 changed files with 84 additions and 1 deletions
+2
View File
@@ -48,6 +48,7 @@ int kvm_iommu_snapshot_host_stage2(struct kvm_hyp_iommu_domain *domain);
int kvm_iommu_dev_block_dma(pkvm_handle_t iommu_id, u32 endpoint_id, bool host_to_guest);
int kvm_iommu_force_free_domain(pkvm_handle_t domain_id, struct pkvm_hyp_vm *vm);
int kvm_iommu_id_to_token(pkvm_handle_t smmu_id, u64 *out_token);
struct kvm_iommu_ops {
int (*init)(void);
@@ -75,6 +76,7 @@ struct kvm_iommu_ops {
int (*resume)(struct kvm_hyp_iommu *iommu);
int (*dev_block_dma)(struct kvm_hyp_iommu *iommu, u32 endpoint_id,
bool is_host_to_guest);
int (*get_iommu_token_by_id)(pkvm_handle_t smmu_id, u64 *out_token);
ANDROID_KABI_RESERVE(1);
ANDROID_KABI_RESERVE(2);
ANDROID_KABI_RESERVE(3);
+1
View File
@@ -184,6 +184,7 @@ 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);
bool pkvm_device_request_dma(struct pkvm_hyp_vcpu *hyp_vcpu, u64 *exit_code);
void pkvm_devices_teardown(struct pkvm_hyp_vm *vm);
int pkvm_devices_get_context(u64 iommu_id, u32 endpoint_id, struct pkvm_hyp_vm *vm);
void pkvm_devices_put_context(u64 iommu_id, u32 endpoint_id);
+54
View File
@@ -8,6 +8,7 @@
#include <nvhe/mem_protect.h>
#include <nvhe/mm.h>
#include <nvhe/pkvm.h>
#include <nvhe/pviommu-host.h>
#include <kvm/arm_hypercalls.h>
#include <kvm/device.h>
@@ -419,3 +420,56 @@ int pkvm_device_register_reset(u64 phys, void *cookie,
return ret;
}
bool pkvm_device_request_dma(struct pkvm_hyp_vcpu *hyp_vcpu, u64 *exit_code)
{
int ret;
struct pkvm_hyp_vm *vm = pkvm_hyp_vcpu_to_hyp_vm(hyp_vcpu);
struct kvm_vcpu *vcpu = &hyp_vcpu->vcpu;
u64 pviommu = smccc_get_arg1(vcpu);
u64 vsid = smccc_get_arg2(vcpu);
u64 token1, token2;
struct pviommu_route route;
struct pkvm_device *dev;
if (smccc_get_arg3(vcpu) || smccc_get_arg4(vcpu) || smccc_get_arg5(vcpu) ||
smccc_get_arg6(vcpu))
goto out_ret;
ret = pkvm_pviommu_get_route(vm, pviommu, vsid, &route);
if (ret)
goto out_ret;
token2 = route.sid;
/*
* route.iommu is the host-hyp iommu ID that has no meaning for guest.
* It needs to be converted to IOMMU token as in the firmware(usually
* base MMIO address).
*/
ret = kvm_iommu_id_to_token(route.iommu, &token1);
if (ret)
goto out_ret;
dev = pkvm_get_device_by_iommu(route.iommu, route.sid);
if (!dev)
goto out_ret;
hyp_spin_lock(&device_spinlock);
if (dev->ctxt == NULL) {
/*
* First time device is assigned to guest, make sure it's resources
* have been donated.
*/
ret = __pkvm_group_assign(dev->group_id, vm);
} else if (dev->ctxt != vm) {
ret = -EPERM;
}
hyp_spin_unlock(&device_spinlock);
if (ret)
goto out_ret;
smccc_set_retval(vcpu, SMCCC_RET_SUCCESS, token1, token2, 0);
return true;
out_ret:
smccc_set_retval(vcpu, SMCCC_RET_INVALID_PARAMETER, 0, 0, 0);
return true;
}
+7
View File
@@ -778,3 +778,10 @@ int kvm_iommu_snapshot_host_stage2(struct kvm_hyp_iommu_domain *domain)
return ret;
}
int kvm_iommu_id_to_token(pkvm_handle_t id, u64 *out_token)
{
if (!kvm_iommu_ops || !kvm_iommu_ops->get_iommu_token_by_id)
return -ENODEV;
return kvm_iommu_ops->get_iommu_token_by_id(id, out_token);
}
+2
View File
@@ -1759,6 +1759,8 @@ bool kvm_handle_pvm_hvc64(struct kvm_vcpu *vcpu, u64 *exit_code)
return kvm_handle_pviommu_hvc(vcpu, exit_code);
case ARM_SMCCC_VENDOR_HYP_KVM_DEV_REQ_MMIO_FUNC_ID:
return pkvm_device_request_mmio(hyp_vcpu, exit_code);
case ARM_SMCCC_VENDOR_HYP_KVM_DEV_REQ_DMA_FUNC_ID:
return pkvm_device_request_dma(hyp_vcpu, exit_code);
default:
if (is_ffa_call(fn))
return kvm_guest_ffa_handler(hyp_vcpu, exit_code);
@@ -1546,6 +1546,16 @@ static bool smmu_dabt_device(struct hyp_arm_smmu_v3_device *smmu,
return true;
}
static int smmu_id_to_token(pkvm_handle_t smmu_id, u64 *out_token)
{
if (smmu_id >= kvm_hyp_arm_smmu_v3_count)
return -EINVAL;
smmu_id = array_index_nospec(smmu_id, kvm_hyp_arm_smmu_v3_count);
*out_token = kvm_hyp_arm_smmu_v3_smmus[smmu_id].mmio_addr;
return 0;
}
static int smmu_dev_block_dma(struct kvm_hyp_iommu *iommu, u32 sid, bool is_host2guest)
{
struct hyp_arm_smmu_v3_device *smmu = to_smmu(iommu);
@@ -1730,4 +1740,5 @@ struct kvm_iommu_ops smmu_ops = {
.resume = smmu_resume,
.host_stage2_idmap = smmu_host_stage2_idmap,
.dev_block_dma = smmu_dev_block_dma,
.get_iommu_token_by_id = smmu_id_to_token,
};
+7 -1
View File
@@ -182,7 +182,7 @@
#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_58 58
#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_59 59
#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_60 60
#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_61 61
#define ARM_SMCCC_KVM_FUNC_DEV_REQ_DMA 61
#define ARM_SMCCC_KVM_FUNC_PVIOMMU_OP 62
#define ARM_SMCCC_KVM_FUNC_DEV_REQ_MMIO 63
/* End of pKVM hypercall range */
@@ -253,6 +253,12 @@
ARM_SMCCC_OWNER_VENDOR_HYP, \
ARM_SMCCC_KVM_FUNC_DEV_REQ_MMIO)
#define ARM_SMCCC_VENDOR_HYP_KVM_DEV_REQ_DMA_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_DMA)
/* ptp_kvm counter type ID */
#define KVM_PTP_VIRT_COUNTER 0
#define KVM_PTP_PHYS_COUNTER 1