From: Lucas De Marchi <lucas.demarchi@intel.com>
To: intel-gfx@lists.freedesktop.org, linux-perf-users@vger.kernel.org
Cc: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>,
dri-devel@lists.freedesktop.org,
Peter Zijlstra <peterz@infradead.org>,
Ingo Molnar <mingo@redhat.com>,
Arnaldo Carvalho de Melo <acme@kernel.org>,
linux-kernel@vger.kernel.org,
Lucas De Marchi <lucas.demarchi@intel.com>
Subject: [PATCH 6/7] drm/i915/pmu: Lazy unregister
Date: Mon, 22 Jul 2024 14:06:47 -0700 [thread overview]
Message-ID: <20240722210648.80892-7-lucas.demarchi@intel.com> (raw)
In-Reply-To: <20240722210648.80892-1-lucas.demarchi@intel.com>
Instead of calling perf_pmu_unregister() when unbinding, defer that to
the destruction of i915 object. Since perf itself holds a reference in
the event, this only happens when all events are gone, which guarantees
i915 is not unregistering the pmu with live events.
Previously, running the following sequence would crash the system after
~2 tries:
1) bind device to i915
2) wait events to show up on sysfs
3) start perf stat -I 1000 -e i915/rcs0-busy/
4) unbind driver
5) kill perf
Most of the time this crashes in perf_pmu_disable() while accessing the
percpu pmu_disable_count. This happens because perf_pmu_unregister()
destroys it with free_percpu(pmu->pmu_disable_count).
With a lazy unbind, the pmu is only unregistered after (5) as opposed to
after (4). The downside is that if a new bind operation is attempted for
the same device/driver without killing the perf process, i915 will fail
to register the pmu (but still load successfully). This seems better
than completely crashing the system.
Signed-off-by: Lucas De Marchi <lucas.demarchi@intel.com>
---
drivers/gpu/drm/i915/i915_pmu.c | 24 +++++++++---------------
1 file changed, 9 insertions(+), 15 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_pmu.c b/drivers/gpu/drm/i915/i915_pmu.c
index 8708f905f4f4..df53a8fe53ec 100644
--- a/drivers/gpu/drm/i915/i915_pmu.c
+++ b/drivers/gpu/drm/i915/i915_pmu.c
@@ -1158,18 +1158,21 @@ static void free_pmu(struct drm_device *dev, void *res)
struct i915_pmu *pmu = res;
struct drm_i915_private *i915 = pmu_to_i915(pmu);
+ perf_pmu_unregister(&pmu->base);
free_event_attributes(pmu);
kfree(pmu->base.attr_groups);
if (IS_DGFX(i915))
kfree(pmu->name);
+
+ /*
+ * Make sure all currently running (but shortcut on pmu->closed) are
+ * gone before proceeding with free'ing the pmu object embedded in i915.
+ */
+ synchronize_rcu();
}
static int i915_pmu_cpu_online(unsigned int cpu, struct hlist_node *node)
{
- struct i915_pmu *pmu = hlist_entry_safe(node, typeof(*pmu), cpuhp.node);
-
- GEM_BUG_ON(!pmu->base.event_init);
-
/* Select the first online CPU as a designated reader. */
if (cpumask_empty(&i915_pmu_cpumask))
cpumask_set_cpu(cpu, &i915_pmu_cpumask);
@@ -1182,8 +1185,6 @@ static int i915_pmu_cpu_offline(unsigned int cpu, struct hlist_node *node)
struct i915_pmu *pmu = hlist_entry_safe(node, typeof(*pmu), cpuhp.node);
unsigned int target = i915_pmu_target_cpu;
- GEM_BUG_ON(!pmu->base.event_init);
-
/*
* Unregistering an instance generates a CPU offline event which we must
* ignore to avoid incorrectly modifying the shared i915_pmu_cpumask.
@@ -1337,21 +1338,14 @@ void i915_pmu_unregister(struct drm_i915_private *i915)
{
struct i915_pmu *pmu = &i915->pmu;
- if (!pmu->base.event_init)
- return;
-
/*
- * "Disconnect" the PMU callbacks - since all are atomic synchronize_rcu
- * ensures all currently executing ones will have exited before we
- * proceed with unregistration.
+ * "Disconnect" the PMU callbacks - unregistering the pmu will be done
+ * later when all currently open events are gone
*/
pmu->closed = true;
- synchronize_rcu();
hrtimer_cancel(&pmu->timer);
-
i915_pmu_unregister_cpuhp_state(pmu);
- perf_pmu_unregister(&pmu->base);
pmu->base.event_init = NULL;
}
--
2.43.0
next prev parent reply other threads:[~2024-07-22 21:07 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-07-22 21:06 [PATCH 0/7] Fix i915 pmu on bind/unbind Lucas De Marchi
2024-07-22 21:06 ` [PATCH 1/7] perf/core: Add pmu get/put Lucas De Marchi
2024-07-23 23:07 ` Ian Rogers
2024-07-22 21:06 ` [PATCH 2/7] drm/i915/pmu: Fix crash due to use-after-free Lucas De Marchi
2024-07-22 21:06 ` [PATCH 3/7] drm/i915/pmu: Use event_to_pmu() Lucas De Marchi
2024-07-23 4:35 ` Dixit, Ashutosh
2024-07-22 21:06 ` [PATCH 4/7] drm/i915/pmu: Drop is_igp() Lucas De Marchi
2024-07-22 23:25 ` Dixit, Ashutosh
2024-07-23 7:52 ` Tvrtko Ursulin
2024-07-22 21:06 ` [PATCH 5/7] drm/i915/pmu: Let resource survive unbind Lucas De Marchi
2024-07-23 7:58 ` Tvrtko Ursulin
2024-07-22 21:06 ` Lucas De Marchi [this message]
2024-07-23 8:03 ` [PATCH 6/7] drm/i915/pmu: Lazy unregister Tvrtko Ursulin
2024-07-23 15:30 ` Lucas De Marchi
2024-07-24 7:48 ` Tvrtko Ursulin
2024-07-24 12:41 ` Peter Zijlstra
2024-07-24 15:39 ` Lucas De Marchi
2024-09-09 21:03 ` Lucas De Marchi
2024-07-22 21:06 ` [PATCH 7/7] drm/i915/pmu: Do not set event_init to NULL Lucas De Marchi
2024-08-05 6:55 ` kernel test robot
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240722210648.80892-7-lucas.demarchi@intel.com \
--to=lucas.demarchi@intel.com \
--cc=acme@kernel.org \
--cc=dri-devel@lists.freedesktop.org \
--cc=intel-gfx@lists.freedesktop.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-perf-users@vger.kernel.org \
--cc=mingo@redhat.com \
--cc=peterz@infradead.org \
--cc=tvrtko.ursulin@linux.intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®