ANDROID: KVM: iommu: Add flags to attach_dev

There is no way to pass device specific information at attach time
(to handle errata or special IOMMU configuration).
Add a new argument to attach hypercalls “flags” which can be passed
from the EL1 to EL2 driver to describe any driver specific information.
It ‘s mandatory for devices supporting pvIOMMU, to reserve the value “0”
as this is not exposed to guests and “0” would be passed.

Bug: 357781595
Change-Id: I81a0b82591a0fe6d952f46025fbd95a82020c14d
Signed-off-by: Mostafa Saleh <smostafa@google.com>
This commit is contained in:
Mostafa Saleh
2025-04-08 10:13:07 +00:00
committed by Carlos Llamas
parent 2ea2a15fa1
commit 87dd5e4d38
8 changed files with 14 additions and 11 deletions

View File

@@ -1767,7 +1767,7 @@ static inline void kvm_iommu_sg_free(struct kvm_iommu_sg *sg, unsigned int nents
#ifndef __KVM_NVHE_HYPERVISOR__
int kvm_iommu_attach_dev(pkvm_handle_t iommu_id, pkvm_handle_t domain_id,
unsigned int endpoint, unsigned int pasid,
unsigned int ssid_bits);
unsigned int ssid_bits, unsigned long flags);
int kvm_iommu_detach_dev(pkvm_handle_t iommu_id, pkvm_handle_t domain_id,
unsigned int endpoint, unsigned int pasid);
int kvm_iommu_alloc_domain(pkvm_handle_t domain_id, int type);

View File

@@ -18,7 +18,8 @@ void kvm_iommu_reclaim_pages_atomic(void *p, u8 order);
int kvm_iommu_alloc_domain(pkvm_handle_t domain_id, int type);
int kvm_iommu_free_domain(pkvm_handle_t domain_id);
int kvm_iommu_attach_dev(pkvm_handle_t iommu_id, pkvm_handle_t domain_id,
u32 endpoint_id, u32 pasid, u32 pasid_bits);
u32 endpoint_id, u32 pasid, u32 pasid_bits,
unsigned long flags);
int kvm_iommu_detach_dev(pkvm_handle_t iommu_id, pkvm_handle_t domain_id,
u32 endpoint_id, u32 pasid);
size_t kvm_iommu_map_pages(pkvm_handle_t domain_id,
@@ -56,7 +57,7 @@ struct kvm_iommu_ops {
void (*free_domain)(struct kvm_hyp_iommu_domain *domain);
struct kvm_hyp_iommu *(*get_iommu_by_id)(pkvm_handle_t iommu_id);
int (*attach_dev)(struct kvm_hyp_iommu *iommu, struct kvm_hyp_iommu_domain *domain,
u32 endpoint_id, u32 pasid, u32 pasid_bits);
u32 endpoint_id, u32 pasid, u32 pasid_bits, unsigned long flags);
int (*detach_dev)(struct kvm_hyp_iommu *iommu, struct kvm_hyp_iommu_domain *domain,
u32 endpoint_id, u32 pasid);
int (*map_pages)(struct kvm_hyp_iommu_domain *domain, unsigned long iova,

View File

@@ -1724,9 +1724,10 @@ static void handle___pkvm_host_iommu_attach_dev(struct kvm_cpu_context *host_ctx
DECLARE_REG(unsigned int, endpoint, host_ctxt, 3);
DECLARE_REG(unsigned int, pasid, host_ctxt, 4);
DECLARE_REG(unsigned int, pasid_bits, host_ctxt, 5);
DECLARE_REG(unsigned long, flags, host_ctxt, 6);
ret = kvm_iommu_attach_dev(iommu, domain, endpoint,
pasid, pasid_bits);
pasid, pasid_bits, flags);
hyp_reqs_smccc_encode(ret, host_ctxt, this_cpu_ptr(&host_hyp_reqs));
}

View File

@@ -387,7 +387,8 @@ int kvm_iommu_force_free_domain(pkvm_handle_t domain_id, struct pkvm_hyp_vm *vm)
}
int kvm_iommu_attach_dev(pkvm_handle_t iommu_id, pkvm_handle_t domain_id,
u32 endpoint_id, u32 pasid, u32 pasid_bits)
u32 endpoint_id, u32 pasid, u32 pasid_bits,
unsigned long flags)
{
int ret;
struct kvm_hyp_iommu *iommu;
@@ -417,7 +418,7 @@ int kvm_iommu_attach_dev(pkvm_handle_t iommu_id, pkvm_handle_t domain_id,
goto out_unlock;
}
ret = kvm_iommu_ops->attach_dev(iommu, domain, endpoint_id, pasid, pasid_bits);
ret = kvm_iommu_ops->attach_dev(iommu, domain, endpoint_id, pasid, pasid_bits, flags);
if (ret)
domain_put(domain);

View File

@@ -86,7 +86,7 @@ static bool pkvm_guest_iommu_attach_dev(struct pkvm_hyp_vcpu *hyp_vcpu, u64 *exi
iommu_id = route.iommu;
sid = route.sid;
ret = kvm_iommu_attach_dev(iommu_id, domain_id, sid, pasid, pasid_bits);
ret = kvm_iommu_attach_dev(iommu_id, domain_id, sid, pasid, pasid_bits, 0);
if (ret == -ENOMEM) {
/*
* The driver will request memory when returning -ENOMEM, so go back to host to

View File

@@ -209,10 +209,10 @@ void kvm_iommu_guest_free_mc(struct kvm_hyp_memcache *mc)
/* Hypercall abstractions exposed to kernel IOMMU drivers */
int kvm_iommu_attach_dev(pkvm_handle_t iommu_id, pkvm_handle_t domain_id,
unsigned int endpoint, unsigned int pasid,
unsigned int ssid_bits)
unsigned int ssid_bits, unsigned long flags)
{
return kvm_call_hyp_nvhe_mc(__pkvm_host_iommu_attach_dev, iommu_id, domain_id,
endpoint, pasid, ssid_bits);
endpoint, pasid, ssid_bits, flags);
}
EXPORT_SYMBOL(kvm_iommu_attach_dev);

View File

@@ -324,7 +324,7 @@ static int kvm_arm_smmu_set_dev_pasid(struct iommu_domain *domain,
int sid = fwspec->ids[i];
ret = kvm_iommu_attach_dev(host_smmu->id, kvm_smmu_domain->id,
sid, pasid, master->ssid_bits);
sid, pasid, master->ssid_bits, 0);
if (ret) {
dev_err(smmu->dev, "cannot attach device %s (0x%x): %d\n",
dev_name(dev), sid, ret);

View File

@@ -1246,7 +1246,7 @@ static int smmu_fix_up_domains(struct hyp_arm_smmu_v3_device *smmu,
}
static int smmu_attach_dev(struct kvm_hyp_iommu *iommu, struct kvm_hyp_iommu_domain *domain,
u32 sid, u32 pasid, u32 pasid_bits)
u32 sid, u32 pasid, u32 pasid_bits, unsigned long flags)
{
int i;
int ret;