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