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