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