irqentry_exit_to_kernel_mode_after_preempt(regs, state);
}
+static __always_inline void arm64_syscall_enter_from_user_mode(struct pt_regs *regs)
+{
+ enter_from_user_mode(regs);
+ mte_disable_tco_entry(current);
+ sme_enter_from_user_mode();
+}
+
/*
* Handle IRQ/context state management when entering from user mode.
* Before this function is called it is not safe to call regular kernel code,
static __always_inline void arm64_enter_from_user_mode(struct pt_regs *regs)
{
enter_from_user_mode(regs);
+ rseq_note_user_irq_entry();
mte_disable_tco_entry(current);
sme_enter_from_user_mode();
}
+static __always_inline void arm64_syscall_exit_to_user_mode(struct pt_regs *regs)
+{
+ local_irq_disable();
+ syscall_exit_to_user_mode_prepare(regs);
+ local_daif_mask();
+ sme_exit_to_user_mode();
+ mte_check_tfsr_exit();
+ exit_to_user_mode();
+}
+
/*
* Handle IRQ/context state management when exiting to user mode.
* After this function returns it is not safe to call regular kernel code,
* instrumentable code, or any code which may trigger an exception.
*/
-
static __always_inline void arm64_exit_to_user_mode(struct pt_regs *regs)
{
local_irq_disable();
- exit_to_user_mode_prepare_legacy(regs);
+ irqentry_exit_to_user_mode_prepare(regs);
local_daif_mask();
sme_exit_to_user_mode();
mte_check_tfsr_exit();
asmlinkage void noinstr asm_exit_to_user_mode(struct pt_regs *regs)
{
- arm64_exit_to_user_mode(regs);
+ arm64_syscall_exit_to_user_mode(regs);
}
/*
static void noinstr el0_svc(struct pt_regs *regs)
{
- arm64_enter_from_user_mode(regs);
+ arm64_syscall_enter_from_user_mode(regs);
cortex_a76_erratum_1463225_svc_handler();
fpsimd_syscall_enter();
local_daif_restore(DAIF_PROCCTX);
do_el0_svc(regs);
- arm64_exit_to_user_mode(regs);
+ arm64_syscall_exit_to_user_mode(regs);
fpsimd_syscall_exit();
}
static void noinstr el0_svc_compat(struct pt_regs *regs)
{
- arm64_enter_from_user_mode(regs);
+ arm64_syscall_enter_from_user_mode(regs);
cortex_a76_erratum_1463225_svc_handler();
local_daif_restore(DAIF_PROCCTX);
do_el0_svc_compat(regs);
- arm64_exit_to_user_mode(regs);
+ arm64_syscall_exit_to_user_mode(regs);
}
static void noinstr el0_bkpt32(struct pt_regs *regs, unsigned long esr)
lockdep_sys_exit();
}
-/* Temporary workaround to keep ARM64 alive */
-static __always_inline void exit_to_user_mode_prepare_legacy(struct pt_regs *regs)
-{
- __exit_to_user_mode_prepare(regs, EXIT_TO_USER_MODE_WORK);
- rseq_exit_to_user_mode_legacy();
- __exit_to_user_mode_validate();
-}
-
/**
* syscall_exit_to_user_mode_prepare - call exit_to_user_mode_loop() if required
* @regs: Pointer to pt_regs on entry stack
ev->events = 0;
}
-/* Required to keep ARM64 working */
-static __always_inline void rseq_exit_to_user_mode_legacy(void)
-{
- struct rseq_event *ev = ¤t->rseq.event;
-
- rseq_stat_inc(rseq_stats.exit);
-
- if (static_branch_unlikely(&rseq_debug_enabled))
- WARN_ON_ONCE(ev->sched_switch);
-
- /*
- * Ensure that event (especially user_irq) is cleared when the
- * interrupt did not result in a schedule and therefore the
- * rseq processing did not clear it.
- */
- ev->events = 0;
-}
-
void __rseq_debug_syscall_return(struct pt_regs *regs);
static __always_inline void rseq_debug_syscall_return(struct pt_regs *regs)
}
static inline void rseq_syscall_exit_to_user_mode(void) { }
static inline void rseq_irqentry_exit_to_user_mode(void) { }
-static inline void rseq_exit_to_user_mode_legacy(void) { }
static inline void rseq_debug_syscall_return(struct pt_regs *regs) { }
static inline bool rseq_grant_slice_extension(unsigned long ti_work, unsigned long mask) { return false; }
#endif /* !CONFIG_RSEQ */