.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* By Ross Biro 1/23/92 */ |
---|
2 | 3 | /* |
---|
3 | 4 | * Pentium III FXSR, SSE support |
---|
.. | .. |
---|
27 | 28 | #include <linux/nospec.h> |
---|
28 | 29 | |
---|
29 | 30 | #include <linux/uaccess.h> |
---|
30 | | -#include <asm/pgtable.h> |
---|
31 | 31 | #include <asm/processor.h> |
---|
32 | 32 | #include <asm/fpu/internal.h> |
---|
33 | 33 | #include <asm/fpu/signal.h> |
---|
.. | .. |
---|
40 | 40 | #include <asm/hw_breakpoint.h> |
---|
41 | 41 | #include <asm/traps.h> |
---|
42 | 42 | #include <asm/syscall.h> |
---|
43 | | -#include <asm/mmu_context.h> |
---|
| 43 | +#include <asm/fsgsbase.h> |
---|
| 44 | +#include <asm/io_bitmap.h> |
---|
44 | 45 | |
---|
45 | 46 | #include "tls.h" |
---|
46 | 47 | |
---|
.. | .. |
---|
154 | 155 | |
---|
155 | 156 | #define FLAG_MASK FLAG_MASK_32 |
---|
156 | 157 | |
---|
157 | | -/* |
---|
158 | | - * X86_32 CPUs don't save ss and esp if the CPU is already in kernel mode |
---|
159 | | - * when it traps. The previous stack will be directly underneath the saved |
---|
160 | | - * registers, and 'sp/ss' won't even have been saved. Thus the '®s->sp'. |
---|
161 | | - * |
---|
162 | | - * Now, if the stack is empty, '®s->sp' is out of range. In this |
---|
163 | | - * case we try to take the previous stack. To always return a non-null |
---|
164 | | - * stack pointer we fall back to regs as stack if no previous stack |
---|
165 | | - * exists. |
---|
166 | | - * |
---|
167 | | - * This is valid only for kernel mode traps. |
---|
168 | | - */ |
---|
169 | | -unsigned long kernel_stack_pointer(struct pt_regs *regs) |
---|
170 | | -{ |
---|
171 | | - unsigned long context = (unsigned long)regs & ~(THREAD_SIZE - 1); |
---|
172 | | - unsigned long sp = (unsigned long)®s->sp; |
---|
173 | | - u32 *prev_esp; |
---|
174 | | - |
---|
175 | | - if (context == (sp & ~(THREAD_SIZE - 1))) |
---|
176 | | - return sp; |
---|
177 | | - |
---|
178 | | - prev_esp = (u32 *)(context); |
---|
179 | | - if (*prev_esp) |
---|
180 | | - return (unsigned long)*prev_esp; |
---|
181 | | - |
---|
182 | | - return (unsigned long)regs; |
---|
183 | | -} |
---|
184 | | -EXPORT_SYMBOL_GPL(kernel_stack_pointer); |
---|
185 | | - |
---|
186 | 158 | static unsigned long *pt_regs_access(struct pt_regs *regs, unsigned long regno) |
---|
187 | 159 | { |
---|
188 | 160 | BUILD_BUG_ON(offsetof(struct pt_regs, bx) != 0); |
---|
.. | .. |
---|
209 | 181 | static int set_segment_reg(struct task_struct *task, |
---|
210 | 182 | unsigned long offset, u16 value) |
---|
211 | 183 | { |
---|
| 184 | + if (WARN_ON_ONCE(task == current)) |
---|
| 185 | + return -EIO; |
---|
| 186 | + |
---|
212 | 187 | /* |
---|
213 | 188 | * The value argument was already truncated to 16 bits. |
---|
214 | 189 | */ |
---|
.. | .. |
---|
229 | 204 | case offsetof(struct user_regs_struct, ss): |
---|
230 | 205 | if (unlikely(value == 0)) |
---|
231 | 206 | return -EIO; |
---|
| 207 | + fallthrough; |
---|
232 | 208 | |
---|
233 | 209 | default: |
---|
234 | 210 | *pt_regs_access(task_pt_regs(task), offset) = value; |
---|
235 | 211 | break; |
---|
236 | 212 | |
---|
237 | 213 | case offsetof(struct user_regs_struct, gs): |
---|
238 | | - if (task == current) |
---|
239 | | - set_user_gs(task_pt_regs(task), value); |
---|
240 | | - else |
---|
241 | | - task_user_gs(task) = value; |
---|
| 214 | + task_user_gs(task) = value; |
---|
242 | 215 | } |
---|
243 | 216 | |
---|
244 | 217 | return 0; |
---|
.. | .. |
---|
298 | 271 | static int set_segment_reg(struct task_struct *task, |
---|
299 | 272 | unsigned long offset, u16 value) |
---|
300 | 273 | { |
---|
| 274 | + if (WARN_ON_ONCE(task == current)) |
---|
| 275 | + return -EIO; |
---|
| 276 | + |
---|
301 | 277 | /* |
---|
302 | 278 | * The value argument was already truncated to 16 bits. |
---|
303 | 279 | */ |
---|
304 | 280 | if (invalid_selector(value)) |
---|
305 | 281 | return -EIO; |
---|
306 | 282 | |
---|
| 283 | + /* |
---|
| 284 | + * Writes to FS and GS will change the stored selector. Whether |
---|
| 285 | + * this changes the segment base as well depends on whether |
---|
| 286 | + * FSGSBASE is enabled. |
---|
| 287 | + */ |
---|
| 288 | + |
---|
307 | 289 | switch (offset) { |
---|
308 | 290 | case offsetof(struct user_regs_struct,fs): |
---|
309 | 291 | task->thread.fsindex = value; |
---|
310 | | - if (task == current) |
---|
311 | | - loadsegment(fs, task->thread.fsindex); |
---|
312 | 292 | break; |
---|
313 | 293 | case offsetof(struct user_regs_struct,gs): |
---|
314 | 294 | task->thread.gsindex = value; |
---|
315 | | - if (task == current) |
---|
316 | | - load_gs_index(task->thread.gsindex); |
---|
317 | 295 | break; |
---|
318 | 296 | case offsetof(struct user_regs_struct,ds): |
---|
319 | 297 | task->thread.ds = value; |
---|
320 | | - if (task == current) |
---|
321 | | - loadsegment(ds, task->thread.ds); |
---|
322 | 298 | break; |
---|
323 | 299 | case offsetof(struct user_regs_struct,es): |
---|
324 | 300 | task->thread.es = value; |
---|
325 | | - if (task == current) |
---|
326 | | - loadsegment(es, task->thread.es); |
---|
327 | 301 | break; |
---|
328 | 302 | |
---|
329 | 303 | /* |
---|
.. | .. |
---|
342 | 316 | } |
---|
343 | 317 | |
---|
344 | 318 | return 0; |
---|
345 | | -} |
---|
346 | | - |
---|
347 | | -static unsigned long task_seg_base(struct task_struct *task, |
---|
348 | | - unsigned short selector) |
---|
349 | | -{ |
---|
350 | | - unsigned short idx = selector >> 3; |
---|
351 | | - unsigned long base; |
---|
352 | | - |
---|
353 | | - if (likely((selector & SEGMENT_TI_MASK) == 0)) { |
---|
354 | | - if (unlikely(idx >= GDT_ENTRIES)) |
---|
355 | | - return 0; |
---|
356 | | - |
---|
357 | | - /* |
---|
358 | | - * There are no user segments in the GDT with nonzero bases |
---|
359 | | - * other than the TLS segments. |
---|
360 | | - */ |
---|
361 | | - if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX) |
---|
362 | | - return 0; |
---|
363 | | - |
---|
364 | | - idx -= GDT_ENTRY_TLS_MIN; |
---|
365 | | - base = get_desc_base(&task->thread.tls_array[idx]); |
---|
366 | | - } else { |
---|
367 | | -#ifdef CONFIG_MODIFY_LDT_SYSCALL |
---|
368 | | - struct ldt_struct *ldt; |
---|
369 | | - |
---|
370 | | - /* |
---|
371 | | - * If performance here mattered, we could protect the LDT |
---|
372 | | - * with RCU. This is a slow path, though, so we can just |
---|
373 | | - * take the mutex. |
---|
374 | | - */ |
---|
375 | | - mutex_lock(&task->mm->context.lock); |
---|
376 | | - ldt = task->mm->context.ldt; |
---|
377 | | - if (unlikely(!ldt || idx >= ldt->nr_entries)) |
---|
378 | | - base = 0; |
---|
379 | | - else |
---|
380 | | - base = get_desc_base(ldt->entries + idx); |
---|
381 | | - mutex_unlock(&task->mm->context.lock); |
---|
382 | | -#else |
---|
383 | | - base = 0; |
---|
384 | | -#endif |
---|
385 | | - } |
---|
386 | | - |
---|
387 | | - return base; |
---|
388 | 319 | } |
---|
389 | 320 | |
---|
390 | 321 | #endif /* CONFIG_X86_32 */ |
---|
.. | .. |
---|
440 | 371 | case offsetof(struct user_regs_struct,fs_base): |
---|
441 | 372 | if (value >= TASK_SIZE_MAX) |
---|
442 | 373 | return -EIO; |
---|
443 | | - /* |
---|
444 | | - * When changing the segment base, use do_arch_prctl_64 |
---|
445 | | - * to set either thread.fs or thread.fsindex and the |
---|
446 | | - * corresponding GDT slot. |
---|
447 | | - */ |
---|
448 | | - if (child->thread.fsbase != value) |
---|
449 | | - return do_arch_prctl_64(child, ARCH_SET_FS, value); |
---|
| 374 | + x86_fsbase_write_task(child, value); |
---|
450 | 375 | return 0; |
---|
451 | 376 | case offsetof(struct user_regs_struct,gs_base): |
---|
452 | | - /* |
---|
453 | | - * Exactly the same here as the %fs handling above. |
---|
454 | | - */ |
---|
455 | 377 | if (value >= TASK_SIZE_MAX) |
---|
456 | 378 | return -EIO; |
---|
457 | | - if (child->thread.gsbase != value) |
---|
458 | | - return do_arch_prctl_64(child, ARCH_SET_GS, value); |
---|
| 379 | + x86_gsbase_write_task(child, value); |
---|
459 | 380 | return 0; |
---|
460 | 381 | #endif |
---|
461 | 382 | } |
---|
.. | .. |
---|
479 | 400 | return get_flags(task); |
---|
480 | 401 | |
---|
481 | 402 | #ifdef CONFIG_X86_64 |
---|
482 | | - case offsetof(struct user_regs_struct, fs_base): { |
---|
483 | | - if (task->thread.fsindex == 0) |
---|
484 | | - return task->thread.fsbase; |
---|
485 | | - else |
---|
486 | | - return task_seg_base(task, task->thread.fsindex); |
---|
487 | | - } |
---|
488 | | - case offsetof(struct user_regs_struct, gs_base): { |
---|
489 | | - if (task->thread.gsindex == 0) |
---|
490 | | - return task->thread.gsbase; |
---|
491 | | - else |
---|
492 | | - return task_seg_base(task, task->thread.gsindex); |
---|
493 | | - } |
---|
| 403 | + case offsetof(struct user_regs_struct, fs_base): |
---|
| 404 | + return x86_fsbase_read_task(task); |
---|
| 405 | + case offsetof(struct user_regs_struct, gs_base): |
---|
| 406 | + return x86_gsbase_read_task(task); |
---|
494 | 407 | #endif |
---|
495 | 408 | } |
---|
496 | 409 | |
---|
.. | .. |
---|
499 | 412 | |
---|
500 | 413 | static int genregs_get(struct task_struct *target, |
---|
501 | 414 | const struct user_regset *regset, |
---|
502 | | - unsigned int pos, unsigned int count, |
---|
503 | | - void *kbuf, void __user *ubuf) |
---|
| 415 | + struct membuf to) |
---|
504 | 416 | { |
---|
505 | | - if (kbuf) { |
---|
506 | | - unsigned long *k = kbuf; |
---|
507 | | - while (count >= sizeof(*k)) { |
---|
508 | | - *k++ = getreg(target, pos); |
---|
509 | | - count -= sizeof(*k); |
---|
510 | | - pos += sizeof(*k); |
---|
511 | | - } |
---|
512 | | - } else { |
---|
513 | | - unsigned long __user *u = ubuf; |
---|
514 | | - while (count >= sizeof(*u)) { |
---|
515 | | - if (__put_user(getreg(target, pos), u++)) |
---|
516 | | - return -EFAULT; |
---|
517 | | - count -= sizeof(*u); |
---|
518 | | - pos += sizeof(*u); |
---|
519 | | - } |
---|
520 | | - } |
---|
| 417 | + int reg; |
---|
521 | 418 | |
---|
| 419 | + for (reg = 0; to.left; reg++) |
---|
| 420 | + membuf_store(&to, getreg(target, reg * sizeof(unsigned long))); |
---|
522 | 421 | return 0; |
---|
523 | 422 | } |
---|
524 | 423 | |
---|
.. | .. |
---|
566 | 465 | break; |
---|
567 | 466 | } |
---|
568 | 467 | |
---|
569 | | - thread->debugreg6 |= (DR_TRAP0 << i); |
---|
| 468 | + thread->virtual_dr6 |= (DR_TRAP0 << i); |
---|
570 | 469 | } |
---|
571 | 470 | |
---|
572 | 471 | /* |
---|
.. | .. |
---|
702 | 601 | if (bp) |
---|
703 | 602 | val = bp->hw.info.address; |
---|
704 | 603 | } else if (n == 6) { |
---|
705 | | - val = thread->debugreg6; |
---|
| 604 | + val = thread->virtual_dr6 ^ DR6_RESERVED; /* Flip back to arch polarity */ |
---|
706 | 605 | } else if (n == 7) { |
---|
707 | 606 | val = thread->ptrace_dr7; |
---|
708 | 607 | } |
---|
.. | .. |
---|
758 | 657 | if (n < HBP_NUM) { |
---|
759 | 658 | rc = ptrace_set_breakpoint_addr(tsk, n, val); |
---|
760 | 659 | } else if (n == 6) { |
---|
761 | | - thread->debugreg6 = val; |
---|
| 660 | + thread->virtual_dr6 = val ^ DR6_RESERVED; /* Flip to positive polarity */ |
---|
762 | 661 | rc = 0; |
---|
763 | 662 | } else if (n == 7) { |
---|
764 | 663 | rc = ptrace_write_dr7(tsk, val); |
---|
.. | .. |
---|
775 | 674 | static int ioperm_active(struct task_struct *target, |
---|
776 | 675 | const struct user_regset *regset) |
---|
777 | 676 | { |
---|
778 | | - return target->thread.io_bitmap_max / regset->size; |
---|
| 677 | + struct io_bitmap *iobm = target->thread.io_bitmap; |
---|
| 678 | + |
---|
| 679 | + return iobm ? DIV_ROUND_UP(iobm->max, regset->size) : 0; |
---|
779 | 680 | } |
---|
780 | 681 | |
---|
781 | 682 | static int ioperm_get(struct task_struct *target, |
---|
782 | 683 | const struct user_regset *regset, |
---|
783 | | - unsigned int pos, unsigned int count, |
---|
784 | | - void *kbuf, void __user *ubuf) |
---|
| 684 | + struct membuf to) |
---|
785 | 685 | { |
---|
786 | | - if (!target->thread.io_bitmap_ptr) |
---|
| 686 | + struct io_bitmap *iobm = target->thread.io_bitmap; |
---|
| 687 | + |
---|
| 688 | + if (!iobm) |
---|
787 | 689 | return -ENXIO; |
---|
788 | 690 | |
---|
789 | | - return user_regset_copyout(&pos, &count, &kbuf, &ubuf, |
---|
790 | | - target->thread.io_bitmap_ptr, |
---|
791 | | - 0, IO_BITMAP_BYTES); |
---|
| 691 | + return membuf_write(&to, iobm->bitmap, IO_BITMAP_BYTES); |
---|
792 | 692 | } |
---|
793 | 693 | |
---|
794 | 694 | /* |
---|
.. | .. |
---|
799 | 699 | void ptrace_disable(struct task_struct *child) |
---|
800 | 700 | { |
---|
801 | 701 | user_disable_single_step(child); |
---|
802 | | -#ifdef TIF_SYSCALL_EMU |
---|
803 | | - clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); |
---|
804 | | -#endif |
---|
805 | 702 | } |
---|
806 | 703 | |
---|
807 | 704 | #if defined CONFIG_X86_32 || defined CONFIG_IA32_EMULATION |
---|
.. | .. |
---|
946 | 843 | static int putreg32(struct task_struct *child, unsigned regno, u32 value) |
---|
947 | 844 | { |
---|
948 | 845 | struct pt_regs *regs = task_pt_regs(child); |
---|
| 846 | + int ret; |
---|
949 | 847 | |
---|
950 | 848 | switch (regno) { |
---|
951 | 849 | |
---|
952 | 850 | SEG32(cs); |
---|
953 | 851 | SEG32(ds); |
---|
954 | 852 | SEG32(es); |
---|
955 | | - SEG32(fs); |
---|
956 | | - SEG32(gs); |
---|
| 853 | + |
---|
| 854 | + /* |
---|
| 855 | + * A 32-bit ptracer on a 64-bit kernel expects that writing |
---|
| 856 | + * FS or GS will also update the base. This is needed for |
---|
| 857 | + * operations like PTRACE_SETREGS to fully restore a saved |
---|
| 858 | + * CPU state. |
---|
| 859 | + */ |
---|
| 860 | + |
---|
| 861 | + case offsetof(struct user32, regs.fs): |
---|
| 862 | + ret = set_segment_reg(child, |
---|
| 863 | + offsetof(struct user_regs_struct, fs), |
---|
| 864 | + value); |
---|
| 865 | + if (ret == 0) |
---|
| 866 | + child->thread.fsbase = |
---|
| 867 | + x86_fsgsbase_read_task(child, value); |
---|
| 868 | + return ret; |
---|
| 869 | + |
---|
| 870 | + case offsetof(struct user32, regs.gs): |
---|
| 871 | + ret = set_segment_reg(child, |
---|
| 872 | + offsetof(struct user_regs_struct, gs), |
---|
| 873 | + value); |
---|
| 874 | + if (ret == 0) |
---|
| 875 | + child->thread.gsbase = |
---|
| 876 | + x86_fsgsbase_read_task(child, value); |
---|
| 877 | + return ret; |
---|
| 878 | + |
---|
957 | 879 | SEG32(ss); |
---|
958 | 880 | |
---|
959 | 881 | R32(ebx, bx); |
---|
.. | .. |
---|
1069 | 991 | |
---|
1070 | 992 | static int genregs32_get(struct task_struct *target, |
---|
1071 | 993 | const struct user_regset *regset, |
---|
1072 | | - unsigned int pos, unsigned int count, |
---|
1073 | | - void *kbuf, void __user *ubuf) |
---|
| 994 | + struct membuf to) |
---|
1074 | 995 | { |
---|
1075 | | - if (kbuf) { |
---|
1076 | | - compat_ulong_t *k = kbuf; |
---|
1077 | | - while (count >= sizeof(*k)) { |
---|
1078 | | - getreg32(target, pos, k++); |
---|
1079 | | - count -= sizeof(*k); |
---|
1080 | | - pos += sizeof(*k); |
---|
1081 | | - } |
---|
1082 | | - } else { |
---|
1083 | | - compat_ulong_t __user *u = ubuf; |
---|
1084 | | - while (count >= sizeof(*u)) { |
---|
1085 | | - compat_ulong_t word; |
---|
1086 | | - getreg32(target, pos, &word); |
---|
1087 | | - if (__put_user(word, u++)) |
---|
1088 | | - return -EFAULT; |
---|
1089 | | - count -= sizeof(*u); |
---|
1090 | | - pos += sizeof(*u); |
---|
1091 | | - } |
---|
1092 | | - } |
---|
| 996 | + int reg; |
---|
1093 | 997 | |
---|
| 998 | + for (reg = 0; to.left; reg++) { |
---|
| 999 | + u32 val; |
---|
| 1000 | + getreg32(target, reg * 4, &val); |
---|
| 1001 | + membuf_store(&to, val); |
---|
| 1002 | + } |
---|
1094 | 1003 | return 0; |
---|
1095 | 1004 | } |
---|
1096 | 1005 | |
---|
.. | .. |
---|
1300 | 1209 | .core_note_type = NT_PRSTATUS, |
---|
1301 | 1210 | .n = sizeof(struct user_regs_struct) / sizeof(long), |
---|
1302 | 1211 | .size = sizeof(long), .align = sizeof(long), |
---|
1303 | | - .get = genregs_get, .set = genregs_set |
---|
| 1212 | + .regset_get = genregs_get, .set = genregs_set |
---|
1304 | 1213 | }, |
---|
1305 | 1214 | [REGSET_FP] = { |
---|
1306 | 1215 | .core_note_type = NT_PRFPREG, |
---|
1307 | 1216 | .n = sizeof(struct user_i387_struct) / sizeof(long), |
---|
1308 | 1217 | .size = sizeof(long), .align = sizeof(long), |
---|
1309 | | - .active = regset_xregset_fpregs_active, .get = xfpregs_get, .set = xfpregs_set |
---|
| 1218 | + .active = regset_xregset_fpregs_active, .regset_get = xfpregs_get, .set = xfpregs_set |
---|
1310 | 1219 | }, |
---|
1311 | 1220 | [REGSET_XSTATE] = { |
---|
1312 | 1221 | .core_note_type = NT_X86_XSTATE, |
---|
1313 | 1222 | .size = sizeof(u64), .align = sizeof(u64), |
---|
1314 | | - .active = xstateregs_active, .get = xstateregs_get, |
---|
| 1223 | + .active = xstateregs_active, .regset_get = xstateregs_get, |
---|
1315 | 1224 | .set = xstateregs_set |
---|
1316 | 1225 | }, |
---|
1317 | 1226 | [REGSET_IOPERM64] = { |
---|
1318 | 1227 | .core_note_type = NT_386_IOPERM, |
---|
1319 | 1228 | .n = IO_BITMAP_LONGS, |
---|
1320 | 1229 | .size = sizeof(long), .align = sizeof(long), |
---|
1321 | | - .active = ioperm_active, .get = ioperm_get |
---|
| 1230 | + .active = ioperm_active, .regset_get = ioperm_get |
---|
1322 | 1231 | }, |
---|
1323 | 1232 | }; |
---|
1324 | 1233 | |
---|
.. | .. |
---|
1341 | 1250 | .core_note_type = NT_PRSTATUS, |
---|
1342 | 1251 | .n = sizeof(struct user_regs_struct32) / sizeof(u32), |
---|
1343 | 1252 | .size = sizeof(u32), .align = sizeof(u32), |
---|
1344 | | - .get = genregs32_get, .set = genregs32_set |
---|
| 1253 | + .regset_get = genregs32_get, .set = genregs32_set |
---|
1345 | 1254 | }, |
---|
1346 | 1255 | [REGSET_FP] = { |
---|
1347 | 1256 | .core_note_type = NT_PRFPREG, |
---|
1348 | 1257 | .n = sizeof(struct user_i387_ia32_struct) / sizeof(u32), |
---|
1349 | 1258 | .size = sizeof(u32), .align = sizeof(u32), |
---|
1350 | | - .active = regset_fpregs_active, .get = fpregs_get, .set = fpregs_set |
---|
| 1259 | + .active = regset_fpregs_active, .regset_get = fpregs_get, .set = fpregs_set |
---|
1351 | 1260 | }, |
---|
1352 | 1261 | [REGSET_XFP] = { |
---|
1353 | 1262 | .core_note_type = NT_PRXFPREG, |
---|
1354 | 1263 | .n = sizeof(struct user32_fxsr_struct) / sizeof(u32), |
---|
1355 | 1264 | .size = sizeof(u32), .align = sizeof(u32), |
---|
1356 | | - .active = regset_xregset_fpregs_active, .get = xfpregs_get, .set = xfpregs_set |
---|
| 1265 | + .active = regset_xregset_fpregs_active, .regset_get = xfpregs_get, .set = xfpregs_set |
---|
1357 | 1266 | }, |
---|
1358 | 1267 | [REGSET_XSTATE] = { |
---|
1359 | 1268 | .core_note_type = NT_X86_XSTATE, |
---|
1360 | 1269 | .size = sizeof(u64), .align = sizeof(u64), |
---|
1361 | | - .active = xstateregs_active, .get = xstateregs_get, |
---|
| 1270 | + .active = xstateregs_active, .regset_get = xstateregs_get, |
---|
1362 | 1271 | .set = xstateregs_set |
---|
1363 | 1272 | }, |
---|
1364 | 1273 | [REGSET_TLS] = { |
---|
.. | .. |
---|
1367 | 1276 | .size = sizeof(struct user_desc), |
---|
1368 | 1277 | .align = sizeof(struct user_desc), |
---|
1369 | 1278 | .active = regset_tls_active, |
---|
1370 | | - .get = regset_tls_get, .set = regset_tls_set |
---|
| 1279 | + .regset_get = regset_tls_get, .set = regset_tls_set |
---|
1371 | 1280 | }, |
---|
1372 | 1281 | [REGSET_IOPERM32] = { |
---|
1373 | 1282 | .core_note_type = NT_386_IOPERM, |
---|
1374 | 1283 | .n = IO_BITMAP_BYTES / sizeof(u32), |
---|
1375 | 1284 | .size = sizeof(u32), .align = sizeof(u32), |
---|
1376 | | - .active = ioperm_active, .get = ioperm_get |
---|
| 1285 | + .active = ioperm_active, .regset_get = ioperm_get |
---|
1377 | 1286 | }, |
---|
1378 | 1287 | }; |
---|
1379 | 1288 | |
---|
.. | .. |
---|
1413 | 1322 | #endif |
---|
1414 | 1323 | } |
---|
1415 | 1324 | |
---|
1416 | | -static void fill_sigtrap_info(struct task_struct *tsk, |
---|
1417 | | - struct pt_regs *regs, |
---|
1418 | | - int error_code, int si_code, |
---|
1419 | | - struct siginfo *info) |
---|
| 1325 | +void send_sigtrap(struct pt_regs *regs, int error_code, int si_code) |
---|
1420 | 1326 | { |
---|
| 1327 | + struct task_struct *tsk = current; |
---|
| 1328 | + |
---|
1421 | 1329 | tsk->thread.trap_nr = X86_TRAP_DB; |
---|
1422 | 1330 | tsk->thread.error_code = error_code; |
---|
1423 | 1331 | |
---|
1424 | | - info->si_signo = SIGTRAP; |
---|
1425 | | - info->si_code = si_code; |
---|
1426 | | - info->si_addr = user_mode(regs) ? (void __user *)regs->ip : NULL; |
---|
1427 | | -} |
---|
1428 | | - |
---|
1429 | | -void user_single_step_siginfo(struct task_struct *tsk, |
---|
1430 | | - struct pt_regs *regs, |
---|
1431 | | - struct siginfo *info) |
---|
1432 | | -{ |
---|
1433 | | - fill_sigtrap_info(tsk, regs, 0, TRAP_BRKPT, info); |
---|
1434 | | -} |
---|
1435 | | - |
---|
1436 | | -void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, |
---|
1437 | | - int error_code, int si_code) |
---|
1438 | | -{ |
---|
1439 | | - struct siginfo info; |
---|
1440 | | - |
---|
1441 | | - clear_siginfo(&info); |
---|
1442 | | - fill_sigtrap_info(tsk, regs, error_code, si_code, &info); |
---|
1443 | 1332 | /* Send us the fake SIGTRAP */ |
---|
1444 | | - force_sig_info(SIGTRAP, &info, tsk); |
---|
| 1333 | + force_sig_fault(SIGTRAP, si_code, |
---|
| 1334 | + user_mode(regs) ? (void __user *)regs->ip : NULL); |
---|
| 1335 | +} |
---|
| 1336 | + |
---|
| 1337 | +void user_single_step_report(struct pt_regs *regs) |
---|
| 1338 | +{ |
---|
| 1339 | + send_sigtrap(regs, 0, TRAP_BRKPT); |
---|
1445 | 1340 | } |
---|