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:
committed by
Carlos Llamas
parent
3ab3693c96
commit
f5ca8b1321
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user