ANDROID: KVM: arm64: iommu: Add new ops iotlb_sync_map()

Some IOMMU drivers might want to implement the iommu_ops
iotlb_sync_map() in the hypervisor. Add a new hypercall
and a hypervisor ops for that.

Bug: 431432127
Change-Id: Ic4ed322b6288ecc421865aaeb3b5e2878e294962
Signed-off-by: Mostafa Saleh <smostafa@google.com>
This commit is contained in:
Mostafa Saleh
2025-07-14 09:05:30 +00:00
parent e9aa22409a
commit 8dd7c74e66
6 changed files with 80 additions and 2 deletions

View File

@@ -22743,6 +22743,11 @@ pointer_reference {
kind: POINTER
pointee_type_id: 0x977bcf07
}
pointer_reference {
id: 0x2f4f676a
kind: POINTER
pointee_type_id: 0x977d7b37
}
pointer_reference {
id: 0x2f4f9f95
kind: POINTER
@@ -43798,6 +43803,11 @@ member {
id: 0x3a3e9211
type_id: 0x67d43857
}
member {
id: 0x3a6f0eb6
type_id: 0x66926050
offset: 896
}
member {
id: 0x3a7ed482
type_id: 0x66d53bfd
@@ -116148,6 +116158,11 @@ member {
type_id: 0x0c55d62d
offset: 512
}
member {
id: 0xc185c03f
name: "iotlb_sync_map"
type_id: 0x2f4f676a
}
member {
id: 0xc1a6eb7e
name: "iotlb_sync_map"
@@ -227172,6 +227187,16 @@ struct_union {
member_id: 0x082b1975
}
}
struct_union {
id: 0x66926050
kind: UNION
definition {
bytesize: 8
member_id: 0xc185c03f
member_id: 0x27000c61
member_id: 0x36752b74
}
}
struct_union {
id: 0x66d53bfd
kind: UNION
@@ -253676,7 +253701,7 @@ struct_union {
member_id: 0xa60fc2c2
member_id: 0xd12a0a5e
member_id: 0x80f5a8ec
member_id: 0x2d081f94
member_id: 0x3a6f0eb6
member_id: 0x63760151
member_id: 0xac894e49
member_id: 0xe0f6393d
@@ -333806,6 +333831,13 @@ function {
parameter_id: 0x2bc93f35
parameter_id: 0x0258f96e
}
function {
id: 0x977d7b37
return_type_id: 0x6720d32f
parameter_id: 0x28350343
parameter_id: 0x33756485
parameter_id: 0xf435685e
}
function {
id: 0x977e98cb
return_type_id: 0x6720d32f

View File

@@ -213,3 +213,7 @@ type 'struct scm_stat' changed
type 'struct scm_fp_list' changed
member 'bool dead' was added
type 'struct kvm_iommu_ops' changed
member 'u64 android_kabi_reserved1' was removed
member 'union { int(* iotlb_sync_map)(struct kvm_hyp_iommu_domain*, unsigned long, size_t); struct { u64 android_kabi_reserved1; }; union { }; }' was added

View File

@@ -115,6 +115,7 @@ enum __kvm_host_smccc_func {
__KVM_HOST_SMCCC_FUNC___pkvm_host_iommu_iova_to_phys,
__KVM_HOST_SMCCC_FUNC___pkvm_host_hvc_pd,
__KVM_HOST_SMCCC_FUNC___pkvm_stage2_snapshot,
__KVM_HOST_SMCCC_FUNC___pkvm_host_iommu_iotlb_sync_map,
/*
* Start of the dynamically registered hypercalls. Start a bit

View File

@@ -54,6 +54,8 @@ void kvm_iommu_iotlb_gather_add_page(struct kvm_hyp_iommu_domain *domain,
void kvm_iommu_host_stage2_idmap(phys_addr_t start, phys_addr_t end,
enum kvm_pgtable_prot prot);
int kvm_iommu_snapshot_host_stage2(struct kvm_hyp_iommu_domain *domain);
int kvm_iommu_iotlb_sync_map(pkvm_handle_t domain_id,
unsigned long iova, size_t size);
#define KVM_IOMMU_PADDR_CACHE_MAX ((size_t)511)
/**
@@ -112,6 +114,7 @@ static inline void kvm_iommu_unlock(struct kvm_hyp_iommu *iommu)
* @map_pages: Map pages in a domain.
* @unmap_pages: Unmap pages from a domain.
* @iova_to_phys: get physical address from IOVA in a domain.
* @iotlb_sync_map: Sync mapping created using @map_pages to the hardware.
*/
struct kvm_iommu_ops {
int (*init)(unsigned long arg);
@@ -138,7 +141,8 @@ struct kvm_iommu_ops {
struct iommu_iotlb_gather *gather,
struct kvm_iommu_paddr_cache *cache);
phys_addr_t (*iova_to_phys)(struct kvm_hyp_iommu_domain *domain, unsigned long iova);
ANDROID_KABI_RESERVE(1);
ANDROID_KABI_USE(1, int (*iotlb_sync_map)(struct kvm_hyp_iommu_domain *domain,
unsigned long iova, size_t size));
ANDROID_KABI_RESERVE(2);
ANDROID_KABI_RESERVE(3);
ANDROID_KABI_RESERVE(4);

View File

@@ -1574,6 +1574,17 @@ static void handle___pkvm_host_iommu_iova_to_phys(struct kvm_cpu_context *host_c
hyp_reqs_smccc_encode(ret, host_ctxt, this_cpu_ptr(&host_hyp_reqs));
}
static void handle___pkvm_host_iommu_iotlb_sync_map(struct kvm_cpu_context *host_ctxt)
{
unsigned long ret;
DECLARE_REG(pkvm_handle_t, domain, host_ctxt, 1);
DECLARE_REG(unsigned long, iova, host_ctxt, 2);
DECLARE_REG(size_t, size, host_ctxt, 3);
ret = kvm_iommu_iotlb_sync_map(domain, iova, size);
hyp_reqs_smccc_encode(ret, host_ctxt, this_cpu_ptr(&host_hyp_reqs));
}
static void handle___pkvm_iommu_init(struct kvm_cpu_context *host_ctxt)
{
DECLARE_REG(struct kvm_iommu_ops *, ops, host_ctxt, 1);
@@ -1671,6 +1682,7 @@ static const hcall_t host_hcall[] = {
HANDLE_FUNC(__pkvm_host_iommu_iova_to_phys),
HANDLE_FUNC(__pkvm_host_hvc_pd),
HANDLE_FUNC(__pkvm_stage2_snapshot),
HANDLE_FUNC(__pkvm_host_iommu_iotlb_sync_map),
};
static void handle_host_hcall(struct kvm_cpu_context *host_ctxt)

View File

@@ -825,3 +825,28 @@ int kvm_iommu_snapshot_host_stage2(struct kvm_hyp_iommu_domain *domain)
return ret;
}
int kvm_iommu_iotlb_sync_map(pkvm_handle_t domain_id,
unsigned long iova, size_t size)
{
struct kvm_hyp_iommu_domain *domain;
int ret;
if (!kvm_iommu_ops || !kvm_iommu_ops->iotlb_sync_map)
return -ENODEV;
if (!size || (iova + size < iova))
return -EINVAL;
if (domain_id == KVM_IOMMU_DOMAIN_IDMAP_ID)
return -EINVAL;
domain = handle_to_domain(domain_id);
if (!domain || domain_get(domain))
return -EINVAL;
ret = kvm_iommu_ops->iotlb_sync_map(domain, iova, size);
domain_put(domain);
return ret;
}