LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH v2 0/3] powerpc/crash: protect kdump from active watchdogs
From: Ritesh Harjani @ 2026-07-13  6:40 UTC (permalink / raw)
  To: Sourabh Jain, linuxppc-dev, maddy, mpe
  Cc: npiggin, chleroy, shivangu, hbathini, mahesh, adityag, venkat88,
	stable
In-Reply-To: <91e04278-aa90-4cbc-aeb4-f4663bf1f058@linux.ibm.com>

Sourabh Jain <sourabhjain@linux.ibm.com> writes:

> On 13/07/26 10:51, Ritesh Harjani (IBM) wrote:
>> Sourabh Jain <sourabhjain@linux.ibm.com> writes:
>>
>>> Changelog:
>>> ==========
>>>
>>> v2:
>>>   - Move H_WATCHDOG definitions to a common header for shared use
>>>     across pseries code. 1/3
>>>   - Added a new patch to handle pseries watchdog device registration
>>>     failure. 2/3
>>>   - Stop active watchdogs in crash hanlder. 3/3 Ritesh
>>>   - Add suggested-by tag 1/3 & 3/3
>>
>> Reviewed the changes and mostly looks good with some minor nits added to
>> the individual patches.
>>
>> Small request -
>> Could you please also update test results with v3 in your changelog
>> (since you mentioned we are able to reproduce the issue easily with your
>> test code).
>
> I tested this fix with the program I shared in cover letter. The watchdog
> was successfully stopped even when H_WATCHDOG is called form crash
> handler.  I will share my test details in v3 cover letter also.
>
>>
>>
>> aah one other thing I just noticed since you are ccing stable and you
>> added a Fixes tag in patch-3.
>> Patch-3 alone cannot be easily backported now due to patch-1 and
>> patch-2. There must be a way to define the dependencies if you are
>> looking for backporting the fix patch to stable tree, please check that
>> and follow that accordingly in v3.
>
> I thought about that as well, but since they are part of the same patch 
> series,
> I assumed they would be picked together. However, I don't think that 
> will work
> in all cases.
>
> I checked the older commits and noticed that a backport note was added. 
> I think
> we can do the same for the fix patch. I'll add a note indicating that the
> following patches should be backported first:
>
> powerpc/pseries: Move H_WATCHDOG definitions to a common header
> powerpc/pseries: Handle and log pseries-wdt registration failures
>
> Since these patches are not upstream yet, I'll refer to them by their 
> commit titles.
>
> Does that look good to you?
>

Documentation/process/stable-kernel-rules.rst
  Note that for a patch series, you do not have to list as prerequisites the
  patches present in the series itself. For example, if you have the following
  patch series::

    patch1
    patch2

  where patch2 depends on patch1, you do not have to list patch1 as
  prerequisite of patch2 if you have already marked patch1 for stable
  inclusion.


In that case, I think, we should mark all 3 patches for stable inclusion.

  patch 1/3   Cc: stable@vger.kernel.org
  patch 2/3   Cc: stable@vger.kernel.org
  patch 3/3   Cc: stable@vger.kernel.org
              Fixes: 69472ffa6575 ("watchdog/pseries-wdt: initial support for H_WATCHDOG-based watchdog timers")

-ritesh


^ permalink raw reply

* Re: [PATCH v2 0/3] powerpc/crash: protect kdump from active watchdogs
From: Sourabh Jain @ 2026-07-13  5:59 UTC (permalink / raw)
  To: Ritesh Harjani (IBM), linuxppc-dev, maddy, mpe
  Cc: npiggin, chleroy, shivangu, hbathini, mahesh, adityag, venkat88,
	stable
In-Reply-To: <mrvvv515.ritesh.list@gmail.com>



On 13/07/26 10:51, Ritesh Harjani (IBM) wrote:
> Sourabh Jain <sourabhjain@linux.ibm.com> writes:
>
>> Changelog:
>> ==========
>>
>> v2:
>>   - Move H_WATCHDOG definitions to a common header for shared use
>>     across pseries code. 1/3
>>   - Added a new patch to handle pseries watchdog device registration
>>     failure. 2/3
>>   - Stop active watchdogs in crash hanlder. 3/3 Ritesh
>>   - Add suggested-by tag 1/3 & 3/3
>
> Reviewed the changes and mostly looks good with some minor nits added to
> the individual patches.
>
> Small request -
> Could you please also update test results with v3 in your changelog
> (since you mentioned we are able to reproduce the issue easily with your
> test code).

I tested this fix with the program I shared in cover letter. The watchdog
was successfully stopped even when H_WATCHDOG is called form crash
handler.  I will share my test details in v3 cover letter also.

>
>
> aah one other thing I just noticed since you are ccing stable and you
> added a Fixes tag in patch-3.
> Patch-3 alone cannot be easily backported now due to patch-1 and
> patch-2. There must be a way to define the dependencies if you are
> looking for backporting the fix patch to stable tree, please check that
> and follow that accordingly in v3.

I thought about that as well, but since they are part of the same patch 
series,
I assumed they would be picked together. However, I don't think that 
will work
in all cases.

I checked the older commits and noticed that a backport note was added. 
I think
we can do the same for the fix patch. I'll add a note indicating that the
following patches should be backported first:

powerpc/pseries: Move H_WATCHDOG definitions to a common header
powerpc/pseries: Handle and log pseries-wdt registration failures

Since these patches are not upstream yet, I'll refer to them by their 
commit titles.

Does that look good to you?

- Sourabh Jain


^ permalink raw reply

* Re: [PATCH v2 0/3] powerpc/crash: protect kdump from active watchdogs
From: Ritesh Harjani @ 2026-07-13  5:21 UTC (permalink / raw)
  To: Sourabh Jain, linuxppc-dev, maddy, mpe
  Cc: npiggin, chleroy, shivangu, hbathini, mahesh, adityag, venkat88,
	stable, Sourabh Jain
In-Reply-To: <20260713035954.1559605-1-sourabhjain@linux.ibm.com>

Sourabh Jain <sourabhjain@linux.ibm.com> writes:

> Changelog:
> ==========
>
> v2:
>  - Move H_WATCHDOG definitions to a common header for shared use
>    across pseries code. 1/3
>  - Added a new patch to handle pseries watchdog device registration
>    failure. 2/3
>  - Stop active watchdogs in crash hanlder. 3/3 Ritesh
>  - Add suggested-by tag 1/3 & 3/3


Reviewed the changes and mostly looks good with some minor nits added to
the individual patches.

Small request -
Could you please also update test results with v3 in your changelog
(since you mentioned we are able to reproduce the issue easily with your
test code).


aah one other thing I just noticed since you are ccing stable and you
added a Fixes tag in patch-3.
Patch-3 alone cannot be easily backported now due to patch-1 and
patch-2. There must be a way to define the dependencies if you are
looking for backporting the fix patch to stable tree, please check that
and follow that accordingly in v3.

-ritesh



^ permalink raw reply

* Re: [PATCH v2 3/3] powerpc/crash: stop watchdogs before booting kdump kernel
From: Ritesh Harjani @ 2026-07-13  5:10 UTC (permalink / raw)
  To: Sourabh Jain, linuxppc-dev, maddy, mpe
  Cc: npiggin, chleroy, shivangu, hbathini, mahesh, adityag, venkat88,
	stable, Sourabh Jain, Mahesh Kumar G
In-Reply-To: <20260713035954.1559605-4-sourabhjain@linux.ibm.com>

Sourabh Jain <sourabhjain@linux.ibm.com> writes:

> On pseries LPAR systems, watchdog timers configured from userspace can
> remain active after a kernel panic. When a panic triggers kdump, the
> crashing kernel jumps directly to the kdump kernel without stopping
> active watchdogs. As a result, the watchdogs remain active after the
> kdump kernel starts.
>
> If dump capture takes longer than the watchdog timeout, PHYP resets the
> LPAR before the dump is fully captured, causing dump capture to fail.
>
> Fix this by issuing the `H_WATCHDOG` hcall during the crash shutdown
> sequence to stop all active watchdogs before booting the kdump kernel.
>
> Fixes: 69472ffa6575 ("watchdog/pseries-wdt: initial support for H_WATCHDOG-based watchdog timers")
> Reported-by: Mahesh Kumar G <mahe657@linux.ibm.com>
> Suggested-by: Ritesh Harjani (IBM) <ritesh.list@gmail.com>
> Signed-off-by: Sourabh Jain <sourabhjain@linux.ibm.com>
> ---
>  arch/powerpc/include/asm/papr-watchdog.h |  2 ++
>  arch/powerpc/platforms/pseries/setup.c   | 18 ++++++++++++++++++
>  2 files changed, 20 insertions(+)
>
> diff --git a/arch/powerpc/include/asm/papr-watchdog.h b/arch/powerpc/include/asm/papr-watchdog.h
> index fb3a511aa861..84bbe1ddd56f 100644
> --- a/arch/powerpc/include/asm/papr-watchdog.h
> +++ b/arch/powerpc/include/asm/papr-watchdog.h
> @@ -55,4 +55,6 @@
>  #define PSERIES_WDTQ_MIN_TIMEOUT(cap)	(((cap) >> 48) & 0xffff)
>  #define PSERIES_WDTQ_MAX_NUMBER(cap)	(((cap) >> 32) & 0xffff)
>  
> +#define PSERIES_WDT_NUM_ALL	((unsigned long)-1)
> +

minor nit:

This should be defined at the end of the H_WATCHDOG Input section.
/*
 * H_WATCHDOG Input
 *

<...>

Something like this maybe?

/*
 * R5: "watchdogNumber":
 *       PAPR says use -1 (all ones) to stop all watchdogs.
 */
#define PSERIES_WDT_NUM_ALL	((unsigned long)-1)

/*
 * H_WATCHDOG Output
 *
 * R3: Return code
 *
 <...> 

>  #endif /* _ASM_POWERPC_CRASHDUMP_PPC64_H */
> diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
> index bbb2813f8ede..2e40a9dba637 100644
> --- a/arch/powerpc/platforms/pseries/setup.c
> +++ b/arch/powerpc/platforms/pseries/setup.c
> @@ -77,6 +77,7 @@
>  #include <asm/dtl.h>
>  #include <asm/hvconsole.h>
>  #include <asm/setup.h>
> +#include <asm/papr-watchdog.h>
>  
>  #include "pseries.h"
>  
> @@ -185,6 +186,18 @@ static void __init fwnmi_init(void)
>  #endif
>  }
>  
> +#ifdef CONFIG_CRASH_DUMP
> +static void pseries_crash_stop_watchdogs(void)
> +{
> +	long rc;
> +
> +	rc = plpar_hcall_norets_notrace(H_WATCHDOG, PSERIES_WDTF_OP_STOP,
> +					PSERIES_WDT_NUM_ALL);
> +	if (rc != H_SUCCESS && rc != H_NOOP)
> +		pr_warn("Could not stop watchdogs before kdump rc=%ld\n", rc);
> +}
> +#endif /* CONFIG_CRASH_DUMP */
> +
>  /*
>   * Affix a device for the first timer to the platform bus if
>   * we have firmware support for the H_WATCHDOG hypercall.
> @@ -203,6 +216,11 @@ static __init int pseries_wdt_init(void)
>  		return PTR_ERR(pseries_wdt_dev);
>  	}
>  
> +#ifdef CONFIG_CRASH_DUMP
> +	if (crash_shutdown_register(pseries_crash_stop_watchdogs))
> +		pr_warn("Could not register watchdog crash shutdown handler\n");
> +#endif
> +

minor nit:
I don't think we need any of the #ifdef. All definitions used inside
pseries_crash_stop_watchdogs are already available and
crash_shutdown_register() already exists for !CONFIG_CRASH_DUMP, so we
may as well drop all of the ifdefs.


Otherwise LGTM, so feel free to add:
Reviewed-by: Ritesh Harjani (IBM) <ritesh.list@gmail.com>



^ permalink raw reply

* Re: [PATCH v2 2/3] powerpc/pseries: Handle and log pseries-wdt registration failures
From: Sourabh Jain @ 2026-07-13  4:44 UTC (permalink / raw)
  To: Ritesh Harjani (IBM), linuxppc-dev, maddy, mpe
  Cc: npiggin, chleroy, shivangu, hbathini, mahesh, adityag, venkat88,
	stable
In-Reply-To: <qzl7v7eh.ritesh.list@gmail.com>



On 13/07/26 09:59, Ritesh Harjani (IBM) wrote:
> Sourabh Jain <sourabhjain@linux.ibm.com> writes:
>
>> The pseries watchdog initialization registers the pseries-wdt platform
>> device using platform_device_register_simple(), but currently ignores
>> its return value.
>>
>> Check the returned pointer for errors, log a descriptive error message
>> when registration fails, and propagate the failure code to the caller.
>> This avoids silently ignoring platform device registration failures.
>>
> Fair enough.
>
>> Signed-off-by: Sourabh Jain <sourabhjain@linux.ibm.com>
>> ---
>>   arch/powerpc/platforms/pseries/setup.c | 14 ++++++++++++--
>>   1 file changed, 12 insertions(+), 2 deletions(-)
>>
>> diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
>> index 1223dc961242..bbb2813f8ede 100644
>> --- a/arch/powerpc/platforms/pseries/setup.c
>> +++ b/arch/powerpc/platforms/pseries/setup.c
>> @@ -191,8 +191,18 @@ static void __init fwnmi_init(void)
>>    */
>>   static __init int pseries_wdt_init(void)
>>   {
>> -	if (firmware_has_feature(FW_FEATURE_WATCHDOG))
>> -		platform_device_register_simple("pseries-wdt", 0, NULL, 0);
>> +	struct platform_device *pseries_wdt_dev;
> minor nit: we should rename this to pdev, since it is already under
> pseries_wdt_init(). That is generally how all platform drivers use it
> unless it requires more than one platform device.
>
> But either ways the patch looks good to me:
>
> Reviewed-by: Ritesh Harjani (IBM) <ritesh.list@gmail.com>

Thanks for the review. I will rename the variable in next version.

- Sourabh Jain

>
>> +
>> +	if (!firmware_has_feature(FW_FEATURE_WATCHDOG))
>> +		return 0;
>> +
>> +	pseries_wdt_dev = platform_device_register_simple("pseries-wdt", 0, NULL, 0);
>> +
>> +	if (IS_ERR(pseries_wdt_dev)) {
>> +		pr_err("Failed to register pseries-wdt platform device\n");
>> +		return PTR_ERR(pseries_wdt_dev);
>> +	}
>> +
>>   	return 0;
>>   }
>>   machine_subsys_initcall(pseries, pseries_wdt_init);
>> -- 
>> 2.52.0



^ permalink raw reply

* Re: [PATCH v2 2/3] powerpc/pseries: Handle and log pseries-wdt registration failures
From: Ritesh Harjani @ 2026-07-13  4:29 UTC (permalink / raw)
  To: Sourabh Jain, linuxppc-dev, maddy, mpe
  Cc: npiggin, chleroy, shivangu, hbathini, mahesh, adityag, venkat88,
	stable, Sourabh Jain
In-Reply-To: <20260713035954.1559605-3-sourabhjain@linux.ibm.com>

Sourabh Jain <sourabhjain@linux.ibm.com> writes:

> The pseries watchdog initialization registers the pseries-wdt platform
> device using platform_device_register_simple(), but currently ignores
> its return value.
>
> Check the returned pointer for errors, log a descriptive error message
> when registration fails, and propagate the failure code to the caller.
> This avoids silently ignoring platform device registration failures.
>

Fair enough.

> Signed-off-by: Sourabh Jain <sourabhjain@linux.ibm.com>
> ---
>  arch/powerpc/platforms/pseries/setup.c | 14 ++++++++++++--
>  1 file changed, 12 insertions(+), 2 deletions(-)
>
> diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
> index 1223dc961242..bbb2813f8ede 100644
> --- a/arch/powerpc/platforms/pseries/setup.c
> +++ b/arch/powerpc/platforms/pseries/setup.c
> @@ -191,8 +191,18 @@ static void __init fwnmi_init(void)
>   */
>  static __init int pseries_wdt_init(void)
>  {
> -	if (firmware_has_feature(FW_FEATURE_WATCHDOG))
> -		platform_device_register_simple("pseries-wdt", 0, NULL, 0);
> +	struct platform_device *pseries_wdt_dev;

minor nit: we should rename this to pdev, since it is already under
pseries_wdt_init(). That is generally how all platform drivers use it
unless it requires more than one platform device.

But either ways the patch looks good to me:

Reviewed-by: Ritesh Harjani (IBM) <ritesh.list@gmail.com>

> +
> +	if (!firmware_has_feature(FW_FEATURE_WATCHDOG))
> +		return 0;
> +
> +	pseries_wdt_dev = platform_device_register_simple("pseries-wdt", 0, NULL, 0);
> +
> +	if (IS_ERR(pseries_wdt_dev)) {
> +		pr_err("Failed to register pseries-wdt platform device\n");
> +		return PTR_ERR(pseries_wdt_dev);
> +	}
> +
>  	return 0;
>  }
>  machine_subsys_initcall(pseries, pseries_wdt_init);
> -- 
> 2.52.0


^ permalink raw reply

* Re: [PATCH v2 1/3] powerpc/pseries: Move H_WATCHDOG definitions to a common header
From: Sourabh Jain @ 2026-07-13  4:29 UTC (permalink / raw)
  To: Ritesh Harjani (IBM), linuxppc-dev, maddy, mpe
  Cc: npiggin, chleroy, shivangu, hbathini, mahesh, adityag, venkat88,
	stable
In-Reply-To: <se5nv7wu.ritesh.list@gmail.com>



On 13/07/26 09:48, Ritesh Harjani (IBM) wrote:
> Sourabh Jain <sourabhjain@linux.ibm.com> writes:
>
>> The H_WATCHDOG input and output definitions are currently local to the
>> pseries watchdog driver. The next patch in this series also needs these
>> definitions to issue H_WATCHDOG hypercalls outside the watchdog driver.
>>
>> Move the H_WATCHDOG definitions to a new common header,
>> asm/papr-watchdog.h, so they can be shared without duplicating the
>> PAPR watchdog definitions.
>>
>> No functional changes.
>>
>> Suggested-by: Ritesh Harjani (IBM) <ritesh.list@gmail.com>
>> Signed-off-by: Sourabh Jain <sourabhjain@linux.ibm.com>
>> ---
>>   arch/powerpc/include/asm/papr-watchdog.h | 58 ++++++++++++++++++++++++
>>   drivers/watchdog/pseries-wdt.c           | 53 +---------------------
>>   2 files changed, 59 insertions(+), 52 deletions(-)
>>   create mode 100644 arch/powerpc/include/asm/papr-watchdog.h
>>
>> diff --git a/arch/powerpc/include/asm/papr-watchdog.h b/arch/powerpc/include/asm/papr-watchdog.h
>> new file mode 100644
>> index 000000000000..fb3a511aa861
>> --- /dev/null
>> +++ b/arch/powerpc/include/asm/papr-watchdog.h
>> @@ -0,0 +1,58 @@
>> +/* SPDX-License-Identifier: GPL-2.0-only */
>> +
>> +#ifndef _ASM_POWERPC_CRASHDUMP_PPC64_H
>> +#define _ASM_POWERPC_CRASHDUMP_PPC64_H
> should be _ASM_POWERPC_PAPR_WATCHDOG_H

oops my bad. I will fix it in v3.


>
>> +
>> +/*
>> + * H_WATCHDOG Input
>> + *
>> + * R4: "flags":
>> + *
>> + *         Bits 48-55: "operation"
>> + */
>> +#define PSERIES_WDTF_OP_START	0x100UL		/* start timer */
>> +#define PSERIES_WDTF_OP_STOP	0x200UL		/* stop timer */
>> +#define PSERIES_WDTF_OP_QUERY	0x300UL		/* query timer capabilities */
>> +
>> +/*
>> + *         Bits 56-63: "timeoutAction" (for "Start Watchdog" only)
>> + */
>> +#define PSERIES_WDTF_ACTION_HARD_POWEROFF	0x1UL	/* poweroff */
>> +#define PSERIES_WDTF_ACTION_HARD_RESTART	0x2UL	/* restart */
>> +#define PSERIES_WDTF_ACTION_DUMP_RESTART	0x3UL	/* dump + restart */
>> +
>> +/*
>> + * H_WATCHDOG Output
>> + *
>> + * R3: Return code
>> + *
>> + *     H_SUCCESS    The operation completed.
>> + *
>> + *     H_BUSY	    The hypervisor is too busy; retry the operation.
>> + *
>> + *     H_PARAMETER  The given "flags" are somehow invalid.  Either the
>> + *                  "operation" or "timeoutAction" is invalid, or a
>> + *                  reserved bit is set.
>> + *
>> + *     H_P2         The given "watchdogNumber" is zero or exceeds the
>> + *                  supported maximum value.
>> + *
>> + *     H_P3         The given "timeoutInMs" is below the supported
>> + *                  minimum value.
>> + *
>> + *     H_NOOP       The given "watchdogNumber" is already stopped.
>> + *
>> + *     H_HARDWARE   The operation failed for ineffable reasons.
>> + *
>> + *     H_FUNCTION   The H_WATCHDOG hypercall is not supported by this
>> + *                  hypervisor.
>> + *
>> + * R4:
>> + *
>> + * - For the "Query Watchdog Capabilities" operation, a 64-bit
>> + *   structure:
>> + */
>> +#define PSERIES_WDTQ_MIN_TIMEOUT(cap)	(((cap) >> 48) & 0xffff)
>> +#define PSERIES_WDTQ_MAX_NUMBER(cap)	(((cap) >> 32) & 0xffff)
>> +
>> +#endif /* _ASM_POWERPC_CRASHDUMP_PPC64_H */
> ditto


^ permalink raw reply

* [PATCH v2 2/2] Documentation/ABI: remove old fadump sysfs doc
From: Sourabh Jain @ 2026-07-13  4:26 UTC (permalink / raw)
  To: linuxppc-dev, maddy, mpe, ritesh.list
  Cc: npiggin, chleroy, shivangu, hbathini, mahesh, adityag, venkat88,
	Sourabh Jain
In-Reply-To: <20260713042636.1599868-1-sourabhjain@linux.ibm.com>

Patch with title "powerpc/fadump: remove old sysfs symlink" removed the
deprecated fadump sysfs. So remove the respective ABI documents.

Additionally remove the reference of old fadump sysfs from fadump
document.

The alternative sysfs is documented at:
Documentation/ABI/testing/sysfs-kernel-fadump

Signed-off-by: Sourabh Jain <sourabhjain@linux.ibm.com>
---
 .../ABI/obsolete/sysfs-kernel-fadump_enabled  |  9 -----
 .../obsolete/sysfs-kernel-fadump_registered   | 10 ------
 .../obsolete/sysfs-kernel-fadump_release_mem  | 10 ------
 .../arch/powerpc/firmware-assisted-dump.rst   | 33 +++++++------------
 4 files changed, 11 insertions(+), 51 deletions(-)
 delete mode 100644 Documentation/ABI/obsolete/sysfs-kernel-fadump_enabled
 delete mode 100644 Documentation/ABI/obsolete/sysfs-kernel-fadump_registered
 delete mode 100644 Documentation/ABI/obsolete/sysfs-kernel-fadump_release_mem

diff --git a/Documentation/ABI/obsolete/sysfs-kernel-fadump_enabled b/Documentation/ABI/obsolete/sysfs-kernel-fadump_enabled
deleted file mode 100644
index e9c2de8b3688..000000000000
--- a/Documentation/ABI/obsolete/sysfs-kernel-fadump_enabled
+++ /dev/null
@@ -1,9 +0,0 @@
-This ABI is renamed and moved to a new location /sys/kernel/fadump/enabled.
-
-What:		/sys/kernel/fadump_enabled
-Date:		Feb 2012
-Contact:	linuxppc-dev@lists.ozlabs.org
-Description:	read only
-		Primarily used to identify whether the FADump is enabled in
-		the kernel or not.
-User:		Kdump service
diff --git a/Documentation/ABI/obsolete/sysfs-kernel-fadump_registered b/Documentation/ABI/obsolete/sysfs-kernel-fadump_registered
deleted file mode 100644
index dae880b1a5d5..000000000000
--- a/Documentation/ABI/obsolete/sysfs-kernel-fadump_registered
+++ /dev/null
@@ -1,10 +0,0 @@
-This ABI is renamed and moved to a new location /sys/kernel/fadump/registered.
-
-What:		/sys/kernel/fadump_registered
-Date:		Feb 2012
-Contact:	linuxppc-dev@lists.ozlabs.org
-Description:	read/write
-		Helps to control the dump collect feature from userspace.
-		Setting 1 to this file enables the system to collect the
-		dump and 0 to disable it.
-User:		Kdump service
diff --git a/Documentation/ABI/obsolete/sysfs-kernel-fadump_release_mem b/Documentation/ABI/obsolete/sysfs-kernel-fadump_release_mem
deleted file mode 100644
index ca2396edb5f1..000000000000
--- a/Documentation/ABI/obsolete/sysfs-kernel-fadump_release_mem
+++ /dev/null
@@ -1,10 +0,0 @@
-This ABI is renamed and moved to a new location /sys/kernel/fadump/release_mem.
-
-What:		/sys/kernel/fadump_release_mem
-Date:		Feb 2012
-Contact:	linuxppc-dev@lists.ozlabs.org
-Description:	write only
-		This is a special sysfs file and only available when
-		the system is booted to capture the vmcore using FADump.
-		It is used to release the memory reserved by FADump to
-		save the crash dump.
diff --git a/Documentation/arch/powerpc/firmware-assisted-dump.rst b/Documentation/arch/powerpc/firmware-assisted-dump.rst
index 7e266e749cd5..717e30e8b6cd 100644
--- a/Documentation/arch/powerpc/firmware-assisted-dump.rst
+++ b/Documentation/arch/powerpc/firmware-assisted-dump.rst
@@ -19,9 +19,9 @@ in production use.
 - Unlike phyp dump, userspace tool does not need to refer any sysfs
   interface while reading /proc/vmcore.
 - Unlike phyp dump, FADump allows user to release all the memory reserved
-  for dump, with a single operation of echo 1 > /sys/kernel/fadump_release_mem.
+  for dump, with a single operation of echo 1 > /sys/kernel/fadump/release_mem.
 - Once enabled through kernel boot parameter, FADump can be
-  started/stopped through /sys/kernel/fadump_registered interface (see
+  started/stopped through /sys/kernel/fadump/registered interface (see
   sysfs files section below) and can be easily integrated with kdump
   service start/stop init scripts.
 
@@ -86,13 +86,13 @@ as follows:
    network, nas, san, iscsi, etc. as desired.
 
 -  Once the userspace tool is done saving dump, it will echo
-   '1' to /sys/kernel/fadump_release_mem to release the reserved
+   '1' to /sys/kernel/fadump/release_mem to release the reserved
    memory back to general use, except the memory required for
    next firmware-assisted dump registration.
 
    e.g.::
 
-     # echo 1 > /sys/kernel/fadump_release_mem
+     # echo 1 > /sys/kernel/fadump/release_mem
 
 Please note that the firmware-assisted dump feature
 is only available on POWER6 and above systems on pSeries
@@ -152,7 +152,7 @@ then everything but boot memory size of RAM is reserved during
 early boot (See Fig. 2). This area is released once we finish
 collecting the dump from user land scripts (e.g. kdump scripts)
 that are run. If there is dump data, then the
-/sys/kernel/fadump_release_mem file is created, and the reserved
+/sys/kernel/fadump/release_mem file is created, and the reserved
 memory is held.
 
 If there is no waiting dump data, then only the memory required to
@@ -281,7 +281,7 @@ the control files and debugfs file to display memory reserved region.
 
 Here is the list of files under kernel sysfs:
 
- /sys/kernel/fadump_enabled
+ /sys/kernel/fadump/enabled
     This is used to display the FADump status.
 
     - 0 = FADump is disabled
@@ -290,15 +290,15 @@ Here is the list of files under kernel sysfs:
     This interface can be used by kdump init scripts to identify if
     FADump is enabled in the kernel and act accordingly.
 
- /sys/kernel/fadump_registered
+ /sys/kernel/fadump/registered
     This is used to display the FADump registration status as well
     as to control (start/stop) the FADump registration.
 
     - 0 = FADump is not registered.
     - 1 = FADump is registered and ready to handle system crash.
 
-    To register FADump echo 1 > /sys/kernel/fadump_registered and
-    echo 0 > /sys/kernel/fadump_registered for un-register and stop the
+    To register FADump echo 1 > /sys/kernel/fadump/registered and
+    echo 0 > /sys/kernel/fadump/registered for un-register and stop the
     FADump. Once the FADump is un-registered, the system crash will not
     be handled and vmcore will not be captured. This interface can be
     easily integrated with kdump service start/stop.
@@ -308,13 +308,13 @@ Here is the list of files under kernel sysfs:
    This is used to display the memory reserved by FADump for saving the
    crash dump.
 
- /sys/kernel/fadump_release_mem
+ /sys/kernel/fadump/release_mem
     This file is available only when FADump is active during
     second kernel. This is used to release the reserved memory
     region that are held for saving crash dump. To release the
     reserved memory echo 1 to it::
 
-	echo 1  > /sys/kernel/fadump_release_mem
+	echo 1  > /sys/kernel/fadump/release_mem
 
     After echo 1, the content of the /sys/kernel/debug/powerpc/fadump_region
     file will change to reflect the new memory reservations.
@@ -335,17 +335,6 @@ Note: /sys/kernel/fadump_release_opalcore sysfs has moved to
 
     echo 1  > /sys/firmware/opal/mpipl/release_core
 
-Note: The following FADump sysfs files are deprecated.
-
-+----------------------------------+--------------------------------+
-| Deprecated                       | Alternative                    |
-+----------------------------------+--------------------------------+
-| /sys/kernel/fadump_enabled       | /sys/kernel/fadump/enabled     |
-+----------------------------------+--------------------------------+
-| /sys/kernel/fadump_registered    | /sys/kernel/fadump/registered  |
-+----------------------------------+--------------------------------+
-| /sys/kernel/fadump_release_mem   | /sys/kernel/fadump/release_mem |
-+----------------------------------+--------------------------------+
 
 Here is the list of files under powerpc debugfs:
 (Assuming debugfs is mounted on /sys/kernel/debug directory.)
-- 
2.52.0



^ permalink raw reply related

* [PATCH v2 1/2] powerpc/fadump: remove old sysfs symlink
From: Sourabh Jain @ 2026-07-13  4:26 UTC (permalink / raw)
  To: linuxppc-dev, maddy, mpe, ritesh.list
  Cc: npiggin, chleroy, shivangu, hbathini, mahesh, adityag, venkat88,
	Sourabh Jain
In-Reply-To: <20260713042636.1599868-1-sourabhjain@linux.ibm.com>

Commit d418b19f34ed ("powerpc/fadump: Reorganize /sys/kernel/fadump_*
sysfs files") and commit 3f5f1f22ef10 ("Documentation/ABI: Mark
/sys/kernel/fadump_* sysfs files deprecated") moved the
/sys/kernel/fadump_* sysfs files to /sys/kernel/fadump/ and deprecated
the old files in 2019.

To maintain backward compatibility, symlinks were added at the old
locations so existing tools could still work. References [1][2] now use
the new sysfs interface, so we can safely remove the old symlinks.

Link: https://github.com/rhkdump/kdump-utils/commit/fc7c65312a5bef115ce40818bf43ddd3b01b8958 [1]
Link: https://github.com/openSUSE/kdump/commit/c274a22ff5f326c8afaa7bba60bd1b86abfc4fab [2]

Signed-off-by: Sourabh Jain <sourabhjain@linux.ibm.com>
---
 arch/powerpc/kernel/fadump.c | 36 ------------------------------------
 1 file changed, 36 deletions(-)

diff --git a/arch/powerpc/kernel/fadump.c b/arch/powerpc/kernel/fadump.c
index 7f79c9aea4a9..7a23b7e7d643 100644
--- a/arch/powerpc/kernel/fadump.c
+++ b/arch/powerpc/kernel/fadump.c
@@ -1592,43 +1592,7 @@ static void __init fadump_init_files(void)
 		pr_err("sysfs group creation failed (%d), unregistering FADump",
 		       rc);
 		unregister_fadump();
-		return;
-	}
-
-	/*
-	 * The FADump sysfs are moved from kernel_kobj to fadump_kobj need to
-	 * create symlink at old location to maintain backward compatibility.
-	 *
-	 *      - fadump_enabled -> fadump/enabled
-	 *      - fadump_registered -> fadump/registered
-	 *      - fadump_release_mem -> fadump/release_mem
-	 */
-	rc = compat_only_sysfs_link_entry_to_kobj(kernel_kobj, fadump_kobj,
-						  "enabled", "fadump_enabled");
-	if (rc) {
-		pr_err("unable to create fadump_enabled symlink (%d)", rc);
-		return;
-	}
-
-	rc = compat_only_sysfs_link_entry_to_kobj(kernel_kobj, fadump_kobj,
-						  "registered",
-						  "fadump_registered");
-	if (rc) {
-		pr_err("unable to create fadump_registered symlink (%d)", rc);
-		sysfs_remove_link(kernel_kobj, "fadump_enabled");
-		return;
 	}
-
-	if (fw_dump.dump_active) {
-		rc = compat_only_sysfs_link_entry_to_kobj(kernel_kobj,
-							  fadump_kobj,
-							  "release_mem",
-							  "fadump_release_mem");
-		if (rc)
-			pr_err("unable to create fadump_release_mem symlink (%d)",
-			       rc);
-	}
-	return;
 }
 
 static int __init fadump_setup_elfcorehdr_buf(void)
-- 
2.52.0



^ permalink raw reply related

* [PATCH v2 0/2] powerpc/fadump: remove deprecated sysfs compatibility links
From: Sourabh Jain @ 2026-07-13  4:26 UTC (permalink / raw)
  To: linuxppc-dev, maddy, mpe, ritesh.list
  Cc: npiggin, chleroy, shivangu, hbathini, mahesh, adityag, venkat88,
	Sourabh Jain

The FADump sysfs interface was reorganized in 2019 by moving the
/sys/kernel/fadump_* files under /sys/kernel/fadump/ and marking the
old paths as deprecated. Compatibility symlinks were retained to avoid
breaking existing userspace.

The following deprecated compatibility symlinks are removed by this
series:

/sys/kernel/fadump_enabled
/sys/kernel/fadump_registered
/sys/kernel/fadump_release_mem

The corresponding supported interfaces remain:

/sys/kernel/fadump/enabled
/sys/kernel/fadump/registered
/sys/kernel/fadump/release_mem

The major userspace consumers have since been updated to use the new
interface, and the deprecated paths have remained supported for several
years. This series completes the transition by removing the compatibility
symlinks and updating the documentation to reference only the current
sysfs interface.

Sourabh Jain (2):
  powerpc/fadump: remove old sysfs symlink
  Documentation/ABI: remove old fadump sysfs doc

 .../ABI/obsolete/sysfs-kernel-fadump_enabled  |  9 -----
 .../obsolete/sysfs-kernel-fadump_registered   | 10 ------
 .../obsolete/sysfs-kernel-fadump_release_mem  | 10 ------
 .../arch/powerpc/firmware-assisted-dump.rst   | 33 ++++++-----------
 arch/powerpc/kernel/fadump.c                  | 36 -------------------
 5 files changed, 11 insertions(+), 87 deletions(-)
 delete mode 100644 Documentation/ABI/obsolete/sysfs-kernel-fadump_enabled
 delete mode 100644 Documentation/ABI/obsolete/sysfs-kernel-fadump_registered
 delete mode 100644 Documentation/ABI/obsolete/sysfs-kernel-fadump_release_mem

-- 
2.52.0



^ permalink raw reply

* Re: [PATCH v2 1/3] powerpc/pseries: Move H_WATCHDOG definitions to a common header
From: Ritesh Harjani @ 2026-07-13  4:18 UTC (permalink / raw)
  To: Sourabh Jain, linuxppc-dev, maddy, mpe
  Cc: npiggin, chleroy, shivangu, hbathini, mahesh, adityag, venkat88,
	stable, Sourabh Jain
In-Reply-To: <20260713035954.1559605-2-sourabhjain@linux.ibm.com>

Sourabh Jain <sourabhjain@linux.ibm.com> writes:

> The H_WATCHDOG input and output definitions are currently local to the
> pseries watchdog driver. The next patch in this series also needs these
> definitions to issue H_WATCHDOG hypercalls outside the watchdog driver.
>
> Move the H_WATCHDOG definitions to a new common header,
> asm/papr-watchdog.h, so they can be shared without duplicating the
> PAPR watchdog definitions.
>
> No functional changes.
>
> Suggested-by: Ritesh Harjani (IBM) <ritesh.list@gmail.com>
> Signed-off-by: Sourabh Jain <sourabhjain@linux.ibm.com>
> ---
>  arch/powerpc/include/asm/papr-watchdog.h | 58 ++++++++++++++++++++++++
>  drivers/watchdog/pseries-wdt.c           | 53 +---------------------
>  2 files changed, 59 insertions(+), 52 deletions(-)
>  create mode 100644 arch/powerpc/include/asm/papr-watchdog.h
>
> diff --git a/arch/powerpc/include/asm/papr-watchdog.h b/arch/powerpc/include/asm/papr-watchdog.h
> new file mode 100644
> index 000000000000..fb3a511aa861
> --- /dev/null
> +++ b/arch/powerpc/include/asm/papr-watchdog.h
> @@ -0,0 +1,58 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +
> +#ifndef _ASM_POWERPC_CRASHDUMP_PPC64_H
> +#define _ASM_POWERPC_CRASHDUMP_PPC64_H

should be _ASM_POWERPC_PAPR_WATCHDOG_H

> +
> +/*
> + * H_WATCHDOG Input
> + *
> + * R4: "flags":
> + *
> + *         Bits 48-55: "operation"
> + */
> +#define PSERIES_WDTF_OP_START	0x100UL		/* start timer */
> +#define PSERIES_WDTF_OP_STOP	0x200UL		/* stop timer */
> +#define PSERIES_WDTF_OP_QUERY	0x300UL		/* query timer capabilities */
> +
> +/*
> + *         Bits 56-63: "timeoutAction" (for "Start Watchdog" only)
> + */
> +#define PSERIES_WDTF_ACTION_HARD_POWEROFF	0x1UL	/* poweroff */
> +#define PSERIES_WDTF_ACTION_HARD_RESTART	0x2UL	/* restart */
> +#define PSERIES_WDTF_ACTION_DUMP_RESTART	0x3UL	/* dump + restart */
> +
> +/*
> + * H_WATCHDOG Output
> + *
> + * R3: Return code
> + *
> + *     H_SUCCESS    The operation completed.
> + *
> + *     H_BUSY	    The hypervisor is too busy; retry the operation.
> + *
> + *     H_PARAMETER  The given "flags" are somehow invalid.  Either the
> + *                  "operation" or "timeoutAction" is invalid, or a
> + *                  reserved bit is set.
> + *
> + *     H_P2         The given "watchdogNumber" is zero or exceeds the
> + *                  supported maximum value.
> + *
> + *     H_P3         The given "timeoutInMs" is below the supported
> + *                  minimum value.
> + *
> + *     H_NOOP       The given "watchdogNumber" is already stopped.
> + *
> + *     H_HARDWARE   The operation failed for ineffable reasons.
> + *
> + *     H_FUNCTION   The H_WATCHDOG hypercall is not supported by this
> + *                  hypervisor.
> + *
> + * R4:
> + *
> + * - For the "Query Watchdog Capabilities" operation, a 64-bit
> + *   structure:
> + */
> +#define PSERIES_WDTQ_MIN_TIMEOUT(cap)	(((cap) >> 48) & 0xffff)
> +#define PSERIES_WDTQ_MAX_NUMBER(cap)	(((cap) >> 32) & 0xffff)
> +
> +#endif /* _ASM_POWERPC_CRASHDUMP_PPC64_H */

ditto

-ritesh


^ permalink raw reply

* [PATCH v2 3/3] powerpc/crash: stop watchdogs before booting kdump kernel
From: Sourabh Jain @ 2026-07-13  3:59 UTC (permalink / raw)
  To: linuxppc-dev, maddy, mpe, ritesh.list
  Cc: npiggin, chleroy, shivangu, hbathini, mahesh, adityag, venkat88,
	stable, Sourabh Jain, Mahesh Kumar G
In-Reply-To: <20260713035954.1559605-1-sourabhjain@linux.ibm.com>

On pseries LPAR systems, watchdog timers configured from userspace can
remain active after a kernel panic. When a panic triggers kdump, the
crashing kernel jumps directly to the kdump kernel without stopping
active watchdogs. As a result, the watchdogs remain active after the
kdump kernel starts.

If dump capture takes longer than the watchdog timeout, PHYP resets the
LPAR before the dump is fully captured, causing dump capture to fail.

Fix this by issuing the `H_WATCHDOG` hcall during the crash shutdown
sequence to stop all active watchdogs before booting the kdump kernel.

Fixes: 69472ffa6575 ("watchdog/pseries-wdt: initial support for H_WATCHDOG-based watchdog timers")
Reported-by: Mahesh Kumar G <mahe657@linux.ibm.com>
Suggested-by: Ritesh Harjani (IBM) <ritesh.list@gmail.com>
Signed-off-by: Sourabh Jain <sourabhjain@linux.ibm.com>
---
 arch/powerpc/include/asm/papr-watchdog.h |  2 ++
 arch/powerpc/platforms/pseries/setup.c   | 18 ++++++++++++++++++
 2 files changed, 20 insertions(+)

diff --git a/arch/powerpc/include/asm/papr-watchdog.h b/arch/powerpc/include/asm/papr-watchdog.h
index fb3a511aa861..84bbe1ddd56f 100644
--- a/arch/powerpc/include/asm/papr-watchdog.h
+++ b/arch/powerpc/include/asm/papr-watchdog.h
@@ -55,4 +55,6 @@
 #define PSERIES_WDTQ_MIN_TIMEOUT(cap)	(((cap) >> 48) & 0xffff)
 #define PSERIES_WDTQ_MAX_NUMBER(cap)	(((cap) >> 32) & 0xffff)
 
+#define PSERIES_WDT_NUM_ALL	((unsigned long)-1)
+
 #endif /* _ASM_POWERPC_CRASHDUMP_PPC64_H */
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index bbb2813f8ede..2e40a9dba637 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -77,6 +77,7 @@
 #include <asm/dtl.h>
 #include <asm/hvconsole.h>
 #include <asm/setup.h>
+#include <asm/papr-watchdog.h>
 
 #include "pseries.h"
 
@@ -185,6 +186,18 @@ static void __init fwnmi_init(void)
 #endif
 }
 
+#ifdef CONFIG_CRASH_DUMP
+static void pseries_crash_stop_watchdogs(void)
+{
+	long rc;
+
+	rc = plpar_hcall_norets_notrace(H_WATCHDOG, PSERIES_WDTF_OP_STOP,
+					PSERIES_WDT_NUM_ALL);
+	if (rc != H_SUCCESS && rc != H_NOOP)
+		pr_warn("Could not stop watchdogs before kdump rc=%ld\n", rc);
+}
+#endif /* CONFIG_CRASH_DUMP */
+
 /*
  * Affix a device for the first timer to the platform bus if
  * we have firmware support for the H_WATCHDOG hypercall.
@@ -203,6 +216,11 @@ static __init int pseries_wdt_init(void)
 		return PTR_ERR(pseries_wdt_dev);
 	}
 
+#ifdef CONFIG_CRASH_DUMP
+	if (crash_shutdown_register(pseries_crash_stop_watchdogs))
+		pr_warn("Could not register watchdog crash shutdown handler\n");
+#endif
+
 	return 0;
 }
 machine_subsys_initcall(pseries, pseries_wdt_init);
-- 
2.52.0



^ permalink raw reply related

* [PATCH v2 2/3] powerpc/pseries: Handle and log pseries-wdt registration failures
From: Sourabh Jain @ 2026-07-13  3:59 UTC (permalink / raw)
  To: linuxppc-dev, maddy, mpe, ritesh.list
  Cc: npiggin, chleroy, shivangu, hbathini, mahesh, adityag, venkat88,
	stable, Sourabh Jain
In-Reply-To: <20260713035954.1559605-1-sourabhjain@linux.ibm.com>

The pseries watchdog initialization registers the pseries-wdt platform
device using platform_device_register_simple(), but currently ignores
its return value.

Check the returned pointer for errors, log a descriptive error message
when registration fails, and propagate the failure code to the caller.
This avoids silently ignoring platform device registration failures.

Signed-off-by: Sourabh Jain <sourabhjain@linux.ibm.com>
---
 arch/powerpc/platforms/pseries/setup.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index 1223dc961242..bbb2813f8ede 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -191,8 +191,18 @@ static void __init fwnmi_init(void)
  */
 static __init int pseries_wdt_init(void)
 {
-	if (firmware_has_feature(FW_FEATURE_WATCHDOG))
-		platform_device_register_simple("pseries-wdt", 0, NULL, 0);
+	struct platform_device *pseries_wdt_dev;
+
+	if (!firmware_has_feature(FW_FEATURE_WATCHDOG))
+		return 0;
+
+	pseries_wdt_dev = platform_device_register_simple("pseries-wdt", 0, NULL, 0);
+
+	if (IS_ERR(pseries_wdt_dev)) {
+		pr_err("Failed to register pseries-wdt platform device\n");
+		return PTR_ERR(pseries_wdt_dev);
+	}
+
 	return 0;
 }
 machine_subsys_initcall(pseries, pseries_wdt_init);
-- 
2.52.0



^ permalink raw reply related

* [PATCH v2 0/3] powerpc/crash: protect kdump from active watchdogs
From: Sourabh Jain @ 2026-07-13  3:59 UTC (permalink / raw)
  To: linuxppc-dev, maddy, mpe, ritesh.list
  Cc: npiggin, chleroy, shivangu, hbathini, mahesh, adityag, venkat88,
	stable, Sourabh Jain

On pseries LPAR systems in a high-availability environment using the
SBD[1][2] service, I observed that the system abruptly rebooted before
dump capture could complete.

Further investigation showed that SBD had configured a watchdog with
a 30-second timeout. Since the kernel crashes directly into the
kdump kernel without shutting down userspace services, the watchdog
remained active during dump capture. Once the watchdog timeout
expired, PHYP reset the LPAR, causing dump capture to fail.

The issue was reproducible only when the watchdog was active. Dump
capture completed successfully after disabling the watchdog,
stopping the SBD service, or increasing the watchdog timeout value.

This patch fixes the issue by stopping all active watchdogs on the
crash shutdown path before booting the kdump kernel.

Driver that export the hardware watchdog device is:
drivers/watchdog/pseries-wdt.c

[1] https://github.com/clusterlabs/sbd/blob/main/man/sbd.8.pod.in
[2] https://documentation.suse.com/sle-ha/15-SP4/html/SLE-HA-all/cha-ha-storage-protect.html

Changelog:
==========

v2:
 - Move H_WATCHDOG definitions to a common header for shared use
   across pseries code. 1/3
 - Added a new patch to handle pseries watchdog device registration
   failure. 2/3
 - Stop active watchdogs in crash hanlder. 3/3 Ritesh
 - Add suggested-by tag 1/3 & 3/3

v1:
https://lore.kernel.org/all/20260603070217.483696-1-sourabhjain@linux.ibm.com/


This issue can be reproduce using below program:
------------------------------------------------

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <linux/watchdog.h>

#define WATCHDOG_DEV    "/dev/watchdog"
#define TIMEOUT         10
#define PET_INTERVAL    1

static int wdt_fd = -1;

static void watchdog_close(int disarm)
{
    int flags;

    if (wdt_fd < 0)
        return;

    if (disarm) {
        flags = WDIOS_DISABLECARD;
        if (ioctl(wdt_fd, WDIOC_SETOPTIONS, &flags) < 0)
            printf("WDIOS_DISABLECARD failed: %m (nowayout may be set)\n");
        else
            printf("Watchdog disabled via WDIOS_DISABLECARD\n");

        if (write(wdt_fd, "V", 1) < 0)
            printf("Magic 'V' write failed: %m\n");
        else
            printf("Magic 'V' written\n");
    } else {
        printf("Closing WITHOUT disarming - watchdog keeps running!\n");
    }

    close(wdt_fd);
    wdt_fd = -1;
    printf("Watchdog fd closed\n");
}

static void safe_exit(int sig)
{
    printf("\nSignal %d received - disarming watchdog...\n", sig);
    watchdog_close(1);
    exit(0);
}

static int watchdog_init(void)
{
    int flags, timeout = TIMEOUT;
    struct watchdog_info ident;

    printf("Opening %s...\n", WATCHDOG_DEV);
    wdt_fd = open(WATCHDOG_DEV, O_WRONLY);
    if (wdt_fd < 0) {
        printf("Failed to open %s: %m\n", WATCHDOG_DEV);
        return -1;
    }
    printf("Watchdog opened and ARMED\n");

    flags = WDIOS_ENABLECARD;
    if (ioctl(wdt_fd, WDIOC_SETOPTIONS, &flags) < 0)
        /* ENOTTY = driver always enabled, that's fine */
        printf("WDIOS_ENABLECARD: %m (ok if ENOTTY)\n");
    else
        printf("Watchdog enabled via WDIOS_ENABLECARD\n");

    if (ioctl(wdt_fd, WDIOC_SETTIMEOUT, &timeout) < 0)
        printf("WDIOC_SETTIMEOUT failed: %m\n");
    else
        printf("Timeout set to %d seconds\n", timeout);

    /* verify what the driver actually set */
    if (ioctl(wdt_fd, WDIOC_GETTIMEOUT, &timeout) == 0)
        printf("Actual timeout  : %d seconds\n", timeout);

    if (ioctl(wdt_fd, WDIOC_GETSUPPORT, &ident) == 0)
        printf("Identity        : %s\n", ident.identity);

    return 0;
}

static void watchdog_tickle(void)
{
    int timeleft = 0;

    if (ioctl(wdt_fd, WDIOC_KEEPALIVE, 0) < 0) {
        printf("WDIOC_KEEPALIVE failed: %m - falling back to write\n");
        write(wdt_fd, "1", 1);
    }

    if (ioctl(wdt_fd, WDIOC_GETTIMELEFT, &timeleft) == 0)
        printf("Petted watchdog. Timeleft: %d sec\n", timeleft);
    else
        printf("Petted watchdog.\n");
}

int main(void)
{
    signal(SIGINT,  safe_exit);
    signal(SIGTERM, safe_exit);

    if (watchdog_init() < 0)
        return 1;

    printf("\nPetting every %d seconds. Ctrl+C to safely stop.\n\n",
           PET_INTERVAL);

    while (1) {
        watchdog_tickle();
        sleep(PET_INTERVAL);
    }

    return 0;
}

Steps to reproduce the issue:
-----------------------------
1. Load kdump kernel
2. Insert pseries-wdt driver
3. Compile the above proram and run the binary
4. Crash the kernel (echo c > /proc/sysrq-trigger)

Sourabh Jain (3):
  powerpc/pseries: Move H_WATCHDOG definitions to a common header
  powerpc/pseries: Handle and log pseries-wdt registration failures
  powerpc/crash: stop watchdogs before booting kdump kernel

 arch/powerpc/include/asm/papr-watchdog.h | 60 ++++++++++++++++++++++++
 arch/powerpc/platforms/pseries/setup.c   | 32 ++++++++++++-
 drivers/watchdog/pseries-wdt.c           | 53 +--------------------
 3 files changed, 91 insertions(+), 54 deletions(-)
 create mode 100644 arch/powerpc/include/asm/papr-watchdog.h

-- 
2.52.0



^ permalink raw reply

* [PATCH v2 1/3] powerpc/pseries: Move H_WATCHDOG definitions to a common header
From: Sourabh Jain @ 2026-07-13  3:59 UTC (permalink / raw)
  To: linuxppc-dev, maddy, mpe, ritesh.list
  Cc: npiggin, chleroy, shivangu, hbathini, mahesh, adityag, venkat88,
	stable, Sourabh Jain
In-Reply-To: <20260713035954.1559605-1-sourabhjain@linux.ibm.com>

The H_WATCHDOG input and output definitions are currently local to the
pseries watchdog driver. The next patch in this series also needs these
definitions to issue H_WATCHDOG hypercalls outside the watchdog driver.

Move the H_WATCHDOG definitions to a new common header,
asm/papr-watchdog.h, so they can be shared without duplicating the
PAPR watchdog definitions.

No functional changes.

Suggested-by: Ritesh Harjani (IBM) <ritesh.list@gmail.com>
Signed-off-by: Sourabh Jain <sourabhjain@linux.ibm.com>
---
 arch/powerpc/include/asm/papr-watchdog.h | 58 ++++++++++++++++++++++++
 drivers/watchdog/pseries-wdt.c           | 53 +---------------------
 2 files changed, 59 insertions(+), 52 deletions(-)
 create mode 100644 arch/powerpc/include/asm/papr-watchdog.h

diff --git a/arch/powerpc/include/asm/papr-watchdog.h b/arch/powerpc/include/asm/papr-watchdog.h
new file mode 100644
index 000000000000..fb3a511aa861
--- /dev/null
+++ b/arch/powerpc/include/asm/papr-watchdog.h
@@ -0,0 +1,58 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef _ASM_POWERPC_CRASHDUMP_PPC64_H
+#define _ASM_POWERPC_CRASHDUMP_PPC64_H
+
+/*
+ * H_WATCHDOG Input
+ *
+ * R4: "flags":
+ *
+ *         Bits 48-55: "operation"
+ */
+#define PSERIES_WDTF_OP_START	0x100UL		/* start timer */
+#define PSERIES_WDTF_OP_STOP	0x200UL		/* stop timer */
+#define PSERIES_WDTF_OP_QUERY	0x300UL		/* query timer capabilities */
+
+/*
+ *         Bits 56-63: "timeoutAction" (for "Start Watchdog" only)
+ */
+#define PSERIES_WDTF_ACTION_HARD_POWEROFF	0x1UL	/* poweroff */
+#define PSERIES_WDTF_ACTION_HARD_RESTART	0x2UL	/* restart */
+#define PSERIES_WDTF_ACTION_DUMP_RESTART	0x3UL	/* dump + restart */
+
+/*
+ * H_WATCHDOG Output
+ *
+ * R3: Return code
+ *
+ *     H_SUCCESS    The operation completed.
+ *
+ *     H_BUSY	    The hypervisor is too busy; retry the operation.
+ *
+ *     H_PARAMETER  The given "flags" are somehow invalid.  Either the
+ *                  "operation" or "timeoutAction" is invalid, or a
+ *                  reserved bit is set.
+ *
+ *     H_P2         The given "watchdogNumber" is zero or exceeds the
+ *                  supported maximum value.
+ *
+ *     H_P3         The given "timeoutInMs" is below the supported
+ *                  minimum value.
+ *
+ *     H_NOOP       The given "watchdogNumber" is already stopped.
+ *
+ *     H_HARDWARE   The operation failed for ineffable reasons.
+ *
+ *     H_FUNCTION   The H_WATCHDOG hypercall is not supported by this
+ *                  hypervisor.
+ *
+ * R4:
+ *
+ * - For the "Query Watchdog Capabilities" operation, a 64-bit
+ *   structure:
+ */
+#define PSERIES_WDTQ_MIN_TIMEOUT(cap)	(((cap) >> 48) & 0xffff)
+#define PSERIES_WDTQ_MAX_NUMBER(cap)	(((cap) >> 32) & 0xffff)
+
+#endif /* _ASM_POWERPC_CRASHDUMP_PPC64_H */
diff --git a/drivers/watchdog/pseries-wdt.c b/drivers/watchdog/pseries-wdt.c
index 48d67f7c972a..e97b943e1d3c 100644
--- a/drivers/watchdog/pseries-wdt.c
+++ b/drivers/watchdog/pseries-wdt.c
@@ -12,61 +12,10 @@
 #include <linux/platform_device.h>
 #include <linux/time64.h>
 #include <linux/watchdog.h>
+#include <asm/papr-watchdog.h>
 
 #define DRV_NAME "pseries-wdt"
 
-/*
- * H_WATCHDOG Input
- *
- * R4: "flags":
- *
- *         Bits 48-55: "operation"
- */
-#define PSERIES_WDTF_OP_START	0x100UL		/* start timer */
-#define PSERIES_WDTF_OP_STOP	0x200UL		/* stop timer */
-#define PSERIES_WDTF_OP_QUERY	0x300UL		/* query timer capabilities */
-
-/*
- *         Bits 56-63: "timeoutAction" (for "Start Watchdog" only)
- */
-#define PSERIES_WDTF_ACTION_HARD_POWEROFF	0x1UL	/* poweroff */
-#define PSERIES_WDTF_ACTION_HARD_RESTART	0x2UL	/* restart */
-#define PSERIES_WDTF_ACTION_DUMP_RESTART	0x3UL	/* dump + restart */
-
-/*
- * H_WATCHDOG Output
- *
- * R3: Return code
- *
- *     H_SUCCESS    The operation completed.
- *
- *     H_BUSY	    The hypervisor is too busy; retry the operation.
- *
- *     H_PARAMETER  The given "flags" are somehow invalid.  Either the
- *                  "operation" or "timeoutAction" is invalid, or a
- *                  reserved bit is set.
- *
- *     H_P2         The given "watchdogNumber" is zero or exceeds the
- *                  supported maximum value.
- *
- *     H_P3         The given "timeoutInMs" is below the supported
- *                  minimum value.
- *
- *     H_NOOP       The given "watchdogNumber" is already stopped.
- *
- *     H_HARDWARE   The operation failed for ineffable reasons.
- *
- *     H_FUNCTION   The H_WATCHDOG hypercall is not supported by this
- *                  hypervisor.
- *
- * R4:
- *
- * - For the "Query Watchdog Capabilities" operation, a 64-bit
- *   structure:
- */
-#define PSERIES_WDTQ_MIN_TIMEOUT(cap)	(((cap) >> 48) & 0xffff)
-#define PSERIES_WDTQ_MAX_NUMBER(cap)	(((cap) >> 32) & 0xffff)
-
 static const unsigned long pseries_wdt_action[] = {
 	[0] = PSERIES_WDTF_ACTION_HARD_POWEROFF,
 	[1] = PSERIES_WDTF_ACTION_HARD_RESTART,
-- 
2.52.0



^ permalink raw reply related

* [PATCH RESEND] syscall_user_dispatch: Introduce ARCH_SUPPORTS_SYSCALL_USER_DISPATCH
From: Jinjie Ruan @ 2026-07-13  3:54 UTC (permalink / raw)
  To: chenhuacai, kernel, maddy, mpe, npiggin, chleroy, pjw, palmer,
	aou, alex, hca, gor, agordeev, borntraeger, svens, tglx, mingo,
	bp, dave.hansen, hpa, nathan, kees, xur, arnd, peterz, gourry,
	lukas.bulwahn, ryan.roberts, yangtiezhu, mchauras, sshegde,
	austin.kim, jchrist, x86, linux-kernel, loongarch, linuxppc-dev,
	linux-riscv, linux-s390
  Cc: ruanjinjie

Currently, only x86 genuinely implements and supports Syscall User
Dispatch (SUD). Multiple architectures provide a stub
arch_syscall_is_vdso_sigreturn() returning 'false' simply to satisfy
GENERIC_ENTRY compilation, which creates a false impression of feature
support.

Introduce ARCH_SUPPORTS_SYSCALL_USER_DISPATCH to decouple this mechanism
from GENERIC_ENTRY. Select it exclusively on x86 and remove the redundant
stub functions from other architectures.

Link: https://lore.kernel.org/linux-arm-kernel/akZgV0Y4YAmB43_g@J2N7QTR9R3.cambridge.arm.com/
Cc: Thomas Gleixner <tglx@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Gregory Price <gourry@gourry.net>
Cc: Ada Couprie Diaz <ada.coupriediaz@arm.com>
Cc: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
Suggested-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
---
v1 -> RESEND
- Define missing ARCH_SUPPORTS_SYSCALL_USER_DISPATCH.
---
 arch/Kconfig                         | 4 ++++
 arch/loongarch/include/asm/syscall.h | 6 ------
 arch/powerpc/include/asm/syscall.h   | 5 -----
 arch/riscv/include/asm/syscall.h     | 5 -----
 arch/s390/include/asm/syscall.h      | 5 -----
 arch/x86/Kconfig                     | 1 +
 6 files changed, 5 insertions(+), 21 deletions(-)

diff --git a/arch/Kconfig b/arch/Kconfig
index d2dbed524f15..066263cc44fe 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -114,8 +114,12 @@ config GENERIC_ENTRY
 	select GENERIC_IRQ_ENTRY
 	select GENERIC_SYSCALL
 
+config ARCH_SUPPORTS_SYSCALL_USER_DISPATCH
+	bool
+
 config SYSCALL_USER_DISPATCH
 	bool "Syscall User Dispatch"
+	depends on ARCH_SUPPORTS_SYSCALL_USER_DISPATCH
 	depends on GENERIC_ENTRY
 	default y
 	help
diff --git a/arch/loongarch/include/asm/syscall.h b/arch/loongarch/include/asm/syscall.h
index df8ea223c77b..d9275010f548 100644
--- a/arch/loongarch/include/asm/syscall.h
+++ b/arch/loongarch/include/asm/syscall.h
@@ -84,10 +84,4 @@ static inline int syscall_get_arch(struct task_struct *task)
 	return AUDIT_ARCH_LOONGARCH64;
 #endif
 }
-
-static inline bool arch_syscall_is_vdso_sigreturn(struct pt_regs *regs)
-{
-	return false;
-}
-
 #endif	/* __ASM_LOONGARCH_SYSCALL_H */
diff --git a/arch/powerpc/include/asm/syscall.h b/arch/powerpc/include/asm/syscall.h
index 834fcc4f7b54..4b3c52ed6e9d 100644
--- a/arch/powerpc/include/asm/syscall.h
+++ b/arch/powerpc/include/asm/syscall.h
@@ -139,9 +139,4 @@ static inline int syscall_get_arch(struct task_struct *task)
 	else
 		return AUDIT_ARCH_PPC64;
 }
-
-static inline bool arch_syscall_is_vdso_sigreturn(struct pt_regs *regs)
-{
-	return false;
-}
 #endif	/* _ASM_SYSCALL_H */
diff --git a/arch/riscv/include/asm/syscall.h b/arch/riscv/include/asm/syscall.h
index 8067e666a4ca..987c9a78806f 100644
--- a/arch/riscv/include/asm/syscall.h
+++ b/arch/riscv/include/asm/syscall.h
@@ -112,11 +112,6 @@ static inline void syscall_handler(struct pt_regs *regs, ulong syscall)
 	regs->a0 = fn(regs);
 }
 
-static inline bool arch_syscall_is_vdso_sigreturn(struct pt_regs *regs)
-{
-	return false;
-}
-
 asmlinkage long sys_riscv_flush_icache(uintptr_t, uintptr_t, uintptr_t);
 
 asmlinkage long sys_riscv_hwprobe(struct riscv_hwprobe *, size_t, size_t,
diff --git a/arch/s390/include/asm/syscall.h b/arch/s390/include/asm/syscall.h
index 4271e4169f45..5f310caad1fc 100644
--- a/arch/s390/include/asm/syscall.h
+++ b/arch/s390/include/asm/syscall.h
@@ -89,11 +89,6 @@ static inline int syscall_get_arch(struct task_struct *task)
 	return AUDIT_ARCH_S390X;
 }
 
-static inline bool arch_syscall_is_vdso_sigreturn(struct pt_regs *regs)
-{
-	return false;
-}
-
 #define SYSCALL_FMT_0
 #define SYSCALL_FMT_1 , "0" (r2)
 #define SYSCALL_FMT_2 , "d" (r3) SYSCALL_FMT_1
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index bdad90f210e4..f3f8ad107eeb 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -335,6 +335,7 @@ config X86
 	select SCHED_SMT			if SMP
 	select ARCH_SUPPORTS_SCHED_CLUSTER	if SMP
 	select ARCH_SUPPORTS_SCHED_MC		if SMP
+	select ARCH_SUPPORTS_SYSCALL_USER_DISPATCH
 	select HAVE_SINGLE_FTRACE_DIRECT_OPS	if X86_64 && DYNAMIC_FTRACE_WITH_DIRECT_CALLS
 
 config INSTRUCTION_DECODER
-- 
2.34.1



^ permalink raw reply related

* Re: [PATCH v2] ASoC: fsl_sai: Fix spurious BCLK on resume by clearing BYP
From: Shengjiu Wang @ 2026-07-13  3:21 UTC (permalink / raw)
  To: Chancel Liu
  Cc: Xiubo.Lee, festevam, nicoleotsuka, lgirdwood, broonie, perex,
	tiwai, linux-kernel, linuxppc-dev, linux-sound
In-Reply-To: <20260710070835.3749817-1-chancel.liu@oss.nxp.com>

On Fri, Jul 10, 2026 at 3:08 PM Chancel Liu <chancel.liu@oss.nxp.com> wrote:
>
> From: Chancel Liu <chancel.liu@nxp.com>
>
> When the BCLK divider ratio is 1:1, fsl_sai_set_bclk() enables bypass
> mode by setting BYP, but never clears the bit. The BYP=1 value remains
> in the regcache, and is restored by regcache_sync() on the next runtime
> resume.
>
> Since BYP=1 combined with BCD=1 immediately outputs the ungated MCLK
> as BCLK without waiting for BCE/TE/RE to be enabled, the clock is
> driven prematurely before the stream is fully configured, causing
> noise on some codecs.
>
> Fix this by clearing BYP and BCI in fsl_sai_hw_free() taking into
> account sync mode and the opposite stream's state, so that the regcache
> holds BYP=0 before runtime suspend and regcache_sync() on resume will
> not restore bypass mode prematurely.
>
> Fixes: a50b7926d015 ("ASoC: fsl_sai: implement 1:1 bclk:mclk ratio support")
> Cc: stable@vger.kernel.org
> Signed-off-by: Chancel Liu <chancel.liu@nxp.com>

Thanks for the update.

Reviewed-by: Shengjiu Wang <shengjiu.wang@gmail.com>

Best regards
Shengjiu Wang
> ---
> Changes in v2:
> - Move BYP/BCI clearing from fsl_sai_config_disable() (trigger path)
>   to fsl_sai_hw_free() to avoid breaking pause/suspend-resume cycles
>   where hw_params() is not called again on unpause/resume.
>
>  sound/soc/fsl/fsl_sai.c | 29 +++++++++++++++++++++++++----
>  1 file changed, 25 insertions(+), 4 deletions(-)
>
> diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c
> index 9661602b53c5..d232c8f53061 100644
> --- a/sound/soc/fsl/fsl_sai.c
> +++ b/sound/soc/fsl/fsl_sai.c
> @@ -808,6 +808,8 @@ static int fsl_sai_hw_free(struct snd_pcm_substream *substream,
>         struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
>         bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
>         unsigned int ofs = sai->soc_data->reg_offset;
> +       int adir = tx ? RX : TX;
> +       int dir  = tx ? TX : RX;
>
>         /* Clear xMR to avoid channel swap with mclk_with_tere enabled case */
>         regmap_write(sai->regmap, FSL_SAI_xMR(tx), 0);
> @@ -815,10 +817,29 @@ static int fsl_sai_hw_free(struct snd_pcm_substream *substream,
>         regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx, ofs),
>                            FSL_SAI_CR3_TRCE_MASK, 0);
>
> -       if (!sai->is_consumer_mode[tx] &&
> -           sai->mclk_streams & BIT(substream->stream)) {
> -               clk_disable_unprepare(sai->mclk_clk[sai->mclk_id[tx]]);
> -               sai->mclk_streams &= ~BIT(substream->stream);
> +       if (!sai->is_consumer_mode[tx]) {
> +               bool adir_active = !!(sai->mclk_streams & BIT(!substream->stream));
> +               /*
> +                * If opposite stream provides clocks for synchronous mode and
> +                * it is inactive, Clear BYP and BCI
> +                */
> +               if (fsl_sai_dir_is_synced(sai, adir) && !adir_active)
> +                       regmap_update_bits(sai->regmap, FSL_SAI_xCR2(!tx, ofs),
> +                                          FSL_SAI_CR2_BCI | FSL_SAI_CR2_BYP, 0);
> +               /*
> +                * Clear BYP and BCI of current stream if either of:
> +                * 1. current stream doesn't provide clocks for synchronous mode
> +                * 2. current stream provides clocks for synchronous mode but no
> +                *    more stream is active.
> +                */
> +               if (!fsl_sai_dir_is_synced(sai, dir) || !adir_active)
> +                       regmap_update_bits(sai->regmap, FSL_SAI_xCR2(tx, ofs),
> +                                          FSL_SAI_CR2_BCI | FSL_SAI_CR2_BYP, 0);
> +
> +               if (sai->mclk_streams & BIT(substream->stream)) {
> +                       clk_disable_unprepare(sai->mclk_clk[sai->mclk_id[tx]]);
> +                       sai->mclk_streams &= ~BIT(substream->stream);
> +               }
>         }
>
>         return 0;
> --
> 2.50.1
>


^ permalink raw reply

* Re: [patch 3/4] entry: Make return type of syscall_trace_enter() bool
From: Jinjie Ruan @ 2026-07-13  1:40 UTC (permalink / raw)
  To: Thomas Gleixner, LKML
  Cc: Michal Suchánek, Michael Ellerman, Shrikanth Hegde,
	linuxppc-dev, Huacai Chen, loongarch, Paul Walmsley,
	Palmer Dabbelt, linux-riscv, Sven Schnelle, linux-s390, x86,
	Mark Rutland, Magnus Lindholm, Mukesh Kumar Chaurasiya (IBM),
	Jonathan Corbet, Radu Rendec
In-Reply-To: <20260712141346.699072205@kernel.org>



On 7/13/2026 5:25 AM, Thomas Gleixner wrote:
> From: Thomas Gleixner <tglx@kernel.org>
> 
> This prepares for changing the return types of
> syscall_enter_from_user_mode[_work]() to bool, which in turn separates the
> decision of invoking the syscall from the syscall number, which might have
> been changed in the call by ptrace, seccomp, tracing.
> 
> Signed-off-by: Thomas Gleixner <tglx@kernel.org>
> ---
>  include/linux/entry-common.h |   18 +++++++++++-------
>  1 file changed, 11 insertions(+), 7 deletions(-)
> --- a/include/linux/entry-common.h
> +++ b/include/linux/entry-common.h
> @@ -72,7 +72,7 @@ static __always_inline long syscall_trac
>  	 */
>  	if (work & SYSCALL_WORK_SYSCALL_USER_DISPATCH) {
>  		if (syscall_user_dispatch(regs))
> -			return -1L;
> +			return false;
>  	}
>  
>  	/*
> @@ -87,13 +87,13 @@ static __always_inline long syscall_trac
>  	if (work & (SYSCALL_WORK_SYSCALL_TRACE | SYSCALL_WORK_SYSCALL_EMU)) {
>  		if (!arch_ptrace_report_syscall_permit_entry(regs) ||
>  		    (work & SYSCALL_WORK_SYSCALL_EMU))
> -			return -1L;
> +			return false;
>  	}
>  
>  	/* Do seccomp after ptrace, to catch any tracer changes. */
>  	if (work & SYSCALL_WORK_SECCOMP) {
>  		if (!__seccomp_permit_syscall())
> -			return -1L;
> +			return false;
>  	}
>  
>  	if (unlikely(work & SYSCALL_WORK_SYSCALL_TRACEPOINT))
> @@ -102,8 +102,7 @@ static __always_inline long syscall_trac
>  	if (unlikely(audit_context()))
>  		syscall_enter_audit(regs);
>  
> -	/* Either of the above might have changed the syscall number */
> -	return syscall_get_nr(current, regs);
> +	return true;
>  }
>  
>  /**
> @@ -133,8 +132,13 @@ static __always_inline long syscall_ente
>  {
>  	unsigned long work = READ_ONCE(current_thread_info()->syscall_work);
>  
> -	if (work & SYSCALL_WORK_ENTER)
> -		syscall = syscall_trace_enter(regs, work, syscall);
> +	if (work & SYSCALL_WORK_ENTER) {
> +		if (!syscall_trace_enter(regs, work, syscall))
> +			return -1L;
> +
> +		/* Reread the syscall number as it might have been modified */
> +		syscall = syscall_get_nr(current, regs);
> +	}

Reviewed-by: Jinjie Ruan <ruanjinjie@huawei.com>

>  
>  	return syscall;
>  }
> 



^ permalink raw reply

* Re: [patch 2/4] entry: Rework trace_syscall_enter()
From: Jinjie Ruan @ 2026-07-13  1:36 UTC (permalink / raw)
  To: Thomas Gleixner, LKML
  Cc: Michal Suchánek, Michael Ellerman, Shrikanth Hegde,
	linuxppc-dev, Huacai Chen, loongarch, Paul Walmsley,
	Palmer Dabbelt, linux-riscv, Sven Schnelle, linux-s390, x86,
	Mark Rutland, Magnus Lindholm, Mukesh Kumar Chaurasiya (IBM),
	Jonathan Corbet, Radu Rendec
In-Reply-To: <20260712141346.639115923@kernel.org>



On 7/13/2026 5:25 AM, Thomas Gleixner wrote:
> Reread the syscall number from pt_regs and stop returning the eventually
> modified syscall number.
> 
> That moves the reread to the end of the syscall_trace_enter() and prepares
> for moving it to the call site.
> 
> No functional change.
> 
> Signed-off-by: Thomas Gleixner <tglx@kernel.org>
> ---
>  include/linux/entry-common.h  |   10 ++++------
>  kernel/entry/syscall-common.c |    9 ++-------
>  2 files changed, 6 insertions(+), 13 deletions(-)
> 
> --- a/include/linux/entry-common.h
> +++ b/include/linux/entry-common.h
> @@ -58,7 +58,7 @@ static __always_inline bool arch_ptrace_
>  }
>  #endif
>  
> -long trace_syscall_enter(struct pt_regs *regs, long syscall);
> +void trace_syscall_enter(struct pt_regs *regs);
>  void trace_syscall_exit(struct pt_regs *regs, long ret);
>  void syscall_enter_audit(struct pt_regs *regs);
>  
> @@ -96,16 +96,14 @@ static __always_inline long syscall_trac
>  			return -1L;
>  	}
>  
> -	/* Either of the above might have changed the syscall number */
> -	syscall = syscall_get_nr(current, regs);
> -
>  	if (unlikely(work & SYSCALL_WORK_SYSCALL_TRACEPOINT))
> -		syscall = trace_syscall_enter(regs, syscall);
> +		trace_syscall_enter(regs);
>  
>  	if (unlikely(audit_context()))
>  		syscall_enter_audit(regs);
>  
> -	return syscall;
> +	/* Either of the above might have changed the syscall number */
> +	return syscall_get_nr(current, regs);

Reviewed-by: Jinjie Ruan <ruanjinjie@huawei.com>

>  }
>  
>  /**
> --- a/kernel/entry/syscall-common.c
> +++ b/kernel/entry/syscall-common.c
> @@ -8,14 +8,9 @@
>  
>  /* Out of line to prevent tracepoint code duplication */
>  
> -long trace_syscall_enter(struct pt_regs *regs, long syscall)
> +void trace_syscall_enter(struct pt_regs *regs)
>  {
> -	trace_sys_enter(regs, syscall);
> -	/*
> -	 * Probes or BPF hooks in the tracepoint may have changed the
> -	 * system call number. Reread it.
> -	 */
> -	return syscall_get_nr(current, regs);
> +	trace_sys_enter(regs, syscall_get_nr(current, regs));
>  }
>  
>  void trace_syscall_exit(struct pt_regs *regs, long ret)
> 



^ permalink raw reply

* Re: [patch 1/4] entry: Rework syscall_audit_enter()
From: Jinjie Ruan @ 2026-07-13  1:33 UTC (permalink / raw)
  To: Thomas Gleixner, LKML
  Cc: Michal Suchánek, Michael Ellerman, Shrikanth Hegde,
	linuxppc-dev, Huacai Chen, loongarch, Paul Walmsley,
	Palmer Dabbelt, linux-riscv, Sven Schnelle, linux-s390, x86,
	Mark Rutland, Magnus Lindholm, Mukesh Kumar Chaurasiya (IBM),
	Jonathan Corbet, Radu Rendec
In-Reply-To: <20260712141346.576865340@kernel.org>



On 7/13/2026 5:25 AM, Thomas Gleixner wrote:
> Move it out of line and let it reread the syscall number on it's own. That
> makes the low level entry code denser and allows to move the reread to the
> call site of syscall_trace_enter() once the tracer is fixed up.
> 
> Signed-off-by: Thomas Gleixner <tglx@kernel.org>
> ---
>  include/linux/entry-common.h  |   14 +++-----------
>  kernel/entry/syscall-common.c |   10 ++++++++++
>  2 files changed, 13 insertions(+), 11 deletions(-)
> 
> --- a/include/linux/entry-common.h
> +++ b/include/linux/entry-common.h
> @@ -60,16 +60,7 @@ static __always_inline bool arch_ptrace_
>  
>  long trace_syscall_enter(struct pt_regs *regs, long syscall);
>  void trace_syscall_exit(struct pt_regs *regs, long ret);
> -
> -static inline void syscall_enter_audit(struct pt_regs *regs, long syscall)
> -{
> -	if (unlikely(audit_context())) {
> -		unsigned long args[6];
> -
> -		syscall_get_arguments(current, regs, args);
> -		audit_syscall_entry(syscall, args[0], args[1], args[2], args[3]);
> -	}
> -}
> +void syscall_enter_audit(struct pt_regs *regs);
>  
>  static __always_inline long syscall_trace_enter(struct pt_regs *regs, unsigned long work,
>  						long syscall)
> @@ -111,7 +102,8 @@ static __always_inline long syscall_trac
>  	if (unlikely(work & SYSCALL_WORK_SYSCALL_TRACEPOINT))
>  		syscall = trace_syscall_enter(regs, syscall);
>  
> -	syscall_enter_audit(regs, syscall);
> +	if (unlikely(audit_context()))
> +		syscall_enter_audit(regs);

Reviewed-by: Jinjie Ruan <ruanjinjie@huawei.com>

>  
>  	return syscall;
>  }
> --- a/kernel/entry/syscall-common.c
> +++ b/kernel/entry/syscall-common.c
> @@ -1,5 +1,6 @@
>  // SPDX-License-Identifier: GPL-2.0
>  
> +#include <linux/audit.h>
>  #include <linux/entry-common.h>
>  
>  #define CREATE_TRACE_POINTS
> @@ -21,3 +22,12 @@ void trace_syscall_exit(struct pt_regs *
>  {
>  	trace_sys_exit(regs, ret);
>  }
> +
> +void syscall_enter_audit(struct pt_regs *regs)
> +{
> +	long syscall = syscall_get_nr(current, regs);
> +	unsigned long args[6];
> +
> +	syscall_get_arguments(current, regs, args);
> +	__audit_syscall_entry(syscall, args[0], args[1], args[2], args[3]);
> +}
> 



^ permalink raw reply

* Re: [PATCH v7 10/10] RAS: add firmware-first CPER provider
From: Uwe Kleine-König @ 2026-07-12 22:21 UTC (permalink / raw)
  To: Ahmed Tiba
  Cc: Rafael J. Wysocki, Tony Luck, Borislav Petkov, Hanjun Guo,
	Mauro Carvalho Chehab, Shuai Xue, Len Brown, Saket Dumbre,
	Davidlohr Bueso, Jonathan Cameron, Dave Jiang, Alison Schofield,
	Vishal Verma, Dan Williams, Ira Weiny, Li Ming,
	Mahesh J Salgaonkar, Oliver O'Halloran, Bjorn Helgaas,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Jonathan Corbet,
	Shuah Khan, linux-kernel, linux-acpi, acpica-devel, linux-cxl,
	linuxppc-dev, linux-pci, devicetree, linux-edac, linux-doc,
	Dmitry.Lamerov
In-Reply-To: <20260708-topics-ahmtib01-ras_ffh_arm_internal_review-v7-10-8b3a85216cef@arm.com>

[-- Attachment #1: Type: text/plain, Size: 244 bytes --]

Hello Ahmed,

On Wed, Jul 08, 2026 at 02:59:09PM +0100, Ahmed Tiba wrote:
> +#include <linux/mod_devicetable.h>

Please don't add new users for this header file. Only use those
<linux/device-id/*.h> that you actually need (if any).

Thanks
Uwe

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply

* [patch 4/4] entry, treewide: Make syscall_enter_from_user_mode[_work]() indicate syscall execution
From: Thomas Gleixner @ 2026-07-12 21:25 UTC (permalink / raw)
  To: LKML
  Cc: Michal Suchánek, Michael Ellerman, Shrikanth Hegde,
	linuxppc-dev, Huacai Chen, loongarch, Paul Walmsley,
	Palmer Dabbelt, linux-riscv, Sven Schnelle, linux-s390, x86,
	Mark Rutland, Jinjie Ruan, Magnus Lindholm,
	Mukesh Kumar Chaurasiya (IBM), Jonathan Corbet, Radu Rendec
In-Reply-To: <20260712134433.549076055@kernel.org>

The return values of syscall_enter_from_user_mode[_work]() are
non-intuitive. Both functions return the syscall number which should be
invoked by the architecture specific syscall entry code. The returned
number can be:

  - the unmodified syscall number which was handed in by the caller

  - a modified syscall number (ptrace, seccomp, trace/probe/bpf)

That has an additional twist. If the return value is -1L then the caller is
not allowed to modify the return value as that indicates that the modifying
entity requests to abort the syscall and set the return value already. That
can obviously not be differentiated from a syscall which handed in -1 as
syscall number.

The most trivial way to deal with that is:

    set_return_value(regs, -ENOSYS);
    nr = syscall_enter_from_user_mode(regs, nr);
    if (valid(nr))
    	handle_syscall(regs, nr);

That's what LOONGARCH, RISCV, and X86 do. But PowerPC and S390 do not
preset the return value, so when user space hands in -1 and there is
nothing setting the return value in the entry work code, then the syscall
is skipped but the return value is whatever random data has been in the
return value register.

Change the return values of syscall_enter_from_user_mode[_work]() to
boolean and return false, when either ptrace or seccomp request to skip the
syscall. If they return true, update the syscall number as it might have
been changed.

That results in slightly different behaviour of the architectures versus
tracing.

If the syscall tracepoint has probe/BPF attached, those might set the
syscall number to -1 and also set the return value. PowerPC and S390 will
then overwrite that value with -ENOSYS. The other architectures will just
ignore it like any other invalid syscall and use the modified one.

Originally-by: Michal Suchánek <msuchanek@suse.de>
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
---
V2: Change the return logic so Power and S390 can insist on being special.
---
 Documentation/core-api/entry.rst |   45 ++++++++++++++++++++++++++++++---------
 arch/loongarch/kernel/syscall.c  |   14 ++++++------
 arch/powerpc/kernel/syscall.c    |    3 +-
 arch/riscv/kernel/traps.c        |   11 ++++-----
 arch/s390/kernel/syscall.c       |    7 ++++--
 arch/x86/entry/syscall_32.c      |   25 ++++++++++-----------
 arch/x86/entry/syscall_64.c      |   12 +++++-----
 include/linux/entry-common.h     |   32 +++++++++++++--------------
 8 files changed, 88 insertions(+), 61 deletions(-)
--- a/Documentation/core-api/entry.rst
+++ b/Documentation/core-api/entry.rst
@@ -58,26 +58,51 @@ state transitions must run with interrup
 Syscalls
 --------
 
-Syscall-entry code starts in assembly code and calls out into low-level C code
-after establishing low-level architecture-specific state and stack frames. This
-low-level C code must not be instrumented. A typical syscall handling function
-invoked from low-level assembly code looks like this:
+Syscall-entry code starts in assembly code and calls out into low-level C
+code after establishing low-level architecture-specific state and stack
+frames. This low-level C code must not be instrumented. The recommended
+syscall handling function invoked from low-level assembly code looks like
+this:
 
 .. code-block:: c
 
-  noinstr void syscall(struct pt_regs *regs, int nr)
+  noinstr void syscall(struct pt_regs *regs, long nr)
   {
 	arch_syscall_enter(regs);
-	nr = syscall_enter_from_user_mode_randomize_stack(regs, nr);
+	result_reg(regs) = -ENOSYS;
+	if (syscall_enter_from_user_mode_randomize_stack(regs, &nr)) {
+		instrumentation_begin();
+		if (valid(nr)
+			result_reg(regs) = invoke_syscall(regs, nr);
+		instrumentation_end();
+	}
+	syscall_exit_to_user_mode(regs);
+  }
 
-	instrumentation_begin();
-	if (!invoke_syscall(regs, nr) && nr != -1)
-	 	result_reg(regs) = __sys_ni_syscall(regs);
-	instrumentation_end();
+This is the most resilent variant as it has always a guaranteed valid
+return code. The alternative variant is:
+
+.. code-block:: c
 
+  noinstr void syscall(struct pt_regs *regs, long nr)
+  {
+	arch_syscall_enter(regs);
+	if (syscall_enter_from_user_mode_randomize_stack(regs, &nr)) {
+		instrumentation_begin();
+		if (valid(nr)
+			result_reg(regs) = invoke_syscall(regs, nr);
+		else
+			result_reg(regs) = -ENOSYS;
+		instrumentation_end();
+	}
 	syscall_exit_to_user_mode(regs);
   }
 
+That works for most situations except when a probe/BPF attached to the
+syscall tracepoint sets an invalid syscall number e.g. -1 and also modifies
+the result register. So this variant will obviously overwrite the modified
+result with -ENOSYS.
+
 syscall_enter_from_user_mode_randomize_stack() first invokes
 enter_from_user_mode_randomize_stack() which establishes state in the
 following order:
--- a/arch/loongarch/kernel/syscall.c
+++ b/arch/loongarch/kernel/syscall.c
@@ -57,8 +57,8 @@ typedef long (*sys_call_fn)(unsigned lon
 
 void noinstr __no_stack_protector do_syscall(struct pt_regs *regs)
 {
-	unsigned long nr;
 	sys_call_fn syscall_fn;
+	unsigned long nr;
 
 	nr = regs->regs[11];
 	/* Set for syscall restarting */
@@ -69,12 +69,12 @@ void noinstr __no_stack_protector do_sys
 	regs->orig_a0 = regs->regs[4];
 	regs->regs[4] = -ENOSYS;
 
-	nr = syscall_enter_from_user_mode_randomize_stack(regs, nr);
-
-	if (nr < NR_syscalls) {
-		syscall_fn = sys_call_table[array_index_nospec(nr, NR_syscalls)];
-		regs->regs[4] = syscall_fn(regs->orig_a0, regs->regs[5], regs->regs[6],
-					   regs->regs[7], regs->regs[8], regs->regs[9]);
+	if (likely(syscall_enter_from_user_mode_randomize_stack(regs, &nr))) {
+		if (nr < NR_syscalls) {
+			syscall_fn = sys_call_table[array_index_nospec(nr, NR_syscalls)];
+			regs->regs[4] = syscall_fn(regs->orig_a0, regs->regs[5], regs->regs[6],
+						   regs->regs[7], regs->regs[8], regs->regs[9]);
+		}
 	}
 
 	syscall_exit_to_user_mode(regs);
--- a/arch/powerpc/kernel/syscall.c
+++ b/arch/powerpc/kernel/syscall.c
@@ -18,7 +18,8 @@ notrace long system_call_exception(struc
 	long ret;
 	syscall_fn f;
 
-	r0 = syscall_enter_from_user_mode_randomize_stack(regs, r0);
+	if (unlikely(!syscall_enter_from_user_mode_randomize_stack(regs, &r0)))
+		return syscall_get_error(current, regs);
 
 	if (unlikely(r0 >= NR_syscalls)) {
 		if (unlikely(trap_is_unsupported_scv(regs))) {
--- a/arch/riscv/kernel/traps.c
+++ b/arch/riscv/kernel/traps.c
@@ -332,13 +332,12 @@ void do_trap_ecall_u(struct pt_regs *reg
 
 		riscv_v_vstate_discard(regs);
 
-		syscall = syscall_enter_from_user_mode_randomize_stack(regs, syscall);
-
-		if (syscall >= 0 && syscall < NR_syscalls) {
-			syscall = array_index_nospec(syscall, NR_syscalls);
-			syscall_handler(regs, syscall);
+		if (likely(syscall_enter_from_user_mode_randomize_stack(regs, &syscall))) {
+			if (syscall >= 0 && syscall < NR_syscalls) {
+				syscall = array_index_nospec(syscall, NR_syscalls);
+				syscall_handler(regs, syscall);
+			}
 		}
-
 		syscall_exit_to_user_mode(regs);
 	} else {
 		irqentry_state_t state = irqentry_nmi_enter(regs);
--- a/arch/s390/kernel/syscall.c
+++ b/arch/s390/kernel/syscall.c
@@ -96,6 +96,7 @@ SYSCALL_DEFINE0(ni_syscall)
 void noinstr __do_syscall(struct pt_regs *regs, int per_trap)
 {
 	unsigned long nr;
+	bool permit;
 
 	enter_from_user_mode_randomize_stack(regs);
 
@@ -121,7 +122,9 @@ void noinstr __do_syscall(struct pt_regs
 		regs->psw.addr = current->restart_block.arch_data;
 		current->restart_block.arch_data = 1;
 	}
-	nr = syscall_enter_from_user_mode_work(regs, nr);
+
+	permit = syscall_enter_from_user_mode_work(regs, &nr);
+
 	/*
 	 * In the s390 ptrace ABI, both the syscall number and the return value
 	 * use gpr2. However, userspace puts the syscall number either in the
@@ -129,7 +132,7 @@ void noinstr __do_syscall(struct pt_regs
 	 * work, the ptrace code sets PIF_SYSCALL_RET_SET, which is checked here
 	 * and if set, the syscall will be skipped.
 	 */
-	if (unlikely(test_and_clear_pt_regs_flag(regs, PIF_SYSCALL_RET_SET)))
+	if (unlikely(test_and_clear_pt_regs_flag(regs, PIF_SYSCALL_RET_SET) || !permit))
 		goto out;
 	regs->gprs[2] = -ENOSYS;
 	if (likely(nr < NR_syscalls)) {
--- a/arch/x86/entry/syscall_32.c
+++ b/arch/x86/entry/syscall_32.c
@@ -161,8 +161,9 @@ static __always_inline bool int80_is_ext
 	nr = syscall_32_enter(regs);
 
 	local_irq_enable();
-	nr = syscall_enter_from_user_mode_work(regs, nr);
-	do_syscall_32_irqs_on(regs, nr);
+
+	if (likely(syscall_enter_from_user_mode_work(regs, &nr)))
+		do_syscall_32_irqs_on(regs, nr);
 
 	instrumentation_end();
 	syscall_exit_to_user_mode(regs);
@@ -223,8 +224,8 @@ DEFINE_FREDENTRY_RAW(int80_emulation)
 	nr = syscall_32_enter(regs);
 
 	local_irq_enable();
-	nr = syscall_enter_from_user_mode_work(regs, nr);
-	do_syscall_32_irqs_on(regs, nr);
+	if (likely(syscall_enter_from_user_mode_work(regs, &nr)))
+		do_syscall_32_irqs_on(regs, nr);
 
 	instrumentation_end();
 	syscall_exit_to_user_mode(regs);
@@ -243,13 +244,13 @@ DEFINE_FREDENTRY_RAW(int80_emulation)
 	 * orig_ax, the int return value truncates it. This matches
 	 * the semantics of syscall_get_nr().
 	 */
-	nr = syscall_enter_from_user_mode_randomize_stack(regs, nr);
-
-	instrumentation_begin();
+	if (likely(syscall_enter_from_user_mode_randomize_stack(regs, &nr))) {
+		instrumentation_begin();
 
-	do_syscall_32_irqs_on(regs, nr);
+		do_syscall_32_irqs_on(regs, nr);
 
-	instrumentation_end();
+		instrumentation_end();
+	}
 	syscall_exit_to_user_mode(regs);
 }
 #endif /* !CONFIG_IA32_EMULATION */
@@ -286,10 +287,8 @@ static noinstr bool __do_fast_syscall_32
 		return false;
 	}
 
-	nr = syscall_enter_from_user_mode_work(regs, nr);
-
-	/* Now this is just like a normal syscall. */
-	do_syscall_32_irqs_on(regs, nr);
+	if (likely(syscall_enter_from_user_mode_work(regs, &nr)))
+		do_syscall_32_irqs_on(regs, nr);
 
 	instrumentation_end();
 	syscall_exit_to_user_mode(regs);
--- a/arch/x86/entry/syscall_64.c
+++ b/arch/x86/entry/syscall_64.c
@@ -78,14 +78,14 @@ static __always_inline void do_syscall_x
 /* Returns true to return using SYSRET, or false to use IRET */
 __visible noinstr bool do_syscall_64(struct pt_regs *regs, long nr)
 {
-	nr = syscall_enter_from_user_mode_randomize_stack(regs, nr);
+	if (likely(syscall_enter_from_user_mode_randomize_stack(regs, &nr))) {
+		instrumentation_begin();
 
-	instrumentation_begin();
+		if (!do_syscall_x64(regs, nr))
+			do_syscall_x32(regs, nr);
 
-	if (!do_syscall_x64(regs, nr))
-		do_syscall_x32(regs, nr);
-
-	instrumentation_end();
+		instrumentation_end();
+	}
 	syscall_exit_to_user_mode(regs);
 
 	/*
--- a/include/linux/entry-common.h
+++ b/include/linux/entry-common.h
@@ -111,16 +111,15 @@ static __always_inline long syscall_trac
  * @regs:	Pointer to currents pt_regs
  * @syscall:	The syscall number
  *
- * Invoked from architecture specific syscall entry code with interrupts
- * enabled after invoking enter_from_user_mode(), enabling interrupts and
- * extra architecture specific work.
+ * Invoked from architecture specific syscall entry code with interrupts enabled
+ * after invoking enter_from_user_mode(), enabling interrupts and extra
+ * architecture specific work with the syscall return value preset to -ENOSYS.
  *
- * Returns: The original or a modified syscall number
+ * Returns: True if the syscall should be invoked, False otherwise.
  *
- * If the returned syscall number is -1 then the syscall should be
- * skipped. In this case the caller may invoke syscall_set_error() or
- * syscall_set_return_value() first.  If neither of those are called and -1
- * is returned, then the syscall will fail with ENOSYS.
+ * If the return value is false, the caller must skip the syscall and leave the
+ * syscall return value unmodified as it might have been set by one of the entry
+ * work functions.
  *
  * It handles the following work items:
  *
@@ -128,19 +127,20 @@ static __always_inline long syscall_trac
  *     ptrace_report_syscall_permit_entry(), __seccomp_permit_syscall(), trace_sys_enter()
  *  2) Invocation of audit_syscall_entry()
  */
-static __always_inline long syscall_enter_from_user_mode_work(struct pt_regs *regs, long syscall)
+static __always_inline bool syscall_enter_from_user_mode_work(struct pt_regs *regs, long *syscall)
 {
 	unsigned long work = READ_ONCE(current_thread_info()->syscall_work);
 
-	if (work & SYSCALL_WORK_ENTER) {
-		if (!syscall_trace_enter(regs, work, syscall))
-			return -1L;
+	if (!(work & SYSCALL_WORK_ENTER))
+		return true;
 
-		/* Reread the syscall number as it might have been modified */
-		syscall = syscall_get_nr(current, regs);
-	}
+	if (unlikely(!syscall_trace_enter(regs, work, *syscall)))
+		return false;
 
-	return syscall;
+	/* Reread the syscall number as it might have been modified */
+	*syscall = syscall_get_nr(current, regs);
+
+	return true;
 }
 
 /**



^ permalink raw reply

* [patch 3/4] entry: Make return type of syscall_trace_enter() bool
From: Thomas Gleixner @ 2026-07-12 21:25 UTC (permalink / raw)
  To: LKML
  Cc: Michal Suchánek, Michael Ellerman, Shrikanth Hegde,
	linuxppc-dev, Huacai Chen, loongarch, Paul Walmsley,
	Palmer Dabbelt, linux-riscv, Sven Schnelle, linux-s390, x86,
	Mark Rutland, Jinjie Ruan, Magnus Lindholm,
	Mukesh Kumar Chaurasiya (IBM), Jonathan Corbet, Radu Rendec
In-Reply-To: <20260712134433.549076055@kernel.org>

From: Thomas Gleixner <tglx@kernel.org>

This prepares for changing the return types of
syscall_enter_from_user_mode[_work]() to bool, which in turn separates the
decision of invoking the syscall from the syscall number, which might have
been changed in the call by ptrace, seccomp, tracing.

Signed-off-by: Thomas Gleixner <tglx@kernel.org>
---
 include/linux/entry-common.h |   18 +++++++++++-------
 1 file changed, 11 insertions(+), 7 deletions(-)
--- a/include/linux/entry-common.h
+++ b/include/linux/entry-common.h
@@ -72,7 +72,7 @@ static __always_inline long syscall_trac
 	 */
 	if (work & SYSCALL_WORK_SYSCALL_USER_DISPATCH) {
 		if (syscall_user_dispatch(regs))
-			return -1L;
+			return false;
 	}
 
 	/*
@@ -87,13 +87,13 @@ static __always_inline long syscall_trac
 	if (work & (SYSCALL_WORK_SYSCALL_TRACE | SYSCALL_WORK_SYSCALL_EMU)) {
 		if (!arch_ptrace_report_syscall_permit_entry(regs) ||
 		    (work & SYSCALL_WORK_SYSCALL_EMU))
-			return -1L;
+			return false;
 	}
 
 	/* Do seccomp after ptrace, to catch any tracer changes. */
 	if (work & SYSCALL_WORK_SECCOMP) {
 		if (!__seccomp_permit_syscall())
-			return -1L;
+			return false;
 	}
 
 	if (unlikely(work & SYSCALL_WORK_SYSCALL_TRACEPOINT))
@@ -102,8 +102,7 @@ static __always_inline long syscall_trac
 	if (unlikely(audit_context()))
 		syscall_enter_audit(regs);
 
-	/* Either of the above might have changed the syscall number */
-	return syscall_get_nr(current, regs);
+	return true;
 }
 
 /**
@@ -133,8 +132,13 @@ static __always_inline long syscall_ente
 {
 	unsigned long work = READ_ONCE(current_thread_info()->syscall_work);
 
-	if (work & SYSCALL_WORK_ENTER)
-		syscall = syscall_trace_enter(regs, work, syscall);
+	if (work & SYSCALL_WORK_ENTER) {
+		if (!syscall_trace_enter(regs, work, syscall))
+			return -1L;
+
+		/* Reread the syscall number as it might have been modified */
+		syscall = syscall_get_nr(current, regs);
+	}
 
 	return syscall;
 }



^ permalink raw reply

* [patch 2/4] entry: Rework trace_syscall_enter()
From: Thomas Gleixner @ 2026-07-12 21:25 UTC (permalink / raw)
  To: LKML
  Cc: Michal Suchánek, Michael Ellerman, Shrikanth Hegde,
	linuxppc-dev, Huacai Chen, loongarch, Paul Walmsley,
	Palmer Dabbelt, linux-riscv, Sven Schnelle, linux-s390, x86,
	Mark Rutland, Jinjie Ruan, Magnus Lindholm,
	Mukesh Kumar Chaurasiya (IBM), Jonathan Corbet, Radu Rendec
In-Reply-To: <20260712134433.549076055@kernel.org>

Reread the syscall number from pt_regs and stop returning the eventually
modified syscall number.

That moves the reread to the end of the syscall_trace_enter() and prepares
for moving it to the call site.

No functional change.

Signed-off-by: Thomas Gleixner <tglx@kernel.org>
---
 include/linux/entry-common.h  |   10 ++++------
 kernel/entry/syscall-common.c |    9 ++-------
 2 files changed, 6 insertions(+), 13 deletions(-)

--- a/include/linux/entry-common.h
+++ b/include/linux/entry-common.h
@@ -58,7 +58,7 @@ static __always_inline bool arch_ptrace_
 }
 #endif
 
-long trace_syscall_enter(struct pt_regs *regs, long syscall);
+void trace_syscall_enter(struct pt_regs *regs);
 void trace_syscall_exit(struct pt_regs *regs, long ret);
 void syscall_enter_audit(struct pt_regs *regs);
 
@@ -96,16 +96,14 @@ static __always_inline long syscall_trac
 			return -1L;
 	}
 
-	/* Either of the above might have changed the syscall number */
-	syscall = syscall_get_nr(current, regs);
-
 	if (unlikely(work & SYSCALL_WORK_SYSCALL_TRACEPOINT))
-		syscall = trace_syscall_enter(regs, syscall);
+		trace_syscall_enter(regs);
 
 	if (unlikely(audit_context()))
 		syscall_enter_audit(regs);
 
-	return syscall;
+	/* Either of the above might have changed the syscall number */
+	return syscall_get_nr(current, regs);
 }
 
 /**
--- a/kernel/entry/syscall-common.c
+++ b/kernel/entry/syscall-common.c
@@ -8,14 +8,9 @@
 
 /* Out of line to prevent tracepoint code duplication */
 
-long trace_syscall_enter(struct pt_regs *regs, long syscall)
+void trace_syscall_enter(struct pt_regs *regs)
 {
-	trace_sys_enter(regs, syscall);
-	/*
-	 * Probes or BPF hooks in the tracepoint may have changed the
-	 * system call number. Reread it.
-	 */
-	return syscall_get_nr(current, regs);
+	trace_sys_enter(regs, syscall_get_nr(current, regs));
 }
 
 void trace_syscall_exit(struct pt_regs *regs, long ret)



^ permalink raw reply

* [patch 1/4] entry: Rework syscall_audit_enter()
From: Thomas Gleixner @ 2026-07-12 21:25 UTC (permalink / raw)
  To: LKML
  Cc: Michal Suchánek, Michael Ellerman, Shrikanth Hegde,
	linuxppc-dev, Huacai Chen, loongarch, Paul Walmsley,
	Palmer Dabbelt, linux-riscv, Sven Schnelle, linux-s390, x86,
	Mark Rutland, Jinjie Ruan, Magnus Lindholm,
	Mukesh Kumar Chaurasiya (IBM), Jonathan Corbet, Radu Rendec
In-Reply-To: <20260712134433.549076055@kernel.org>

Move it out of line and let it reread the syscall number on it's own. That
makes the low level entry code denser and allows to move the reread to the
call site of syscall_trace_enter() once the tracer is fixed up.

Signed-off-by: Thomas Gleixner <tglx@kernel.org>
---
 include/linux/entry-common.h  |   14 +++-----------
 kernel/entry/syscall-common.c |   10 ++++++++++
 2 files changed, 13 insertions(+), 11 deletions(-)

--- a/include/linux/entry-common.h
+++ b/include/linux/entry-common.h
@@ -60,16 +60,7 @@ static __always_inline bool arch_ptrace_
 
 long trace_syscall_enter(struct pt_regs *regs, long syscall);
 void trace_syscall_exit(struct pt_regs *regs, long ret);
-
-static inline void syscall_enter_audit(struct pt_regs *regs, long syscall)
-{
-	if (unlikely(audit_context())) {
-		unsigned long args[6];
-
-		syscall_get_arguments(current, regs, args);
-		audit_syscall_entry(syscall, args[0], args[1], args[2], args[3]);
-	}
-}
+void syscall_enter_audit(struct pt_regs *regs);
 
 static __always_inline long syscall_trace_enter(struct pt_regs *regs, unsigned long work,
 						long syscall)
@@ -111,7 +102,8 @@ static __always_inline long syscall_trac
 	if (unlikely(work & SYSCALL_WORK_SYSCALL_TRACEPOINT))
 		syscall = trace_syscall_enter(regs, syscall);
 
-	syscall_enter_audit(regs, syscall);
+	if (unlikely(audit_context()))
+		syscall_enter_audit(regs);
 
 	return syscall;
 }
--- a/kernel/entry/syscall-common.c
+++ b/kernel/entry/syscall-common.c
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 
+#include <linux/audit.h>
 #include <linux/entry-common.h>
 
 #define CREATE_TRACE_POINTS
@@ -21,3 +22,12 @@ void trace_syscall_exit(struct pt_regs *
 {
 	trace_sys_exit(regs, ret);
 }
+
+void syscall_enter_audit(struct pt_regs *regs)
+{
+	long syscall = syscall_get_nr(current, regs);
+	unsigned long args[6];
+
+	syscall_get_arguments(current, regs, args);
+	__audit_syscall_entry(syscall, args[0], args[1], args[2], args[3]);
+}



^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox