| .. | .. |
|---|
| 11 | 11 | #include <linux/errno.h> |
|---|
| 12 | 12 | #include <linux/kernel.h> |
|---|
| 13 | 13 | #include <linux/signal.h> |
|---|
| 14 | +#include <linux/irq_pipeline.h> |
|---|
| 14 | 15 | #include <linux/personality.h> |
|---|
| 15 | 16 | #include <linux/freezer.h> |
|---|
| 16 | 17 | #include <linux/stddef.h> |
|---|
| .. | .. |
|---|
| 914 | 915 | restore_saved_sigmask(); |
|---|
| 915 | 916 | } |
|---|
| 916 | 917 | |
|---|
| 918 | +static inline void do_retuser(void) |
|---|
| 919 | +{ |
|---|
| 920 | + unsigned long thread_flags; |
|---|
| 921 | + |
|---|
| 922 | + if (dovetailing()) { |
|---|
| 923 | + thread_flags = current_thread_info()->flags; |
|---|
| 924 | + if (thread_flags & _TIF_RETUSER) |
|---|
| 925 | + inband_retuser_notify(); |
|---|
| 926 | + } |
|---|
| 927 | +} |
|---|
| 928 | + |
|---|
| 917 | 929 | asmlinkage void do_notify_resume(struct pt_regs *regs, |
|---|
| 918 | 930 | unsigned long thread_flags) |
|---|
| 919 | 931 | { |
|---|
| 932 | + WARN_ON_ONCE(irq_pipeline_debug() && running_oob()); |
|---|
| 933 | + |
|---|
| 934 | + stall_inband(); |
|---|
| 935 | + |
|---|
| 920 | 936 | do { |
|---|
| 921 | 937 | /* Check valid user FS if needed */ |
|---|
| 922 | 938 | addr_limit_user_check(); |
|---|
| 923 | 939 | |
|---|
| 924 | 940 | if (thread_flags & _TIF_NEED_RESCHED) { |
|---|
| 925 | 941 | /* Unmask Debug and SError for the next task */ |
|---|
| 926 | | - local_daif_restore(DAIF_PROCCTX_NOIRQ); |
|---|
| 942 | + local_daif_restore(irqs_pipelined() ? DAIF_PROCCTX : |
|---|
| 943 | + DAIF_PROCCTX_NOIRQ); |
|---|
| 927 | 944 | |
|---|
| 928 | 945 | schedule(); |
|---|
| 929 | 946 | } else { |
|---|
| 947 | + unstall_inband(); |
|---|
| 930 | 948 | local_daif_restore(DAIF_PROCCTX); |
|---|
| 931 | 949 | |
|---|
| 932 | 950 | if (thread_flags & _TIF_UPROBE) |
|---|
| .. | .. |
|---|
| 948 | 966 | |
|---|
| 949 | 967 | if (thread_flags & _TIF_FOREIGN_FPSTATE) |
|---|
| 950 | 968 | fpsimd_restore_current_state(); |
|---|
| 969 | + |
|---|
| 970 | + do_retuser(); |
|---|
| 971 | + /* RETUSER might have switched oob */ |
|---|
| 972 | + if (running_oob()) { |
|---|
| 973 | + local_daif_mask(); |
|---|
| 974 | + return; |
|---|
| 975 | + } |
|---|
| 951 | 976 | } |
|---|
| 952 | 977 | |
|---|
| 978 | + /* |
|---|
| 979 | + * Dovetail: we may have restored the fpsimd state for |
|---|
| 980 | + * current with no other opportunity to check for |
|---|
| 981 | + * _TIF_FOREIGN_FPSTATE until we are back running on |
|---|
| 982 | + * el0, so we must not take any interrupt until then, |
|---|
| 983 | + * otherwise we may end up resuming with some OOB |
|---|
| 984 | + * thread's fpsimd state. |
|---|
| 985 | + */ |
|---|
| 953 | 986 | local_daif_mask(); |
|---|
| 987 | + stall_inband(); |
|---|
| 954 | 988 | thread_flags = READ_ONCE(current_thread_info()->flags); |
|---|
| 955 | 989 | } while (thread_flags & _TIF_WORK_MASK); |
|---|
| 990 | + |
|---|
| 991 | + unstall_inband(); |
|---|
| 956 | 992 | } |
|---|
| 957 | 993 | |
|---|
| 958 | 994 | unsigned long __ro_after_init signal_minsigstksz; |
|---|