Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /* ptrace.c: Sparc process tracing support.
0003  *
0004  * Copyright (C) 1996, 2008 David S. Miller (davem@davemloft.net)
0005  * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
0006  *
0007  * Based upon code written by Ross Biro, Linus Torvalds, Bob Manson,
0008  * and David Mosberger.
0009  *
0010  * Added Linux support -miguel (weird, eh?, the original code was meant
0011  * to emulate SunOS).
0012  */
0013 
0014 #include <linux/kernel.h>
0015 #include <linux/sched.h>
0016 #include <linux/sched/task_stack.h>
0017 #include <linux/mm.h>
0018 #include <linux/errno.h>
0019 #include <linux/export.h>
0020 #include <linux/ptrace.h>
0021 #include <linux/user.h>
0022 #include <linux/smp.h>
0023 #include <linux/security.h>
0024 #include <linux/seccomp.h>
0025 #include <linux/audit.h>
0026 #include <linux/signal.h>
0027 #include <linux/regset.h>
0028 #include <trace/syscall.h>
0029 #include <linux/compat.h>
0030 #include <linux/elf.h>
0031 #include <linux/context_tracking.h>
0032 
0033 #include <asm/asi.h>
0034 #include <linux/uaccess.h>
0035 #include <asm/psrcompat.h>
0036 #include <asm/visasm.h>
0037 #include <asm/spitfire.h>
0038 #include <asm/page.h>
0039 #include <asm/cpudata.h>
0040 #include <asm/cacheflush.h>
0041 
0042 #define CREATE_TRACE_POINTS
0043 #include <trace/events/syscalls.h>
0044 
0045 #include "entry.h"
0046 
0047 /* #define ALLOW_INIT_TRACING */
0048 
0049 struct pt_regs_offset {
0050     const char *name;
0051     int offset;
0052 };
0053 
0054 #define REG_OFFSET_NAME(n, r) \
0055     {.name = n, .offset = (PT_V9_##r)}
0056 #define REG_OFFSET_END {.name = NULL, .offset = 0}
0057 
0058 static const struct pt_regs_offset regoffset_table[] = {
0059     REG_OFFSET_NAME("g0", G0),
0060     REG_OFFSET_NAME("g1", G1),
0061     REG_OFFSET_NAME("g2", G2),
0062     REG_OFFSET_NAME("g3", G3),
0063     REG_OFFSET_NAME("g4", G4),
0064     REG_OFFSET_NAME("g5", G5),
0065     REG_OFFSET_NAME("g6", G6),
0066     REG_OFFSET_NAME("g7", G7),
0067 
0068     REG_OFFSET_NAME("i0", I0),
0069     REG_OFFSET_NAME("i1", I1),
0070     REG_OFFSET_NAME("i2", I2),
0071     REG_OFFSET_NAME("i3", I3),
0072     REG_OFFSET_NAME("i4", I4),
0073     REG_OFFSET_NAME("i5", I5),
0074     REG_OFFSET_NAME("i6", I6),
0075     REG_OFFSET_NAME("i7", I7),
0076 
0077     REG_OFFSET_NAME("tstate", TSTATE),
0078     REG_OFFSET_NAME("pc", TPC),
0079     REG_OFFSET_NAME("npc", TNPC),
0080     REG_OFFSET_NAME("y", Y),
0081     REG_OFFSET_NAME("lr", I7),
0082 
0083     REG_OFFSET_END,
0084 };
0085 
0086 /*
0087  * Called by kernel/ptrace.c when detaching..
0088  *
0089  * Make sure single step bits etc are not set.
0090  */
0091 void ptrace_disable(struct task_struct *child)
0092 {
0093     /* nothing to do */
0094 }
0095 
0096 /* To get the necessary page struct, access_process_vm() first calls
0097  * get_user_pages().  This has done a flush_dcache_page() on the
0098  * accessed page.  Then our caller (copy_{to,from}_user_page()) did
0099  * to memcpy to read/write the data from that page.
0100  *
0101  * Now, the only thing we have to do is:
0102  * 1) flush the D-cache if it's possible than an illegal alias
0103  *    has been created
0104  * 2) flush the I-cache if this is pre-cheetah and we did a write
0105  */
0106 void flush_ptrace_access(struct vm_area_struct *vma, struct page *page,
0107              unsigned long uaddr, void *kaddr,
0108              unsigned long len, int write)
0109 {
0110     BUG_ON(len > PAGE_SIZE);
0111 
0112     if (tlb_type == hypervisor)
0113         return;
0114 
0115     preempt_disable();
0116 
0117 #ifdef DCACHE_ALIASING_POSSIBLE
0118     /* If bit 13 of the kernel address we used to access the
0119      * user page is the same as the virtual address that page
0120      * is mapped to in the user's address space, we can skip the
0121      * D-cache flush.
0122      */
0123     if ((uaddr ^ (unsigned long) kaddr) & (1UL << 13)) {
0124         unsigned long start = __pa(kaddr);
0125         unsigned long end = start + len;
0126         unsigned long dcache_line_size;
0127 
0128         dcache_line_size = local_cpu_data().dcache_line_size;
0129 
0130         if (tlb_type == spitfire) {
0131             for (; start < end; start += dcache_line_size)
0132                 spitfire_put_dcache_tag(start & 0x3fe0, 0x0);
0133         } else {
0134             start &= ~(dcache_line_size - 1);
0135             for (; start < end; start += dcache_line_size)
0136                 __asm__ __volatile__(
0137                     "stxa %%g0, [%0] %1\n\t"
0138                     "membar #Sync"
0139                     : /* no outputs */
0140                     : "r" (start),
0141                     "i" (ASI_DCACHE_INVALIDATE));
0142         }
0143     }
0144 #endif
0145     if (write && tlb_type == spitfire) {
0146         unsigned long start = (unsigned long) kaddr;
0147         unsigned long end = start + len;
0148         unsigned long icache_line_size;
0149 
0150         icache_line_size = local_cpu_data().icache_line_size;
0151 
0152         for (; start < end; start += icache_line_size)
0153             flushi(start);
0154     }
0155 
0156     preempt_enable();
0157 }
0158 EXPORT_SYMBOL_GPL(flush_ptrace_access);
0159 
0160 static int get_from_target(struct task_struct *target, unsigned long uaddr,
0161                void *kbuf, int len)
0162 {
0163     if (target == current) {
0164         if (copy_from_user(kbuf, (void __user *) uaddr, len))
0165             return -EFAULT;
0166     } else {
0167         int len2 = access_process_vm(target, uaddr, kbuf, len,
0168                 FOLL_FORCE);
0169         if (len2 != len)
0170             return -EFAULT;
0171     }
0172     return 0;
0173 }
0174 
0175 static int set_to_target(struct task_struct *target, unsigned long uaddr,
0176              void *kbuf, int len)
0177 {
0178     if (target == current) {
0179         if (copy_to_user((void __user *) uaddr, kbuf, len))
0180             return -EFAULT;
0181     } else {
0182         int len2 = access_process_vm(target, uaddr, kbuf, len,
0183                 FOLL_FORCE | FOLL_WRITE);
0184         if (len2 != len)
0185             return -EFAULT;
0186     }
0187     return 0;
0188 }
0189 
0190 static int regwindow64_get(struct task_struct *target,
0191                const struct pt_regs *regs,
0192                struct reg_window *wbuf)
0193 {
0194     unsigned long rw_addr = regs->u_regs[UREG_I6];
0195 
0196     if (!test_thread_64bit_stack(rw_addr)) {
0197         struct reg_window32 win32;
0198         int i;
0199 
0200         if (get_from_target(target, rw_addr, &win32, sizeof(win32)))
0201             return -EFAULT;
0202         for (i = 0; i < 8; i++)
0203             wbuf->locals[i] = win32.locals[i];
0204         for (i = 0; i < 8; i++)
0205             wbuf->ins[i] = win32.ins[i];
0206     } else {
0207         rw_addr += STACK_BIAS;
0208         if (get_from_target(target, rw_addr, wbuf, sizeof(*wbuf)))
0209             return -EFAULT;
0210     }
0211 
0212     return 0;
0213 }
0214 
0215 static int regwindow64_set(struct task_struct *target,
0216                const struct pt_regs *regs,
0217                struct reg_window *wbuf)
0218 {
0219     unsigned long rw_addr = regs->u_regs[UREG_I6];
0220 
0221     if (!test_thread_64bit_stack(rw_addr)) {
0222         struct reg_window32 win32;
0223         int i;
0224 
0225         for (i = 0; i < 8; i++)
0226             win32.locals[i] = wbuf->locals[i];
0227         for (i = 0; i < 8; i++)
0228             win32.ins[i] = wbuf->ins[i];
0229 
0230         if (set_to_target(target, rw_addr, &win32, sizeof(win32)))
0231             return -EFAULT;
0232     } else {
0233         rw_addr += STACK_BIAS;
0234         if (set_to_target(target, rw_addr, wbuf, sizeof(*wbuf)))
0235             return -EFAULT;
0236     }
0237 
0238     return 0;
0239 }
0240 
0241 enum sparc_regset {
0242     REGSET_GENERAL,
0243     REGSET_FP,
0244 };
0245 
0246 static int genregs64_get(struct task_struct *target,
0247              const struct user_regset *regset,
0248              struct membuf to)
0249 {
0250     const struct pt_regs *regs = task_pt_regs(target);
0251     struct reg_window window;
0252 
0253     if (target == current)
0254         flushw_user();
0255 
0256     membuf_write(&to, regs->u_regs, 16 * sizeof(u64));
0257     if (!to.left)
0258         return 0;
0259     if (regwindow64_get(target, regs, &window))
0260         return -EFAULT;
0261     membuf_write(&to, &window, 16 * sizeof(u64));
0262     /* TSTATE, TPC, TNPC */
0263     membuf_write(&to, &regs->tstate, 3 * sizeof(u64));
0264     return membuf_store(&to, (u64)regs->y);
0265 }
0266 
0267 static int genregs64_set(struct task_struct *target,
0268              const struct user_regset *regset,
0269              unsigned int pos, unsigned int count,
0270              const void *kbuf, const void __user *ubuf)
0271 {
0272     struct pt_regs *regs = task_pt_regs(target);
0273     int ret;
0274 
0275     if (target == current)
0276         flushw_user();
0277 
0278     ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
0279                  regs->u_regs,
0280                  0, 16 * sizeof(u64));
0281     if (!ret && count && pos < (32 * sizeof(u64))) {
0282         struct reg_window window;
0283 
0284         if (regwindow64_get(target, regs, &window))
0285             return -EFAULT;
0286 
0287         ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
0288                      &window,
0289                      16 * sizeof(u64),
0290                      32 * sizeof(u64));
0291 
0292         if (!ret &&
0293             regwindow64_set(target, regs, &window))
0294             return -EFAULT;
0295     }
0296 
0297     if (!ret && count > 0) {
0298         unsigned long tstate;
0299 
0300         /* TSTATE */
0301         ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
0302                      &tstate,
0303                      32 * sizeof(u64),
0304                      33 * sizeof(u64));
0305         if (!ret) {
0306             /* Only the condition codes and the "in syscall"
0307              * state can be modified in the %tstate register.
0308              */
0309             tstate &= (TSTATE_ICC | TSTATE_XCC | TSTATE_SYSCALL);
0310             regs->tstate &= ~(TSTATE_ICC | TSTATE_XCC | TSTATE_SYSCALL);
0311             regs->tstate |= tstate;
0312         }
0313     }
0314 
0315     if (!ret) {
0316         /* TPC, TNPC */
0317         ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
0318                      &regs->tpc,
0319                      33 * sizeof(u64),
0320                      35 * sizeof(u64));
0321     }
0322 
0323     if (!ret) {
0324         unsigned long y = regs->y;
0325 
0326         ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
0327                      &y,
0328                      35 * sizeof(u64),
0329                      36 * sizeof(u64));
0330         if (!ret)
0331             regs->y = y;
0332     }
0333 
0334     if (!ret)
0335         ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
0336                         36 * sizeof(u64), -1);
0337 
0338     return ret;
0339 }
0340 
0341 static int fpregs64_get(struct task_struct *target,
0342             const struct user_regset *regset,
0343             struct membuf to)
0344 {
0345     struct thread_info *t = task_thread_info(target);
0346     unsigned long fprs;
0347 
0348     if (target == current)
0349         save_and_clear_fpu();
0350 
0351     fprs = t->fpsaved[0];
0352 
0353     if (fprs & FPRS_DL)
0354         membuf_write(&to, t->fpregs, 16 * sizeof(u64));
0355     else
0356         membuf_zero(&to, 16 * sizeof(u64));
0357 
0358     if (fprs & FPRS_DU)
0359         membuf_write(&to, t->fpregs + 16, 16 * sizeof(u64));
0360     else
0361         membuf_zero(&to, 16 * sizeof(u64));
0362     if (fprs & FPRS_FEF) {
0363         membuf_store(&to, t->xfsr[0]);
0364         membuf_store(&to, t->gsr[0]);
0365     } else {
0366         membuf_zero(&to, 2 * sizeof(u64));
0367     }
0368     return membuf_store(&to, fprs);
0369 }
0370 
0371 static int fpregs64_set(struct task_struct *target,
0372             const struct user_regset *regset,
0373             unsigned int pos, unsigned int count,
0374             const void *kbuf, const void __user *ubuf)
0375 {
0376     unsigned long *fpregs = task_thread_info(target)->fpregs;
0377     unsigned long fprs;
0378     int ret;
0379 
0380     if (target == current)
0381         save_and_clear_fpu();
0382 
0383     ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
0384                  fpregs,
0385                  0, 32 * sizeof(u64));
0386     if (!ret)
0387         ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
0388                      task_thread_info(target)->xfsr,
0389                      32 * sizeof(u64),
0390                      33 * sizeof(u64));
0391     if (!ret)
0392         ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
0393                      task_thread_info(target)->gsr,
0394                      33 * sizeof(u64),
0395                      34 * sizeof(u64));
0396 
0397     fprs = task_thread_info(target)->fpsaved[0];
0398     if (!ret && count > 0) {
0399         ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
0400                      &fprs,
0401                      34 * sizeof(u64),
0402                      35 * sizeof(u64));
0403     }
0404 
0405     fprs |= (FPRS_FEF | FPRS_DL | FPRS_DU);
0406     task_thread_info(target)->fpsaved[0] = fprs;
0407 
0408     if (!ret)
0409         ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
0410                         35 * sizeof(u64), -1);
0411     return ret;
0412 }
0413 
0414 static const struct user_regset sparc64_regsets[] = {
0415     /* Format is:
0416      *  G0 --> G7
0417      *  O0 --> O7
0418      *  L0 --> L7
0419      *  I0 --> I7
0420      *  TSTATE, TPC, TNPC, Y
0421      */
0422     [REGSET_GENERAL] = {
0423         .core_note_type = NT_PRSTATUS,
0424         .n = 36,
0425         .size = sizeof(u64), .align = sizeof(u64),
0426         .regset_get = genregs64_get, .set = genregs64_set
0427     },
0428     /* Format is:
0429      *  F0 --> F63
0430      *  FSR
0431      *  GSR
0432      *  FPRS
0433      */
0434     [REGSET_FP] = {
0435         .core_note_type = NT_PRFPREG,
0436         .n = 35,
0437         .size = sizeof(u64), .align = sizeof(u64),
0438         .regset_get = fpregs64_get, .set = fpregs64_set
0439     },
0440 };
0441 
0442 static int getregs64_get(struct task_struct *target,
0443              const struct user_regset *regset,
0444              struct membuf to)
0445 {
0446     const struct pt_regs *regs = task_pt_regs(target);
0447 
0448     if (target == current)
0449         flushw_user();
0450 
0451     membuf_write(&to, regs->u_regs + 1, 15 * sizeof(u64));
0452     membuf_store(&to, (u64)0);
0453     membuf_write(&to, &regs->tstate, 3 * sizeof(u64));
0454     return membuf_store(&to, (u64)regs->y);
0455 }
0456 
0457 static int setregs64_set(struct task_struct *target,
0458              const struct user_regset *regset,
0459              unsigned int pos, unsigned int count,
0460              const void *kbuf, const void __user *ubuf)
0461 {
0462     struct pt_regs *regs = task_pt_regs(target);
0463     unsigned long y = regs->y;
0464     unsigned long tstate;
0465     int ret;
0466 
0467     if (target == current)
0468         flushw_user();
0469 
0470     ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
0471                  regs->u_regs + 1,
0472                  0 * sizeof(u64),
0473                  15 * sizeof(u64));
0474     if (ret)
0475         return ret;
0476     ret =user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
0477                  15 * sizeof(u64), 16 * sizeof(u64));
0478     if (ret)
0479         return ret;
0480     /* TSTATE */
0481     ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
0482                  &tstate,
0483                  16 * sizeof(u64),
0484                  17 * sizeof(u64));
0485     if (ret)
0486         return ret;
0487     /* Only the condition codes and the "in syscall"
0488      * state can be modified in the %tstate register.
0489      */
0490     tstate &= (TSTATE_ICC | TSTATE_XCC | TSTATE_SYSCALL);
0491     regs->tstate &= ~(TSTATE_ICC | TSTATE_XCC | TSTATE_SYSCALL);
0492     regs->tstate |= tstate;
0493 
0494     /* TPC, TNPC */
0495     ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
0496                  &regs->tpc,
0497                  17 * sizeof(u64),
0498                  19 * sizeof(u64));
0499     if (ret)
0500         return ret;
0501     /* Y */
0502     ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
0503                  &y,
0504                  19 * sizeof(u64),
0505                  20 * sizeof(u64));
0506     if (!ret)
0507         regs->y = y;
0508     return ret;
0509 }
0510 
0511 static const struct user_regset ptrace64_regsets[] = {
0512     /* Format is:
0513      *      G1 --> G7
0514      *      O0 --> O7
0515      *  0
0516      *      TSTATE, TPC, TNPC, Y
0517      */
0518     [REGSET_GENERAL] = {
0519         .n = 20, .size = sizeof(u64),
0520         .regset_get = getregs64_get, .set = setregs64_set,
0521     },
0522 };
0523 
0524 static const struct user_regset_view ptrace64_view = {
0525     .regsets = ptrace64_regsets, .n = ARRAY_SIZE(ptrace64_regsets)
0526 };
0527 
0528 static const struct user_regset_view user_sparc64_view = {
0529     .name = "sparc64", .e_machine = EM_SPARCV9,
0530     .regsets = sparc64_regsets, .n = ARRAY_SIZE(sparc64_regsets)
0531 };
0532 
0533 #ifdef CONFIG_COMPAT
0534 static int genregs32_get(struct task_struct *target,
0535              const struct user_regset *regset,
0536              struct membuf to)
0537 {
0538     const struct pt_regs *regs = task_pt_regs(target);
0539     u32 uregs[16];
0540     int i;
0541 
0542     if (target == current)
0543         flushw_user();
0544 
0545     for (i = 0; i < 16; i++)
0546         membuf_store(&to, (u32)regs->u_regs[i]);
0547     if (!to.left)
0548         return 0;
0549     if (get_from_target(target, regs->u_regs[UREG_I6],
0550                 uregs, sizeof(uregs)))
0551         return -EFAULT;
0552     membuf_write(&to, uregs, 16 * sizeof(u32));
0553     membuf_store(&to, (u32)tstate_to_psr(regs->tstate));
0554     membuf_store(&to, (u32)(regs->tpc));
0555     membuf_store(&to, (u32)(regs->tnpc));
0556     membuf_store(&to, (u32)(regs->y));
0557     return membuf_zero(&to, 2 * sizeof(u32));
0558 }
0559 
0560 static int genregs32_set(struct task_struct *target,
0561              const struct user_regset *regset,
0562              unsigned int pos, unsigned int count,
0563              const void *kbuf, const void __user *ubuf)
0564 {
0565     struct pt_regs *regs = task_pt_regs(target);
0566     compat_ulong_t __user *reg_window;
0567     const compat_ulong_t *k = kbuf;
0568     const compat_ulong_t __user *u = ubuf;
0569     compat_ulong_t reg;
0570 
0571     if (target == current)
0572         flushw_user();
0573 
0574     pos /= sizeof(reg);
0575     count /= sizeof(reg);
0576 
0577     if (kbuf) {
0578         for (; count > 0 && pos < 16; count--)
0579             regs->u_regs[pos++] = *k++;
0580 
0581         reg_window = (compat_ulong_t __user *) regs->u_regs[UREG_I6];
0582         reg_window -= 16;
0583         if (target == current) {
0584             for (; count > 0 && pos < 32; count--) {
0585                 if (put_user(*k++, &reg_window[pos++]))
0586                     return -EFAULT;
0587             }
0588         } else {
0589             for (; count > 0 && pos < 32; count--) {
0590                 if (access_process_vm(target,
0591                               (unsigned long)
0592                               &reg_window[pos],
0593                               (void *) k,
0594                               sizeof(*k),
0595                               FOLL_FORCE | FOLL_WRITE)
0596                     != sizeof(*k))
0597                     return -EFAULT;
0598                 k++;
0599                 pos++;
0600             }
0601         }
0602     } else {
0603         for (; count > 0 && pos < 16; count--) {
0604             if (get_user(reg, u++))
0605                 return -EFAULT;
0606             regs->u_regs[pos++] = reg;
0607         }
0608 
0609         reg_window = (compat_ulong_t __user *) regs->u_regs[UREG_I6];
0610         reg_window -= 16;
0611         if (target == current) {
0612             for (; count > 0 && pos < 32; count--) {
0613                 if (get_user(reg, u++) ||
0614                     put_user(reg, &reg_window[pos++]))
0615                     return -EFAULT;
0616             }
0617         } else {
0618             for (; count > 0 && pos < 32; count--) {
0619                 if (get_user(reg, u++))
0620                     return -EFAULT;
0621                 if (access_process_vm(target,
0622                               (unsigned long)
0623                               &reg_window[pos],
0624                               &reg, sizeof(reg),
0625                               FOLL_FORCE | FOLL_WRITE)
0626                     != sizeof(reg))
0627                     return -EFAULT;
0628                 pos++;
0629                 u++;
0630             }
0631         }
0632     }
0633     while (count > 0) {
0634         unsigned long tstate;
0635 
0636         if (kbuf)
0637             reg = *k++;
0638         else if (get_user(reg, u++))
0639             return -EFAULT;
0640 
0641         switch (pos) {
0642         case 32: /* PSR */
0643             tstate = regs->tstate;
0644             tstate &= ~(TSTATE_ICC | TSTATE_XCC | TSTATE_SYSCALL);
0645             tstate |= psr_to_tstate_icc(reg);
0646             if (reg & PSR_SYSCALL)
0647                 tstate |= TSTATE_SYSCALL;
0648             regs->tstate = tstate;
0649             break;
0650         case 33: /* PC */
0651             regs->tpc = reg;
0652             break;
0653         case 34: /* NPC */
0654             regs->tnpc = reg;
0655             break;
0656         case 35: /* Y */
0657             regs->y = reg;
0658             break;
0659         case 36: /* WIM */
0660         case 37: /* TBR */
0661             break;
0662         default:
0663             goto finish;
0664         }
0665 
0666         pos++;
0667         count--;
0668     }
0669 finish:
0670     pos *= sizeof(reg);
0671     count *= sizeof(reg);
0672 
0673     return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
0674                      38 * sizeof(reg), -1);
0675 }
0676 
0677 static int fpregs32_get(struct task_struct *target,
0678             const struct user_regset *regset,
0679             struct membuf to)
0680 {
0681     struct thread_info *t = task_thread_info(target);
0682     bool enabled;
0683 
0684     if (target == current)
0685         save_and_clear_fpu();
0686 
0687     enabled = t->fpsaved[0] & FPRS_FEF;
0688 
0689     membuf_write(&to, t->fpregs, 32 * sizeof(u32));
0690     membuf_zero(&to, sizeof(u32));
0691     if (enabled)
0692         membuf_store(&to, (u32)t->xfsr[0]);
0693     else
0694         membuf_zero(&to, sizeof(u32));
0695     membuf_store(&to, (u32)((enabled << 8) | (8 << 16)));
0696     return membuf_zero(&to, 64 * sizeof(u32));
0697 }
0698 
0699 static int fpregs32_set(struct task_struct *target,
0700             const struct user_regset *regset,
0701             unsigned int pos, unsigned int count,
0702             const void *kbuf, const void __user *ubuf)
0703 {
0704     unsigned long *fpregs = task_thread_info(target)->fpregs;
0705     unsigned long fprs;
0706     int ret;
0707 
0708     if (target == current)
0709         save_and_clear_fpu();
0710 
0711     fprs = task_thread_info(target)->fpsaved[0];
0712 
0713     ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
0714                  fpregs,
0715                  0, 32 * sizeof(u32));
0716     if (!ret)
0717         user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
0718                       32 * sizeof(u32),
0719                       33 * sizeof(u32));
0720     if (!ret && count > 0) {
0721         compat_ulong_t fsr;
0722         unsigned long val;
0723 
0724         ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
0725                      &fsr,
0726                      33 * sizeof(u32),
0727                      34 * sizeof(u32));
0728         if (!ret) {
0729             val = task_thread_info(target)->xfsr[0];
0730             val &= 0xffffffff00000000UL;
0731             val |= fsr;
0732             task_thread_info(target)->xfsr[0] = val;
0733         }
0734     }
0735 
0736     fprs |= (FPRS_FEF | FPRS_DL);
0737     task_thread_info(target)->fpsaved[0] = fprs;
0738 
0739     if (!ret)
0740         ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
0741                         34 * sizeof(u32), -1);
0742     return ret;
0743 }
0744 
0745 static const struct user_regset sparc32_regsets[] = {
0746     /* Format is:
0747      *  G0 --> G7
0748      *  O0 --> O7
0749      *  L0 --> L7
0750      *  I0 --> I7
0751      *  PSR, PC, nPC, Y, WIM, TBR
0752      */
0753     [REGSET_GENERAL] = {
0754         .core_note_type = NT_PRSTATUS,
0755         .n = 38,
0756         .size = sizeof(u32), .align = sizeof(u32),
0757         .regset_get = genregs32_get, .set = genregs32_set
0758     },
0759     /* Format is:
0760      *  F0 --> F31
0761      *  empty 32-bit word
0762      *  FSR (32--bit word)
0763      *  FPU QUEUE COUNT (8-bit char)
0764      *  FPU QUEUE ENTRYSIZE (8-bit char)
0765      *  FPU ENABLED (8-bit char)
0766      *  empty 8-bit char
0767      *  FPU QUEUE (64 32-bit ints)
0768      */
0769     [REGSET_FP] = {
0770         .core_note_type = NT_PRFPREG,
0771         .n = 99,
0772         .size = sizeof(u32), .align = sizeof(u32),
0773         .regset_get = fpregs32_get, .set = fpregs32_set
0774     },
0775 };
0776 
0777 static int getregs_get(struct task_struct *target,
0778              const struct user_regset *regset,
0779              struct membuf to)
0780 {
0781     const struct pt_regs *regs = task_pt_regs(target);
0782     int i;
0783 
0784     if (target == current)
0785         flushw_user();
0786 
0787     membuf_store(&to, (u32)tstate_to_psr(regs->tstate));
0788     membuf_store(&to, (u32)(regs->tpc));
0789     membuf_store(&to, (u32)(regs->tnpc));
0790     membuf_store(&to, (u32)(regs->y));
0791     for (i = 1; i < 16; i++)
0792         membuf_store(&to, (u32)regs->u_regs[i]);
0793     return to.left;
0794 }
0795 
0796 static int setregs_set(struct task_struct *target,
0797              const struct user_regset *regset,
0798              unsigned int pos, unsigned int count,
0799              const void *kbuf, const void __user *ubuf)
0800 {
0801     struct pt_regs *regs = task_pt_regs(target);
0802     unsigned long tstate;
0803     u32 uregs[19];
0804     int i, ret;
0805 
0806     if (target == current)
0807         flushw_user();
0808 
0809     ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
0810                  uregs,
0811                  0, 19 * sizeof(u32));
0812     if (ret)
0813         return ret;
0814 
0815     tstate = regs->tstate;
0816     tstate &= ~(TSTATE_ICC | TSTATE_XCC | TSTATE_SYSCALL);
0817     tstate |= psr_to_tstate_icc(uregs[0]);
0818     if (uregs[0] & PSR_SYSCALL)
0819         tstate |= TSTATE_SYSCALL;
0820     regs->tstate = tstate;
0821     regs->tpc = uregs[1];
0822     regs->tnpc = uregs[2];
0823     regs->y = uregs[3];
0824 
0825     for (i = 1; i < 15; i++)
0826         regs->u_regs[i] = uregs[3 + i];
0827     return 0;
0828 }
0829 
0830 static int getfpregs_get(struct task_struct *target,
0831             const struct user_regset *regset,
0832             struct membuf to)
0833 {
0834     struct thread_info *t = task_thread_info(target);
0835 
0836     if (target == current)
0837         save_and_clear_fpu();
0838 
0839     membuf_write(&to, t->fpregs, 32 * sizeof(u32));
0840     if (t->fpsaved[0] & FPRS_FEF)
0841         membuf_store(&to, (u32)t->xfsr[0]);
0842     else
0843         membuf_zero(&to, sizeof(u32));
0844     return membuf_zero(&to, 35 * sizeof(u32));
0845 }
0846 
0847 static int setfpregs_set(struct task_struct *target,
0848             const struct user_regset *regset,
0849             unsigned int pos, unsigned int count,
0850             const void *kbuf, const void __user *ubuf)
0851 {
0852     unsigned long *fpregs = task_thread_info(target)->fpregs;
0853     unsigned long fprs;
0854     int ret;
0855 
0856     if (target == current)
0857         save_and_clear_fpu();
0858 
0859     fprs = task_thread_info(target)->fpsaved[0];
0860 
0861     ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
0862                  fpregs,
0863                  0, 32 * sizeof(u32));
0864     if (!ret) {
0865         compat_ulong_t fsr;
0866         unsigned long val;
0867 
0868         ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
0869                      &fsr,
0870                      32 * sizeof(u32),
0871                      33 * sizeof(u32));
0872         if (!ret) {
0873             val = task_thread_info(target)->xfsr[0];
0874             val &= 0xffffffff00000000UL;
0875             val |= fsr;
0876             task_thread_info(target)->xfsr[0] = val;
0877         }
0878     }
0879 
0880     fprs |= (FPRS_FEF | FPRS_DL);
0881     task_thread_info(target)->fpsaved[0] = fprs;
0882     return ret;
0883 }
0884 
0885 static const struct user_regset ptrace32_regsets[] = {
0886     [REGSET_GENERAL] = {
0887         .n = 19, .size = sizeof(u32),
0888         .regset_get = getregs_get, .set = setregs_set,
0889     },
0890     [REGSET_FP] = {
0891         .n = 68, .size = sizeof(u32),
0892         .regset_get = getfpregs_get, .set = setfpregs_set,
0893     },
0894 };
0895 
0896 static const struct user_regset_view ptrace32_view = {
0897     .regsets = ptrace32_regsets, .n = ARRAY_SIZE(ptrace32_regsets)
0898 };
0899 
0900 static const struct user_regset_view user_sparc32_view = {
0901     .name = "sparc", .e_machine = EM_SPARC,
0902     .regsets = sparc32_regsets, .n = ARRAY_SIZE(sparc32_regsets)
0903 };
0904 #endif /* CONFIG_COMPAT */
0905 
0906 const struct user_regset_view *task_user_regset_view(struct task_struct *task)
0907 {
0908 #ifdef CONFIG_COMPAT
0909     if (test_tsk_thread_flag(task, TIF_32BIT))
0910         return &user_sparc32_view;
0911 #endif
0912     return &user_sparc64_view;
0913 }
0914 
0915 #ifdef CONFIG_COMPAT
0916 struct compat_fps {
0917     unsigned int regs[32];
0918     unsigned int fsr;
0919     unsigned int flags;
0920     unsigned int extra;
0921     unsigned int fpqd;
0922     struct compat_fq {
0923         unsigned int insnaddr;
0924         unsigned int insn;
0925     } fpq[16];
0926 };
0927 
0928 long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
0929             compat_ulong_t caddr, compat_ulong_t cdata)
0930 {
0931     compat_ulong_t caddr2 = task_pt_regs(current)->u_regs[UREG_I4];
0932     struct pt_regs32 __user *pregs;
0933     struct compat_fps __user *fps;
0934     unsigned long addr2 = caddr2;
0935     unsigned long addr = caddr;
0936     unsigned long data = cdata;
0937     int ret;
0938 
0939     pregs = (struct pt_regs32 __user *) addr;
0940     fps = (struct compat_fps __user *) addr;
0941 
0942     switch (request) {
0943     case PTRACE_PEEKUSR:
0944         ret = (addr != 0) ? -EIO : 0;
0945         break;
0946 
0947     case PTRACE_GETREGS:
0948         ret = copy_regset_to_user(child, &ptrace32_view,
0949                       REGSET_GENERAL, 0,
0950                       19 * sizeof(u32),
0951                       pregs);
0952         break;
0953 
0954     case PTRACE_SETREGS:
0955         ret = copy_regset_from_user(child, &ptrace32_view,
0956                       REGSET_GENERAL, 0,
0957                       19 * sizeof(u32),
0958                       pregs);
0959         break;
0960 
0961     case PTRACE_GETFPREGS:
0962         ret = copy_regset_to_user(child, &ptrace32_view,
0963                       REGSET_FP, 0,
0964                       68 * sizeof(u32),
0965                       fps);
0966         break;
0967 
0968     case PTRACE_SETFPREGS:
0969         ret = copy_regset_from_user(child, &ptrace32_view,
0970                       REGSET_FP, 0,
0971                       33 * sizeof(u32),
0972                       fps);
0973         break;
0974 
0975     case PTRACE_READTEXT:
0976     case PTRACE_READDATA:
0977         ret = ptrace_readdata(child, addr,
0978                       (char __user *)addr2, data);
0979         if (ret == data)
0980             ret = 0;
0981         else if (ret >= 0)
0982             ret = -EIO;
0983         break;
0984 
0985     case PTRACE_WRITETEXT:
0986     case PTRACE_WRITEDATA:
0987         ret = ptrace_writedata(child, (char __user *) addr2,
0988                        addr, data);
0989         if (ret == data)
0990             ret = 0;
0991         else if (ret >= 0)
0992             ret = -EIO;
0993         break;
0994 
0995     default:
0996         if (request == PTRACE_SPARC_DETACH)
0997             request = PTRACE_DETACH;
0998         ret = compat_ptrace_request(child, request, addr, data);
0999         break;
1000     }
1001 
1002     return ret;
1003 }
1004 #endif /* CONFIG_COMPAT */
1005 
1006 struct fps {
1007     unsigned int regs[64];
1008     unsigned long fsr;
1009 };
1010 
1011 long arch_ptrace(struct task_struct *child, long request,
1012          unsigned long addr, unsigned long data)
1013 {
1014     const struct user_regset_view *view = task_user_regset_view(current);
1015     unsigned long addr2 = task_pt_regs(current)->u_regs[UREG_I4];
1016     struct pt_regs __user *pregs;
1017     struct fps __user *fps;
1018     void __user *addr2p;
1019     int ret;
1020 
1021     pregs = (struct pt_regs __user *) addr;
1022     fps = (struct fps __user *) addr;
1023     addr2p = (void __user *) addr2;
1024 
1025     switch (request) {
1026     case PTRACE_PEEKUSR:
1027         ret = (addr != 0) ? -EIO : 0;
1028         break;
1029 
1030     case PTRACE_GETREGS64:
1031         ret = copy_regset_to_user(child, &ptrace64_view,
1032                       REGSET_GENERAL, 0,
1033                       19 * sizeof(u64),
1034                       pregs);
1035         break;
1036 
1037     case PTRACE_SETREGS64:
1038         ret = copy_regset_from_user(child, &ptrace64_view,
1039                       REGSET_GENERAL, 0,
1040                       19 * sizeof(u64),
1041                       pregs);
1042         break;
1043 
1044     case PTRACE_GETFPREGS64:
1045         ret = copy_regset_to_user(child, view, REGSET_FP,
1046                       0 * sizeof(u64),
1047                       33 * sizeof(u64),
1048                       fps);
1049         break;
1050 
1051     case PTRACE_SETFPREGS64:
1052         ret = copy_regset_from_user(child, view, REGSET_FP,
1053                       0 * sizeof(u64),
1054                       33 * sizeof(u64),
1055                       fps);
1056         break;
1057 
1058     case PTRACE_READTEXT:
1059     case PTRACE_READDATA:
1060         ret = ptrace_readdata(child, addr, addr2p, data);
1061         if (ret == data)
1062             ret = 0;
1063         else if (ret >= 0)
1064             ret = -EIO;
1065         break;
1066 
1067     case PTRACE_WRITETEXT:
1068     case PTRACE_WRITEDATA:
1069         ret = ptrace_writedata(child, addr2p, addr, data);
1070         if (ret == data)
1071             ret = 0;
1072         else if (ret >= 0)
1073             ret = -EIO;
1074         break;
1075 
1076     default:
1077         if (request == PTRACE_SPARC_DETACH)
1078             request = PTRACE_DETACH;
1079         ret = ptrace_request(child, request, addr, data);
1080         break;
1081     }
1082 
1083     return ret;
1084 }
1085 
1086 asmlinkage int syscall_trace_enter(struct pt_regs *regs)
1087 {
1088     int ret = 0;
1089 
1090     /* do the secure computing check first */
1091     secure_computing_strict(regs->u_regs[UREG_G1]);
1092 
1093     if (test_thread_flag(TIF_NOHZ))
1094         user_exit();
1095 
1096     if (test_thread_flag(TIF_SYSCALL_TRACE))
1097         ret = ptrace_report_syscall_entry(regs);
1098 
1099     if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
1100         trace_sys_enter(regs, regs->u_regs[UREG_G1]);
1101 
1102     audit_syscall_entry(regs->u_regs[UREG_G1], regs->u_regs[UREG_I0],
1103                 regs->u_regs[UREG_I1], regs->u_regs[UREG_I2],
1104                 regs->u_regs[UREG_I3]);
1105 
1106     return ret;
1107 }
1108 
1109 asmlinkage void syscall_trace_leave(struct pt_regs *regs)
1110 {
1111     if (test_thread_flag(TIF_NOHZ))
1112         user_exit();
1113 
1114     audit_syscall_exit(regs);
1115 
1116     if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
1117         trace_sys_exit(regs, regs->u_regs[UREG_I0]);
1118 
1119     if (test_thread_flag(TIF_SYSCALL_TRACE))
1120         ptrace_report_syscall_exit(regs, 0);
1121 
1122     if (test_thread_flag(TIF_NOHZ))
1123         user_enter();
1124 }
1125 
1126 /**
1127  * regs_query_register_offset() - query register offset from its name
1128  * @name:   the name of a register
1129  *
1130  * regs_query_register_offset() returns the offset of a register in struct
1131  * pt_regs from its name. If the name is invalid, this returns -EINVAL;
1132  */
1133 int regs_query_register_offset(const char *name)
1134 {
1135     const struct pt_regs_offset *roff;
1136 
1137     for (roff = regoffset_table; roff->name != NULL; roff++)
1138         if (!strcmp(roff->name, name))
1139             return roff->offset;
1140     return -EINVAL;
1141 }
1142 
1143 /**
1144  * regs_within_kernel_stack() - check the address in the stack
1145  * @regs:   pt_regs which contains kernel stack pointer.
1146  * @addr:   address which is checked.
1147  *
1148  * regs_within_kernel_stack() checks @addr is within the kernel stack page(s).
1149  * If @addr is within the kernel stack, it returns true. If not, returns false.
1150  */
1151 static inline int regs_within_kernel_stack(struct pt_regs *regs,
1152                        unsigned long addr)
1153 {
1154     unsigned long ksp = kernel_stack_pointer(regs) + STACK_BIAS;
1155     return ((addr & ~(THREAD_SIZE - 1))  ==
1156         (ksp & ~(THREAD_SIZE - 1)));
1157 }
1158 
1159 /**
1160  * regs_get_kernel_stack_nth() - get Nth entry of the stack
1161  * @regs:   pt_regs which contains kernel stack pointer.
1162  * @n:      stack entry number.
1163  *
1164  * regs_get_kernel_stack_nth() returns @n th entry of the kernel stack which
1165  * is specified by @regs. If the @n th entry is NOT in the kernel stack,
1166  * this returns 0.
1167  */
1168 unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, unsigned int n)
1169 {
1170     unsigned long ksp = kernel_stack_pointer(regs) + STACK_BIAS;
1171     unsigned long *addr = (unsigned long *)ksp;
1172     addr += n;
1173     if (regs_within_kernel_stack(regs, (unsigned long)addr))
1174         return *addr;
1175     else
1176         return 0;
1177 }