linux/arch/sparc/kernel/ptrace_64.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/* ptrace.c: Sparc process tracing support.
   3 *
   4 * Copyright (C) 1996, 2008 David S. Miller (davem@davemloft.net)
   5 * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
   6 *
   7 * Based upon code written by Ross Biro, Linus Torvalds, Bob Manson,
   8 * and David Mosberger.
   9 *
  10 * Added Linux support -miguel (weird, eh?, the original code was meant
  11 * to emulate SunOS).
  12 */
  13
  14#include <linux/kernel.h>
  15#include <linux/sched.h>
  16#include <linux/sched/task_stack.h>
  17#include <linux/mm.h>
  18#include <linux/errno.h>
  19#include <linux/export.h>
  20#include <linux/ptrace.h>
  21#include <linux/user.h>
  22#include <linux/smp.h>
  23#include <linux/security.h>
  24#include <linux/seccomp.h>
  25#include <linux/audit.h>
  26#include <linux/signal.h>
  27#include <linux/regset.h>
  28#include <trace/syscall.h>
  29#include <linux/compat.h>
  30#include <linux/elf.h>
  31#include <linux/context_tracking.h>
  32
  33#include <asm/asi.h>
  34#include <linux/uaccess.h>
  35#include <asm/psrcompat.h>
  36#include <asm/visasm.h>
  37#include <asm/spitfire.h>
  38#include <asm/page.h>
  39#include <asm/cpudata.h>
  40#include <asm/cacheflush.h>
  41
  42#define CREATE_TRACE_POINTS
  43#include <trace/events/syscalls.h>
  44
  45#include "entry.h"
  46
  47/* #define ALLOW_INIT_TRACING */
  48
  49struct pt_regs_offset {
  50        const char *name;
  51        int offset;
  52};
  53
  54#define REG_OFFSET_NAME(n, r) \
  55        {.name = n, .offset = (PT_V9_##r)}
  56#define REG_OFFSET_END {.name = NULL, .offset = 0}
  57
  58static const struct pt_regs_offset regoffset_table[] = {
  59        REG_OFFSET_NAME("g0", G0),
  60        REG_OFFSET_NAME("g1", G1),
  61        REG_OFFSET_NAME("g2", G2),
  62        REG_OFFSET_NAME("g3", G3),
  63        REG_OFFSET_NAME("g4", G4),
  64        REG_OFFSET_NAME("g5", G5),
  65        REG_OFFSET_NAME("g6", G6),
  66        REG_OFFSET_NAME("g7", G7),
  67
  68        REG_OFFSET_NAME("i0", I0),
  69        REG_OFFSET_NAME("i1", I1),
  70        REG_OFFSET_NAME("i2", I2),
  71        REG_OFFSET_NAME("i3", I3),
  72        REG_OFFSET_NAME("i4", I4),
  73        REG_OFFSET_NAME("i5", I5),
  74        REG_OFFSET_NAME("i6", I6),
  75        REG_OFFSET_NAME("i7", I7),
  76
  77        REG_OFFSET_NAME("tstate", TSTATE),
  78        REG_OFFSET_NAME("pc", TPC),
  79        REG_OFFSET_NAME("npc", TNPC),
  80        REG_OFFSET_NAME("y", Y),
  81        REG_OFFSET_NAME("lr", I7),
  82
  83        REG_OFFSET_END,
  84};
  85
  86/*
  87 * Called by kernel/ptrace.c when detaching..
  88 *
  89 * Make sure single step bits etc are not set.
  90 */
  91void ptrace_disable(struct task_struct *child)
  92{
  93        /* nothing to do */
  94}
  95
  96/* To get the necessary page struct, access_process_vm() first calls
  97 * get_user_pages().  This has done a flush_dcache_page() on the
  98 * accessed page.  Then our caller (copy_{to,from}_user_page()) did
  99 * to memcpy to read/write the data from that page.
 100 *
 101 * Now, the only thing we have to do is:
 102 * 1) flush the D-cache if it's possible than an illegal alias
 103 *    has been created
 104 * 2) flush the I-cache if this is pre-cheetah and we did a write
 105 */
 106void flush_ptrace_access(struct vm_area_struct *vma, struct page *page,
 107                         unsigned long uaddr, void *kaddr,
 108                         unsigned long len, int write)
 109{
 110        BUG_ON(len > PAGE_SIZE);
 111
 112        if (tlb_type == hypervisor)
 113                return;
 114
 115        preempt_disable();
 116
 117#ifdef DCACHE_ALIASING_POSSIBLE
 118        /* If bit 13 of the kernel address we used to access the
 119         * user page is the same as the virtual address that page
 120         * is mapped to in the user's address space, we can skip the
 121         * D-cache flush.
 122         */
 123        if ((uaddr ^ (unsigned long) kaddr) & (1UL << 13)) {
 124                unsigned long start = __pa(kaddr);
 125                unsigned long end = start + len;
 126                unsigned long dcache_line_size;
 127
 128                dcache_line_size = local_cpu_data().dcache_line_size;
 129
 130                if (tlb_type == spitfire) {
 131                        for (; start < end; start += dcache_line_size)
 132                                spitfire_put_dcache_tag(start & 0x3fe0, 0x0);
 133                } else {
 134                        start &= ~(dcache_line_size - 1);
 135                        for (; start < end; start += dcache_line_size)
 136                                __asm__ __volatile__(
 137                                        "stxa %%g0, [%0] %1\n\t"
 138                                        "membar #Sync"
 139                                        : /* no outputs */
 140                                        : "r" (start),
 141                                        "i" (ASI_DCACHE_INVALIDATE));
 142                }
 143        }
 144#endif
 145        if (write && tlb_type == spitfire) {
 146                unsigned long start = (unsigned long) kaddr;
 147                unsigned long end = start + len;
 148                unsigned long icache_line_size;
 149
 150                icache_line_size = local_cpu_data().icache_line_size;
 151
 152                for (; start < end; start += icache_line_size)
 153                        flushi(start);
 154        }
 155
 156        preempt_enable();
 157}
 158EXPORT_SYMBOL_GPL(flush_ptrace_access);
 159
 160static int get_from_target(struct task_struct *target, unsigned long uaddr,
 161                           void *kbuf, int len)
 162{
 163        if (target == current) {
 164                if (copy_from_user(kbuf, (void __user *) uaddr, len))
 165                        return -EFAULT;
 166        } else {
 167                int len2 = access_process_vm(target, uaddr, kbuf, len,
 168                                FOLL_FORCE);
 169                if (len2 != len)
 170                        return -EFAULT;
 171        }
 172        return 0;
 173}
 174
 175static int set_to_target(struct task_struct *target, unsigned long uaddr,
 176                         void *kbuf, int len)
 177{
 178        if (target == current) {
 179                if (copy_to_user((void __user *) uaddr, kbuf, len))
 180                        return -EFAULT;
 181        } else {
 182                int len2 = access_process_vm(target, uaddr, kbuf, len,
 183                                FOLL_FORCE | FOLL_WRITE);
 184                if (len2 != len)
 185                        return -EFAULT;
 186        }
 187        return 0;
 188}
 189
 190static int regwindow64_get(struct task_struct *target,
 191                           const struct pt_regs *regs,
 192                           struct reg_window *wbuf)
 193{
 194        unsigned long rw_addr = regs->u_regs[UREG_I6];
 195
 196        if (!test_thread_64bit_stack(rw_addr)) {
 197                struct reg_window32 win32;
 198                int i;
 199
 200                if (get_from_target(target, rw_addr, &win32, sizeof(win32)))
 201                        return -EFAULT;
 202                for (i = 0; i < 8; i++)
 203                        wbuf->locals[i] = win32.locals[i];
 204                for (i = 0; i < 8; i++)
 205                        wbuf->ins[i] = win32.ins[i];
 206        } else {
 207                rw_addr += STACK_BIAS;
 208                if (get_from_target(target, rw_addr, wbuf, sizeof(*wbuf)))
 209                        return -EFAULT;
 210        }
 211
 212        return 0;
 213}
 214
 215static int regwindow64_set(struct task_struct *target,
 216                           const struct pt_regs *regs,
 217                           struct reg_window *wbuf)
 218{
 219        unsigned long rw_addr = regs->u_regs[UREG_I6];
 220
 221        if (!test_thread_64bit_stack(rw_addr)) {
 222                struct reg_window32 win32;
 223                int i;
 224
 225                for (i = 0; i < 8; i++)
 226                        win32.locals[i] = wbuf->locals[i];
 227                for (i = 0; i < 8; i++)
 228                        win32.ins[i] = wbuf->ins[i];
 229
 230                if (set_to_target(target, rw_addr, &win32, sizeof(win32)))
 231                        return -EFAULT;
 232        } else {
 233                rw_addr += STACK_BIAS;
 234                if (set_to_target(target, rw_addr, wbuf, sizeof(*wbuf)))
 235                        return -EFAULT;
 236        }
 237
 238        return 0;
 239}
 240
 241enum sparc_regset {
 242        REGSET_GENERAL,
 243        REGSET_FP,
 244};
 245
 246static int genregs64_get(struct task_struct *target,
 247                         const struct user_regset *regset,
 248                         struct membuf to)
 249{
 250        const struct pt_regs *regs = task_pt_regs(target);
 251        struct reg_window window;
 252
 253        if (target == current)
 254                flushw_user();
 255
 256        membuf_write(&to, regs->u_regs, 16 * sizeof(u64));
 257        if (!to.left)
 258                return 0;
 259        if (regwindow64_get(target, regs, &window))
 260                return -EFAULT;
 261        membuf_write(&to, &window, 16 * sizeof(u64));
 262        /* TSTATE, TPC, TNPC */
 263        membuf_write(&to, &regs->tstate, 3 * sizeof(u64));
 264        return membuf_store(&to, (u64)regs->y);
 265}
 266
 267static int genregs64_set(struct task_struct *target,
 268                         const struct user_regset *regset,
 269                         unsigned int pos, unsigned int count,
 270                         const void *kbuf, const void __user *ubuf)
 271{
 272        struct pt_regs *regs = task_pt_regs(target);
 273        int ret;
 274
 275        if (target == current)
 276                flushw_user();
 277
 278        ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
 279                                 regs->u_regs,
 280                                 0, 16 * sizeof(u64));
 281        if (!ret && count && pos < (32 * sizeof(u64))) {
 282                struct reg_window window;
 283
 284                if (regwindow64_get(target, regs, &window))
 285                        return -EFAULT;
 286
 287                ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
 288                                         &window,
 289                                         16 * sizeof(u64),
 290                                         32 * sizeof(u64));
 291
 292                if (!ret &&
 293                    regwindow64_set(target, regs, &window))
 294                        return -EFAULT;
 295        }
 296
 297        if (!ret && count > 0) {
 298                unsigned long tstate;
 299
 300                /* TSTATE */
 301                ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
 302                                         &tstate,
 303                                         32 * sizeof(u64),
 304                                         33 * sizeof(u64));
 305                if (!ret) {
 306                        /* Only the condition codes and the "in syscall"
 307                         * state can be modified in the %tstate register.
 308                         */
 309                        tstate &= (TSTATE_ICC | TSTATE_XCC | TSTATE_SYSCALL);
 310                        regs->tstate &= ~(TSTATE_ICC | TSTATE_XCC | TSTATE_SYSCALL);
 311                        regs->tstate |= tstate;
 312                }
 313        }
 314
 315        if (!ret) {
 316                /* TPC, TNPC */
 317                ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
 318                                         &regs->tpc,
 319                                         33 * sizeof(u64),
 320                                         35 * sizeof(u64));
 321        }
 322
 323        if (!ret) {
 324                unsigned long y = regs->y;
 325
 326                ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
 327                                         &y,
 328                                         35 * sizeof(u64),
 329                                         36 * sizeof(u64));
 330                if (!ret)
 331                        regs->y = y;
 332        }
 333
 334        if (!ret)
 335                ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
 336                                                36 * sizeof(u64), -1);
 337
 338        return ret;
 339}
 340
 341static int fpregs64_get(struct task_struct *target,
 342                        const struct user_regset *regset,
 343                        struct membuf to)
 344{
 345        struct thread_info *t = task_thread_info(target);
 346        unsigned long fprs;
 347
 348        if (target == current)
 349                save_and_clear_fpu();
 350
 351        fprs = t->fpsaved[0];
 352
 353        if (fprs & FPRS_DL)
 354                membuf_write(&to, t->fpregs, 16 * sizeof(u64));
 355        else
 356                membuf_zero(&to, 16 * sizeof(u64));
 357
 358        if (fprs & FPRS_DU)
 359                membuf_write(&to, t->fpregs + 16, 16 * sizeof(u64));
 360        else
 361                membuf_zero(&to, 16 * sizeof(u64));
 362        if (fprs & FPRS_FEF) {
 363                membuf_store(&to, t->xfsr[0]);
 364                membuf_store(&to, t->gsr[0]);
 365        } else {
 366                membuf_zero(&to, 2 * sizeof(u64));
 367        }
 368        return membuf_store(&to, fprs);
 369}
 370
 371static int fpregs64_set(struct task_struct *target,
 372                        const struct user_regset *regset,
 373                        unsigned int pos, unsigned int count,
 374                        const void *kbuf, const void __user *ubuf)
 375{
 376        unsigned long *fpregs = task_thread_info(target)->fpregs;
 377        unsigned long fprs;
 378        int ret;
 379
 380        if (target == current)
 381                save_and_clear_fpu();
 382
 383        ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
 384                                 fpregs,
 385                                 0, 32 * sizeof(u64));
 386        if (!ret)
 387                ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
 388                                         task_thread_info(target)->xfsr,
 389                                         32 * sizeof(u64),
 390                                         33 * sizeof(u64));
 391        if (!ret)
 392                ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
 393                                         task_thread_info(target)->gsr,
 394                                         33 * sizeof(u64),
 395                                         34 * sizeof(u64));
 396
 397        fprs = task_thread_info(target)->fpsaved[0];
 398        if (!ret && count > 0) {
 399                ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
 400                                         &fprs,
 401                                         34 * sizeof(u64),
 402                                         35 * sizeof(u64));
 403        }
 404
 405        fprs |= (FPRS_FEF | FPRS_DL | FPRS_DU);
 406        task_thread_info(target)->fpsaved[0] = fprs;
 407
 408        if (!ret)
 409                ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
 410                                                35 * sizeof(u64), -1);
 411        return ret;
 412}
 413
 414static const struct user_regset sparc64_regsets[] = {
 415        /* Format is:
 416         *      G0 --> G7
 417         *      O0 --> O7
 418         *      L0 --> L7
 419         *      I0 --> I7
 420         *      TSTATE, TPC, TNPC, Y
 421         */
 422        [REGSET_GENERAL] = {
 423                .core_note_type = NT_PRSTATUS,
 424                .n = 36,
 425                .size = sizeof(u64), .align = sizeof(u64),
 426                .regset_get = genregs64_get, .set = genregs64_set
 427        },
 428        /* Format is:
 429         *      F0 --> F63
 430         *      FSR
 431         *      GSR
 432         *      FPRS
 433         */
 434        [REGSET_FP] = {
 435                .core_note_type = NT_PRFPREG,
 436                .n = 35,
 437                .size = sizeof(u64), .align = sizeof(u64),
 438                .regset_get = fpregs64_get, .set = fpregs64_set
 439        },
 440};
 441
 442static int getregs64_get(struct task_struct *target,
 443                         const struct user_regset *regset,
 444                         struct membuf to)
 445{
 446        const struct pt_regs *regs = task_pt_regs(target);
 447
 448        if (target == current)
 449                flushw_user();
 450
 451        membuf_write(&to, regs->u_regs + 1, 15 * sizeof(u64));
 452        membuf_store(&to, (u64)0);
 453        membuf_write(&to, &regs->tstate, 3 * sizeof(u64));
 454        return membuf_store(&to, (u64)regs->y);
 455}
 456
 457static int setregs64_set(struct task_struct *target,
 458                         const struct user_regset *regset,
 459                         unsigned int pos, unsigned int count,
 460                         const void *kbuf, const void __user *ubuf)
 461{
 462        struct pt_regs *regs = task_pt_regs(target);
 463        unsigned long y = regs->y;
 464        unsigned long tstate;
 465        int ret;
 466
 467        if (target == current)
 468                flushw_user();
 469
 470        ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
 471                                 regs->u_regs + 1,
 472                                 0 * sizeof(u64),
 473                                 15 * sizeof(u64));
 474        if (ret)
 475                return ret;
 476        ret =user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
 477                                 15 * sizeof(u64), 16 * sizeof(u64));
 478        if (ret)
 479                return ret;
 480        /* TSTATE */
 481        ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
 482                                 &tstate,
 483                                 16 * sizeof(u64),
 484                                 17 * sizeof(u64));
 485        if (ret)
 486                return ret;
 487        /* Only the condition codes and the "in syscall"
 488         * state can be modified in the %tstate register.
 489         */
 490        tstate &= (TSTATE_ICC | TSTATE_XCC | TSTATE_SYSCALL);
 491        regs->tstate &= ~(TSTATE_ICC | TSTATE_XCC | TSTATE_SYSCALL);
 492        regs->tstate |= tstate;
 493
 494        /* TPC, TNPC */
 495        ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
 496                                 &regs->tpc,
 497                                 17 * sizeof(u64),
 498                                 19 * sizeof(u64));
 499        if (ret)
 500                return ret;
 501        /* Y */
 502        ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
 503                                 &y,
 504                                 19 * sizeof(u64),
 505                                 20 * sizeof(u64));
 506        if (!ret)
 507                regs->y = y;
 508        return ret;
 509}
 510
 511static const struct user_regset ptrace64_regsets[] = {
 512        /* Format is:
 513         *      G1 --> G7
 514         *      O0 --> O7
 515         *      0
 516         *      TSTATE, TPC, TNPC, Y
 517         */
 518        [REGSET_GENERAL] = {
 519                .n = 20, .size = sizeof(u64),
 520                .regset_get = getregs64_get, .set = setregs64_set,
 521        },
 522};
 523
 524static const struct user_regset_view ptrace64_view = {
 525        .regsets = ptrace64_regsets, .n = ARRAY_SIZE(ptrace64_regsets)
 526};
 527
 528static const struct user_regset_view user_sparc64_view = {
 529        .name = "sparc64", .e_machine = EM_SPARCV9,
 530        .regsets = sparc64_regsets, .n = ARRAY_SIZE(sparc64_regsets)
 531};
 532
 533#ifdef CONFIG_COMPAT
 534static int genregs32_get(struct task_struct *target,
 535                         const struct user_regset *regset,
 536                         struct membuf to)
 537{
 538        const struct pt_regs *regs = task_pt_regs(target);
 539        u32 uregs[16];
 540        int i;
 541
 542        if (target == current)
 543                flushw_user();
 544
 545        for (i = 0; i < 16; i++)
 546                membuf_store(&to, (u32)regs->u_regs[i]);
 547        if (!to.left)
 548                return 0;
 549        if (get_from_target(target, regs->u_regs[UREG_I6],
 550                            uregs, sizeof(uregs)))
 551                return -EFAULT;
 552        membuf_write(&to, uregs, 16 * sizeof(u32));
 553        membuf_store(&to, (u32)tstate_to_psr(regs->tstate));
 554        membuf_store(&to, (u32)(regs->tpc));
 555        membuf_store(&to, (u32)(regs->tnpc));
 556        membuf_store(&to, (u32)(regs->y));
 557        return membuf_zero(&to, 2 * sizeof(u32));
 558}
 559
 560static int genregs32_set(struct task_struct *target,
 561                         const struct user_regset *regset,
 562                         unsigned int pos, unsigned int count,
 563                         const void *kbuf, const void __user *ubuf)
 564{
 565        struct pt_regs *regs = task_pt_regs(target);
 566        compat_ulong_t __user *reg_window;
 567        const compat_ulong_t *k = kbuf;
 568        const compat_ulong_t __user *u = ubuf;
 569        compat_ulong_t reg;
 570
 571        if (target == current)
 572                flushw_user();
 573
 574        pos /= sizeof(reg);
 575        count /= sizeof(reg);
 576
 577        if (kbuf) {
 578                for (; count > 0 && pos < 16; count--)
 579                        regs->u_regs[pos++] = *k++;
 580
 581                reg_window = (compat_ulong_t __user *) regs->u_regs[UREG_I6];
 582                reg_window -= 16;
 583                if (target == current) {
 584                        for (; count > 0 && pos < 32; count--) {
 585                                if (put_user(*k++, &reg_window[pos++]))
 586                                        return -EFAULT;
 587                        }
 588                } else {
 589                        for (; count > 0 && pos < 32; count--) {
 590                                if (access_process_vm(target,
 591                                                      (unsigned long)
 592                                                      &reg_window[pos],
 593                                                      (void *) k,
 594                                                      sizeof(*k),
 595                                                      FOLL_FORCE | FOLL_WRITE)
 596                                    != sizeof(*k))
 597                                        return -EFAULT;
 598                                k++;
 599                                pos++;
 600                        }
 601                }
 602        } else {
 603                for (; count > 0 && pos < 16; count--) {
 604                        if (get_user(reg, u++))
 605                                return -EFAULT;
 606                        regs->u_regs[pos++] = reg;
 607                }
 608
 609                reg_window = (compat_ulong_t __user *) regs->u_regs[UREG_I6];
 610                reg_window -= 16;
 611                if (target == current) {
 612                        for (; count > 0 && pos < 32; count--) {
 613                                if (get_user(reg, u++) ||
 614                                    put_user(reg, &reg_window[pos++]))
 615                                        return -EFAULT;
 616                        }
 617                } else {
 618                        for (; count > 0 && pos < 32; count--) {
 619                                if (get_user(reg, u++))
 620                                        return -EFAULT;
 621                                if (access_process_vm(target,
 622                                                      (unsigned long)
 623                                                      &reg_window[pos],
 624                                                      &reg, sizeof(reg),
 625                                                      FOLL_FORCE | FOLL_WRITE)
 626                                    != sizeof(reg))
 627                                        return -EFAULT;
 628                                pos++;
 629                                u++;
 630                        }
 631                }
 632        }
 633        while (count > 0) {
 634                unsigned long tstate;
 635
 636                if (kbuf)
 637                        reg = *k++;
 638                else if (get_user(reg, u++))
 639                        return -EFAULT;
 640
 641                switch (pos) {
 642                case 32: /* PSR */
 643                        tstate = regs->tstate;
 644                        tstate &= ~(TSTATE_ICC | TSTATE_XCC | TSTATE_SYSCALL);
 645                        tstate |= psr_to_tstate_icc(reg);
 646                        if (reg & PSR_SYSCALL)
 647                                tstate |= TSTATE_SYSCALL;
 648                        regs->tstate = tstate;
 649                        break;
 650                case 33: /* PC */
 651                        regs->tpc = reg;
 652                        break;
 653                case 34: /* NPC */
 654                        regs->tnpc = reg;
 655                        break;
 656                case 35: /* Y */
 657                        regs->y = reg;
 658                        break;
 659                case 36: /* WIM */
 660                case 37: /* TBR */
 661                        break;
 662                default:
 663                        goto finish;
 664                }
 665
 666                pos++;
 667                count--;
 668        }
 669finish:
 670        pos *= sizeof(reg);
 671        count *= sizeof(reg);
 672
 673        return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
 674                                         38 * sizeof(reg), -1);
 675}
 676
 677static int fpregs32_get(struct task_struct *target,
 678                        const struct user_regset *regset,
 679                        struct membuf to)
 680{
 681        struct thread_info *t = task_thread_info(target);
 682        bool enabled;
 683
 684        if (target == current)
 685                save_and_clear_fpu();
 686
 687        enabled = t->fpsaved[0] & FPRS_FEF;
 688
 689        membuf_write(&to, t->fpregs, 32 * sizeof(u32));
 690        membuf_zero(&to, sizeof(u32));
 691        if (enabled)
 692                membuf_store(&to, (u32)t->xfsr[0]);
 693        else
 694                membuf_zero(&to, sizeof(u32));
 695        membuf_store(&to, (u32)((enabled << 8) | (8 << 16)));
 696        return membuf_zero(&to, 64 * sizeof(u32));
 697}
 698
 699static int fpregs32_set(struct task_struct *target,
 700                        const struct user_regset *regset,
 701                        unsigned int pos, unsigned int count,
 702                        const void *kbuf, const void __user *ubuf)
 703{
 704        unsigned long *fpregs = task_thread_info(target)->fpregs;
 705        unsigned long fprs;
 706        int ret;
 707
 708        if (target == current)
 709                save_and_clear_fpu();
 710
 711        fprs = task_thread_info(target)->fpsaved[0];
 712
 713        ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
 714                                 fpregs,
 715                                 0, 32 * sizeof(u32));
 716        if (!ret)
 717                user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
 718                                          32 * sizeof(u32),
 719                                          33 * sizeof(u32));
 720        if (!ret && count > 0) {
 721                compat_ulong_t fsr;
 722                unsigned long val;
 723
 724                ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
 725                                         &fsr,
 726                                         33 * sizeof(u32),
 727                                         34 * sizeof(u32));
 728                if (!ret) {
 729                        val = task_thread_info(target)->xfsr[0];
 730                        val &= 0xffffffff00000000UL;
 731                        val |= fsr;
 732                        task_thread_info(target)->xfsr[0] = val;
 733                }
 734        }
 735
 736        fprs |= (FPRS_FEF | FPRS_DL);
 737        task_thread_info(target)->fpsaved[0] = fprs;
 738
 739        if (!ret)
 740                ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
 741                                                34 * sizeof(u32), -1);
 742        return ret;
 743}
 744
 745static const struct user_regset sparc32_regsets[] = {
 746        /* Format is:
 747         *      G0 --> G7
 748         *      O0 --> O7
 749         *      L0 --> L7
 750         *      I0 --> I7
 751         *      PSR, PC, nPC, Y, WIM, TBR
 752         */
 753        [REGSET_GENERAL] = {
 754                .core_note_type = NT_PRSTATUS,
 755                .n = 38,
 756                .size = sizeof(u32), .align = sizeof(u32),
 757                .regset_get = genregs32_get, .set = genregs32_set
 758        },
 759        /* Format is:
 760         *      F0 --> F31
 761         *      empty 32-bit word
 762         *      FSR (32--bit word)
 763         *      FPU QUEUE COUNT (8-bit char)
 764         *      FPU QUEUE ENTRYSIZE (8-bit char)
 765         *      FPU ENABLED (8-bit char)
 766         *      empty 8-bit char
 767         *      FPU QUEUE (64 32-bit ints)
 768         */
 769        [REGSET_FP] = {
 770                .core_note_type = NT_PRFPREG,
 771                .n = 99,
 772                .size = sizeof(u32), .align = sizeof(u32),
 773                .regset_get = fpregs32_get, .set = fpregs32_set
 774        },
 775};
 776
 777static int getregs_get(struct task_struct *target,
 778                         const struct user_regset *regset,
 779                         struct membuf to)
 780{
 781        const struct pt_regs *regs = task_pt_regs(target);
 782        int i;
 783
 784        if (target == current)
 785                flushw_user();
 786
 787        membuf_store(&to, (u32)tstate_to_psr(regs->tstate));
 788        membuf_store(&to, (u32)(regs->tpc));
 789        membuf_store(&to, (u32)(regs->tnpc));
 790        membuf_store(&to, (u32)(regs->y));
 791        for (i = 1; i < 16; i++)
 792                membuf_store(&to, (u32)regs->u_regs[i]);
 793        return to.left;
 794}
 795
 796static int setregs_set(struct task_struct *target,
 797                         const struct user_regset *regset,
 798                         unsigned int pos, unsigned int count,
 799                         const void *kbuf, const void __user *ubuf)
 800{
 801        struct pt_regs *regs = task_pt_regs(target);
 802        unsigned long tstate;
 803        u32 uregs[19];
 804        int i, ret;
 805
 806        if (target == current)
 807                flushw_user();
 808
 809        ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
 810                                 uregs,
 811                                 0, 19 * sizeof(u32));
 812        if (ret)
 813                return ret;
 814
 815        tstate = regs->tstate;
 816        tstate &= ~(TSTATE_ICC | TSTATE_XCC | TSTATE_SYSCALL);
 817        tstate |= psr_to_tstate_icc(uregs[0]);
 818        if (uregs[0] & PSR_SYSCALL)
 819                tstate |= TSTATE_SYSCALL;
 820        regs->tstate = tstate;
 821        regs->tpc = uregs[1];
 822        regs->tnpc = uregs[2];
 823        regs->y = uregs[3];
 824
 825        for (i = 1; i < 15; i++)
 826                regs->u_regs[i] = uregs[3 + i];
 827        return 0;
 828}
 829
 830static int getfpregs_get(struct task_struct *target,
 831                        const struct user_regset *regset,
 832                        struct membuf to)
 833{
 834        struct thread_info *t = task_thread_info(target);
 835
 836        if (target == current)
 837                save_and_clear_fpu();
 838
 839        membuf_write(&to, t->fpregs, 32 * sizeof(u32));
 840        if (t->fpsaved[0] & FPRS_FEF)
 841                membuf_store(&to, (u32)t->xfsr[0]);
 842        else
 843                membuf_zero(&to, sizeof(u32));
 844        return membuf_zero(&to, 35 * sizeof(u32));
 845}
 846
 847static int setfpregs_set(struct task_struct *target,
 848                        const struct user_regset *regset,
 849                        unsigned int pos, unsigned int count,
 850                        const void *kbuf, const void __user *ubuf)
 851{
 852        unsigned long *fpregs = task_thread_info(target)->fpregs;
 853        unsigned long fprs;
 854        int ret;
 855
 856        if (target == current)
 857                save_and_clear_fpu();
 858
 859        fprs = task_thread_info(target)->fpsaved[0];
 860
 861        ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
 862                                 fpregs,
 863                                 0, 32 * sizeof(u32));
 864        if (!ret) {
 865                compat_ulong_t fsr;
 866                unsigned long val;
 867
 868                ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
 869                                         &fsr,
 870                                         32 * sizeof(u32),
 871                                         33 * sizeof(u32));
 872                if (!ret) {
 873                        val = task_thread_info(target)->xfsr[0];
 874                        val &= 0xffffffff00000000UL;
 875                        val |= fsr;
 876                        task_thread_info(target)->xfsr[0] = val;
 877                }
 878        }
 879
 880        fprs |= (FPRS_FEF | FPRS_DL);
 881        task_thread_info(target)->fpsaved[0] = fprs;
 882        return ret;
 883}
 884
 885static const struct user_regset ptrace32_regsets[] = {
 886        [REGSET_GENERAL] = {
 887                .n = 19, .size = sizeof(u32),
 888                .regset_get = getregs_get, .set = setregs_set,
 889        },
 890        [REGSET_FP] = {
 891                .n = 68, .size = sizeof(u32),
 892                .regset_get = getfpregs_get, .set = setfpregs_set,
 893        },
 894};
 895
 896static const struct user_regset_view ptrace32_view = {
 897        .regsets = ptrace32_regsets, .n = ARRAY_SIZE(ptrace32_regsets)
 898};
 899
 900static const struct user_regset_view user_sparc32_view = {
 901        .name = "sparc", .e_machine = EM_SPARC,
 902        .regsets = sparc32_regsets, .n = ARRAY_SIZE(sparc32_regsets)
 903};
 904#endif /* CONFIG_COMPAT */
 905
 906const struct user_regset_view *task_user_regset_view(struct task_struct *task)
 907{
 908#ifdef CONFIG_COMPAT
 909        if (test_tsk_thread_flag(task, TIF_32BIT))
 910                return &user_sparc32_view;
 911#endif
 912        return &user_sparc64_view;
 913}
 914
 915#ifdef CONFIG_COMPAT
 916struct compat_fps {
 917        unsigned int regs[32];
 918        unsigned int fsr;
 919        unsigned int flags;
 920        unsigned int extra;
 921        unsigned int fpqd;
 922        struct compat_fq {
 923                unsigned int insnaddr;
 924                unsigned int insn;
 925        } fpq[16];
 926};
 927
 928long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
 929                        compat_ulong_t caddr, compat_ulong_t cdata)
 930{
 931        compat_ulong_t caddr2 = task_pt_regs(current)->u_regs[UREG_I4];
 932        struct pt_regs32 __user *pregs;
 933        struct compat_fps __user *fps;
 934        unsigned long addr2 = caddr2;
 935        unsigned long addr = caddr;
 936        unsigned long data = cdata;
 937        int ret;
 938
 939        pregs = (struct pt_regs32 __user *) addr;
 940        fps = (struct compat_fps __user *) addr;
 941
 942        switch (request) {
 943        case PTRACE_PEEKUSR:
 944                ret = (addr != 0) ? -EIO : 0;
 945                break;
 946
 947        case PTRACE_GETREGS:
 948                ret = copy_regset_to_user(child, &ptrace32_view,
 949                                          REGSET_GENERAL, 0,
 950                                          19 * sizeof(u32),
 951                                          pregs);
 952                break;
 953
 954        case PTRACE_SETREGS:
 955                ret = copy_regset_from_user(child, &ptrace32_view,
 956                                          REGSET_GENERAL, 0,
 957                                          19 * sizeof(u32),
 958                                          pregs);
 959                break;
 960
 961        case PTRACE_GETFPREGS:
 962                ret = copy_regset_to_user(child, &ptrace32_view,
 963                                          REGSET_FP, 0,
 964                                          68 * sizeof(u32),
 965                                          fps);
 966                break;
 967
 968        case PTRACE_SETFPREGS:
 969                ret = copy_regset_from_user(child, &ptrace32_view,
 970                                          REGSET_FP, 0,
 971                                          33 * sizeof(u32),
 972                                          fps);
 973                break;
 974
 975        case PTRACE_READTEXT:
 976        case PTRACE_READDATA:
 977                ret = ptrace_readdata(child, addr,
 978                                      (char __user *)addr2, data);
 979                if (ret == data)
 980                        ret = 0;
 981                else if (ret >= 0)
 982                        ret = -EIO;
 983                break;
 984
 985        case PTRACE_WRITETEXT:
 986        case PTRACE_WRITEDATA:
 987                ret = ptrace_writedata(child, (char __user *) addr2,
 988                                       addr, data);
 989                if (ret == data)
 990                        ret = 0;
 991                else if (ret >= 0)
 992                        ret = -EIO;
 993                break;
 994
 995        default:
 996                if (request == PTRACE_SPARC_DETACH)
 997                        request = PTRACE_DETACH;
 998                ret = compat_ptrace_request(child, request, addr, data);
 999                break;
1000        }
1001
1002        return ret;
1003}
1004#endif /* CONFIG_COMPAT */
1005
1006struct fps {
1007        unsigned int regs[64];
1008        unsigned long fsr;
1009};
1010
1011long arch_ptrace(struct task_struct *child, long request,
1012                 unsigned long addr, unsigned long data)
1013{
1014        const struct user_regset_view *view = task_user_regset_view(current);
1015        unsigned long addr2 = task_pt_regs(current)->u_regs[UREG_I4];
1016        struct pt_regs __user *pregs;
1017        struct fps __user *fps;
1018        void __user *addr2p;
1019        int ret;
1020
1021        pregs = (struct pt_regs __user *) addr;
1022        fps = (struct fps __user *) addr;
1023        addr2p = (void __user *) addr2;
1024
1025        switch (request) {
1026        case PTRACE_PEEKUSR:
1027                ret = (addr != 0) ? -EIO : 0;
1028                break;
1029
1030        case PTRACE_GETREGS64:
1031                ret = copy_regset_to_user(child, &ptrace64_view,
1032                                          REGSET_GENERAL, 0,
1033                                          19 * sizeof(u64),
1034                                          pregs);
1035                break;
1036
1037        case PTRACE_SETREGS64:
1038                ret = copy_regset_from_user(child, &ptrace64_view,
1039                                          REGSET_GENERAL, 0,
1040                                          19 * sizeof(u64),
1041                                          pregs);
1042                break;
1043
1044        case PTRACE_GETFPREGS64:
1045                ret = copy_regset_to_user(child, view, REGSET_FP,
1046                                          0 * sizeof(u64),
1047                                          33 * sizeof(u64),
1048                                          fps);
1049                break;
1050
1051        case PTRACE_SETFPREGS64:
1052                ret = copy_regset_from_user(child, view, REGSET_FP,
1053                                          0 * sizeof(u64),
1054                                          33 * sizeof(u64),
1055                                          fps);
1056                break;
1057
1058        case PTRACE_READTEXT:
1059        case PTRACE_READDATA:
1060                ret = ptrace_readdata(child, addr, addr2p, data);
1061                if (ret == data)
1062                        ret = 0;
1063                else if (ret >= 0)
1064                        ret = -EIO;
1065                break;
1066
1067        case PTRACE_WRITETEXT:
1068        case PTRACE_WRITEDATA:
1069                ret = ptrace_writedata(child, addr2p, addr, data);
1070                if (ret == data)
1071                        ret = 0;
1072                else if (ret >= 0)
1073                        ret = -EIO;
1074                break;
1075
1076        default:
1077                if (request == PTRACE_SPARC_DETACH)
1078                        request = PTRACE_DETACH;
1079                ret = ptrace_request(child, request, addr, data);
1080                break;
1081        }
1082
1083        return ret;
1084}
1085
1086asmlinkage int syscall_trace_enter(struct pt_regs *regs)
1087{
1088        int ret = 0;
1089
1090        /* do the secure computing check first */
1091        secure_computing_strict(regs->u_regs[UREG_G1]);
1092
1093        if (test_thread_flag(TIF_NOHZ))
1094                user_exit();
1095
1096        if (test_thread_flag(TIF_SYSCALL_TRACE))
1097                ret = ptrace_report_syscall_entry(regs);
1098
1099        if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
1100                trace_sys_enter(regs, regs->u_regs[UREG_G1]);
1101
1102        audit_syscall_entry(regs->u_regs[UREG_G1], regs->u_regs[UREG_I0],
1103                            regs->u_regs[UREG_I1], regs->u_regs[UREG_I2],
1104                            regs->u_regs[UREG_I3]);
1105
1106        return ret;
1107}
1108
1109asmlinkage void syscall_trace_leave(struct pt_regs *regs)
1110{
1111        if (test_thread_flag(TIF_NOHZ))
1112                user_exit();
1113
1114        audit_syscall_exit(regs);
1115
1116        if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
1117                trace_sys_exit(regs, regs->u_regs[UREG_I0]);
1118
1119        if (test_thread_flag(TIF_SYSCALL_TRACE))
1120                ptrace_report_syscall_exit(regs, 0);
1121
1122        if (test_thread_flag(TIF_NOHZ))
1123                user_enter();
1124}
1125
1126/**
1127 * regs_query_register_offset() - query register offset from its name
1128 * @name:       the name of a register
1129 *
1130 * regs_query_register_offset() returns the offset of a register in struct
1131 * pt_regs from its name. If the name is invalid, this returns -EINVAL;
1132 */
1133int regs_query_register_offset(const char *name)
1134{
1135        const struct pt_regs_offset *roff;
1136
1137        for (roff = regoffset_table; roff->name != NULL; roff++)
1138                if (!strcmp(roff->name, name))
1139                        return roff->offset;
1140        return -EINVAL;
1141}
1142
1143/**
1144 * regs_within_kernel_stack() - check the address in the stack
1145 * @regs:       pt_regs which contains kernel stack pointer.
1146 * @addr:       address which is checked.
1147 *
1148 * regs_within_kernel_stack() checks @addr is within the kernel stack page(s).
1149 * If @addr is within the kernel stack, it returns true. If not, returns false.
1150 */
1151static inline int regs_within_kernel_stack(struct pt_regs *regs,
1152                                           unsigned long addr)
1153{
1154        unsigned long ksp = kernel_stack_pointer(regs) + STACK_BIAS;
1155        return ((addr & ~(THREAD_SIZE - 1))  ==
1156                (ksp & ~(THREAD_SIZE - 1)));
1157}
1158
1159/**
1160 * regs_get_kernel_stack_nth() - get Nth entry of the stack
1161 * @regs:       pt_regs which contains kernel stack pointer.
1162 * @n:          stack entry number.
1163 *
1164 * regs_get_kernel_stack_nth() returns @n th entry of the kernel stack which
1165 * is specified by @regs. If the @n th entry is NOT in the kernel stack,
1166 * this returns 0.
1167 */
1168unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, unsigned int n)
1169{
1170        unsigned long ksp = kernel_stack_pointer(regs) + STACK_BIAS;
1171        unsigned long *addr = (unsigned long *)ksp;
1172        addr += n;
1173        if (regs_within_kernel_stack(regs, (unsigned long)addr))
1174                return *addr;
1175        else
1176                return 0;
1177}
1178