.. | .. |
---|
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; |
---|