[PATCH v11 09/14] entry: Rework syscall_exit_to_user_mode_work() for arch reuse

Jinjie Ruan posted 14 patches 1 week, 6 days ago
There is a newer version of this series
[PATCH v11 09/14] entry: Rework syscall_exit_to_user_mode_work() for arch reuse
Posted by Jinjie Ruan 1 week, 6 days ago
In the generic entry code, the beginning of
syscall_exit_to_user_mode_work() can be reused on arm64 so it makes
sense to rework it.

In preparation for moving arm64 over to the generic entry
code, as nothing calls syscall_exit_to_user_mode_work() except for
syscall_exit_to_user_mode(), move local_irq_disable_exit_to_user() and
syscall_exit_to_user_mode_prepare() out from
syscall_exit_to_user_mode_work() to the only one caller.

Also update the comment and no functional changes.

Reviewed-by: Kevin Brodsky <kevin.brodsky@arm.com>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
---
 include/linux/entry-common.h | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/include/linux/entry-common.h b/include/linux/entry-common.h
index e4a8287af822..c4fea642d931 100644
--- a/include/linux/entry-common.h
+++ b/include/linux/entry-common.h
@@ -125,14 +125,14 @@ void syscall_exit_work(struct pt_regs *regs, unsigned long work);
  * syscall_exit_to_user_mode_work - Handle work before returning to user mode
  * @regs:	Pointer to currents pt_regs
  *
- * Same as step 1 and 2 of syscall_exit_to_user_mode() but without calling
+ * Same as step 1 of syscall_exit_to_user_mode() but without calling
+ * local_irq_disable(), syscall_exit_to_user_mode_prepare() and
  * exit_to_user_mode() to perform the final transition to user mode.
  *
- * Calling convention is the same as for syscall_exit_to_user_mode() and it
- * returns with all work handled and interrupts disabled. The caller must
- * invoke exit_to_user_mode() before actually switching to user mode to
- * make the final state transitions. Interrupts must stay disabled between
- * return from this function and the invocation of exit_to_user_mode().
+ * Calling convention is the same as for syscall_exit_to_user_mode(). The
+ * caller must invoke local_irq_disable(), __exit_to_user_mode_prepare() and
+ * exit_to_user_mode() before actually switching to user mode to
+ * make the final state transitions.
  */
 static __always_inline void syscall_exit_to_user_mode_work(struct pt_regs *regs)
 {
@@ -155,8 +155,6 @@ static __always_inline void syscall_exit_to_user_mode_work(struct pt_regs *regs)
 	 */
 	if (unlikely(work & SYSCALL_WORK_EXIT))
 		syscall_exit_work(regs, work);
-	local_irq_disable_exit_to_user();
-	syscall_exit_to_user_mode_prepare(regs);
 }
 
 /**
@@ -192,6 +190,8 @@ static __always_inline void syscall_exit_to_user_mode(struct pt_regs *regs)
 {
 	instrumentation_begin();
 	syscall_exit_to_user_mode_work(regs);
+	local_irq_disable_exit_to_user();
+	syscall_exit_to_user_mode_prepare(regs);
 	instrumentation_end();
 	exit_to_user_mode();
 }
-- 
2.34.1
Re: [PATCH v11 09/14] entry: Rework syscall_exit_to_user_mode_work() for arch reuse
Posted by Kevin Brodsky 1 week, 4 days ago
On 28/01/2026 04:19, Jinjie Ruan wrote:
> In the generic entry code, the beginning of
> syscall_exit_to_user_mode_work() can be reused on arm64 so it makes
> sense to rework it.
>
> In preparation for moving arm64 over to the generic entry
> code, as nothing calls syscall_exit_to_user_mode_work() except for
> syscall_exit_to_user_mode(), move local_irq_disable_exit_to_user() and
> syscall_exit_to_user_mode_prepare() out from
> syscall_exit_to_user_mode_work() to the only one caller.
>
> Also update the comment and no functional changes.
>
> Reviewed-by: Kevin Brodsky <kevin.brodsky@arm.com>
> Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
> Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
> ---
>  include/linux/entry-common.h | 16 ++++++++--------
>  1 file changed, 8 insertions(+), 8 deletions(-)
>
> diff --git a/include/linux/entry-common.h b/include/linux/entry-common.h
> index e4a8287af822..c4fea642d931 100644
> --- a/include/linux/entry-common.h
> +++ b/include/linux/entry-common.h
> @@ -125,14 +125,14 @@ void syscall_exit_work(struct pt_regs *regs, unsigned long work);
>   * syscall_exit_to_user_mode_work - Handle work before returning to user mode
>   * @regs:	Pointer to currents pt_regs
>   *
> - * Same as step 1 and 2 of syscall_exit_to_user_mode() but without calling
> + * Same as step 1 of syscall_exit_to_user_mode() but without calling
> + * local_irq_disable(), syscall_exit_to_user_mode_prepare() and
>   * exit_to_user_mode() to perform the final transition to user mode.
>   *
> - * Calling convention is the same as for syscall_exit_to_user_mode() and it
> - * returns with all work handled and interrupts disabled. The caller must
> - * invoke exit_to_user_mode() before actually switching to user mode to
> - * make the final state transitions. Interrupts must stay disabled between
> - * return from this function and the invocation of exit_to_user_mode().
> + * Calling convention is the same as for syscall_exit_to_user_mode(). The
> + * caller must invoke local_irq_disable(), __exit_to_user_mode_prepare() and

Shouldn't it be syscall_exit_to_user_mode_prepare() rather than
__exit_to_user_mode_prepare()? The former has extra calls (e.g. rseq).

- Kevin

> + * exit_to_user_mode() before actually switching to user mode to
> + * make the final state transitions.
>   */
>  static __always_inline void syscall_exit_to_user_mode_work(struct pt_regs *regs)
>  {
> @@ -155,8 +155,6 @@ static __always_inline void syscall_exit_to_user_mode_work(struct pt_regs *regs)
>  	 */
>  	if (unlikely(work & SYSCALL_WORK_EXIT))
>  		syscall_exit_work(regs, work);
> -	local_irq_disable_exit_to_user();
> -	syscall_exit_to_user_mode_prepare(regs);
>  }
>  
>  /**
> @@ -192,6 +190,8 @@ static __always_inline void syscall_exit_to_user_mode(struct pt_regs *regs)
>  {
>  	instrumentation_begin();
>  	syscall_exit_to_user_mode_work(regs);
> +	local_irq_disable_exit_to_user();
> +	syscall_exit_to_user_mode_prepare(regs);
>  	instrumentation_end();
>  	exit_to_user_mode();
>  }
Re: [PATCH v11 09/14] entry: Rework syscall_exit_to_user_mode_work() for arch reuse
Posted by Jinjie Ruan 1 week, 4 days ago

On 2026/1/29 20:06, Kevin Brodsky wrote:
> On 28/01/2026 04:19, Jinjie Ruan wrote:
>> In the generic entry code, the beginning of
>> syscall_exit_to_user_mode_work() can be reused on arm64 so it makes
>> sense to rework it.
>>
>> In preparation for moving arm64 over to the generic entry
>> code, as nothing calls syscall_exit_to_user_mode_work() except for
>> syscall_exit_to_user_mode(), move local_irq_disable_exit_to_user() and
>> syscall_exit_to_user_mode_prepare() out from
>> syscall_exit_to_user_mode_work() to the only one caller.
>>
>> Also update the comment and no functional changes.
>>
>> Reviewed-by: Kevin Brodsky <kevin.brodsky@arm.com>
>> Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
>> Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
>> ---
>>  include/linux/entry-common.h | 16 ++++++++--------
>>  1 file changed, 8 insertions(+), 8 deletions(-)
>>
>> diff --git a/include/linux/entry-common.h b/include/linux/entry-common.h
>> index e4a8287af822..c4fea642d931 100644
>> --- a/include/linux/entry-common.h
>> +++ b/include/linux/entry-common.h
>> @@ -125,14 +125,14 @@ void syscall_exit_work(struct pt_regs *regs, unsigned long work);
>>   * syscall_exit_to_user_mode_work - Handle work before returning to user mode
>>   * @regs:	Pointer to currents pt_regs
>>   *
>> - * Same as step 1 and 2 of syscall_exit_to_user_mode() but without calling
>> + * Same as step 1 of syscall_exit_to_user_mode() but without calling
>> + * local_irq_disable(), syscall_exit_to_user_mode_prepare() and
>>   * exit_to_user_mode() to perform the final transition to user mode.
>>   *
>> - * Calling convention is the same as for syscall_exit_to_user_mode() and it
>> - * returns with all work handled and interrupts disabled. The caller must
>> - * invoke exit_to_user_mode() before actually switching to user mode to
>> - * make the final state transitions. Interrupts must stay disabled between
>> - * return from this function and the invocation of exit_to_user_mode().
>> + * Calling convention is the same as for syscall_exit_to_user_mode(). The
>> + * caller must invoke local_irq_disable(), __exit_to_user_mode_prepare() and
> 
> Shouldn't it be syscall_exit_to_user_mode_prepare() rather than
> __exit_to_user_mode_prepare()? The former has extra calls (e.g. rseq).

Perhaps we can just delete these comments — at present only generic
entry and arm64 use it, and nowhere else needs it; after the refactoring
the comments now seem rather unclear.

> 
> - Kevin
> 
>> + * exit_to_user_mode() before actually switching to user mode to
>> + * make the final state transitions.
>>   */
>>  static __always_inline void syscall_exit_to_user_mode_work(struct pt_regs *regs)
>>  {
>> @@ -155,8 +155,6 @@ static __always_inline void syscall_exit_to_user_mode_work(struct pt_regs *regs)
>>  	 */
>>  	if (unlikely(work & SYSCALL_WORK_EXIT))
>>  		syscall_exit_work(regs, work);
>> -	local_irq_disable_exit_to_user();
>> -	syscall_exit_to_user_mode_prepare(regs);
>>  }
>>  
>>  /**
>> @@ -192,6 +190,8 @@ static __always_inline void syscall_exit_to_user_mode(struct pt_regs *regs)
>>  {
>>  	instrumentation_begin();
>>  	syscall_exit_to_user_mode_work(regs);
>> +	local_irq_disable_exit_to_user();
>> +	syscall_exit_to_user_mode_prepare(regs);
>>  	instrumentation_end();
>>  	exit_to_user_mode();
>>  }
> 
Re: [PATCH v11 09/14] entry: Rework syscall_exit_to_user_mode_work() for arch reuse
Posted by Kevin Brodsky 1 week, 4 days ago
On 29/01/2026 14:11, Jinjie Ruan wrote:
>>> diff --git a/include/linux/entry-common.h b/include/linux/entry-common.h
>>> index e4a8287af822..c4fea642d931 100644
>>> --- a/include/linux/entry-common.h
>>> +++ b/include/linux/entry-common.h
>>> @@ -125,14 +125,14 @@ void syscall_exit_work(struct pt_regs *regs, unsigned long work);
>>>   * syscall_exit_to_user_mode_work - Handle work before returning to user mode
>>>   * @regs:	Pointer to currents pt_regs
>>>   *
>>> - * Same as step 1 and 2 of syscall_exit_to_user_mode() but without calling
>>> + * Same as step 1 of syscall_exit_to_user_mode() but without calling
>>> + * local_irq_disable(), syscall_exit_to_user_mode_prepare() and
>>>   * exit_to_user_mode() to perform the final transition to user mode.
>>>   *
>>> - * Calling convention is the same as for syscall_exit_to_user_mode() and it
>>> - * returns with all work handled and interrupts disabled. The caller must
>>> - * invoke exit_to_user_mode() before actually switching to user mode to
>>> - * make the final state transitions. Interrupts must stay disabled between
>>> - * return from this function and the invocation of exit_to_user_mode().
>>> + * Calling convention is the same as for syscall_exit_to_user_mode(). The
>>> + * caller must invoke local_irq_disable(), __exit_to_user_mode_prepare() and
>> Shouldn't it be syscall_exit_to_user_mode_prepare() rather than
>> __exit_to_user_mode_prepare()? The former has extra calls (e.g. rseq).
> Perhaps we can just delete these comments — at present only generic
> entry and arm64 use it, and nowhere else needs it; after the refactoring
> the comments now seem rather unclear.

Agreed, the comments are essentially describing what each function
calls; considering how short they are, directly reading the code is
probably easier.

- Kevin
Re: [PATCH v11 09/14] entry: Rework syscall_exit_to_user_mode_work() for arch reuse
Posted by Thomas Gleixner 1 week, 3 days ago
On Thu, Jan 29 2026 at 17:00, Kevin Brodsky wrote:
> On 29/01/2026 14:11, Jinjie Ruan wrote:
>>>> - * Calling convention is the same as for syscall_exit_to_user_mode() and it
>>>> - * returns with all work handled and interrupts disabled. The caller must
>>>> - * invoke exit_to_user_mode() before actually switching to user mode to
>>>> - * make the final state transitions. Interrupts must stay disabled between
>>>> - * return from this function and the invocation of exit_to_user_mode().
>>>> + * Calling convention is the same as for syscall_exit_to_user_mode(). The
>>>> + * caller must invoke local_irq_disable(), __exit_to_user_mode_prepare() and
>>> Shouldn't it be syscall_exit_to_user_mode_prepare() rather than
>>> __exit_to_user_mode_prepare()? The former has extra calls (e.g. rseq).
>> Perhaps we can just delete these comments — at present only generic
>> entry and arm64 use it, and nowhere else needs it; after the refactoring
>> the comments now seem rather unclear.
>
> Agreed, the comments are essentially describing what each function
> calls; considering how short they are, directly reading the code is
> probably easier.

No. Please keep them. There is more information in them than just the
pure 'what's' called.
Re: [PATCH v11 09/14] entry: Rework syscall_exit_to_user_mode_work() for arch reuse
Posted by Kevin Brodsky 1 week, 3 days ago
On 30/01/2026 11:16, Thomas Gleixner wrote:
> On Thu, Jan 29 2026 at 17:00, Kevin Brodsky wrote:
>> On 29/01/2026 14:11, Jinjie Ruan wrote:
>>>>> - * Calling convention is the same as for syscall_exit_to_user_mode() and it
>>>>> - * returns with all work handled and interrupts disabled. The caller must
>>>>> - * invoke exit_to_user_mode() before actually switching to user mode to
>>>>> - * make the final state transitions. Interrupts must stay disabled between
>>>>> - * return from this function and the invocation of exit_to_user_mode().
>>>>> + * Calling convention is the same as for syscall_exit_to_user_mode(). The
>>>>> + * caller must invoke local_irq_disable(), __exit_to_user_mode_prepare() and
>>>> Shouldn't it be syscall_exit_to_user_mode_prepare() rather than
>>>> __exit_to_user_mode_prepare()? The former has extra calls (e.g. rseq).
>>> Perhaps we can just delete these comments — at present only generic
>>> entry and arm64 use it, and nowhere else needs it; after the refactoring
>>> the comments now seem rather unclear.
>> Agreed, the comments are essentially describing what each function
>> calls; considering how short they are, directly reading the code is
>> probably easier.
> No. Please keep them. There is more information in them than just the
> pure 'what's' called.

That is true before this patch, where it made sense to highlight that
exit_to_user_mode() must still be called after this function (without
re-enabling interrupts). With this patch there is however much more that
this function is lacking, and it feels very likely that comments will go
out of sync with exactly what syscall_exit_to_user_mode() calls.

I suppose we could simply point the reader to
syscall_exit_to_user_mode() to find out what else is needed, and keep
the comment about the calling convention being the same.

- Kevin
Re: [PATCH v11 09/14] entry: Rework syscall_exit_to_user_mode_work() for arch reuse
Posted by Thomas Gleixner 1 week, 3 days ago
On Fri, Jan 30 2026 at 14:27, Kevin Brodsky wrote:
> On 30/01/2026 11:16, Thomas Gleixner wrote:
>>> Agreed, the comments are essentially describing what each function
>>> calls; considering how short they are, directly reading the code is
>>> probably easier.
>> No. Please keep them. There is more information in them than just the
>> pure 'what's' called.
>
> That is true before this patch, where it made sense to highlight that
> exit_to_user_mode() must still be called after this function (without
> re-enabling interrupts). With this patch there is however much more that
> this function is lacking, and it feels very likely that comments will go
> out of sync with exactly what syscall_exit_to_user_mode() calls.
>
> I suppose we could simply point the reader to
> syscall_exit_to_user_mode() to find out what else is needed, and keep
> the comment about the calling convention being the same.

I've picked up _all_ four entry changes and reworked the comments and
changelogs already.

Those patches should have been bundled together at the start of the
series anyway so they can be picked up independently without going
through loops and hoops. When will people learn to think beyond the brim
of their architecture tea cup?

I'll go and apply them on top of 6.19-rc1 into core/entry and merge that
into the scheduler branch to resolve the resulting conflict.

ARM64 can either pull that branch or wait until the next rc1 comes out.

Thanks,

        tglx
Re: [PATCH v11 09/14] entry: Rework syscall_exit_to_user_mode_work() for arch reuse
Posted by Jinjie Ruan 1 week, 3 days ago

On 2026/1/30 23:01, Thomas Gleixner wrote:
> On Fri, Jan 30 2026 at 14:27, Kevin Brodsky wrote:
>> On 30/01/2026 11:16, Thomas Gleixner wrote:
>>>> Agreed, the comments are essentially describing what each function
>>>> calls; considering how short they are, directly reading the code is
>>>> probably easier.
>>> No. Please keep them. There is more information in them than just the
>>> pure 'what's' called.
>>
>> That is true before this patch, where it made sense to highlight that
>> exit_to_user_mode() must still be called after this function (without
>> re-enabling interrupts). With this patch there is however much more that
>> this function is lacking, and it feels very likely that comments will go
>> out of sync with exactly what syscall_exit_to_user_mode() calls.
>>
>> I suppose we could simply point the reader to
>> syscall_exit_to_user_mode() to find out what else is needed, and keep
>> the comment about the calling convention being the same.
> 
> I've picked up _all_ four entry changes and reworked the comments and
> changelogs already.
> 
> Those patches should have been bundled together at the start of the
> series anyway so they can be picked up independently without going
> through loops and hoops. When will people learn to think beyond the brim
> of their architecture tea cup?

I'll make sure to group related changes together from the start next
time and keep the whole series in view, not just the
architecture-specific parts.
Thanks for taking the time to re-work them — much appreciated.

> 
> I'll go and apply them on top of 6.19-rc1 into core/entry and merge that
> into the scheduler branch to resolve the resulting conflict.
> 
> ARM64 can either pull that branch or wait until the next rc1 comes out.

Thanks for re-bundling the four entry patches and reworking the logs —
that definitely makes the series easier to pick up.

I'll rebase my remaining changes on top of 6.19-rc1 once the core/entry
branch lands.

Let me know if there’s anything I can do to simplify the logistics.

Regards,
Jinjie

> 
> Thanks,
> 
>         tglx
> 
> 
Re: [PATCH v11 09/14] entry: Rework syscall_exit_to_user_mode_work() for arch reuse
Posted by Thomas Gleixner 1 week, 3 days ago
On Fri, Jan 30 2026 at 16:01, Thomas Gleixner wrote:
> I'll go and apply them on top of 6.19-rc1 into core/entry and merge that
> into the scheduler branch to resolve the resulting conflict.
>
> ARM64 can either pull that branch or wait until the next rc1 comes out.

  git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git entry-for-arm64-26-01-31

Consider that tag immutable and consumable for ARM64 if you need it. I
did some massaging, but the ARM64 pile should still apply on top of it.

Thanks,

        tglx
[tip: core/entry] entry: Rework syscall_exit_to_user_mode_work() for architecture reuse
Posted by tip-bot2 for Jinjie Ruan 1 week, 3 days ago
The following commit has been merged into the core/entry branch of tip:

Commit-ID:     e1647100c22eb718e9833211722cbb78e339047c
Gitweb:        https://git.kernel.org/tip/e1647100c22eb718e9833211722cbb78e339047c
Author:        Jinjie Ruan <ruanjinjie@huawei.com>
AuthorDate:    Wed, 28 Jan 2026 11:19:29 +08:00
Committer:     Thomas Gleixner <tglx@kernel.org>
CommitterDate: Fri, 30 Jan 2026 15:38:09 +01:00

entry: Rework syscall_exit_to_user_mode_work() for architecture reuse

syscall_exit_to_user_mode_work() invokes local_irq_disable_exit_to_user()
and syscall_exit_to_user_mode_prepare() after handling pending syscall exit
work.

The conversion of ARM64 to the generic entry code requires this to be split
up, so move the invocations of local_irq_disable_exit_to_user() and
syscall_exit_to_user_mode_prepare() into the only caller.

No functional change intended.

[ tglx: Massaged changelog and comments ]

Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Reviewed-by: Kevin Brodsky <kevin.brodsky@arm.com>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://patch.msgid.link/20260128031934.3906955-10-ruanjinjie@huawei.com
---
 include/linux/entry-common.h | 25 +++++++++++--------------
 1 file changed, 11 insertions(+), 14 deletions(-)

diff --git a/include/linux/entry-common.h b/include/linux/entry-common.h
index e4a8287..5316004 100644
--- a/include/linux/entry-common.h
+++ b/include/linux/entry-common.h
@@ -122,17 +122,12 @@ static __always_inline long syscall_enter_from_user_mode(struct pt_regs *regs, l
 void syscall_exit_work(struct pt_regs *regs, unsigned long work);
 
 /**
- * syscall_exit_to_user_mode_work - Handle work before returning to user mode
+ * syscall_exit_to_user_mode_work - Handle one time work before returning to user mode
  * @regs:	Pointer to currents pt_regs
  *
- * Same as step 1 and 2 of syscall_exit_to_user_mode() but without calling
- * exit_to_user_mode() to perform the final transition to user mode.
+ * Step 1 of syscall_exit_to_user_mode() with the same calling convention.
  *
- * Calling convention is the same as for syscall_exit_to_user_mode() and it
- * returns with all work handled and interrupts disabled. The caller must
- * invoke exit_to_user_mode() before actually switching to user mode to
- * make the final state transitions. Interrupts must stay disabled between
- * return from this function and the invocation of exit_to_user_mode().
+ * The caller must invoke steps 2-3 of syscall_exit_to_user_mode() afterwards.
  */
 static __always_inline void syscall_exit_to_user_mode_work(struct pt_regs *regs)
 {
@@ -155,15 +150,13 @@ static __always_inline void syscall_exit_to_user_mode_work(struct pt_regs *regs)
 	 */
 	if (unlikely(work & SYSCALL_WORK_EXIT))
 		syscall_exit_work(regs, work);
-	local_irq_disable_exit_to_user();
-	syscall_exit_to_user_mode_prepare(regs);
 }
 
 /**
  * syscall_exit_to_user_mode - Handle work before returning to user mode
  * @regs:	Pointer to currents pt_regs
  *
- * Invoked with interrupts enabled and fully valid regs. Returns with all
+ * Invoked with interrupts enabled and fully valid @regs. Returns with all
  * work handled, interrupts disabled such that the caller can immediately
  * switch to user mode. Called from architecture specific syscall and ret
  * from fork code.
@@ -176,6 +169,7 @@ static __always_inline void syscall_exit_to_user_mode_work(struct pt_regs *regs)
  *	- ptrace (single stepping)
  *
  *  2) Preparatory work
+ *	- Disable interrupts
  *	- Exit to user mode loop (common TIF handling). Invokes
  *	  arch_exit_to_user_mode_work() for architecture specific TIF work
  *	- Architecture specific one time work arch_exit_to_user_mode_prepare()
@@ -184,14 +178,17 @@ static __always_inline void syscall_exit_to_user_mode_work(struct pt_regs *regs)
  *  3) Final transition (lockdep, tracing, context tracking, RCU), i.e. the
  *     functionality in exit_to_user_mode().
  *
- * This is a combination of syscall_exit_to_user_mode_work() (1,2) and
- * exit_to_user_mode(). This function is preferred unless there is a
- * compelling architectural reason to use the separate functions.
+ * This is a combination of syscall_exit_to_user_mode_work() (1), disabling
+ * interrupts followed by syscall_exit_to_user_mode_prepare() (2) and
+ * exit_to_user_mode() (3). This function is preferred unless there is a
+ * compelling architectural reason to invoke the functions separately.
  */
 static __always_inline void syscall_exit_to_user_mode(struct pt_regs *regs)
 {
 	instrumentation_begin();
 	syscall_exit_to_user_mode_work(regs);
+	local_irq_disable_exit_to_user();
+	syscall_exit_to_user_mode_prepare(regs);
 	instrumentation_end();
 	exit_to_user_mode();
 }