* [PATCH v2 0/2] Exynos PMU fixes for cpu hotplug and cpuidle routines
@ 2026-08-28 5:36 Alexey Klimov
2026-08-28 5:36 ` [PATCH v2 1/2] soc: samsung: exynos-pmu: fix use-after-free of interrupt generator node Alexey Klimov
` (2 more replies)
0 siblings, 3 replies; 5+ messages in thread
From: Alexey Klimov @ 2026-08-28 5:36 UTC (permalink / raw)
To: Krzysztof Kozlowski, Alim Akhtar, Peter Griffin
Cc: Sam Protsenko, linux-samsung-soc, linux-arm-kernel, linux-kernel,
stable, Sashiko
This was reported by Sashiko here:
https://sashiko.dev/#/patchset/20260513-exynos850-cpuhotplug-v4-0-54fec5f65362@linaro.org?part=3
and was mainly introduced by enabling cpu hotplug
support and cpuidle for gs101-based SoCs.
In this second version one patch was dropped to keep things consistent with
downstream implementation and due to lack of information. Other patches
deal with a few missing error paths issues here and there in
setup_cpuhp_and_cpuidle() and around. They were updated per discussions.
Tested on exynos850 e850-96 board with sequential series that implements
hotplug. I don't see any regressions but testing from others will be
appreciated.
Signed-off-by: Alexey Klimov <alexey.klimov@linaro.org>
---
Changes in v2:
- destroy_cpuhp_and_cpuidle() is called only if
(pmu_context->pmu_data && pmu_context->pmu_data->pmu_cpuhp) == true
(as suggested by Peter) (second patch in this series);
- in clean_cpuhp_states error path the cpuhp states variables are now
reset to CPUHP_INVALID;
- re-implemented "soc: samsung: exynos-pmu: fix use-after-free of interrupt
generator node" -- used __free(device_node) at declaration;
(as suggested by Peter);
- drop "[PATCH 1/3] soc: samsung: exynos-pmu: use target cpu ID in hotplug
callbacks". If we get some information about CPUx_INFORM registers usage
then we may fix it later, but for now it was decided to keep it
consistent with downstream implementation;
- Link to v1: https://lore.kernel.org/r/20260605-exynos-pmu-cpuhp-idle-fixes-v1-0-0cd05c81a82d@linaro.org
---
Alexey Klimov (2):
soc: samsung: exynos-pmu: fix use-after-free of interrupt generator node
soc: samsung: exynos-pmu: fix error paths in cpuhotplug/idle states setup
drivers/soc/samsung/exynos-pmu.c | 70 ++++++++++++++++++++++++++++++++--------
1 file changed, 57 insertions(+), 13 deletions(-)
---
base-commit: 3d83758432b5e6ed9507500a57efb0f3af41ee7d
change-id: 20260605-exynos-pmu-cpuhp-idle-fixes-32f5ed7c969f
Best regards,
--
Alexey Klimov <alexey.klimov@linaro.org>
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v2 1/2] soc: samsung: exynos-pmu: fix use-after-free of interrupt generator node
2026-08-28 5:36 [PATCH v2 0/2] Exynos PMU fixes for cpu hotplug and cpuidle routines Alexey Klimov
@ 2026-08-28 5:36 ` Alexey Klimov
2026-08-28 5:36 ` [PATCH v2 2/2] soc: samsung: exynos-pmu: fix error paths in cpuhotplug/idle states setup Alexey Klimov
2026-09-07 10:10 ` (subset) [PATCH v2 0/2] Exynos PMU fixes for cpu hotplug and cpuidle routines Krzysztof Kozlowski
2 siblings, 0 replies; 5+ messages in thread
From: Alexey Klimov @ 2026-08-28 5:36 UTC (permalink / raw)
To: Krzysztof Kozlowski, Alim Akhtar, Peter Griffin
Cc: Sam Protsenko, linux-samsung-soc, linux-arm-kernel, linux-kernel,
stable, Sashiko
The setup_cpuhp_and_cpuidle() parses the device tree node for the
interrupt generation block via of_parse_phandle() and decrements its
reference count using of_node_put() immediately after fetching the resource
address. However, later the intr_gen_node pointer is passed into
of_syscon_register_regmap().
Fix this by declaring intr_gen_node with __free() and removing
of_node_put().
Reported-by: Sashiko <sashiko-bot@kernel.org>
Closes: https://sashiko.dev/#/patchset/20260513-exynos850-cpuhotplug-v4-0-54fec5f65362@linaro.org?part=3
Fixes: 78b72897a5c8 ("soc: samsung: exynos-pmu: Enable CPU Idle for gs101")
Cc: stable@vger.kernel.org
Signed-off-by: Alexey Klimov <alexey.klimov@linaro.org>
---
drivers/soc/samsung/exynos-pmu.c | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/drivers/soc/samsung/exynos-pmu.c b/drivers/soc/samsung/exynos-pmu.c
index f5fcdde9750e..efccdd63e40e 100644
--- a/drivers/soc/samsung/exynos-pmu.c
+++ b/drivers/soc/samsung/exynos-pmu.c
@@ -409,13 +409,12 @@ static struct notifier_block exynos_cpupm_reboot_nb = {
static int setup_cpuhp_and_cpuidle(struct device *dev)
{
- struct device_node *intr_gen_node;
+ struct device_node *intr_gen_node __free(device_node) =
+ of_parse_phandle(dev->of_node, "google,pmu-intr-gen-syscon", 0);
struct resource intrgen_res;
void __iomem *virt_addr;
int ret, cpu;
- intr_gen_node = of_parse_phandle(dev->of_node,
- "google,pmu-intr-gen-syscon", 0);
if (!intr_gen_node) {
/*
* To maintain support for older DTs that didn't specify syscon
@@ -431,8 +430,6 @@ static int setup_cpuhp_and_cpuidle(struct device *dev)
* syscon provided regmap.
*/
ret = of_address_to_resource(intr_gen_node, 0, &intrgen_res);
- of_node_put(intr_gen_node);
-
virt_addr = devm_ioremap(dev, intrgen_res.start,
resource_size(&intrgen_res));
if (!virt_addr)
--
2.51.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v2 2/2] soc: samsung: exynos-pmu: fix error paths in cpuhotplug/idle states setup
2026-08-28 5:36 [PATCH v2 0/2] Exynos PMU fixes for cpu hotplug and cpuidle routines Alexey Klimov
2026-08-28 5:36 ` [PATCH v2 1/2] soc: samsung: exynos-pmu: fix use-after-free of interrupt generator node Alexey Klimov
@ 2026-08-28 5:36 ` Alexey Klimov
2026-09-07 10:09 ` Krzysztof Kozlowski
2026-09-07 10:10 ` (subset) [PATCH v2 0/2] Exynos PMU fixes for cpu hotplug and cpuidle routines Krzysztof Kozlowski
2 siblings, 1 reply; 5+ messages in thread
From: Alexey Klimov @ 2026-08-28 5:36 UTC (permalink / raw)
To: Krzysztof Kozlowski, Alim Akhtar, Peter Griffin
Cc: Sam Protsenko, linux-samsung-soc, linux-arm-kernel, linux-kernel,
stable, Sashiko
The setup_cpuhp_and_cpuidle() initialisation sequence currently ignores
the return values of cpuhp_setup_state(), cpu_pm_register_notifier(), and
register_reboot_notifier(). If any of these registrations fail during
probe() routine, the driver returns 0, leaving the driver partially
configured.
Furthermore, if anything after setup_cpuhp_and_cpuidle() fails in probe()
routine, for instance devm_mfd_add_devices(), the probe() lacks an error
path and leaves notifiers and cpu hotplug states registered.
Introduce variables for the cpu hotplug state IDs in exynos_pmu_context
struct, that should be initialised to CPUHP_INVALID by default. Check all
return codes in setup_cpuhp_and_cpuidle(), and add an error path to remove
registered states on failure. Finally, add destroy_cpuhp_and_cpuidle()
helper to safely tear down notifiers and cpu hotplug states.
Reported-by: Sashiko <sashiko-bot@kernel.org>
Closes: https://sashiko.dev/#/patchset/20260513-exynos850-cpuhotplug-v4-0-54fec5f65362@linaro.org?part=3
Fixes: 78b72897a5c8 ("soc: samsung: exynos-pmu: Enable CPU Idle for gs101")
Cc: stable@vger.kernel.org
Signed-off-by: Alexey Klimov <alexey.klimov@linaro.org>
---
drivers/soc/samsung/exynos-pmu.c | 63 +++++++++++++++++++++++++++++++++++-----
1 file changed, 55 insertions(+), 8 deletions(-)
diff --git a/drivers/soc/samsung/exynos-pmu.c b/drivers/soc/samsung/exynos-pmu.c
index efccdd63e40e..fce922d5ab92 100644
--- a/drivers/soc/samsung/exynos-pmu.c
+++ b/drivers/soc/samsung/exynos-pmu.c
@@ -38,6 +38,8 @@ struct exynos_pmu_context {
unsigned long *in_cpuhp;
bool sys_insuspend;
bool sys_inreboot;
+ int cpuhp_prepare_state;
+ int cpuhp_online_state;
};
void __iomem *pmu_base_addr;
@@ -407,6 +409,17 @@ static struct notifier_block exynos_cpupm_reboot_nb = {
.notifier_call = exynos_cpupm_reboot_notifier,
};
+static void destroy_cpuhp_and_cpuidle(void)
+{
+ cpu_pm_unregister_notifier(&gs101_cpu_pm_notifier);
+ unregister_reboot_notifier(&exynos_cpupm_reboot_nb);
+
+ if (pmu_context->cpuhp_prepare_state != CPUHP_INVALID)
+ cpuhp_remove_state(pmu_context->cpuhp_prepare_state);
+ if (pmu_context->cpuhp_online_state != CPUHP_INVALID)
+ cpuhp_remove_state(pmu_context->cpuhp_online_state);
+}
+
static int setup_cpuhp_and_cpuidle(struct device *dev)
{
struct device_node *intr_gen_node __free(device_node) =
@@ -458,16 +471,46 @@ static int setup_cpuhp_and_cpuidle(struct device *dev)
gs101_cpuhp_pmu_online(cpu);
/* register CPU hotplug callbacks */
- cpuhp_setup_state(CPUHP_BP_PREPARE_DYN, "soc/exynos-pmu:prepare",
- gs101_cpuhp_pmu_online, NULL);
+ pmu_context->cpuhp_prepare_state = CPUHP_INVALID;
+ pmu_context->cpuhp_online_state = CPUHP_INVALID;
+
+ ret = cpuhp_setup_state(CPUHP_BP_PREPARE_DYN, "soc/exynos-pmu:prepare",
+ gs101_cpuhp_pmu_online, NULL);
+ if (ret < 0)
+ return ret;
+
+ pmu_context->cpuhp_prepare_state = ret;
+
+ ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "soc/exynos-pmu:online",
+ NULL, gs101_cpuhp_pmu_offline);
+ if (ret < 0)
+ goto clean_cpuhp_states;
- cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "soc/exynos-pmu:online",
- NULL, gs101_cpuhp_pmu_offline);
+ pmu_context->cpuhp_online_state = ret;
/* register CPU PM notifiers for cpuidle */
- cpu_pm_register_notifier(&gs101_cpu_pm_notifier);
- register_reboot_notifier(&exynos_cpupm_reboot_nb);
- return 0;
+ ret = cpu_pm_register_notifier(&gs101_cpu_pm_notifier);
+ if (ret)
+ goto clean_cpuhp_states;
+
+ ret = register_reboot_notifier(&exynos_cpupm_reboot_nb);
+ if (!ret)
+ /* Success */
+ return ret;
+
+ cpu_pm_unregister_notifier(&gs101_cpu_pm_notifier);
+
+clean_cpuhp_states:
+ if (pmu_context->cpuhp_prepare_state != CPUHP_INVALID) {
+ cpuhp_remove_state(pmu_context->cpuhp_prepare_state);
+ pmu_context->cpuhp_prepare_state = CPUHP_INVALID;
+ }
+ if (pmu_context->cpuhp_online_state != CPUHP_INVALID) {
+ cpuhp_remove_state(pmu_context->cpuhp_online_state);
+ pmu_context->cpuhp_online_state = CPUHP_INVALID;
+ }
+
+ return ret;
}
static int exynos_pmu_probe(struct platform_device *pdev)
@@ -541,8 +584,12 @@ static int exynos_pmu_probe(struct platform_device *pdev)
ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE, exynos_pmu_devs,
ARRAY_SIZE(exynos_pmu_devs), NULL, 0, NULL);
- if (ret)
+ if (ret) {
+ if (pmu_context->pmu_data && pmu_context->pmu_data->pmu_cpuhp)
+ destroy_cpuhp_and_cpuidle();
+
return ret;
+ }
if (devm_of_platform_populate(dev))
dev_err(dev, "Error populating children, reboot and poweroff might not work properly\n");
--
2.51.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH v2 2/2] soc: samsung: exynos-pmu: fix error paths in cpuhotplug/idle states setup
2026-08-28 5:36 ` [PATCH v2 2/2] soc: samsung: exynos-pmu: fix error paths in cpuhotplug/idle states setup Alexey Klimov
@ 2026-09-07 10:09 ` Krzysztof Kozlowski
0 siblings, 0 replies; 5+ messages in thread
From: Krzysztof Kozlowski @ 2026-09-07 10:09 UTC (permalink / raw)
To: Alexey Klimov, Alim Akhtar, Peter Griffin
Cc: Sam Protsenko, linux-samsung-soc, linux-arm-kernel, linux-kernel,
stable, Sashiko
On 28/08/2026 07:36, Alexey Klimov wrote:
> void __iomem *pmu_base_addr;
> @@ -407,6 +409,17 @@ static struct notifier_block exynos_cpupm_reboot_nb = {
> .notifier_call = exynos_cpupm_reboot_notifier,
> };
>
> +static void destroy_cpuhp_and_cpuidle(void)
> +{
> + cpu_pm_unregister_notifier(&gs101_cpu_pm_notifier);
> + unregister_reboot_notifier(&exynos_cpupm_reboot_nb);
> +
> + if (pmu_context->cpuhp_prepare_state != CPUHP_INVALID)
> + cpuhp_remove_state(pmu_context->cpuhp_prepare_state);
> + if (pmu_context->cpuhp_online_state != CPUHP_INVALID)
> + cpuhp_remove_state(pmu_context->cpuhp_online_state);
> +}
cleanup follows the setup usually, so this function should be after
setup_cpuhp_and_cpuidle().
> +
> static int setup_cpuhp_and_cpuidle(struct device *dev)
> {
> struct device_node *intr_gen_node __free(device_node) =
> @@ -458,16 +471,46 @@ static int setup_cpuhp_and_cpuidle(struct device *dev)
> gs101_cpuhp_pmu_online(cpu);
>
> /* register CPU hotplug callbacks */
> - cpuhp_setup_state(CPUHP_BP_PREPARE_DYN, "soc/exynos-pmu:prepare",
> - gs101_cpuhp_pmu_online, NULL);
> + pmu_context->cpuhp_prepare_state = CPUHP_INVALID;
> + pmu_context->cpuhp_online_state = CPUHP_INVALID;
> +
> + ret = cpuhp_setup_state(CPUHP_BP_PREPARE_DYN, "soc/exynos-pmu:prepare",
> + gs101_cpuhp_pmu_online, NULL);
> + if (ret < 0)
> + return ret;
> +
> + pmu_context->cpuhp_prepare_state = ret;
> +
> + ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "soc/exynos-pmu:online",
> + NULL, gs101_cpuhp_pmu_offline);
> + if (ret < 0)
> + goto clean_cpuhp_states;
You have only one state to clean here, no? Error paths must be specific
- clean only what's needed, not a catch-all with if-checks.
>
> - cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "soc/exynos-pmu:online",
> - NULL, gs101_cpuhp_pmu_offline);
> + pmu_context->cpuhp_online_state = ret;
>
> /* register CPU PM notifiers for cpuidle */
> - cpu_pm_register_notifier(&gs101_cpu_pm_notifier);
> - register_reboot_notifier(&exynos_cpupm_reboot_nb);
> - return 0;
> + ret = cpu_pm_register_notifier(&gs101_cpu_pm_notifier);
> + if (ret)
> + goto clean_cpuhp_states;
> +
> + ret = register_reboot_notifier(&exynos_cpupm_reboot_nb);
> + if (!ret)
> + /* Success */
> + return ret;
> +
> + cpu_pm_unregister_notifier(&gs101_cpu_pm_notifier);
> +
> +clean_cpuhp_states:
> + if (pmu_context->cpuhp_prepare_state != CPUHP_INVALID) {
> + cpuhp_remove_state(pmu_context->cpuhp_prepare_state);
> + pmu_context->cpuhp_prepare_state = CPUHP_INVALID;
> + }
> + if (pmu_context->cpuhp_online_state != CPUHP_INVALID) {
> + cpuhp_remove_state(pmu_context->cpuhp_online_state);
> + pmu_context->cpuhp_online_state = CPUHP_INVALID;
> + }
> +
> + return ret;
> }
>
> static int exynos_pmu_probe(struct platform_device *pdev)
> @@ -541,8 +584,12 @@ static int exynos_pmu_probe(struct platform_device *pdev)
>
> ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE, exynos_pmu_devs,
> ARRAY_SIZE(exynos_pmu_devs), NULL, 0, NULL);
> - if (ret)
> + if (ret) {
> + if (pmu_context->pmu_data && pmu_context->pmu_data->pmu_cpuhp)
> + destroy_cpuhp_and_cpuidle();
> +
> return ret;
> + }
>
> if (devm_of_platform_populate(dev))
> dev_err(dev, "Error populating children, reboot and poweroff might not work properly\n");
>
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: (subset) [PATCH v2 0/2] Exynos PMU fixes for cpu hotplug and cpuidle routines
2026-08-28 5:36 [PATCH v2 0/2] Exynos PMU fixes for cpu hotplug and cpuidle routines Alexey Klimov
2026-08-28 5:36 ` [PATCH v2 1/2] soc: samsung: exynos-pmu: fix use-after-free of interrupt generator node Alexey Klimov
2026-08-28 5:36 ` [PATCH v2 2/2] soc: samsung: exynos-pmu: fix error paths in cpuhotplug/idle states setup Alexey Klimov
@ 2026-09-07 10:10 ` Krzysztof Kozlowski
2 siblings, 0 replies; 5+ messages in thread
From: Krzysztof Kozlowski @ 2026-09-07 10:10 UTC (permalink / raw)
To: Alim Akhtar, Peter Griffin, Alexey Klimov
Cc: Sam Protsenko, linux-samsung-soc, linux-arm-kernel, linux-kernel,
stable, Sashiko
On Fri, 28 Aug 2026 06:36:45 +0100, Alexey Klimov wrote:
> This was reported by Sashiko here:
> https://sashiko.dev/#/patchset/20260513-exynos850-cpuhotplug-v4-0-54fec5f65362@linaro.org?part=3
> and was mainly introduced by enabling cpu hotplug
> support and cpuidle for gs101-based SoCs.
>
> In this second version one patch was dropped to keep things consistent with
> downstream implementation and due to lack of information. Other patches
> deal with a few missing error paths issues here and there in
> setup_cpuhp_and_cpuidle() and around. They were updated per discussions.
>
> [...]
Applied, thanks!
[1/2] soc: samsung: exynos-pmu: fix use-after-free of interrupt generator node
https://git.kernel.org/krzk/linux/c/48f344b3e83211025763ca9bc1c5f3dc544b9613
Best regards,
--
Krzysztof Kozlowski <krzk@kernel.org>
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-09-07 10:10 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-28 5:36 [PATCH v2 0/2] Exynos PMU fixes for cpu hotplug and cpuidle routines Alexey Klimov
2026-08-28 5:36 ` [PATCH v2 1/2] soc: samsung: exynos-pmu: fix use-after-free of interrupt generator node Alexey Klimov
2026-08-28 5:36 ` [PATCH v2 2/2] soc: samsung: exynos-pmu: fix error paths in cpuhotplug/idle states setup Alexey Klimov
2026-09-07 10:09 ` Krzysztof Kozlowski
2026-09-07 10:10 ` (subset) [PATCH v2 0/2] Exynos PMU fixes for cpu hotplug and cpuidle routines Krzysztof Kozlowski
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.