From 0b381ef0475cc6ea9a7fc7912c5defc7d71fdbb2 Mon Sep 17 00:00:00 2001 From: YeBiaoXiang Date: Fri, 25 Apr 2025 18:02:10 +0800 Subject: [PATCH 1/6] KVM: Add generic infrastructure to support pinned VMIDs euleros inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IBMHO0 Reference: https://gitee.com/openeuler/kernel/commit/ead59901a5661a81e459af305abbaee1cfb6cf21 https://gitee.com/openeuler/kernel/commit/49907c99a05740a673aacace9c05c70fb9df5414 -------------------------------- Provide generic helper functions to get/put pinned VMIDs if the arch Provide interfaces to get/put pinned VMIDs from KVM VMID allocator. This will be used by ummu driver in subsequent patch. Signed-off-by: Shameer Kolothum Signed-off-by: Kunkun Jiang Signed-off-by: lishusen Signed-off-by: YeBiaoXiang --- arch/arm64/kvm/Kconfig | 1 + arch/arm64/kvm/arm.c | 14 ++++++++++++++ include/linux/kvm_host.h | 16 ++++++++++++++++ virt/kvm/Kconfig | 3 +++ virt/kvm/kvm_main.c | 23 +++++++++++++++++++++++ 5 files changed, 57 insertions(+) diff --git a/arch/arm64/kvm/Kconfig b/arch/arm64/kvm/Kconfig index 52edbd7f6340..d4740f693fdf 100644 --- a/arch/arm64/kvm/Kconfig +++ b/arch/arm64/kvm/Kconfig @@ -44,6 +44,7 @@ menuconfig KVM select GUEST_PERF_EVENTS if PERF_EVENTS select INTERVAL_TREE select XARRAY_MULTI + select HAVE_KVM_PINNED_VMID help Support hosting virtualized guest machines. diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c index d3831c273843..16fdd57798dd 100644 --- a/arch/arm64/kvm/arm.c +++ b/arch/arm64/kvm/arm.c @@ -960,6 +960,20 @@ int kvm_arch_vcpu_run_pid_change(struct kvm_vcpu *vcpu) return ret; } +int kvm_arch_pinned_vmid_get(struct kvm *kvm) +{ + int vmid; + + vmid = kvm_arm_pinned_vmid_get(&kvm->arch.mmu.vmid); + + return (vmid == 0) ? -EINVAL : vmid; +} + +void kvm_arch_pinned_vmid_put(struct kvm *kvm) +{ + kvm_arm_pinned_vmid_put(&kvm->arch.mmu.vmid); +} + bool kvm_arch_intc_initialized(struct kvm *kvm) { return vgic_initialized(kvm); diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index a5cebf76aaa5..d3be6620d1be 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -2447,6 +2447,22 @@ static inline void kvm_handle_signal_exit(struct kvm_vcpu *vcpu) } #endif /* CONFIG_KVM_XFER_TO_GUEST_WORK */ +#ifdef CONFIG_HAVE_KVM_PINNED_VMID +int kvm_pinned_vmid_get(struct kvm *kvm); +void kvm_pinned_vmid_put(struct kvm *kvm); +int kvm_arch_pinned_vmid_get(struct kvm *kvm); +void kvm_arch_pinned_vmid_put(struct kvm *kvm); +#else +static inline int kvm_pinned_vmid_get(struct kvm *kvm) +{ + return -EINVAL; +} + +static inline void kvm_pinned_vmid_put(struct kvm *kvm) +{ +} +#endif + /* * If more than one page is being (un)accounted, @virt must be the address of * the first page of a block of pages what were allocated together (i.e diff --git a/virt/kvm/Kconfig b/virt/kvm/Kconfig index 484d0873061c..7e19e8ada121 100644 --- a/virt/kvm/Kconfig +++ b/virt/kvm/Kconfig @@ -92,3 +92,6 @@ config HAVE_KVM_PM_NOTIFIER config KVM_GENERIC_HARDWARE_ENABLING bool + +config HAVE_KVM_PINNED_VMID + bool diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 9e351bce483e..512e8acfb23b 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -3684,6 +3684,29 @@ bool kvm_vcpu_wake_up(struct kvm_vcpu *vcpu) } EXPORT_SYMBOL_GPL(kvm_vcpu_wake_up); +#ifdef CONFIG_HAVE_KVM_PINNED_VMID +int kvm_pinned_vmid_get(struct kvm *kvm) +{ + int ret; + + if (!kvm_get_kvm_safe(kvm)) + return -ENOENT; + ret = kvm_arch_pinned_vmid_get(kvm); + if (ret < 0) + kvm_put_kvm(kvm); + + return ret; +} +EXPORT_SYMBOL_GPL(kvm_pinned_vmid_get); + +void kvm_pinned_vmid_put(struct kvm *kvm) +{ + kvm_arch_pinned_vmid_put(kvm); + kvm_put_kvm(kvm); +} +EXPORT_SYMBOL_GPL(kvm_pinned_vmid_put); +#endif + #ifndef CONFIG_S390 /* * Kick a sleeping VCPU, or a guest VCPU in guest mode, into host kernel mode. -- Gitee From 4df5cf053d7ebf161c106ae9b37951bcfc00e85c Mon Sep 17 00:00:00 2001 From: YeBiaoXiang Date: Fri, 25 Apr 2025 18:09:57 +0800 Subject: [PATCH 2/6] KVM: arm64: Introduce support to pin VMIDs euleros inclusion bugzilla: https://gitee.com/openeuler/kernel/issues/IBMHO0 Reference: https://gitee.com/openeuler/kernel/commit/063f2253a44d66de0c278723245d75e2cd1570e9 -------------------------------- Introduce kvm_arm_pinned_vmid_get() and kvm_arm_pinned_vmid_put(), to pin a VMID associated with a KVM instance. This will guarantee that VMID remains the same after a rollover. This is in preparation of introducing support in the SMMUv3 driver to use the KVM VMID for S2 stage configuration in nested mode. Signed-off-by: Shameer Kolothum Signed-off-by: Kunkun Jiang Signed-off-by: lishusen Signed-off-by: YeBiaoXiang --- arch/arm64/include/asm/kvm_host.h | 3 ++ arch/arm64/kvm/vmid.c | 84 ++++++++++++++++++++++++++++++- 2 files changed, 86 insertions(+), 1 deletion(-) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index 2ebcd14b1612..c13a2d28459a 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -144,6 +144,7 @@ int topup_hyp_memcache(struct kvm_hyp_memcache *mc, unsigned long min_pages); struct kvm_vmid { atomic64_t id; + refcount_t pinned; }; struct kvm_s2_mmu { @@ -1146,6 +1147,8 @@ int __init kvm_arm_vmid_alloc_init(void); void __init kvm_arm_vmid_alloc_free(void); void kvm_arm_vmid_update(struct kvm_vmid *kvm_vmid); void kvm_arm_vmid_clear_active(void); +unsigned long kvm_arm_pinned_vmid_get(struct kvm_vmid *kvm_vmid); +void kvm_arm_pinned_vmid_put(struct kvm_vmid *kvm_vmid); static inline void kvm_arm_pvtime_vcpu_init(struct kvm_vcpu_arch *vcpu_arch) { diff --git a/arch/arm64/kvm/vmid.c b/arch/arm64/kvm/vmid.c index 7fe8ba1a2851..4e956aaa575e 100644 --- a/arch/arm64/kvm/vmid.c +++ b/arch/arm64/kvm/vmid.c @@ -25,6 +25,10 @@ static unsigned long *vmid_map; static DEFINE_PER_CPU(atomic64_t, active_vmids); static DEFINE_PER_CPU(u64, reserved_vmids); +static unsigned long max_pinned_vmids; +static unsigned long nr_pinned_vmids; +static unsigned long *pinned_vmid_map; + #define VMID_MASK (~GENMASK(kvm_arm_vmid_bits - 1, 0)) #define VMID_FIRST_VERSION (1UL << kvm_arm_vmid_bits) @@ -47,7 +51,10 @@ static void flush_context(void) int cpu; u64 vmid; - bitmap_zero(vmid_map, NUM_USER_VMIDS); + if (pinned_vmid_map) + bitmap_copy(vmid_map, pinned_vmid_map, NUM_USER_VMIDS); + else + bitmap_zero(vmid_map, NUM_USER_VMIDS); for_each_possible_cpu(cpu) { vmid = atomic64_xchg_relaxed(&per_cpu(active_vmids, cpu), 0); @@ -103,6 +110,14 @@ static u64 new_vmid(struct kvm_vmid *kvm_vmid) return newvmid; } + /* + * If it is pinned, we can keep using it. Note that reserved + * takes priority, because even if it is also pinned, we need to + * update the generation into the reserved_vmids. + */ + if (refcount_read(&kvm_vmid->pinned)) + return newvmid; + if (!__test_and_set_bit(vmid2idx(vmid), vmid_map)) { atomic64_set(&kvm_vmid->id, newvmid); return newvmid; @@ -169,6 +184,63 @@ void kvm_arm_vmid_update(struct kvm_vmid *kvm_vmid) raw_spin_unlock_irqrestore(&cpu_vmid_lock, flags); } +unsigned long kvm_arm_pinned_vmid_get(struct kvm_vmid *kvm_vmid) +{ + unsigned long flags; + u64 vmid; + + if (!pinned_vmid_map) + return 0; + + raw_spin_lock_irqsave(&cpu_vmid_lock, flags); + + vmid = atomic64_read(&kvm_vmid->id); + + if (refcount_inc_not_zero(&kvm_vmid->pinned)) + goto out_unlock; + + if (nr_pinned_vmids >= max_pinned_vmids) { + vmid = 0; + goto out_unlock; + } + + /* + * If we went through one or more rollover since that VMID was + * used, make sure it is still valid, or generate a new one. + */ + if (!vmid_gen_match(vmid)) + vmid = new_vmid(kvm_vmid); + + nr_pinned_vmids++; + __set_bit(vmid2idx(vmid), pinned_vmid_map); + refcount_set(&kvm_vmid->pinned, 1); + +out_unlock: + raw_spin_unlock_irqrestore(&cpu_vmid_lock, flags); + + vmid &= ~VMID_MASK; + + return vmid; +} + +void kvm_arm_pinned_vmid_put(struct kvm_vmid *kvm_vmid) +{ + unsigned long flags; + u64 vmid = atomic64_read(&kvm_vmid->id); + + if (!pinned_vmid_map) + return; + + raw_spin_lock_irqsave(&cpu_vmid_lock, flags); + + if (refcount_dec_and_test(&kvm_vmid->pinned)) { + __clear_bit(vmid2idx(vmid), pinned_vmid_map); + nr_pinned_vmids--; + } + + raw_spin_unlock_irqrestore(&cpu_vmid_lock, flags); +} + /* * Initialize the VMID allocator */ @@ -186,10 +258,20 @@ int __init kvm_arm_vmid_alloc_init(void) if (!vmid_map) return -ENOMEM; + pinned_vmid_map = bitmap_zalloc(NUM_USER_VMIDS, GFP_KERNEL); + nr_pinned_vmids = 0; + + /* + * Ensure we have at least one empty slot available after rollover + * and maximum number of VMIDs are pinned. VMID#0 is reserved. + */ + max_pinned_vmids = NUM_USER_VMIDS - num_possible_cpus() - 2; + return 0; } void __init kvm_arm_vmid_alloc_free(void) { + bitmap_free(pinned_vmid_map); bitmap_free(vmid_map); } -- Gitee From da8ada6bab0a7c9c0b1d4cab7918181f41e1f243 Mon Sep 17 00:00:00 2001 From: YeBiaoXiang Date: Fri, 25 Apr 2025 18:17:19 +0800 Subject: [PATCH 3/6] iommufd: Associate kvm pointer to iommufd ctx euleros inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IBMHO0 Reference: https://gitee.com/openeuler/kernel/commit/31359270cf61ce6f7d0b01d1f1ca41d119ddbaa0 -------------------------------- Introduce an API to set the KVM pointer to the iommufd ctx and set the same when a vfio dev is bind to iommufd. Signed-off-by: Shameer Kolothum Signed-off-by: Kunkun Jiang Signed-off-by: lishusen Signed-off-by: YeBiaoXiang --- drivers/iommu/iommufd/iommufd_private.h | 3 +++ drivers/iommu/iommufd/main.c | 14 ++++++++++++++ drivers/vfio/device_cdev.c | 3 +++ include/linux/iommufd.h | 7 +++++++ 4 files changed, 27 insertions(+) diff --git a/drivers/iommu/iommufd/iommufd_private.h b/drivers/iommu/iommufd/iommufd_private.h index 85a2d4c1cd83..53189dfd1879 100644 --- a/drivers/iommu/iommufd/iommufd_private.h +++ b/drivers/iommu/iommufd/iommufd_private.h @@ -18,6 +18,7 @@ struct iommu_domain; struct iommu_group; struct iommu_option; struct iommufd_device; +struct kvm; struct iommufd_ctx { struct file *file; @@ -29,6 +30,8 @@ struct iommufd_ctx { /* Compatibility with VFIO no iommu */ u8 no_iommu_mode; struct iommufd_ioas *vfio_ioas; + /* Associated KVM pointer */ + struct kvm *kvm; }; /* diff --git a/drivers/iommu/iommufd/main.c b/drivers/iommu/iommufd/main.c index 3872abbd8729..0be8d7279bf2 100644 --- a/drivers/iommu/iommufd/main.c +++ b/drivers/iommu/iommufd/main.c @@ -478,6 +478,20 @@ void iommufd_ctx_put(struct iommufd_ctx *ictx) } EXPORT_SYMBOL_NS_GPL(iommufd_ctx_put, IOMMUFD); +/** + * iommufd_ctx_set_kvm - Called to set a KVM pointer to iommufd context + * @ictx: Context to operate on + * @kvm: KVM pointer with a reference taken using kvm_get_kvm_safe() + */ +void iommufd_ctx_set_kvm(struct iommufd_ctx *ictx, struct kvm *kvm) +{ + xa_lock(&ictx->objects); + if (!ictx->kvm) + ictx->kvm = kvm; + xa_unlock(&ictx->objects); +} +EXPORT_SYMBOL_NS_GPL(iommufd_ctx_set_kvm, IOMMUFD); + static const struct iommufd_object_ops iommufd_object_ops[] = { [IOMMUFD_OBJ_ACCESS] = { .destroy = iommufd_access_destroy_object, diff --git a/drivers/vfio/device_cdev.c b/drivers/vfio/device_cdev.c index e75da0a70d1f..e75e96fb57cb 100644 --- a/drivers/vfio/device_cdev.c +++ b/drivers/vfio/device_cdev.c @@ -101,6 +101,9 @@ long vfio_df_ioctl_bind_iommufd(struct vfio_device_file *df, */ vfio_df_get_kvm_safe(df); + if (df->kvm) + iommufd_ctx_set_kvm(df->iommufd, df->kvm); + ret = vfio_df_open(df); if (ret) goto out_put_kvm; diff --git a/include/linux/iommufd.h b/include/linux/iommufd.h index 11110c749200..f3d921b8222f 100644 --- a/include/linux/iommufd.h +++ b/include/linux/iommufd.h @@ -22,6 +22,7 @@ struct iommufd_ctx; struct iommufd_device; struct iommufd_viommu_ops; struct page; +struct kvm; enum iommufd_object_type { IOMMUFD_OBJ_NONE, @@ -128,6 +129,7 @@ struct iommufd_ctx *iommufd_ctx_from_file(struct file *file); struct iommufd_ctx *iommufd_ctx_from_fd(int fd); void iommufd_ctx_put(struct iommufd_ctx *ictx); bool iommufd_ctx_has_group(struct iommufd_ctx *ictx, struct iommu_group *group); +void iommufd_ctx_set_kvm(struct iommufd_ctx *ictx, struct kvm *kvm); int iommufd_access_pin_pages(struct iommufd_access *access, unsigned long iova, unsigned long length, struct page **out_pages, @@ -149,6 +151,11 @@ static inline void iommufd_ctx_put(struct iommufd_ctx *ictx) { } +static inline void iommufd_ctx_set_kvm(struct iommufd_ctx *ictx, + struct kvm *kvm) +{ +} + static inline int iommufd_access_pin_pages(struct iommufd_access *access, unsigned long iova, unsigned long length, -- Gitee From e593cd4943f6f0b6d8e18874af714ae7ea726dce Mon Sep 17 00:00:00 2001 From: YeBiaoXiang Date: Fri, 25 Apr 2025 18:26:33 +0800 Subject: [PATCH 4/6] iommu: Pass in kvm pointer to domain_alloc_user euleros inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IBMHO0 Reference: https://gitee.com/openeuler/kernel/commit/160803e4561a5b087f092407307a18ec48f5629d -------------------------------- No functional changes. This will be used in a later patch to add support to use KVM VMID in ARM SMMUv3 s2 stage configuration. Signed-off-by: Shameer Kolothum Signed-off-by: Kunkun Jiang Signed-off-by: lishusen Signed-off-by: YeBiaoXiang --- drivers/iommu/amd/iommu.c | 1 + drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 1 + drivers/iommu/intel/iommu.c | 1 + drivers/iommu/iommufd/hw_pagetable.c | 5 +++-- drivers/iommu/iommufd/selftest.c | 1 + include/linux/iommu.h | 9 ++++++--- 6 files changed, 13 insertions(+), 5 deletions(-) diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c index 41557c5e158b..d6872f7d9e0c 100644 --- a/drivers/iommu/amd/iommu.c +++ b/drivers/iommu/amd/iommu.c @@ -2220,6 +2220,7 @@ static struct iommu_domain *amd_iommu_domain_alloc(unsigned int type) static struct iommu_domain * amd_iommu_domain_alloc_user(struct device *dev, u32 flags, struct iommu_domain *parent, + struct kvm *kvm, const struct iommu_user_data *user_data) { diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c index f85492a26e8f..005fa30d966a 100644 --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c @@ -3386,6 +3386,7 @@ static struct iommu_domain arm_smmu_blocked_domain = { static struct iommu_domain * arm_smmu_domain_alloc_user(struct device *dev, u32 flags, struct iommu_domain *parent, + struct kvm *kvm, const struct iommu_user_data *user_data) { struct arm_smmu_master *master = dev_iommu_priv_get(dev); diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c index bb23fc0f4832..41a27df51a20 100644 --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -3977,6 +3977,7 @@ static struct iommu_domain *intel_iommu_domain_alloc(unsigned type) static struct iommu_domain * intel_iommu_domain_alloc_user(struct device *dev, u32 flags, struct iommu_domain *parent, + struct kvm *kvm, const struct iommu_user_data *user_data) { struct device_domain_info *info = dev_iommu_priv_get(dev); diff --git a/drivers/iommu/iommufd/hw_pagetable.c b/drivers/iommu/iommufd/hw_pagetable.c index c92e575cf01e..5f75cbc255f3 100644 --- a/drivers/iommu/iommufd/hw_pagetable.c +++ b/drivers/iommu/iommufd/hw_pagetable.c @@ -140,7 +140,7 @@ iommufd_hwpt_paging_alloc(struct iommufd_ctx *ictx, struct iommufd_ioas *ioas, if (ops->domain_alloc_user) { hwpt->domain = ops->domain_alloc_user(idev->dev, flags, NULL, - user_data); + ictx->kvm, user_data); if (IS_ERR(hwpt->domain)) { rc = PTR_ERR(hwpt->domain); hwpt->domain = NULL; @@ -241,7 +241,8 @@ iommufd_hwpt_nested_alloc(struct iommufd_ctx *ictx, hwpt->domain = ops->domain_alloc_user(idev->dev, flags & ~IOMMU_HWPT_FAULT_ID_VALID, - parent->common.domain, user_data); + parent->common.domain, + ictx->kvm, user_data); if (IS_ERR(hwpt->domain)) { rc = PTR_ERR(hwpt->domain); hwpt->domain = NULL; diff --git a/drivers/iommu/iommufd/selftest.c b/drivers/iommu/iommufd/selftest.c index 8e727bdca877..34500385b713 100644 --- a/drivers/iommu/iommufd/selftest.c +++ b/drivers/iommu/iommufd/selftest.c @@ -381,6 +381,7 @@ mock_domain_alloc_nested(struct iommu_domain *parent, u32 flags, static struct iommu_domain * mock_domain_alloc_user(struct device *dev, u32 flags, struct iommu_domain *parent, + struct kvm *kvm, const struct iommu_user_data *user_data) { bool has_dirty_flag = flags & IOMMU_HWPT_ALLOC_DIRTY_TRACKING; diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 0dea4c637fd2..5924d6a8d791 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -682,9 +682,12 @@ struct iommu_ops { /* Domain allocation and freeing by the iommu driver */ struct iommu_domain *(*domain_alloc)(unsigned iommu_domain_type); - struct iommu_domain *(*domain_alloc_user)( - struct device *dev, u32 flags, struct iommu_domain *parent, - const struct iommu_user_data *user_data); + KABI_REPLACE(struct iommu_domain *(*domain_alloc_user)( + struct device *dev, u32 flags, struct iommu_domain *parent, + const struct iommu_user_data *user_data), + struct iommu_domain *(*domain_alloc_user)( + struct device *dev, u32 flags, struct iommu_domain *parent, + struct kvm *kvm, const struct iommu_user_data *user_data)) struct iommu_domain *(*domain_alloc_paging)(struct device *dev); struct iommu_device *(*probe_device)(struct device *dev); -- Gitee From 589acbca785c3d29e3e9bc2996fd4e0841200457 Mon Sep 17 00:00:00 2001 From: Kunkun Jiang Date: Sat, 15 Feb 2025 15:40:42 +0800 Subject: [PATCH 5/6] vfio: Fix kabi breakage due to closing VFIO_CONTAINER euleros inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IBMHO0 -------------------------------- To support vSVA, we need to open IOMMUFD_VFIO_CONTAINER and close VFIO_CONTAINER. Turning off VFIO_CONTAINER will cause kabi breakage. This patch fixes it and fixes the other kabi breakages. Signed-off-by: Kunkun Jiang Signed-off-by: lishusen --- arch/arm64/configs/openeuler_defconfig | 1 + arch/arm64/include/asm/kvm_host.h | 3 +-- arch/arm64/kvm/vmid.c | 14 ++++++++++---- drivers/vfio/vfio.h | 2 ++ 4 files changed, 14 insertions(+), 6 deletions(-) diff --git a/arch/arm64/configs/openeuler_defconfig b/arch/arm64/configs/openeuler_defconfig index e80fc0985a50..d031d7ab07af 100644 --- a/arch/arm64/configs/openeuler_defconfig +++ b/arch/arm64/configs/openeuler_defconfig @@ -789,6 +789,7 @@ CONFIG_HAVE_KVM_IRQ_BYPASS=y CONFIG_HAVE_KVM_VCPU_RUN_PID_CHANGE=y CONFIG_KVM_XFER_TO_GUEST_WORK=y CONFIG_KVM_GENERIC_HARDWARE_ENABLING=y +CONFIG_HAVE_KVM_PINNED_VMID=y CONFIG_KVM_HISI_VIRT=y CONFIG_VIRTUALIZATION=y CONFIG_KVM=y diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index c13a2d28459a..69a08a4f3d85 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -144,7 +144,6 @@ int topup_hyp_memcache(struct kvm_hyp_memcache *mc, unsigned long min_pages); struct kvm_vmid { atomic64_t id; - refcount_t pinned; }; struct kvm_s2_mmu { @@ -224,7 +223,7 @@ struct kvm_arch { /* Mandated version of PSCI */ u32 psci_version; - + KABI_FILL_HOLE(refcount_t pinned) /* Protects VM-scoped configuration data */ struct mutex config_lock; diff --git a/arch/arm64/kvm/vmid.c b/arch/arm64/kvm/vmid.c index 4e956aaa575e..e1d958644425 100644 --- a/arch/arm64/kvm/vmid.c +++ b/arch/arm64/kvm/vmid.c @@ -104,6 +104,8 @@ static u64 new_vmid(struct kvm_vmid *kvm_vmid) if (vmid != 0) { u64 newvmid = generation | (vmid & ~VMID_MASK); + struct kvm_s2_mmu *kvm_s2_mmu = + container_of(kvm_vmid, struct kvm_s2_mmu, vmid); if (check_update_reserved_vmid(vmid, newvmid)) { atomic64_set(&kvm_vmid->id, newvmid); @@ -115,7 +117,7 @@ static u64 new_vmid(struct kvm_vmid *kvm_vmid) * takes priority, because even if it is also pinned, we need to * update the generation into the reserved_vmids. */ - if (refcount_read(&kvm_vmid->pinned)) + if (refcount_read(&kvm_s2_mmu->arch->pinned)) return newvmid; if (!__test_and_set_bit(vmid2idx(vmid), vmid_map)) { @@ -188,6 +190,7 @@ unsigned long kvm_arm_pinned_vmid_get(struct kvm_vmid *kvm_vmid) { unsigned long flags; u64 vmid; + struct kvm_s2_mmu *kvm_s2_mmu; if (!pinned_vmid_map) return 0; @@ -196,7 +199,8 @@ unsigned long kvm_arm_pinned_vmid_get(struct kvm_vmid *kvm_vmid) vmid = atomic64_read(&kvm_vmid->id); - if (refcount_inc_not_zero(&kvm_vmid->pinned)) + kvm_s2_mmu = container_of(kvm_vmid, struct kvm_s2_mmu, vmid); + if (refcount_inc_not_zero(&kvm_s2_mmu->arch->pinned)) goto out_unlock; if (nr_pinned_vmids >= max_pinned_vmids) { @@ -213,7 +217,7 @@ unsigned long kvm_arm_pinned_vmid_get(struct kvm_vmid *kvm_vmid) nr_pinned_vmids++; __set_bit(vmid2idx(vmid), pinned_vmid_map); - refcount_set(&kvm_vmid->pinned, 1); + refcount_set(&kvm_s2_mmu->arch->pinned, 1); out_unlock: raw_spin_unlock_irqrestore(&cpu_vmid_lock, flags); @@ -226,6 +230,7 @@ unsigned long kvm_arm_pinned_vmid_get(struct kvm_vmid *kvm_vmid) void kvm_arm_pinned_vmid_put(struct kvm_vmid *kvm_vmid) { unsigned long flags; + struct kvm_s2_mmu *kvm_s2_mmu; u64 vmid = atomic64_read(&kvm_vmid->id); if (!pinned_vmid_map) @@ -233,7 +238,8 @@ void kvm_arm_pinned_vmid_put(struct kvm_vmid *kvm_vmid) raw_spin_lock_irqsave(&cpu_vmid_lock, flags); - if (refcount_dec_and_test(&kvm_vmid->pinned)) { + kvm_s2_mmu = container_of(kvm_vmid, struct kvm_s2_mmu, vmid); + if (refcount_dec_and_test(&kvm_s2_mmu->arch->pinned)) { __clear_bit(vmid2idx(vmid), pinned_vmid_map); nr_pinned_vmids--; } diff --git a/drivers/vfio/vfio.h b/drivers/vfio/vfio.h index bde84ad344e5..488b815db970 100644 --- a/drivers/vfio/vfio.h +++ b/drivers/vfio/vfio.h @@ -85,6 +85,8 @@ struct vfio_group { struct list_head vfio_next; #if IS_ENABLED(CONFIG_VFIO_CONTAINER) struct list_head container_next; +#else + KABI_DEPRECATE(struct list_head, container_next) #endif enum vfio_group_type type; struct mutex group_lock; -- Gitee From 2047ce4a36900ecaa728927b72f93444940abf43 Mon Sep 17 00:00:00 2001 From: YeBiaoXiang Date: Sat, 15 Feb 2025 15:40:42 +0800 Subject: [PATCH 6/6] iommu: Fix kabi breakage due to opening KVM_PINNED_VMID euleros inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IBMHO0 -------------------------------- Turning on CONFIG_HAVE_KVM_PINNED_VMID will cause kabi breakage, The previous commit use KABI_REPLACE cannot completely solve the kabi change, this patch use KABI_RESERVE(8) to fixes it. Signed-off-by: YeBiaoXiang --- drivers/iommu/amd/iommu.c | 1 - drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 2 +- drivers/iommu/intel/iommu.c | 1 - drivers/iommu/iommufd/hw_pagetable.c | 33 ++++++++++++++++----- drivers/iommu/iommufd/selftest.c | 1 - include/linux/iommu.h | 14 ++++----- 6 files changed, 33 insertions(+), 19 deletions(-) diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c index d6872f7d9e0c..41557c5e158b 100644 --- a/drivers/iommu/amd/iommu.c +++ b/drivers/iommu/amd/iommu.c @@ -2220,7 +2220,6 @@ static struct iommu_domain *amd_iommu_domain_alloc(unsigned int type) static struct iommu_domain * amd_iommu_domain_alloc_user(struct device *dev, u32 flags, struct iommu_domain *parent, - struct kvm *kvm, const struct iommu_user_data *user_data) { diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c index 005fa30d966a..6b87f0116657 100644 --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c @@ -4130,7 +4130,7 @@ static struct iommu_ops arm_smmu_ops = { .hw_info = arm_smmu_hw_info, .domain_alloc_paging = arm_smmu_domain_alloc_paging, .domain_alloc_sva = arm_smmu_sva_domain_alloc, - .domain_alloc_user = arm_smmu_domain_alloc_user, + .domain_alloc_user_v2 = arm_smmu_domain_alloc_user, .probe_device = arm_smmu_probe_device, .release_device = arm_smmu_release_device, .device_group = arm_smmu_device_group, diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c index 41a27df51a20..bb23fc0f4832 100644 --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -3977,7 +3977,6 @@ static struct iommu_domain *intel_iommu_domain_alloc(unsigned type) static struct iommu_domain * intel_iommu_domain_alloc_user(struct device *dev, u32 flags, struct iommu_domain *parent, - struct kvm *kvm, const struct iommu_user_data *user_data) { struct device_domain_info *info = dev_iommu_priv_get(dev); diff --git a/drivers/iommu/iommufd/hw_pagetable.c b/drivers/iommu/iommufd/hw_pagetable.c index 5f75cbc255f3..0a5a379a19ac 100644 --- a/drivers/iommu/iommufd/hw_pagetable.c +++ b/drivers/iommu/iommufd/hw_pagetable.c @@ -118,7 +118,8 @@ iommufd_hwpt_paging_alloc(struct iommufd_ctx *ictx, struct iommufd_ioas *ioas, lockdep_assert_held(&ioas->mutex); - if ((flags || user_data) && !ops->domain_alloc_user) + if ((flags || user_data) && + (!ops->domain_alloc_user && !ops->domain_alloc_user_v2)) return ERR_PTR(-EOPNOTSUPP); if (flags & ~valid_flags) return ERR_PTR(-EOPNOTSUPP); @@ -140,7 +141,16 @@ iommufd_hwpt_paging_alloc(struct iommufd_ctx *ictx, struct iommufd_ioas *ioas, if (ops->domain_alloc_user) { hwpt->domain = ops->domain_alloc_user(idev->dev, flags, NULL, - ictx->kvm, user_data); + user_data); + if (IS_ERR(hwpt->domain)) { + rc = PTR_ERR(hwpt->domain); + hwpt->domain = NULL; + goto out_abort; + } + hwpt->domain->owner = ops; + } else if (ops->domain_alloc_user_v2) { + hwpt->domain = ops->domain_alloc_user_v2(idev->dev, flags, NULL, + ictx->kvm, user_data); if (IS_ERR(hwpt->domain)) { rc = PTR_ERR(hwpt->domain); hwpt->domain = NULL; @@ -224,8 +234,8 @@ iommufd_hwpt_nested_alloc(struct iommufd_ctx *ictx, struct iommufd_hw_pagetable *hwpt; int rc; - if ((flags & ~IOMMU_HWPT_FAULT_ID_VALID) || - !user_data->len || !ops->domain_alloc_user) + if ((flags & ~IOMMU_HWPT_FAULT_ID_VALID) || !user_data->len || + (!ops->domain_alloc_user && !ops->domain_alloc_user_v2)) return ERR_PTR(-EOPNOTSUPP); if (parent->auto_domain || !parent->nest_parent) return ERR_PTR(-EINVAL); @@ -239,10 +249,17 @@ iommufd_hwpt_nested_alloc(struct iommufd_ctx *ictx, refcount_inc(&parent->common.obj.users); hwpt_nested->parent = parent; - hwpt->domain = ops->domain_alloc_user(idev->dev, - flags & ~IOMMU_HWPT_FAULT_ID_VALID, - parent->common.domain, - ictx->kvm, user_data); + if (ops->domain_alloc_user) { + hwpt->domain = ops->domain_alloc_user(idev->dev, + flags & ~IOMMU_HWPT_FAULT_ID_VALID, + parent->common.domain, user_data); + } else { + hwpt->domain = ops->domain_alloc_user_v2(idev->dev, + flags & ~IOMMU_HWPT_FAULT_ID_VALID, + parent->common.domain, + ictx->kvm, user_data); + } + if (IS_ERR(hwpt->domain)) { rc = PTR_ERR(hwpt->domain); hwpt->domain = NULL; diff --git a/drivers/iommu/iommufd/selftest.c b/drivers/iommu/iommufd/selftest.c index 34500385b713..8e727bdca877 100644 --- a/drivers/iommu/iommufd/selftest.c +++ b/drivers/iommu/iommufd/selftest.c @@ -381,7 +381,6 @@ mock_domain_alloc_nested(struct iommu_domain *parent, u32 flags, static struct iommu_domain * mock_domain_alloc_user(struct device *dev, u32 flags, struct iommu_domain *parent, - struct kvm *kvm, const struct iommu_user_data *user_data) { bool has_dirty_flag = flags & IOMMU_HWPT_ALLOC_DIRTY_TRACKING; diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 5924d6a8d791..ed3e024b1e39 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -682,12 +682,10 @@ struct iommu_ops { /* Domain allocation and freeing by the iommu driver */ struct iommu_domain *(*domain_alloc)(unsigned iommu_domain_type); - KABI_REPLACE(struct iommu_domain *(*domain_alloc_user)( - struct device *dev, u32 flags, struct iommu_domain *parent, - const struct iommu_user_data *user_data), - struct iommu_domain *(*domain_alloc_user)( - struct device *dev, u32 flags, struct iommu_domain *parent, - struct kvm *kvm, const struct iommu_user_data *user_data)) + struct iommu_domain *(*domain_alloc_user)( + struct device *dev, u32 flags, struct iommu_domain *parent, + const struct iommu_user_data *user_data); + struct iommu_domain *(*domain_alloc_paging)(struct device *dev); struct iommu_device *(*probe_device)(struct device *dev); @@ -737,7 +735,9 @@ struct iommu_ops { KABI_USE(6, struct iommu_domain *release_domain) KABI_RESERVE(7) KABI_RESERVE(8) - KABI_RESERVE(9) + KABI_USE(9, struct iommu_domain *(*domain_alloc_user_v2)( + struct device *dev, u32 flags, struct iommu_domain *parent, + struct kvm *kvm, const struct iommu_user_data *user_data)) }; /** -- Gitee