Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

entry: Split up exit_to_user_mode_prepare()

exit_to_user_mode_prepare() is used for both interrupts and syscalls, but
there is extra rseq work, which is only required for in the interrupt exit
case.

Split up the function and provide wrappers for syscalls and interrupts,
which allows to separate the rseq exit work in the next step.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Reviewed-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Link: https://patch.msgid.link/20251027084307.782234789@linutronix.de

authored by

Thomas Gleixner and committed by
Ingo Molnar
70fe25a3 3db6b38d

+46 -7
+1 -1
arch/arm64/kernel/entry-common.c
··· 100 100 static __always_inline void arm64_exit_to_user_mode(struct pt_regs *regs) 101 101 { 102 102 local_irq_disable(); 103 - exit_to_user_mode_prepare(regs); 103 + exit_to_user_mode_prepare_legacy(regs); 104 104 local_daif_mask(); 105 105 mte_check_tfsr_exit(); 106 106 exit_to_user_mode();
+1 -1
include/linux/entry-common.h
··· 156 156 if (unlikely(work & SYSCALL_WORK_EXIT)) 157 157 syscall_exit_work(regs, work); 158 158 local_irq_disable_exit_to_user(); 159 - exit_to_user_mode_prepare(regs); 159 + syscall_exit_to_user_mode_prepare(regs); 160 160 } 161 161 162 162 /**
+44 -5
include/linux/irq-entry-common.h
··· 201 201 unsigned long exit_to_user_mode_loop(struct pt_regs *regs, unsigned long ti_work); 202 202 203 203 /** 204 - * exit_to_user_mode_prepare - call exit_to_user_mode_loop() if required 204 + * __exit_to_user_mode_prepare - call exit_to_user_mode_loop() if required 205 205 * @regs: Pointer to pt_regs on entry stack 206 206 * 207 207 * 1) check that interrupts are disabled ··· 209 209 * 3) call exit_to_user_mode_loop() if any flags from 210 210 * EXIT_TO_USER_MODE_WORK are set 211 211 * 4) check that interrupts are still disabled 212 + * 213 + * Don't invoke directly, use the syscall/irqentry_ prefixed variants below 212 214 */ 213 - static __always_inline void exit_to_user_mode_prepare(struct pt_regs *regs) 215 + static __always_inline void __exit_to_user_mode_prepare(struct pt_regs *regs) 214 216 { 215 217 unsigned long ti_work; 216 218 ··· 226 224 ti_work = exit_to_user_mode_loop(regs, ti_work); 227 225 228 226 arch_exit_to_user_mode_prepare(regs, ti_work); 227 + } 229 228 230 - rseq_exit_to_user_mode(); 231 - 229 + static __always_inline void __exit_to_user_mode_validate(void) 230 + { 232 231 /* Ensure that kernel state is sane for a return to userspace */ 233 232 kmap_assert_nomap(); 234 233 lockdep_assert_irqs_disabled(); 235 234 lockdep_sys_exit(); 235 + } 236 + 237 + /* Temporary workaround to keep ARM64 alive */ 238 + static __always_inline void exit_to_user_mode_prepare_legacy(struct pt_regs *regs) 239 + { 240 + __exit_to_user_mode_prepare(regs); 241 + rseq_exit_to_user_mode(); 242 + __exit_to_user_mode_validate(); 243 + } 244 + 245 + /** 246 + * syscall_exit_to_user_mode_prepare - call exit_to_user_mode_loop() if required 247 + * @regs: Pointer to pt_regs on entry stack 248 + * 249 + * Wrapper around __exit_to_user_mode_prepare() to separate the exit work for 250 + * syscalls and interrupts. 251 + */ 252 + static __always_inline void syscall_exit_to_user_mode_prepare(struct pt_regs *regs) 253 + { 254 + __exit_to_user_mode_prepare(regs); 255 + rseq_exit_to_user_mode(); 256 + __exit_to_user_mode_validate(); 257 + } 258 + 259 + /** 260 + * irqentry_exit_to_user_mode_prepare - call exit_to_user_mode_loop() if required 261 + * @regs: Pointer to pt_regs on entry stack 262 + * 263 + * Wrapper around __exit_to_user_mode_prepare() to separate the exit work for 264 + * syscalls and interrupts. 265 + */ 266 + static __always_inline void irqentry_exit_to_user_mode_prepare(struct pt_regs *regs) 267 + { 268 + __exit_to_user_mode_prepare(regs); 269 + rseq_exit_to_user_mode(); 270 + __exit_to_user_mode_validate(); 236 271 } 237 272 238 273 /** ··· 336 297 static __always_inline void irqentry_exit_to_user_mode(struct pt_regs *regs) 337 298 { 338 299 instrumentation_begin(); 339 - exit_to_user_mode_prepare(regs); 300 + irqentry_exit_to_user_mode_prepare(regs); 340 301 instrumentation_end(); 341 302 exit_to_user_mode(); 342 303 }