提交 685ace6c 编写于 作者: J Jean-Philippe Brucker 提交者: Zheng Zengkai

DEBUG: iommu/arm-smmu-v3: Add SVA trace events

maillist inclusion
category: feature
bugzilla: 51855
CVE: NA

Reference: https://jpbrucker.net/git/linux/commit/?h=sva/2021-03-01&id=870541b34bfa7ba8d5846fcb3246e533e7492e20

---------------------------------------------

It's useful when debugging to have some trace events for SVA object
allocation and freeing.
Signed-off-by: NJean-Philippe Brucker <jean-philippe@linaro.org>
Signed-off-by: NLijun Fang <fanglijun3@huawei.com>
Reviewed-by: NWeilong Chen <chenweilong@huawei.com>
Signed-off-by: NZheng Zengkai <zhengzengkai@huawei.com>
上级 2d2df4d9
...@@ -8,6 +8,8 @@ ...@@ -8,6 +8,8 @@
#include <linux/mmu_notifier.h> #include <linux/mmu_notifier.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <trace/events/smmu.h>
#include "arm-smmu-v3.h" #include "arm-smmu-v3.h"
#include "../../iommu-sva-lib.h" #include "../../iommu-sva-lib.h"
#include "../../io-pgtable-arm.h" #include "../../io-pgtable-arm.h"
...@@ -191,6 +193,7 @@ static void arm_smmu_mm_invalidate_range(struct mmu_notifier *mn, ...@@ -191,6 +193,7 @@ static void arm_smmu_mm_invalidate_range(struct mmu_notifier *mn,
arm_smmu_tlb_inv_range_asid(start, size, smmu_mn->cd->asid, arm_smmu_tlb_inv_range_asid(start, size, smmu_mn->cd->asid,
PAGE_SIZE, false, smmu_domain); PAGE_SIZE, false, smmu_domain);
arm_smmu_atc_inv_domain(smmu_domain, mm->pasid, start, size); arm_smmu_atc_inv_domain(smmu_domain, mm->pasid, start, size);
trace_smmu_mm_invalidate(mm->pasid, start, end);
} }
static void arm_smmu_mm_release(struct mmu_notifier *mn, struct mm_struct *mm) static void arm_smmu_mm_release(struct mmu_notifier *mn, struct mm_struct *mm)
...@@ -240,6 +243,7 @@ arm_smmu_mmu_notifier_get(struct arm_smmu_domain *smmu_domain, ...@@ -240,6 +243,7 @@ arm_smmu_mmu_notifier_get(struct arm_smmu_domain *smmu_domain,
list_for_each_entry(smmu_mn, &smmu_domain->mmu_notifiers, list) { list_for_each_entry(smmu_mn, &smmu_domain->mmu_notifiers, list) {
if (smmu_mn->mn.mm == mm) { if (smmu_mn->mn.mm == mm) {
refcount_inc(&smmu_mn->refs); refcount_inc(&smmu_mn->refs);
trace_smmu_mn_get(mm->pasid);
return smmu_mn; return smmu_mn;
} }
} }
...@@ -270,6 +274,7 @@ arm_smmu_mmu_notifier_get(struct arm_smmu_domain *smmu_domain, ...@@ -270,6 +274,7 @@ arm_smmu_mmu_notifier_get(struct arm_smmu_domain *smmu_domain,
goto err_put_notifier; goto err_put_notifier;
list_add(&smmu_mn->list, &smmu_domain->mmu_notifiers); list_add(&smmu_mn->list, &smmu_domain->mmu_notifiers);
trace_smmu_mn_alloc(mm->pasid);
return smmu_mn; return smmu_mn;
err_put_notifier: err_put_notifier:
...@@ -286,8 +291,10 @@ static void arm_smmu_mmu_notifier_put(struct arm_smmu_mmu_notifier *smmu_mn) ...@@ -286,8 +291,10 @@ static void arm_smmu_mmu_notifier_put(struct arm_smmu_mmu_notifier *smmu_mn)
struct arm_smmu_ctx_desc *cd = smmu_mn->cd; struct arm_smmu_ctx_desc *cd = smmu_mn->cd;
struct arm_smmu_domain *smmu_domain = smmu_mn->domain; struct arm_smmu_domain *smmu_domain = smmu_mn->domain;
if (!refcount_dec_and_test(&smmu_mn->refs)) if (!refcount_dec_and_test(&smmu_mn->refs)) {
trace_smmu_mn_put(mm->pasid);
return; return;
}
list_del(&smmu_mn->list); list_del(&smmu_mn->list);
arm_smmu_write_ctx_desc(smmu_domain, mm->pasid, NULL); arm_smmu_write_ctx_desc(smmu_domain, mm->pasid, NULL);
...@@ -303,6 +310,7 @@ static void arm_smmu_mmu_notifier_put(struct arm_smmu_mmu_notifier *smmu_mn) ...@@ -303,6 +310,7 @@ static void arm_smmu_mmu_notifier_put(struct arm_smmu_mmu_notifier *smmu_mn)
/* Frees smmu_mn */ /* Frees smmu_mn */
mmu_notifier_put(&smmu_mn->mn); mmu_notifier_put(&smmu_mn->mn);
trace_smmu_mn_free(mm->pasid);
arm_smmu_free_shared_cd(cd); arm_smmu_free_shared_cd(cd);
} }
...@@ -321,6 +329,7 @@ __arm_smmu_sva_bind(struct device *dev, struct mm_struct *mm) ...@@ -321,6 +329,7 @@ __arm_smmu_sva_bind(struct device *dev, struct mm_struct *mm)
/* If bind() was already called for this {dev, mm} pair, reuse it. */ /* If bind() was already called for this {dev, mm} pair, reuse it. */
list_for_each_entry(bond, &master->bonds, list) { list_for_each_entry(bond, &master->bonds, list) {
if (bond->mm == mm) { if (bond->mm == mm) {
trace_smmu_bind_get(dev, mm->pasid);
refcount_inc(&bond->refs); refcount_inc(&bond->refs);
return &bond->sva; return &bond->sva;
} }
...@@ -346,6 +355,7 @@ __arm_smmu_sva_bind(struct device *dev, struct mm_struct *mm) ...@@ -346,6 +355,7 @@ __arm_smmu_sva_bind(struct device *dev, struct mm_struct *mm)
} }
list_add(&bond->list, &master->bonds); list_add(&bond->list, &master->bonds);
trace_smmu_bind_alloc(dev, mm->pasid);
return &bond->sva; return &bond->sva;
err_free_pasid: err_free_pasid:
...@@ -390,10 +400,13 @@ void arm_smmu_sva_unbind(struct iommu_sva *handle) ...@@ -390,10 +400,13 @@ void arm_smmu_sva_unbind(struct iommu_sva *handle)
mutex_lock(&sva_lock); mutex_lock(&sva_lock);
if (refcount_dec_and_test(&bond->refs)) { if (refcount_dec_and_test(&bond->refs)) {
trace_smmu_unbind_free(handle->dev, bond->mm->pasid);
list_del(&bond->list); list_del(&bond->list);
arm_smmu_mmu_notifier_put(bond->smmu_mn); arm_smmu_mmu_notifier_put(bond->smmu_mn);
iommu_sva_free_pasid(bond->mm); iommu_sva_free_pasid(bond->mm);
kfree(bond); kfree(bond);
} else {
trace_smmu_unbind_put(handle->dev, bond->mm->pasid);
} }
mutex_unlock(&sva_lock); mutex_unlock(&sva_lock);
} }
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#define CREATE_TRACE_POINTS #define CREATE_TRACE_POINTS
#include <trace/events/iommu.h> #include <trace/events/iommu.h>
#include <trace/events/smmu.h>
/* iommu_group_event */ /* iommu_group_event */
EXPORT_TRACEPOINT_SYMBOL_GPL(add_device_to_group); EXPORT_TRACEPOINT_SYMBOL_GPL(add_device_to_group);
...@@ -26,3 +27,15 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(unmap); ...@@ -26,3 +27,15 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(unmap);
/* iommu_error */ /* iommu_error */
EXPORT_TRACEPOINT_SYMBOL_GPL(io_page_fault); EXPORT_TRACEPOINT_SYMBOL_GPL(io_page_fault);
/* Arm SMMUv3 traces */
EXPORT_TRACEPOINT_SYMBOL_GPL(smmu_bind_alloc);
EXPORT_TRACEPOINT_SYMBOL_GPL(smmu_bind_get);
EXPORT_TRACEPOINT_SYMBOL_GPL(smmu_unbind_put);
EXPORT_TRACEPOINT_SYMBOL_GPL(smmu_unbind_free);
EXPORT_TRACEPOINT_SYMBOL_GPL(smmu_mm_release);
EXPORT_TRACEPOINT_SYMBOL_GPL(smmu_mm_invalidate);
EXPORT_TRACEPOINT_SYMBOL_GPL(smmu_mn_alloc);
EXPORT_TRACEPOINT_SYMBOL_GPL(smmu_mn_free);
EXPORT_TRACEPOINT_SYMBOL_GPL(smmu_mn_get);
EXPORT_TRACEPOINT_SYMBOL_GPL(smmu_mn_put);
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Arm SMMUv3 trace points
*/
#undef TRACE_SYSTEM
#define TRACE_SYSTEM smmu
#if !defined(_TRACE_SMMU_H) || defined(TRACE_HEADER_MULTI_READ)
#define _TRACE_SMMU_H
#include <linux/tracepoint.h>
struct device;
DECLARE_EVENT_CLASS(smmu_bond,
TP_PROTO(struct device *dev, unsigned int pasid),
TP_ARGS(dev, pasid),
TP_STRUCT__entry(
__string(dev, dev_name(dev))
__field(int, pasid)
),
TP_fast_assign(
__assign_str(dev, dev_name(dev));
__entry->pasid = pasid;
),
TP_printk("dev=%s pasid=%d", __get_str(dev), __entry->pasid)
);
DEFINE_EVENT(smmu_bond, smmu_bind_alloc,
TP_PROTO(struct device *dev, unsigned int pasid),
TP_ARGS(dev, pasid));
DEFINE_EVENT(smmu_bond, smmu_bind_get,
TP_PROTO(struct device *dev, unsigned int pasid),
TP_ARGS(dev, pasid));
DEFINE_EVENT(smmu_bond, smmu_unbind_put,
TP_PROTO(struct device *dev, unsigned int pasid),
TP_ARGS(dev, pasid));
DEFINE_EVENT(smmu_bond, smmu_unbind_free,
TP_PROTO(struct device *dev, unsigned int pasid),
TP_ARGS(dev, pasid));
TRACE_EVENT(smmu_mm_release,
TP_PROTO(unsigned int pasid),
TP_ARGS(pasid),
TP_STRUCT__entry(__field(int, pasid)),
TP_fast_assign(__entry->pasid = pasid;),
TP_printk("pasid=%d", __entry->pasid)
);
TRACE_EVENT(smmu_mm_invalidate,
TP_PROTO(unsigned int pasid,
unsigned long start, unsigned long end),
TP_ARGS(pasid, start, end),
TP_STRUCT__entry(
__field(int, pasid)
__field(unsigned long, start)
__field(unsigned long, end)
),
TP_fast_assign(
__entry->pasid = pasid;
__entry->start = start;
__entry->end = end;
),
TP_printk("pasid=%d start=0x%lx end=0x%lx",
__entry->pasid, __entry->start,
__entry->end)
)
DECLARE_EVENT_CLASS(smmu_mn,
TP_PROTO(unsigned int pasid),
TP_ARGS(pasid),
TP_STRUCT__entry(__field(int, pasid)),
TP_fast_assign(__entry->pasid = pasid;),
TP_printk("pasid=%d", __entry->pasid)
);
DEFINE_EVENT(smmu_mn, smmu_mn_alloc, TP_PROTO(unsigned int pasid), TP_ARGS(pasid));
DEFINE_EVENT(smmu_mn, smmu_mn_free, TP_PROTO(unsigned int pasid), TP_ARGS(pasid));
DEFINE_EVENT(smmu_mn, smmu_mn_get, TP_PROTO(unsigned int pasid), TP_ARGS(pasid));
DEFINE_EVENT(smmu_mn, smmu_mn_put, TP_PROTO(unsigned int pasid), TP_ARGS(pasid));
#endif /* _TRACE_SMMU_H */
/* This part must be outside protection */
#include <trace/define_trace.h>
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册