* [PATCH 0/2] Fix crash due to open pmu events during unbind
@ 2024-02-13 6:46 Umesh Nerlige Ramappa
2024-02-13 6:46 ` [PATCH 1/2] i915/pmu: Add pmu_teardown helper Umesh Nerlige Ramappa
2024-02-13 18:04 ` [PATCH 0/2] Fix crash due to open pmu events during unbind Umesh Nerlige Ramappa
0 siblings, 2 replies; 4+ messages in thread
From: Umesh Nerlige Ramappa @ 2024-02-13 6:46 UTC (permalink / raw)
To: intel-gfx; +Cc: Tvrtko Ursulin
Once a user opens an fd for a perf event, if the driver undergoes a
function level reset (FLR), the resources are not cleaned up as
expected. For this discussion FLR is defined as a PCI unbind followed by
a bind. perf_pmu_unregister() would cleanup everything, but when the
user closes the perf fd much later, perf_release() is called and we
encounter null pointer dereferences and/or list corruption in that path
which require a reboot to recover.
The only approach that worked to resolve this was to close the file
associated with the event such that the relevant cleanup happens w.r.t.
the open file. To do so, use the event->owner task and find the file
relevant to the event and close it. This relies on the
file->private_data matching the event object.
Test-with: 20240213062948.32735-1-umesh.nerlige.ramappa@intel.com
Signed-off-by: Umesh Nerlige Ramappa <umesh.nerlige.ramappa@intel.com>
Umesh Nerlige Ramappa (2):
i915/pmu: Add pmu_teardown helper
INTEL_DII: i915/pmu: Cleanup pending events on unbind
drivers/gpu/drm/i915/i915_pmu.c | 192 ++++++++++++++++++++++++--------
drivers/gpu/drm/i915/i915_pmu.h | 15 +++
2 files changed, 161 insertions(+), 46 deletions(-)
--
2.34.1
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH 1/2] i915/pmu: Add pmu_teardown helper
2024-02-13 6:46 [PATCH 0/2] Fix crash due to open pmu events during unbind Umesh Nerlige Ramappa
@ 2024-02-13 6:46 ` Umesh Nerlige Ramappa
2024-02-13 18:04 ` [PATCH 0/2] Fix crash due to open pmu events during unbind Umesh Nerlige Ramappa
1 sibling, 0 replies; 4+ messages in thread
From: Umesh Nerlige Ramappa @ 2024-02-13 6:46 UTC (permalink / raw)
To: intel-gfx; +Cc: Tvrtko Ursulin
Move pmu teardown to a helper and place it above the destroy hook so
that teardown can also happen inside destroy when events are closed
after i915 pmu is unregistered.
Signed-off-by: Umesh Nerlige Ramappa <umesh.nerlige.ramappa@intel.com>
---
drivers/gpu/drm/i915/i915_pmu.c | 106 +++++++++++++++++---------------
1 file changed, 56 insertions(+), 50 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_pmu.c b/drivers/gpu/drm/i915/i915_pmu.c
index 21eb0c5b320d..4d2a289f848a 100644
--- a/drivers/gpu/drm/i915/i915_pmu.c
+++ b/drivers/gpu/drm/i915/i915_pmu.c
@@ -514,6 +514,61 @@ static enum hrtimer_restart i915_sample(struct hrtimer *hrtimer)
return HRTIMER_RESTART;
}
+static enum cpuhp_state cpuhp_slot = CPUHP_INVALID;
+
+static int i915_pmu_register_cpuhp_state(struct i915_pmu *pmu)
+{
+ if (cpuhp_slot == CPUHP_INVALID)
+ return -EINVAL;
+
+ return cpuhp_state_add_instance(cpuhp_slot, &pmu->cpuhp.node);
+}
+
+static void i915_pmu_unregister_cpuhp_state(struct i915_pmu *pmu)
+{
+ cpuhp_state_remove_instance(cpuhp_slot, &pmu->cpuhp.node);
+}
+
+static void free_event_attributes(struct i915_pmu *pmu)
+{
+ struct attribute **attr_iter = pmu->events_attr_group.attrs;
+
+ for (; *attr_iter; attr_iter++)
+ kfree((*attr_iter)->name);
+
+ kfree(pmu->events_attr_group.attrs);
+ kfree(pmu->i915_attr);
+ kfree(pmu->pmu_attr);
+
+ pmu->events_attr_group.attrs = NULL;
+ pmu->i915_attr = NULL;
+ pmu->pmu_attr = NULL;
+}
+
+static bool is_igp(struct drm_i915_private *i915)
+{
+ struct pci_dev *pdev = to_pci_dev(i915->drm.dev);
+
+ /* IGP is 0000:00:02.0 */
+ return pci_domain_nr(pdev->bus) == 0 &&
+ pdev->bus->number == 0 &&
+ PCI_SLOT(pdev->devfn) == 2 &&
+ PCI_FUNC(pdev->devfn) == 0;
+}
+
+static void pmu_teardown(struct i915_pmu *pmu)
+{
+ struct drm_i915_private *i915 = pmu_to_i915(pmu);
+
+ i915_pmu_unregister_cpuhp_state(pmu);
+ perf_pmu_unregister(&pmu->base);
+ pmu->base.event_init = NULL;
+ kfree(pmu->base.attr_groups);
+ if (!is_igp(i915))
+ kfree(pmu->name);
+ free_event_attributes(pmu);
+}
+
static void i915_pmu_event_destroy(struct perf_event *event)
{
struct i915_pmu *pmu = event_to_pmu(event);
@@ -1133,22 +1188,6 @@ err:;
return NULL;
}
-static void free_event_attributes(struct i915_pmu *pmu)
-{
- struct attribute **attr_iter = pmu->events_attr_group.attrs;
-
- for (; *attr_iter; attr_iter++)
- kfree((*attr_iter)->name);
-
- kfree(pmu->events_attr_group.attrs);
- kfree(pmu->i915_attr);
- kfree(pmu->pmu_attr);
-
- pmu->events_attr_group.attrs = NULL;
- pmu->i915_attr = NULL;
- pmu->pmu_attr = NULL;
-}
-
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);
@@ -1194,8 +1233,6 @@ static int i915_pmu_cpu_offline(unsigned int cpu, struct hlist_node *node)
return 0;
}
-static enum cpuhp_state cpuhp_slot = CPUHP_INVALID;
-
int i915_pmu_init(void)
{
int ret;
@@ -1219,30 +1256,6 @@ void i915_pmu_exit(void)
cpuhp_remove_multi_state(cpuhp_slot);
}
-static int i915_pmu_register_cpuhp_state(struct i915_pmu *pmu)
-{
- if (cpuhp_slot == CPUHP_INVALID)
- return -EINVAL;
-
- return cpuhp_state_add_instance(cpuhp_slot, &pmu->cpuhp.node);
-}
-
-static void i915_pmu_unregister_cpuhp_state(struct i915_pmu *pmu)
-{
- cpuhp_state_remove_instance(cpuhp_slot, &pmu->cpuhp.node);
-}
-
-static bool is_igp(struct drm_i915_private *i915)
-{
- struct pci_dev *pdev = to_pci_dev(i915->drm.dev);
-
- /* IGP is 0000:00:02.0 */
- return pci_domain_nr(pdev->bus) == 0 &&
- pdev->bus->number == 0 &&
- PCI_SLOT(pdev->devfn) == 2 &&
- PCI_FUNC(pdev->devfn) == 0;
-}
-
void i915_pmu_register(struct drm_i915_private *i915)
{
struct i915_pmu *pmu = &i915->pmu;
@@ -1341,12 +1354,5 @@ void i915_pmu_unregister(struct drm_i915_private *i915)
hrtimer_cancel(&pmu->timer);
- i915_pmu_unregister_cpuhp_state(pmu);
-
- perf_pmu_unregister(&pmu->base);
- pmu->base.event_init = NULL;
- kfree(pmu->base.attr_groups);
- if (!is_igp(i915))
- kfree(pmu->name);
- free_event_attributes(pmu);
+ pmu_teardown(pmu);
}
--
2.34.1
^ permalink raw reply related [flat|nested] 4+ messages in thread* Re: [PATCH 0/2] Fix crash due to open pmu events during unbind
2024-02-13 6:46 [PATCH 0/2] Fix crash due to open pmu events during unbind Umesh Nerlige Ramappa
2024-02-13 6:46 ` [PATCH 1/2] i915/pmu: Add pmu_teardown helper Umesh Nerlige Ramappa
@ 2024-02-13 18:04 ` Umesh Nerlige Ramappa
1 sibling, 0 replies; 4+ messages in thread
From: Umesh Nerlige Ramappa @ 2024-02-13 18:04 UTC (permalink / raw)
To: intel-gfx; +Cc: Tvrtko Ursulin
Resending to include patch 2/2. Please ignore this series.
On Mon, Feb 12, 2024 at 10:46:48PM -0800, Umesh Nerlige Ramappa wrote:
>Once a user opens an fd for a perf event, if the driver undergoes a
>function level reset (FLR), the resources are not cleaned up as
>expected. For this discussion FLR is defined as a PCI unbind followed by
>a bind. perf_pmu_unregister() would cleanup everything, but when the
>user closes the perf fd much later, perf_release() is called and we
>encounter null pointer dereferences and/or list corruption in that path
>which require a reboot to recover.
>
>The only approach that worked to resolve this was to close the file
>associated with the event such that the relevant cleanup happens w.r.t.
>the open file. To do so, use the event->owner task and find the file
>relevant to the event and close it. This relies on the
>file->private_data matching the event object.
>
>Test-with: 20240213062948.32735-1-umesh.nerlige.ramappa@intel.com
>Signed-off-by: Umesh Nerlige Ramappa <umesh.nerlige.ramappa@intel.com>
>
>Umesh Nerlige Ramappa (2):
> i915/pmu: Add pmu_teardown helper
> INTEL_DII: i915/pmu: Cleanup pending events on unbind
>
> drivers/gpu/drm/i915/i915_pmu.c | 192 ++++++++++++++++++++++++--------
> drivers/gpu/drm/i915/i915_pmu.h | 15 +++
> 2 files changed, 161 insertions(+), 46 deletions(-)
>
>--
>2.34.1
>
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH 0/2] Fix crash due to open pmu events during unbind
@ 2024-02-13 18:03 Umesh Nerlige Ramappa
2024-02-13 18:03 ` [PATCH 1/2] i915/pmu: Add pmu_teardown helper Umesh Nerlige Ramappa
0 siblings, 1 reply; 4+ messages in thread
From: Umesh Nerlige Ramappa @ 2024-02-13 18:03 UTC (permalink / raw)
To: intel-gfx; +Cc: Tvrtko Ursulin
Once a user opens an fd for a perf event, if the driver undergoes a
function level reset (FLR), the resources are not cleaned up as
expected. For this discussion FLR is defined as a PCI unbind followed by
a bind. perf_pmu_unregister() would cleanup everything, but when the
user closes the perf fd much later, perf_release() is called and we
encounter null pointer dereferences and/or list corruption in that path
which require a reboot to recover.
The only approach that worked to resolve this was to close the file
associated with the event such that the relevant cleanup happens w.r.t.
the open file. To do so, use the event->owner task and find the file
relevant to the event and close it. This relies on the
file->private_data matching the event object.
Test-with: 20240213062948.32735-1-umesh.nerlige.ramappa@intel.com
Signed-off-by: Umesh Nerlige Ramappa <umesh.nerlige.ramappa@intel.com>
Umesh Nerlige Ramappa (2):
i915/pmu: Add pmu_teardown helper
i915/pmu: Cleanup pending events on unbind
drivers/gpu/drm/i915/i915_pmu.c | 192 ++++++++++++++++++++++++--------
drivers/gpu/drm/i915/i915_pmu.h | 15 +++
2 files changed, 161 insertions(+), 46 deletions(-)
--
2.34.1
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH 1/2] i915/pmu: Add pmu_teardown helper
2024-02-13 18:03 Umesh Nerlige Ramappa
@ 2024-02-13 18:03 ` Umesh Nerlige Ramappa
0 siblings, 0 replies; 4+ messages in thread
From: Umesh Nerlige Ramappa @ 2024-02-13 18:03 UTC (permalink / raw)
To: intel-gfx; +Cc: Tvrtko Ursulin
Move pmu teardown to a helper and place it above the destroy hook so
that teardown can also happen inside destroy when events are closed
after i915 pmu is unregistered.
Signed-off-by: Umesh Nerlige Ramappa <umesh.nerlige.ramappa@intel.com>
---
drivers/gpu/drm/i915/i915_pmu.c | 106 +++++++++++++++++---------------
1 file changed, 56 insertions(+), 50 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_pmu.c b/drivers/gpu/drm/i915/i915_pmu.c
index 21eb0c5b320d..4d2a289f848a 100644
--- a/drivers/gpu/drm/i915/i915_pmu.c
+++ b/drivers/gpu/drm/i915/i915_pmu.c
@@ -514,6 +514,61 @@ static enum hrtimer_restart i915_sample(struct hrtimer *hrtimer)
return HRTIMER_RESTART;
}
+static enum cpuhp_state cpuhp_slot = CPUHP_INVALID;
+
+static int i915_pmu_register_cpuhp_state(struct i915_pmu *pmu)
+{
+ if (cpuhp_slot == CPUHP_INVALID)
+ return -EINVAL;
+
+ return cpuhp_state_add_instance(cpuhp_slot, &pmu->cpuhp.node);
+}
+
+static void i915_pmu_unregister_cpuhp_state(struct i915_pmu *pmu)
+{
+ cpuhp_state_remove_instance(cpuhp_slot, &pmu->cpuhp.node);
+}
+
+static void free_event_attributes(struct i915_pmu *pmu)
+{
+ struct attribute **attr_iter = pmu->events_attr_group.attrs;
+
+ for (; *attr_iter; attr_iter++)
+ kfree((*attr_iter)->name);
+
+ kfree(pmu->events_attr_group.attrs);
+ kfree(pmu->i915_attr);
+ kfree(pmu->pmu_attr);
+
+ pmu->events_attr_group.attrs = NULL;
+ pmu->i915_attr = NULL;
+ pmu->pmu_attr = NULL;
+}
+
+static bool is_igp(struct drm_i915_private *i915)
+{
+ struct pci_dev *pdev = to_pci_dev(i915->drm.dev);
+
+ /* IGP is 0000:00:02.0 */
+ return pci_domain_nr(pdev->bus) == 0 &&
+ pdev->bus->number == 0 &&
+ PCI_SLOT(pdev->devfn) == 2 &&
+ PCI_FUNC(pdev->devfn) == 0;
+}
+
+static void pmu_teardown(struct i915_pmu *pmu)
+{
+ struct drm_i915_private *i915 = pmu_to_i915(pmu);
+
+ i915_pmu_unregister_cpuhp_state(pmu);
+ perf_pmu_unregister(&pmu->base);
+ pmu->base.event_init = NULL;
+ kfree(pmu->base.attr_groups);
+ if (!is_igp(i915))
+ kfree(pmu->name);
+ free_event_attributes(pmu);
+}
+
static void i915_pmu_event_destroy(struct perf_event *event)
{
struct i915_pmu *pmu = event_to_pmu(event);
@@ -1133,22 +1188,6 @@ err:;
return NULL;
}
-static void free_event_attributes(struct i915_pmu *pmu)
-{
- struct attribute **attr_iter = pmu->events_attr_group.attrs;
-
- for (; *attr_iter; attr_iter++)
- kfree((*attr_iter)->name);
-
- kfree(pmu->events_attr_group.attrs);
- kfree(pmu->i915_attr);
- kfree(pmu->pmu_attr);
-
- pmu->events_attr_group.attrs = NULL;
- pmu->i915_attr = NULL;
- pmu->pmu_attr = NULL;
-}
-
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);
@@ -1194,8 +1233,6 @@ static int i915_pmu_cpu_offline(unsigned int cpu, struct hlist_node *node)
return 0;
}
-static enum cpuhp_state cpuhp_slot = CPUHP_INVALID;
-
int i915_pmu_init(void)
{
int ret;
@@ -1219,30 +1256,6 @@ void i915_pmu_exit(void)
cpuhp_remove_multi_state(cpuhp_slot);
}
-static int i915_pmu_register_cpuhp_state(struct i915_pmu *pmu)
-{
- if (cpuhp_slot == CPUHP_INVALID)
- return -EINVAL;
-
- return cpuhp_state_add_instance(cpuhp_slot, &pmu->cpuhp.node);
-}
-
-static void i915_pmu_unregister_cpuhp_state(struct i915_pmu *pmu)
-{
- cpuhp_state_remove_instance(cpuhp_slot, &pmu->cpuhp.node);
-}
-
-static bool is_igp(struct drm_i915_private *i915)
-{
- struct pci_dev *pdev = to_pci_dev(i915->drm.dev);
-
- /* IGP is 0000:00:02.0 */
- return pci_domain_nr(pdev->bus) == 0 &&
- pdev->bus->number == 0 &&
- PCI_SLOT(pdev->devfn) == 2 &&
- PCI_FUNC(pdev->devfn) == 0;
-}
-
void i915_pmu_register(struct drm_i915_private *i915)
{
struct i915_pmu *pmu = &i915->pmu;
@@ -1341,12 +1354,5 @@ void i915_pmu_unregister(struct drm_i915_private *i915)
hrtimer_cancel(&pmu->timer);
- i915_pmu_unregister_cpuhp_state(pmu);
-
- perf_pmu_unregister(&pmu->base);
- pmu->base.event_init = NULL;
- kfree(pmu->base.attr_groups);
- if (!is_igp(i915))
- kfree(pmu->name);
- free_event_attributes(pmu);
+ pmu_teardown(pmu);
}
--
2.34.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
end of thread, other threads:[~2024-02-13 18:04 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-02-13 6:46 [PATCH 0/2] Fix crash due to open pmu events during unbind Umesh Nerlige Ramappa
2024-02-13 6:46 ` [PATCH 1/2] i915/pmu: Add pmu_teardown helper Umesh Nerlige Ramappa
2024-02-13 18:04 ` [PATCH 0/2] Fix crash due to open pmu events during unbind Umesh Nerlige Ramappa
-- strict thread matches above, loose matches on Subject: below --
2024-02-13 18:03 Umesh Nerlige Ramappa
2024-02-13 18:03 ` [PATCH 1/2] i915/pmu: Add pmu_teardown helper Umesh Nerlige Ramappa
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox