linux/arch/sparc/kernel/ptrace_64.c
<<
>>
Prefs
   1/* ptrace.c: Sparc process tracing support.
   2 *
   3 * Copyright (C) 1996, 2008 David S. Miller (davem@davemloft.net)
   4 * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
   5 *
   6 * Based upon code written by Ross Biro, Linus Torvalds, Bob Manson,
   7 * and David Mosberger.
   8 *
   9 * Added Linux support -miguel (weird, eh?, the original code was meant
  10 * to emulate SunOS).
  11 */
  12
  13#include <linux/kernel.h>
  14#include <linux/sched.h>
  15#include <linux/sched/task_stack.h>
  16#include <linux/mm.h>
  17#include <linux/errno.h>
  18#include <linux/export.h>
  19#include <linux/ptrace.h>
  20#include <linux/user.h>
  21#include <linux/smp.h>
  22#include <linux/security.h>
  23#include <linux/seccomp.h>
  24#include <linux/audit.h>
  25#include <linux/signal.h>
  26#include <linux/regset.h>
  27#include <linux/tracehook.h>
  28#include <trace/syscall.h>
  29#include <linux/compat.h>
  30#include <linux/elf.h>
  31#include <linux/context_tracking.h>
  32
  33#include <asm/asi.h>
  34#include <asm/pgtable.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                         unsigned int pos, unsigned int count,
 250                         void *kbuf, void __user *ubuf)
 251{
 252        const struct pt_regs *regs = task_pt_regs(target);
 253        int ret;
 254
 255        if (target == current)
 256                flushw_user();
 257
 258        ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
 259                                  regs->u_regs,
 260                                  0, 16 * sizeof(u64));
 261        if (!ret && count && pos < (32 * sizeof(u64))) {
 262                struct reg_window window;
 263
 264                if (regwindow64_get(target, regs, &window))
 265                        return -EFAULT;
 266                ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
 267                                          &window,
 268                                          16 * sizeof(u64),
 269                                          32 * sizeof(u64));
 270        }
 271
 272        if (!ret) {
 273                /* TSTATE, TPC, TNPC */
 274                ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
 275                                          &regs->tstate,
 276                                          32 * sizeof(u64),
 277                                          35 * sizeof(u64));
 278        }
 279
 280        if (!ret) {
 281                unsigned long y = regs->y;
 282
 283                ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
 284                                          &y,
 285                                          35 * sizeof(u64),
 286                                          36 * sizeof(u64));
 287        }
 288
 289        if (!ret) {
 290                ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
 291                                               36 * sizeof(u64), -1);
 292
 293        }
 294        return ret;
 295}
 296
 297static int genregs64_set(struct task_struct *target,
 298                         const struct user_regset *regset,
 299                         unsigned int pos, unsigned int count,
 300                         const void *kbuf, const void __user *ubuf)
 301{
 302        struct pt_regs *regs = task_pt_regs(target);
 303        int ret;
 304
 305        if (target == current)
 306                flushw_user();
 307
 308        ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
 309                                 regs->u_regs,
 310                                 0, 16 * sizeof(u64));
 311        if (!ret && count && pos < (32 * sizeof(u64))) {
 312                struct reg_window window;
 313
 314                if (regwindow64_get(target, regs, &window))
 315                        return -EFAULT;
 316
 317                ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
 318                                         &window,
 319                                         16 * sizeof(u64),
 320                                         32 * sizeof(u64));
 321
 322                if (!ret &&
 323                    regwindow64_set(target, regs, &window))
 324                        return -EFAULT;
 325        }
 326
 327        if (!ret && count > 0) {
 328                unsigned long tstate;
 329
 330                /* TSTATE */
 331                ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
 332                                         &tstate,
 333                                         32 * sizeof(u64),
 334                                         33 * sizeof(u64));
 335                if (!ret) {
 336                        /* Only the condition codes and the "in syscall"
 337                         * state can be modified in the %tstate register.
 338                         */
 339                        tstate &= (TSTATE_ICC | TSTATE_XCC | TSTATE_SYSCALL);
 340                        regs->tstate &= ~(TSTATE_ICC | TSTATE_XCC | TSTATE_SYSCALL);
 341                        regs->tstate |= tstate;
 342                }
 343        }
 344
 345        if (!ret) {
 346                /* TPC, TNPC */
 347                ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
 348                                         &regs->tpc,
 349                                         33 * sizeof(u64),
 350                                         35 * sizeof(u64));
 351        }
 352
 353        if (!ret) {
 354                unsigned long y = regs->y;
 355
 356                ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
 357                                         &y,
 358                                         35 * sizeof(u64),
 359                                         36 * sizeof(u64));
 360                if (!ret)
 361                        regs->y = y;
 362        }
 363
 364        if (!ret)
 365                ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
 366                                                36 * sizeof(u64), -1);
 367
 368        return ret;
 369}
 370
 371static int fpregs64_get(struct task_struct *target,
 372                        const struct user_regset *regset,
 373                        unsigned int pos, unsigned int count,
 374                        void *kbuf, void __user *ubuf)
 375{
 376        const unsigned long *fpregs = task_thread_info(target)->fpregs;
 377        unsigned long fprs, fsr, gsr;
 378        int ret;
 379
 380        if (target == current)
 381                save_and_clear_fpu();
 382
 383        fprs = task_thread_info(target)->fpsaved[0];
 384
 385        if (fprs & FPRS_DL)
 386                ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
 387                                          fpregs,
 388                                          0, 16 * sizeof(u64));
 389        else
 390                ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
 391                                               0,
 392                                               16 * sizeof(u64));
 393
 394        if (!ret) {
 395                if (fprs & FPRS_DU)
 396                        ret = user_regset_copyout(&pos, &count,
 397                                                  &kbuf, &ubuf,
 398                                                  fpregs + 16,
 399                                                  16 * sizeof(u64),
 400                                                  32 * sizeof(u64));
 401                else
 402                        ret = user_regset_copyout_zero(&pos, &count,
 403                                                       &kbuf, &ubuf,
 404                                                       16 * sizeof(u64),
 405                                                       32 * sizeof(u64));
 406        }
 407
 408        if (fprs & FPRS_FEF) {
 409                fsr = task_thread_info(target)->xfsr[0];
 410                gsr = task_thread_info(target)->gsr[0];
 411        } else {
 412                fsr = gsr = 0;
 413        }
 414
 415        if (!ret)
 416                ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
 417                                          &fsr,
 418                                          32 * sizeof(u64),
 419                                          33 * sizeof(u64));
 420        if (!ret)
 421                ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
 422                                          &gsr,
 423                                          33 * sizeof(u64),
 424                                          34 * sizeof(u64));
 425        if (!ret)
 426                ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
 427                                          &fprs,
 428                                          34 * sizeof(u64),
 429                                          35 * sizeof(u64));
 430
 431        if (!ret)
 432                ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
 433                                               35 * sizeof(u64), -1);
 434
 435        return ret;
 436}
 437
 438static int fpregs64_set(struct task_struct *target,
 439                        const struct user_regset *regset,
 440                        unsigned int pos, unsigned int count,
 441                        const void *kbuf, const void __user *ubuf)
 442{
 443        unsigned long *fpregs = task_thread_info(target)->fpregs;
 444        unsigned long fprs;
 445        int ret;
 446
 447        if (target == current)
 448                save_and_clear_fpu();
 449
 450        ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
 451                                 fpregs,
 452                                 0, 32 * sizeof(u64));
 453        if (!ret)
 454                ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
 455                                         task_thread_info(target)->xfsr,
 456                                         32 * sizeof(u64),
 457                                         33 * sizeof(u64));
 458        if (!ret)
 459                ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
 460                                         task_thread_info(target)->gsr,
 461                                         33 * sizeof(u64),
 462                                         34 * sizeof(u64));
 463
 464        fprs = task_thread_info(target)->fpsaved[0];
 465        if (!ret && count > 0) {
 466                ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
 467                                         &fprs,
 468                                         34 * sizeof(u64),
 469                                         35 * sizeof(u64));
 470        }
 471
 472        fprs |= (FPRS_FEF | FPRS_DL | FPRS_DU);
 473        task_thread_info(target)->fpsaved[0] = fprs;
 474
 475        if (!ret)
 476                ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
 477                                                35 * sizeof(u64), -1);
 478        return ret;
 479}
 480
 481static const struct user_regset sparc64_regsets[] = {
 482        /* Format is:
 483         *      G0 --> G7
 484         *      O0 --> O7
 485         *      L0 --> L7
 486         *      I0 --> I7
 487         *      TSTATE, TPC, TNPC, Y
 488         */
 489        [REGSET_GENERAL] = {
 490                .core_note_type = NT_PRSTATUS,
 491                .n = 36,
 492                .size = sizeof(u64), .align = sizeof(u64),
 493                .get = genregs64_get, .set = genregs64_set
 494        },
 495        /* Format is:
 496         *      F0 --> F63
 497         *      FSR
 498         *      GSR
 499         *      FPRS
 500         */
 501        [REGSET_FP] = {
 502                .core_note_type = NT_PRFPREG,
 503                .n = 35,
 504                .size = sizeof(u64), .align = sizeof(u64),
 505                .get = fpregs64_get, .set = fpregs64_set
 506        },
 507};
 508
 509static const struct user_regset_view user_sparc64_view = {
 510        .name = "sparc64", .e_machine = EM_SPARCV9,
 511        .regsets = sparc64_regsets, .n = ARRAY_SIZE(sparc64_regsets)
 512};
 513
 514#ifdef CONFIG_COMPAT
 515static int genregs32_get(struct task_struct *target,
 516                         const struct user_regset *regset,
 517                         unsigned int pos, unsigned int count,
 518                         void *kbuf, void __user *ubuf)
 519{
 520        const struct pt_regs *regs = task_pt_regs(target);
 521        compat_ulong_t __user *reg_window;
 522        compat_ulong_t *k = kbuf;
 523        compat_ulong_t __user *u = ubuf;
 524        compat_ulong_t reg;
 525
 526        if (target == current)
 527                flushw_user();
 528
 529        pos /= sizeof(reg);
 530        count /= sizeof(reg);
 531
 532        if (kbuf) {
 533                for (; count > 0 && pos < 16; count--)
 534                        *k++ = regs->u_regs[pos++];
 535
 536                reg_window = (compat_ulong_t __user *) regs->u_regs[UREG_I6];
 537                reg_window -= 16;
 538                if (target == current) {
 539                        for (; count > 0 && pos < 32; count--) {
 540                                if (get_user(*k++, &reg_window[pos++]))
 541                                        return -EFAULT;
 542                        }
 543                } else {
 544                        for (; count > 0 && pos < 32; count--) {
 545                                if (access_process_vm(target,
 546                                                      (unsigned long)
 547                                                      &reg_window[pos],
 548                                                      k, sizeof(*k),
 549                                                      FOLL_FORCE)
 550                                    != sizeof(*k))
 551                                        return -EFAULT;
 552                                k++;
 553                                pos++;
 554                        }
 555                }
 556        } else {
 557                for (; count > 0 && pos < 16; count--) {
 558                        if (put_user((compat_ulong_t) regs->u_regs[pos++], u++))
 559                                return -EFAULT;
 560                }
 561
 562                reg_window = (compat_ulong_t __user *) regs->u_regs[UREG_I6];
 563                reg_window -= 16;
 564                if (target == current) {
 565                        for (; count > 0 && pos < 32; count--) {
 566                                if (get_user(reg, &reg_window[pos++]) ||
 567                                    put_user(reg, u++))
 568                                        return -EFAULT;
 569                        }
 570                } else {
 571                        for (; count > 0 && pos < 32; count--) {
 572                                if (access_process_vm(target,
 573                                                      (unsigned long)
 574                                                      &reg_window[pos],
 575                                                      &reg, sizeof(reg),
 576                                                      FOLL_FORCE)
 577                                    != sizeof(reg))
 578                                        return -EFAULT;
 579                                if (access_process_vm(target,
 580                                                      (unsigned long) u,
 581                                                      &reg, sizeof(reg),
 582                                                      FOLL_FORCE | FOLL_WRITE)
 583                                    != sizeof(reg))
 584                                        return -EFAULT;
 585                                pos++;
 586                                u++;
 587                        }
 588                }
 589        }
 590        while (count > 0) {
 591                switch (pos) {
 592                case 32: /* PSR */
 593                        reg = tstate_to_psr(regs->tstate);
 594                        break;
 595                case 33: /* PC */
 596                        reg = regs->tpc;
 597                        break;
 598                case 34: /* NPC */
 599                        reg = regs->tnpc;
 600                        break;
 601                case 35: /* Y */
 602                        reg = regs->y;
 603                        break;
 604                case 36: /* WIM */
 605                case 37: /* TBR */
 606                        reg = 0;
 607                        break;
 608                default:
 609                        goto finish;
 610                }
 611
 612                if (kbuf)
 613                        *k++ = reg;
 614                else if (put_user(reg, u++))
 615                        return -EFAULT;
 616                pos++;
 617                count--;
 618        }
 619finish:
 620        pos *= sizeof(reg);
 621        count *= sizeof(reg);
 622
 623        return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
 624                                        38 * sizeof(reg), -1);
 625}
 626
 627static int genregs32_set(struct task_struct *target,
 628                         const struct user_regset *regset,
 629                         unsigned int pos, unsigned int count,
 630                         const void *kbuf, const void __user *ubuf)
 631{
 632        struct pt_regs *regs = task_pt_regs(target);
 633        compat_ulong_t __user *reg_window;
 634        const compat_ulong_t *k = kbuf;
 635        const compat_ulong_t __user *u = ubuf;
 636        compat_ulong_t reg;
 637
 638        if (target == current)
 639                flushw_user();
 640
 641        pos /= sizeof(reg);
 642        count /= sizeof(reg);
 643
 644        if (kbuf) {
 645                for (; count > 0 && pos < 16; count--)
 646                        regs->u_regs[pos++] = *k++;
 647
 648                reg_window = (compat_ulong_t __user *) regs->u_regs[UREG_I6];
 649                reg_window -= 16;
 650                if (target == current) {
 651                        for (; count > 0 && pos < 32; count--) {
 652                                if (put_user(*k++, &reg_window[pos++]))
 653                                        return -EFAULT;
 654                        }
 655                } else {
 656                        for (; count > 0 && pos < 32; count--) {
 657                                if (access_process_vm(target,
 658                                                      (unsigned long)
 659                                                      &reg_window[pos],
 660                                                      (void *) k,
 661                                                      sizeof(*k),
 662                                                      FOLL_FORCE | FOLL_WRITE)
 663                                    != sizeof(*k))
 664                                        return -EFAULT;
 665                                k++;
 666                                pos++;
 667                        }
 668                }
 669        } else {
 670                for (; count > 0 && pos < 16; count--) {
 671                        if (get_user(reg, u++))
 672                                return -EFAULT;
 673                        regs->u_regs[pos++] = reg;
 674                }
 675
 676                reg_window = (compat_ulong_t __user *) regs->u_regs[UREG_I6];
 677                reg_window -= 16;
 678                if (target == current) {
 679                        for (; count > 0 && pos < 32; count--) {
 680                                if (get_user(reg, u++) ||
 681                                    put_user(reg, &reg_window[pos++]))
 682                                        return -EFAULT;
 683                        }
 684                } else {
 685                        for (; count > 0 && pos < 32; count--) {
 686                                if (access_process_vm(target,
 687                                                      (unsigned long)
 688                                                      u,
 689                                                      &reg, sizeof(reg),
 690                                                      FOLL_FORCE)
 691                                    != sizeof(reg))
 692                                        return -EFAULT;
 693                                if (access_process_vm(target,
 694                                                      (unsigned long)
 695                                                      &reg_window[pos],
 696                                                      &reg, sizeof(reg),
 697                                                      FOLL_FORCE | FOLL_WRITE)
 698                                    != sizeof(reg))
 699                                        return -EFAULT;
 700                                pos++;
 701                                u++;
 702                        }
 703                }
 704        }
 705        while (count > 0) {
 706                unsigned long tstate;
 707
 708                if (kbuf)
 709                        reg = *k++;
 710                else if (get_user(reg, u++))
 711                        return -EFAULT;
 712
 713                switch (pos) {
 714                case 32: /* PSR */
 715                        tstate = regs->tstate;
 716                        tstate &= ~(TSTATE_ICC | TSTATE_XCC | TSTATE_SYSCALL);
 717                        tstate |= psr_to_tstate_icc(reg);
 718                        if (reg & PSR_SYSCALL)
 719                                tstate |= TSTATE_SYSCALL;
 720                        regs->tstate = tstate;
 721                        break;
 722                case 33: /* PC */
 723                        regs->tpc = reg;
 724                        break;
 725                case 34: /* NPC */
 726                        regs->tnpc = reg;
 727                        break;
 728                case 35: /* Y */
 729                        regs->y = reg;
 730                        break;
 731                case 36: /* WIM */
 732                case 37: /* TBR */
 733                        break;
 734                default:
 735                        goto finish;
 736                }
 737
 738                pos++;
 739                count--;
 740        }
 741finish:
 742        pos *= sizeof(reg);
 743        count *= sizeof(reg);
 744
 745        return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
 746                                         38 * sizeof(reg), -1);
 747}
 748
 749static int fpregs32_get(struct task_struct *target,
 750                        const struct user_regset *regset,
 751                        unsigned int pos, unsigned int count,
 752                        void *kbuf, void __user *ubuf)
 753{
 754        const unsigned long *fpregs = task_thread_info(target)->fpregs;
 755        compat_ulong_t enabled;
 756        unsigned long fprs;
 757        compat_ulong_t fsr;
 758        int ret = 0;
 759
 760        if (target == current)
 761                save_and_clear_fpu();
 762
 763        fprs = task_thread_info(target)->fpsaved[0];
 764        if (fprs & FPRS_FEF) {
 765                fsr = task_thread_info(target)->xfsr[0];
 766                enabled = 1;
 767        } else {
 768                fsr = 0;
 769                enabled = 0;
 770        }
 771
 772        ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
 773                                  fpregs,
 774                                  0, 32 * sizeof(u32));
 775
 776        if (!ret)
 777                ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
 778                                               32 * sizeof(u32),
 779                                               33 * sizeof(u32));
 780        if (!ret)
 781                ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
 782                                          &fsr,
 783                                          33 * sizeof(u32),
 784                                          34 * sizeof(u32));
 785
 786        if (!ret) {
 787                compat_ulong_t val;
 788
 789                val = (enabled << 8) | (8 << 16);
 790                ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
 791                                          &val,
 792                                          34 * sizeof(u32),
 793                                          35 * sizeof(u32));
 794        }
 795
 796        if (!ret)
 797                ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
 798                                               35 * sizeof(u32), -1);
 799
 800        return ret;
 801}
 802
 803static int fpregs32_set(struct task_struct *target,
 804                        const struct user_regset *regset,
 805                        unsigned int pos, unsigned int count,
 806                        const void *kbuf, const void __user *ubuf)
 807{
 808        unsigned long *fpregs = task_thread_info(target)->fpregs;
 809        unsigned long fprs;
 810        int ret;
 811
 812        if (target == current)
 813                save_and_clear_fpu();
 814
 815        fprs = task_thread_info(target)->fpsaved[0];
 816
 817        ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
 818                                 fpregs,
 819                                 0, 32 * sizeof(u32));
 820        if (!ret)
 821                user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
 822                                          32 * sizeof(u32),
 823                                          33 * sizeof(u32));
 824        if (!ret && count > 0) {
 825                compat_ulong_t fsr;
 826                unsigned long val;
 827
 828                ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
 829                                         &fsr,
 830                                         33 * sizeof(u32),
 831                                         34 * sizeof(u32));
 832                if (!ret) {
 833                        val = task_thread_info(target)->xfsr[0];
 834                        val &= 0xffffffff00000000UL;
 835                        val |= fsr;
 836                        task_thread_info(target)->xfsr[0] = val;
 837                }
 838        }
 839
 840        fprs |= (FPRS_FEF | FPRS_DL);
 841        task_thread_info(target)->fpsaved[0] = fprs;
 842
 843        if (!ret)
 844                ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
 845                                                34 * sizeof(u32), -1);
 846        return ret;
 847}
 848
 849static const struct user_regset sparc32_regsets[] = {
 850        /* Format is:
 851         *      G0 --> G7
 852         *      O0 --> O7
 853         *      L0 --> L7
 854         *      I0 --> I7
 855         *      PSR, PC, nPC, Y, WIM, TBR
 856         */
 857        [REGSET_GENERAL] = {
 858                .core_note_type = NT_PRSTATUS,
 859                .n = 38,
 860                .size = sizeof(u32), .align = sizeof(u32),
 861                .get = genregs32_get, .set = genregs32_set
 862        },
 863        /* Format is:
 864         *      F0 --> F31
 865         *      empty 32-bit word
 866         *      FSR (32--bit word)
 867         *      FPU QUEUE COUNT (8-bit char)
 868         *      FPU QUEUE ENTRYSIZE (8-bit char)
 869         *      FPU ENABLED (8-bit char)
 870         *      empty 8-bit char
 871         *      FPU QUEUE (64 32-bit ints)
 872         */
 873        [REGSET_FP] = {
 874                .core_note_type = NT_PRFPREG,
 875                .n = 99,
 876                .size = sizeof(u32), .align = sizeof(u32),
 877                .get = fpregs32_get, .set = fpregs32_set
 878        },
 879};
 880
 881static const struct user_regset_view user_sparc32_view = {
 882        .name = "sparc", .e_machine = EM_SPARC,
 883        .regsets = sparc32_regsets, .n = ARRAY_SIZE(sparc32_regsets)
 884};
 885#endif /* CONFIG_COMPAT */
 886
 887const struct user_regset_view *task_user_regset_view(struct task_struct *task)
 888{
 889#ifdef CONFIG_COMPAT
 890        if (test_tsk_thread_flag(task, TIF_32BIT))
 891                return &user_sparc32_view;
 892#endif
 893        return &user_sparc64_view;
 894}
 895
 896#ifdef CONFIG_COMPAT
 897struct compat_fps {
 898        unsigned int regs[32];
 899        unsigned int fsr;
 900        unsigned int flags;
 901        unsigned int extra;
 902        unsigned int fpqd;
 903        struct compat_fq {
 904                unsigned int insnaddr;
 905                unsigned int insn;
 906        } fpq[16];
 907};
 908
 909long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
 910                        compat_ulong_t caddr, compat_ulong_t cdata)
 911{
 912        const struct user_regset_view *view = task_user_regset_view(current);
 913        compat_ulong_t caddr2 = task_pt_regs(current)->u_regs[UREG_I4];
 914        struct pt_regs32 __user *pregs;
 915        struct compat_fps __user *fps;
 916        unsigned long addr2 = caddr2;
 917        unsigned long addr = caddr;
 918        unsigned long data = cdata;
 919        int ret;
 920
 921        pregs = (struct pt_regs32 __user *) addr;
 922        fps = (struct compat_fps __user *) addr;
 923
 924        switch (request) {
 925        case PTRACE_PEEKUSR:
 926                ret = (addr != 0) ? -EIO : 0;
 927                break;
 928
 929        case PTRACE_GETREGS:
 930                ret = copy_regset_to_user(child, view, REGSET_GENERAL,
 931                                          32 * sizeof(u32),
 932                                          4 * sizeof(u32),
 933                                          &pregs->psr);
 934                if (!ret)
 935                        ret = copy_regset_to_user(child, view, REGSET_GENERAL,
 936                                                  1 * sizeof(u32),
 937                                                  15 * sizeof(u32),
 938                                                  &pregs->u_regs[0]);
 939                break;
 940
 941        case PTRACE_SETREGS:
 942                ret = copy_regset_from_user(child, view, REGSET_GENERAL,
 943                                            32 * sizeof(u32),
 944                                            4 * sizeof(u32),
 945                                            &pregs->psr);
 946                if (!ret)
 947                        ret = copy_regset_from_user(child, view, REGSET_GENERAL,
 948                                                    1 * sizeof(u32),
 949                                                    15 * sizeof(u32),
 950                                                    &pregs->u_regs[0]);
 951                break;
 952
 953        case PTRACE_GETFPREGS:
 954                ret = copy_regset_to_user(child, view, REGSET_FP,
 955                                          0 * sizeof(u32),
 956                                          32 * sizeof(u32),
 957                                          &fps->regs[0]);
 958                if (!ret)
 959                        ret = copy_regset_to_user(child, view, REGSET_FP,
 960                                                  33 * sizeof(u32),
 961                                                  1 * sizeof(u32),
 962                                                  &fps->fsr);
 963                if (!ret) {
 964                        if (__put_user(0, &fps->flags) ||
 965                            __put_user(0, &fps->extra) ||
 966                            __put_user(0, &fps->fpqd) ||
 967                            clear_user(&fps->fpq[0], 32 * sizeof(unsigned int)))
 968                                ret = -EFAULT;
 969                }
 970                break;
 971
 972        case PTRACE_SETFPREGS:
 973                ret = copy_regset_from_user(child, view, REGSET_FP,
 974                                            0 * sizeof(u32),
 975                                            32 * sizeof(u32),
 976                                            &fps->regs[0]);
 977                if (!ret)
 978                        ret = copy_regset_from_user(child, view, REGSET_FP,
 979                                                    33 * sizeof(u32),
 980                                                    1 * sizeof(u32),
 981                                                    &fps->fsr);
 982                break;
 983
 984        case PTRACE_READTEXT:
 985        case PTRACE_READDATA:
 986                ret = ptrace_readdata(child, addr,
 987                                      (char __user *)addr2, data);
 988                if (ret == data)
 989                        ret = 0;
 990                else if (ret >= 0)
 991                        ret = -EIO;
 992                break;
 993
 994        case PTRACE_WRITETEXT:
 995        case PTRACE_WRITEDATA:
 996                ret = ptrace_writedata(child, (char __user *) addr2,
 997                                       addr, data);
 998                if (ret == data)
 999                        ret = 0;
1000                else if (ret >= 0)
1001                        ret = -EIO;
1002                break;
1003
1004        default:
1005                if (request == PTRACE_SPARC_DETACH)
1006                        request = PTRACE_DETACH;
1007                ret = compat_ptrace_request(child, request, addr, data);
1008                break;
1009        }
1010
1011        return ret;
1012}
1013#endif /* CONFIG_COMPAT */
1014
1015struct fps {
1016        unsigned int regs[64];
1017        unsigned long fsr;
1018};
1019
1020long arch_ptrace(struct task_struct *child, long request,
1021                 unsigned long addr, unsigned long data)
1022{
1023        const struct user_regset_view *view = task_user_regset_view(current);
1024        unsigned long addr2 = task_pt_regs(current)->u_regs[UREG_I4];
1025        struct pt_regs __user *pregs;
1026        struct fps __user *fps;
1027        void __user *addr2p;
1028        int ret;
1029
1030        pregs = (struct pt_regs __user *) addr;
1031        fps = (struct fps __user *) addr;
1032        addr2p = (void __user *) addr2;
1033
1034        switch (request) {
1035        case PTRACE_PEEKUSR:
1036                ret = (addr != 0) ? -EIO : 0;
1037                break;
1038
1039        case PTRACE_GETREGS64:
1040                ret = copy_regset_to_user(child, view, REGSET_GENERAL,
1041                                          1 * sizeof(u64),
1042                                          15 * sizeof(u64),
1043                                          &pregs->u_regs[0]);
1044                if (!ret) {
1045                        /* XXX doesn't handle 'y' register correctly XXX */
1046                        ret = copy_regset_to_user(child, view, REGSET_GENERAL,
1047                                                  32 * sizeof(u64),
1048                                                  4 * sizeof(u64),
1049                                                  &pregs->tstate);
1050                }
1051                break;
1052
1053        case PTRACE_SETREGS64:
1054                ret = copy_regset_from_user(child, view, REGSET_GENERAL,
1055                                            1 * sizeof(u64),
1056                                            15 * sizeof(u64),
1057                                            &pregs->u_regs[0]);
1058                if (!ret) {
1059                        /* XXX doesn't handle 'y' register correctly XXX */
1060                        ret = copy_regset_from_user(child, view, REGSET_GENERAL,
1061                                                    32 * sizeof(u64),
1062                                                    4 * sizeof(u64),
1063                                                    &pregs->tstate);
1064                }
1065                break;
1066
1067        case PTRACE_GETFPREGS64:
1068                ret = copy_regset_to_user(child, view, REGSET_FP,
1069                                          0 * sizeof(u64),
1070                                          33 * sizeof(u64),
1071                                          fps);
1072                break;
1073
1074        case PTRACE_SETFPREGS64:
1075                ret = copy_regset_from_user(child, view, REGSET_FP,
1076                                          0 * sizeof(u64),
1077                                          33 * sizeof(u64),
1078                                          fps);
1079                break;
1080
1081        case PTRACE_READTEXT:
1082        case PTRACE_READDATA:
1083                ret = ptrace_readdata(child, addr, addr2p, data);
1084                if (ret == data)
1085                        ret = 0;
1086                else if (ret >= 0)
1087                        ret = -EIO;
1088                break;
1089
1090        case PTRACE_WRITETEXT:
1091        case PTRACE_WRITEDATA:
1092                ret = ptrace_writedata(child, addr2p, addr, data);
1093                if (ret == data)
1094                        ret = 0;
1095                else if (ret >= 0)
1096                        ret = -EIO;
1097                break;
1098
1099        default:
1100                if (request == PTRACE_SPARC_DETACH)
1101                        request = PTRACE_DETACH;
1102                ret = ptrace_request(child, request, addr, data);
1103                break;
1104        }
1105
1106        return ret;
1107}
1108
1109asmlinkage int syscall_trace_enter(struct pt_regs *regs)
1110{
1111        int ret = 0;
1112
1113        /* do the secure computing check first */
1114        secure_computing_strict(regs->u_regs[UREG_G1]);
1115
1116        if (test_thread_flag(TIF_NOHZ))
1117                user_exit();
1118
1119        if (test_thread_flag(TIF_SYSCALL_TRACE))
1120                ret = tracehook_report_syscall_entry(regs);
1121
1122        if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
1123                trace_sys_enter(regs, regs->u_regs[UREG_G1]);
1124
1125        audit_syscall_entry(regs->u_regs[UREG_G1], regs->u_regs[UREG_I0],
1126                            regs->u_regs[UREG_I1], regs->u_regs[UREG_I2],
1127                            regs->u_regs[UREG_I3]);
1128
1129        return ret;
1130}
1131
1132asmlinkage void syscall_trace_leave(struct pt_regs *regs)
1133{
1134        if (test_thread_flag(TIF_NOHZ))
1135                user_exit();
1136
1137        audit_syscall_exit(regs);
1138
1139        if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
1140                trace_sys_exit(regs, regs->u_regs[UREG_I0]);
1141
1142        if (test_thread_flag(TIF_SYSCALL_TRACE))
1143                tracehook_report_syscall_exit(regs, 0);
1144
1145        if (test_thread_flag(TIF_NOHZ))
1146                user_enter();
1147}
1148
1149/**
1150 * regs_query_register_offset() - query register offset from its name
1151 * @name:       the name of a register
1152 *
1153 * regs_query_register_offset() returns the offset of a register in struct
1154 * pt_regs from its name. If the name is invalid, this returns -EINVAL;
1155 */
1156int regs_query_register_offset(const char *name)
1157{
1158        const struct pt_regs_offset *roff;
1159
1160        for (roff = regoffset_table; roff->name != NULL; roff++)
1161                if (!strcmp(roff->name, name))
1162                        return roff->offset;
1163        return -EINVAL;
1164}
1165
1166/**
1167 * regs_within_kernel_stack() - check the address in the stack
1168 * @regs:       pt_regs which contains kernel stack pointer.
1169 * @addr:       address which is checked.
1170 *
1171 * regs_within_kernel_stack() checks @addr is within the kernel stack page(s).
1172 * If @addr is within the kernel stack, it returns true. If not, returns false.
1173 */
1174static inline int regs_within_kernel_stack(struct pt_regs *regs,
1175                                           unsigned long addr)
1176{
1177        unsigned long ksp = kernel_stack_pointer(regs) + STACK_BIAS;
1178        return ((addr & ~(THREAD_SIZE - 1))  ==
1179                (ksp & ~(THREAD_SIZE - 1)));
1180}
1181
1182/**
1183 * regs_get_kernel_stack_nth() - get Nth entry of the stack
1184 * @regs:       pt_regs which contains kernel stack pointer.
1185 * @n:          stack entry number.
1186 *
1187 * regs_get_kernel_stack_nth() returns @n th entry of the kernel stack which
1188 * is specified by @regs. If the @n th entry is NOT in the kernel stack,
1189 * this returns 0.
1190 */
1191unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, unsigned int n)
1192{
1193        unsigned long ksp = kernel_stack_pointer(regs) + STACK_BIAS;
1194        unsigned long *addr = (unsigned long *)ksp;
1195        addr += n;
1196        if (regs_within_kernel_stack(regs, (unsigned long)addr))
1197                return *addr;
1198        else
1199                return 0;
1200}
1201