hc
2024-05-10 23fa18eaa71266feff7ba8d83022d9e1cc83c65a
kernel/arch/powerpc/kernel/signal.c
....@@ -18,11 +18,152 @@
1818 #include <linux/syscalls.h>
1919 #include <asm/hw_breakpoint.h>
2020 #include <linux/uaccess.h>
21
+#include <asm/switch_to.h>
2122 #include <asm/unistd.h>
2223 #include <asm/debug.h>
2324 #include <asm/tm.h>
2425
2526 #include "signal.h"
27
+
28
+#ifdef CONFIG_VSX
29
+unsigned long copy_fpr_to_user(void __user *to,
30
+ struct task_struct *task)
31
+{
32
+ u64 buf[ELF_NFPREG];
33
+ int i;
34
+
35
+ /* save FPR copy to local buffer then write to the thread_struct */
36
+ for (i = 0; i < (ELF_NFPREG - 1) ; i++)
37
+ buf[i] = task->thread.TS_FPR(i);
38
+ buf[i] = task->thread.fp_state.fpscr;
39
+ return __copy_to_user(to, buf, ELF_NFPREG * sizeof(double));
40
+}
41
+
42
+unsigned long copy_fpr_from_user(struct task_struct *task,
43
+ void __user *from)
44
+{
45
+ u64 buf[ELF_NFPREG];
46
+ int i;
47
+
48
+ if (__copy_from_user(buf, from, ELF_NFPREG * sizeof(double)))
49
+ return 1;
50
+ for (i = 0; i < (ELF_NFPREG - 1) ; i++)
51
+ task->thread.TS_FPR(i) = buf[i];
52
+ task->thread.fp_state.fpscr = buf[i];
53
+
54
+ return 0;
55
+}
56
+
57
+unsigned long copy_vsx_to_user(void __user *to,
58
+ struct task_struct *task)
59
+{
60
+ u64 buf[ELF_NVSRHALFREG];
61
+ int i;
62
+
63
+ /* save FPR copy to local buffer then write to the thread_struct */
64
+ for (i = 0; i < ELF_NVSRHALFREG; i++)
65
+ buf[i] = task->thread.fp_state.fpr[i][TS_VSRLOWOFFSET];
66
+ return __copy_to_user(to, buf, ELF_NVSRHALFREG * sizeof(double));
67
+}
68
+
69
+unsigned long copy_vsx_from_user(struct task_struct *task,
70
+ void __user *from)
71
+{
72
+ u64 buf[ELF_NVSRHALFREG];
73
+ int i;
74
+
75
+ if (__copy_from_user(buf, from, ELF_NVSRHALFREG * sizeof(double)))
76
+ return 1;
77
+ for (i = 0; i < ELF_NVSRHALFREG ; i++)
78
+ task->thread.fp_state.fpr[i][TS_VSRLOWOFFSET] = buf[i];
79
+ return 0;
80
+}
81
+
82
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
83
+unsigned long copy_ckfpr_to_user(void __user *to,
84
+ struct task_struct *task)
85
+{
86
+ u64 buf[ELF_NFPREG];
87
+ int i;
88
+
89
+ /* save FPR copy to local buffer then write to the thread_struct */
90
+ for (i = 0; i < (ELF_NFPREG - 1) ; i++)
91
+ buf[i] = task->thread.TS_CKFPR(i);
92
+ buf[i] = task->thread.ckfp_state.fpscr;
93
+ return __copy_to_user(to, buf, ELF_NFPREG * sizeof(double));
94
+}
95
+
96
+unsigned long copy_ckfpr_from_user(struct task_struct *task,
97
+ void __user *from)
98
+{
99
+ u64 buf[ELF_NFPREG];
100
+ int i;
101
+
102
+ if (__copy_from_user(buf, from, ELF_NFPREG * sizeof(double)))
103
+ return 1;
104
+ for (i = 0; i < (ELF_NFPREG - 1) ; i++)
105
+ task->thread.TS_CKFPR(i) = buf[i];
106
+ task->thread.ckfp_state.fpscr = buf[i];
107
+
108
+ return 0;
109
+}
110
+
111
+unsigned long copy_ckvsx_to_user(void __user *to,
112
+ struct task_struct *task)
113
+{
114
+ u64 buf[ELF_NVSRHALFREG];
115
+ int i;
116
+
117
+ /* save FPR copy to local buffer then write to the thread_struct */
118
+ for (i = 0; i < ELF_NVSRHALFREG; i++)
119
+ buf[i] = task->thread.ckfp_state.fpr[i][TS_VSRLOWOFFSET];
120
+ return __copy_to_user(to, buf, ELF_NVSRHALFREG * sizeof(double));
121
+}
122
+
123
+unsigned long copy_ckvsx_from_user(struct task_struct *task,
124
+ void __user *from)
125
+{
126
+ u64 buf[ELF_NVSRHALFREG];
127
+ int i;
128
+
129
+ if (__copy_from_user(buf, from, ELF_NVSRHALFREG * sizeof(double)))
130
+ return 1;
131
+ for (i = 0; i < ELF_NVSRHALFREG ; i++)
132
+ task->thread.ckfp_state.fpr[i][TS_VSRLOWOFFSET] = buf[i];
133
+ return 0;
134
+}
135
+#endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
136
+#else
137
+inline unsigned long copy_fpr_to_user(void __user *to,
138
+ struct task_struct *task)
139
+{
140
+ return __copy_to_user(to, task->thread.fp_state.fpr,
141
+ ELF_NFPREG * sizeof(double));
142
+}
143
+
144
+inline unsigned long copy_fpr_from_user(struct task_struct *task,
145
+ void __user *from)
146
+{
147
+ return __copy_from_user(task->thread.fp_state.fpr, from,
148
+ ELF_NFPREG * sizeof(double));
149
+}
150
+
151
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
152
+inline unsigned long copy_ckfpr_to_user(void __user *to,
153
+ struct task_struct *task)
154
+{
155
+ return __copy_to_user(to, task->thread.ckfp_state.fpr,
156
+ ELF_NFPREG * sizeof(double));
157
+}
158
+
159
+inline unsigned long copy_ckfpr_from_user(struct task_struct *task,
160
+ void __user *from)
161
+{
162
+ return __copy_from_user(task->thread.ckfp_state.fpr, from,
163
+ ELF_NFPREG * sizeof(double));
164
+}
165
+#endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
166
+#endif
26167
27168 /* Log an error when sending an unhandled signal to a process. Controlled
28169 * through debug.exception-trace sysctl.
....@@ -44,7 +185,7 @@
44185 newsp = (oldsp - frame_size) & ~0xFUL;
45186
46187 /* Check access */
47
- if (!access_ok(VERIFY_WRITE, (void __user *)newsp, oldsp - newsp))
188
+ if (!access_ok((void __user *)newsp, oldsp - newsp))
48189 return NULL;
49190
50191 return (void __user *)newsp;
....@@ -57,12 +198,21 @@
57198 int restart = 1;
58199
59200 /* syscall ? */
60
- if (TRAP(regs) != 0x0C00)
201
+ if (!trap_is_syscall(regs))
202
+ return;
203
+
204
+ if (trap_norestart(regs))
61205 return;
62206
63207 /* error signalled ? */
64
- if (!(regs->ccr & 0x10000000))
208
+ if (trap_is_scv(regs)) {
209
+ /* 32-bit compat mode sign extend? */
210
+ if (!IS_ERR_VALUE(ret))
211
+ return;
212
+ ret = -ret;
213
+ } else if (!(regs->ccr & 0x10000000)) {
65214 return;
215
+ }
66216
67217 switch (ret) {
68218 case ERESTART_RESTARTBLOCK:
....@@ -95,9 +245,14 @@
95245 regs->nip -= 4;
96246 regs->result = 0;
97247 } else {
98
- regs->result = -EINTR;
99
- regs->gpr[3] = EINTR;
100
- regs->ccr |= 0x10000000;
248
+ if (trap_is_scv(regs)) {
249
+ regs->result = -EINTR;
250
+ regs->gpr[3] = -EINTR;
251
+ } else {
252
+ regs->result = -EINTR;
253
+ regs->gpr[3] = EINTR;
254
+ regs->ccr |= 0x10000000;
255
+ }
101256 }
102257 }
103258
....@@ -106,7 +261,6 @@
106261 sigset_t *oldset = sigmask_to_save();
107262 struct ksignal ksig = { .sig = 0 };
108263 int ret;
109
- int is32 = is_32bit_task();
110264
111265 BUG_ON(tsk != current);
112266
....@@ -118,25 +272,30 @@
118272 if (ksig.sig <= 0) {
119273 /* No signal to deliver -- put the saved sigmask back */
120274 restore_saved_sigmask();
121
- tsk->thread.regs->trap = 0;
275
+ set_trap_norestart(tsk->thread.regs);
122276 return; /* no signals delivered */
123277 }
124278
125
-#ifndef CONFIG_PPC_ADV_DEBUG_REGS
126279 /*
127280 * Reenable the DABR before delivering the signal to
128281 * user space. The DABR will have been cleared if it
129282 * triggered inside the kernel.
130283 */
131
- if (tsk->thread.hw_brk.address && tsk->thread.hw_brk.type)
132
- __set_breakpoint(&tsk->thread.hw_brk);
133
-#endif
284
+ if (!IS_ENABLED(CONFIG_PPC_ADV_DEBUG_REGS)) {
285
+ int i;
286
+
287
+ for (i = 0; i < nr_wp_slots(); i++) {
288
+ if (tsk->thread.hw_brk[i].address && tsk->thread.hw_brk[i].type)
289
+ __set_breakpoint(i, &tsk->thread.hw_brk[i]);
290
+ }
291
+ }
292
+
134293 /* Re-enable the breakpoints for the signal stack */
135294 thread_change_pc(tsk, tsk->thread.regs);
136295
137296 rseq_signal_deliver(&ksig, tsk->thread.regs);
138297
139
- if (is32) {
298
+ if (is_32bit_task()) {
140299 if (ksig.ka.sa.sa_flags & SA_SIGINFO)
141300 ret = handle_rt_signal32(&ksig, oldset, tsk);
142301 else
....@@ -145,7 +304,7 @@
145304 ret = handle_rt_signal64(&ksig, oldset, tsk);
146305 }
147306
148
- tsk->thread.regs->trap = 0;
307
+ set_trap_norestart(tsk->thread.regs);
149308 signal_setup_done(ret, &ksig, test_thread_flag(TIF_SINGLESTEP));
150309 }
151310
....@@ -153,22 +312,18 @@
153312 {
154313 user_exit();
155314
156
- /* Check valid addr_limit, TIF check is done there */
157
- addr_limit_user_check();
158
-
159315 if (thread_info_flags & _TIF_UPROBE)
160316 uprobe_notify_resume(regs);
161317
162318 if (thread_info_flags & _TIF_PATCH_PENDING)
163319 klp_update_patch_state(current);
164320
165
- if (thread_info_flags & _TIF_SIGPENDING) {
321
+ if (thread_info_flags & (_TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL)) {
166322 BUG_ON(regs != current->thread.regs);
167323 do_signal(current);
168324 }
169325
170326 if (thread_info_flags & _TIF_NOTIFY_RESUME) {
171
- clear_thread_flag(TIF_NOTIFY_RESUME);
172327 tracehook_notify_resume(regs);
173328 rseq_handle_notify_resume(NULL, regs);
174329 }