[PATCH OLK-6.6 0/8] iommu/arm-smmu-v3: Use KVM VMID for s2 stage

On an ARM64 system with a SMMUv3 implementation that fully supports Broadcast TLB Maintenance(BTM) feature as part of the Distributed Virtual Memory(DVM) protocol, the CPU TLB invalidate instructions are received by SMMUv3. This is very useful when the SMMUv3 shares the page tables with the CPU(eg: Guest SVA use case). For this to work, the SMMUv3 must use the same VMID that is allocated by KVM to configure the nested stage 2(S2) translations. Jean-Philippe Brucker (1): iommu/arm-smmu-v3: Enable broadcast TLB maintenance Kunkun Jiang (1): vfio: Fix kabi breakage due to closing VFIO_CONTAINER Shameer Kolothum (6): KVM: Add generic infrastructure to support pinned VMIDs KVM: arm64: Introduce support to pin VMIDs KVM: arm64: Add interfaces for pinned VMID support iommufd: Associate kvm pointer to iommufd ctx iommu: Pass in kvm pointer to domain_alloc_user iommu/arm-smmu-v3: Use KVM VMID for s2 stage arch/arm64/include/asm/kvm_host.h | 3 + arch/arm64/kvm/Kconfig | 1 + arch/arm64/kvm/arm.c | 14 ++++ arch/arm64/kvm/vmid.c | 84 ++++++++++++++++++++- drivers/iommu/amd/iommu.c | 1 + drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 46 +++++++++-- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 1 + drivers/iommu/intel/iommu.c | 1 + drivers/iommu/iommufd/hw_pagetable.c | 5 +- drivers/iommu/iommufd/iommufd_private.h | 3 + drivers/iommu/iommufd/main.c | 14 ++++ drivers/iommu/iommufd/selftest.c | 1 + drivers/vfio/device_cdev.c | 3 + drivers/vfio/vfio.h | 2 + include/linux/iommu.h | 9 ++- include/linux/iommufd.h | 7 ++ include/linux/kvm_host.h | 18 +++++ virt/kvm/Kconfig | 3 + virt/kvm/kvm_main.c | 23 ++++++ 19 files changed, 225 insertions(+), 14 deletions(-) -- 2.33.0

From: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com> virt inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IBMHO0 CVE: NA -------------------------------- Provide generic helper functions to get/put pinned VMIDs if the arch supports it. Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com> Signed-off-by: Kunkun Jiang <jiangkunkun@huawei.com> Signed-off-by: lishusen <lishusen2@huawei.com> --- include/linux/kvm_host.h | 18 ++++++++++++++++++ virt/kvm/Kconfig | 3 +++ virt/kvm/kvm_main.c | 23 +++++++++++++++++++++++ 3 files changed, 44 insertions(+) diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 3968797272b9..068a9de08247 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -2408,6 +2408,24 @@ 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_arch_pinned_vmid_get(struct kvm *kvm); +void kvm_arch_pinned_vmid_put(struct kvm *kvm); +#endif + +#ifdef CONFIG_HAVE_KVM_PINNED_VMID +int kvm_pinned_vmid_get(struct kvm *kvm); +void kvm_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 4b7378445812..59f406068dd6 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -3659,6 +3659,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. -- 2.33.0

From: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com> virt inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IBMHO0 CVE: NA -------------------------------- 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 <shameerali.kolothum.thodi@huawei.com> Signed-off-by: Kunkun Jiang <jiangkunkun@huawei.com> Signed-off-by: lishusen <lishusen2@huawei.com> --- 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 81898bb87c5e..35b56d38bd96 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -143,6 +143,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 { @@ -1106,6 +1107,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..cbc9c5f25033 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 emty 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); } -- 2.33.0

From: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com> virt inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IBMHO0 CVE: NA -------------------------------- Provide interfaces to get/put pinned VMIDs from KVM VMID allocator. This will be used by SMMUv3 driver in subsequent patch. Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com> Signed-off-by: Kunkun Jiang <jiangkunkun@huawei.com> Signed-off-by: lishusen <lishusen2@huawei.com> --- arch/arm64/kvm/Kconfig | 1 + arch/arm64/kvm/arm.c | 14 ++++++++++++++ 2 files changed, 15 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 d0d4e6bdc06b..08cfe550c155 100644 --- a/arch/arm64/kvm/arm.c +++ b/arch/arm64/kvm/arm.c @@ -892,6 +892,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); -- 2.33.0

From: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com> virt inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IBMHO0 CVE: NA -------------------------------- 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 <shameerali.kolothum.thodi@huawei.com> Signed-off-by: Kunkun Jiang <jiangkunkun@huawei.com> Signed-off-by: lishusen <lishusen2@huawei.com> --- 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, -- 2.33.0

From: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com> virt inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IBMHO0 CVE: NA -------------------------------- 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 <shameerali.kolothum.thodi@huawei.com> Signed-off-by: Kunkun Jiang <jiangkunkun@huawei.com> Signed-off-by: lishusen <lishusen2@huawei.com> --- 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 ccab57f36c62..021548556083 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 7fe05fea676a..d8913d5246cb 100644 --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c @@ -3361,6 +3361,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 8169b4a3d7a0..0be8cb24b925 100644 --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -4001,6 +4001,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 83ec4bf9809e..73239dedac80 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); -- 2.33.0

From: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com> virt inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IBMHO0 CVE: NA -------------------------------- If kvm is available make use of kvm pinned VMID interfaces to set the s2 stage VMID for nested domains. Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com> Signed-off-by: Kunkun Jiang <jiangkunkun@huawei.com> Signed-off-by: lishusen <lishusen2@huawei.com> --- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 22 +++++++++++++++------ drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 1 + 2 files changed, 17 insertions(+), 6 deletions(-) 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 d8913d5246cb..7741aa24f2c3 100644 --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c @@ -18,6 +18,7 @@ #include <linux/interrupt.h> #include <linux/io-pgtable.h> #include <linux/iopoll.h> +#include <linux/kvm_host.h> #include <linux/module.h> #include <linux/msi.h> #include <linux/of.h> @@ -2612,9 +2613,13 @@ static void arm_smmu_domain_free_paging(struct iommu_domain *domain) xa_erase(&arm_smmu_asid_xa, smmu_domain->cd.asid); mutex_unlock(&arm_smmu_asid_lock); } else { - struct arm_smmu_s2_cfg *cfg = &smmu_domain->s2_cfg; - if (cfg->vmid) - ida_free(&smmu->vmid_map, cfg->vmid); + if (smmu_domain->iommufd_kvm) { + kvm_pinned_vmid_put(smmu_domain->iommufd_kvm); + } else { + struct arm_smmu_s2_cfg *cfg = &smmu_domain->s2_cfg; + if (cfg->vmid) + ida_free(&smmu->vmid_map, cfg->vmid); + } } kfree(smmu_domain); @@ -2642,9 +2647,13 @@ static int arm_smmu_domain_finalise_s2(struct arm_smmu_device *smmu, int vmid; struct arm_smmu_s2_cfg *cfg = &smmu_domain->s2_cfg; - /* Reserve VMID 0 for stage-2 bypass STEs */ - vmid = ida_alloc_range(&smmu->vmid_map, 1, (1 << smmu->vmid_bits) - 1, - GFP_KERNEL); + if (smmu_domain->iommufd_kvm) { + vmid = kvm_pinned_vmid_get(smmu_domain->iommufd_kvm); + } else { + /* Reserve VMID 0 for stage-2 bypass STEs */ + vmid = ida_alloc_range(&smmu->vmid_map, 1, + (1 << smmu->vmid_bits) - 1, GFP_KERNEL); + } if (vmid < 0) return vmid; @@ -3386,6 +3395,7 @@ arm_smmu_domain_alloc_user(struct device *dev, u32 flags, } smmu_domain->stage = ARM_SMMU_DOMAIN_S2; smmu_domain->nest_parent = true; + smmu_domain->iommufd_kvm = kvm; } smmu_domain->domain.type = IOMMU_DOMAIN_UNMANAGED; diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h index 38d46098c668..8aa3a46edd6a 100644 --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h @@ -883,6 +883,7 @@ struct arm_smmu_domain { struct list_head node; struct kvm *kvm; #endif + struct kvm *iommufd_kvm; }; struct arm_smmu_nested_domain { -- 2.33.0

From: Jean-Philippe Brucker <jean-philippe@linaro.org> virt inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IBMHO0 CVE: NA -------------------------------- The SMMUv3 can handle invalidation targeted at TLB entries with shared ASIDs. If the implementation supports broadcast TLB maintenance, enable it and keep track of it in a feature bit. The SMMU will then be affected by inner-shareable TLB invalidations from other agents. In order to avoid over invalidation with stage-2 translation contexts, enable BTM only when SMMUv3 supports eiher S1 or both S1 & S2 transaltion contexts. In this way the default domain will use stage-1 and stage 2 will be only used for NESTED Domain setup. Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org> [Shameer: Enable BTM only if S1 is supported] Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com> Signed-off-by: Kunkun Jiang <jiangkunkun@huawei.com> Signed-off-by: lishusen <lishusen2@huawei.com> --- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 23 +++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) 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 7741aa24f2c3..987ff896e802 100644 --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c @@ -4654,11 +4654,14 @@ static int arm_smmu_device_reset(struct arm_smmu_device *smmu, bool resume) writel_relaxed(reg, smmu->base + ARM_SMMU_CR1); /* CR2 (random crap) */ - reg = CR2_PTM | CR2_RECINVSID; + reg = CR2_RECINVSID; if (smmu->features & ARM_SMMU_FEAT_E2H) reg |= CR2_E2H; + if (!(smmu->features & ARM_SMMU_FEAT_BTM)) + reg |= CR2_PTM; + writel_relaxed(reg, smmu->base + ARM_SMMU_CR2); /* Stream table */ @@ -4993,6 +4996,7 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu) { u32 reg; bool coherent = smmu->features & ARM_SMMU_FEAT_COHERENCY; + bool vhe = cpus_have_cap(ARM64_HAS_VIRT_HOST_EXTN); /* IDR0 */ reg = readl_relaxed(smmu->base + ARM_SMMU_IDR0); @@ -5045,7 +5049,7 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu) if (reg & IDR0_HYP) { smmu->features |= ARM_SMMU_FEAT_HYP; - if (cpus_have_cap(ARM64_HAS_VIRT_HOST_EXTN)) + if (vhe) smmu->features |= ARM_SMMU_FEAT_E2H; } @@ -5072,6 +5076,21 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu) if (reg & IDR0_S2P) smmu->features |= ARM_SMMU_FEAT_TRANS_S2; + /* + * If S1 is supported, check we can enable BTM. This means if S2 is available, + * we will use S2 for nested domain only with a KVM VMID. BTM is useful when + * CPU shares the page tables with SMMUv3(eg: vSVA) + */ + if (reg & IDR0_S1P) { + /* + * If the CPU is using VHE, but the SMMU doesn't support it, the SMMU + * will create TLB entries for NH-EL1 world and will miss the + * broadcasted TLB invalidations that target EL2-E2H world. Don't enable + * BTM in that case. + */ + if (reg & IDR0_BTM && (!vhe || reg & IDR0_HYP)) + smmu->features |= ARM_SMMU_FEAT_BTM; + } if (!(reg & (IDR0_S1P | IDR0_S2P))) { dev_err(smmu->dev, "no translation support!\n"); -- 2.33.0

From: Kunkun Jiang <jiangkunkun@huawei.com> virt inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IBMHO0 CVE: NA -------------------------------- 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. Signed-off-by: Kunkun Jiang <jiangkunkun@huawei.com> Signed-off-by: lishusen <lishusen2@huawei.com> --- drivers/vfio/vfio.h | 2 ++ 1 file changed, 2 insertions(+) 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; -- 2.33.0

反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://gitee.com/openeuler/kernel/pulls/15925 邮件列表地址:https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/G7K... FeedBack: The patch(es) which you have sent to kernel@openeuler.org mailing list has been converted to a pull request successfully! Pull request link: https://gitee.com/openeuler/kernel/pulls/15925 Mailing list address: https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/G7K...
participants (2)
-
lishusen
-
patchwork bot