diff --git a/android/abi_gki_aarch64.stg b/android/abi_gki_aarch64.stg index 67655ea1bf44..7d9f1c9d10a4 100644 --- a/android/abi_gki_aarch64.stg +++ b/android/abi_gki_aarch64.stg @@ -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 diff --git a/android/abi_gki_aarch64.stg.allowed_breaks b/android/abi_gki_aarch64.stg.allowed_breaks index 8f5f52dbe65a..c055c76c9002 100644 --- a/android/abi_gki_aarch64.stg.allowed_breaks +++ b/android/abi_gki_aarch64.stg.allowed_breaks @@ -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 + diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h index 9cc0033513a9..ca0c586379eb 100644 --- a/arch/arm64/include/asm/kvm_asm.h +++ b/arch/arm64/include/asm/kvm_asm.h @@ -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 diff --git a/arch/arm64/kvm/hyp/include/nvhe/iommu.h b/arch/arm64/kvm/hyp/include/nvhe/iommu.h index 4afb0b83115e..388ea6e0bd6e 100644 --- a/arch/arm64/kvm/hyp/include/nvhe/iommu.h +++ b/arch/arm64/kvm/hyp/include/nvhe/iommu.h @@ -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); diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c index a5ffc4cd3f70..7fd93d0cda91 100644 --- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c +++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c @@ -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) diff --git a/arch/arm64/kvm/hyp/nvhe/iommu/iommu.c b/arch/arm64/kvm/hyp/nvhe/iommu/iommu.c index f06b84357eb4..2edfc56304fc 100644 --- a/arch/arm64/kvm/hyp/nvhe/iommu/iommu.c +++ b/arch/arm64/kvm/hyp/nvhe/iommu/iommu.c @@ -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; +}