This source file includes following definitions.
- ptrace_disable
- user_disable_single_step
- user_enable_single_step
- user_enable_block_step
- arch_ptrace
- translate_usr_offset
- compat_arch_ptrace
- do_syscall_trace_enter
- do_syscall_trace_exit
- fpr_get
- fpr_set
- get_reg
- set_reg
- gpr_get
- gpr_set
- gpr32_get
- gpr32_set
- task_user_regset_view
- regs_query_register_offset
- regs_query_register_name
- regs_within_kernel_stack
- regs_get_kernel_stack_nth
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 #include <linux/kernel.h>
  12 #include <linux/sched.h>
  13 #include <linux/mm.h>
  14 #include <linux/smp.h>
  15 #include <linux/elf.h>
  16 #include <linux/errno.h>
  17 #include <linux/ptrace.h>
  18 #include <linux/tracehook.h>
  19 #include <linux/user.h>
  20 #include <linux/personality.h>
  21 #include <linux/regset.h>
  22 #include <linux/security.h>
  23 #include <linux/seccomp.h>
  24 #include <linux/compat.h>
  25 #include <linux/signal.h>
  26 #include <linux/audit.h>
  27 
  28 #include <linux/uaccess.h>
  29 #include <asm/pgtable.h>
  30 #include <asm/processor.h>
  31 #include <asm/asm-offsets.h>
  32 
  33 
  34 #define USER_PSW_BITS   (PSW_N | PSW_B | PSW_V | PSW_CB)
  35 
  36 #define CREATE_TRACE_POINTS
  37 #include <trace/events/syscalls.h>
  38 
  39 
  40 
  41 
  42 enum parisc_regset {
  43         REGSET_GENERAL,
  44         REGSET_FP
  45 };
  46 
  47 
  48 
  49 
  50 
  51 
  52 void ptrace_disable(struct task_struct *task)
  53 {
  54         clear_tsk_thread_flag(task, TIF_SINGLESTEP);
  55         clear_tsk_thread_flag(task, TIF_BLOCKSTEP);
  56 
  57         
  58         pa_psw(task)->r = 0;
  59         pa_psw(task)->t = 0;
  60         pa_psw(task)->h = 0;
  61         pa_psw(task)->l = 0;
  62 }
  63 
  64 
  65 
  66 
  67 
  68 void user_disable_single_step(struct task_struct *task)
  69 {
  70         ptrace_disable(task);
  71 }
  72 
  73 void user_enable_single_step(struct task_struct *task)
  74 {
  75         clear_tsk_thread_flag(task, TIF_BLOCKSTEP);
  76         set_tsk_thread_flag(task, TIF_SINGLESTEP);
  77 
  78         if (pa_psw(task)->n) {
  79                 
  80                 task_regs(task)->iaoq[0] = task_regs(task)->iaoq[1];
  81                 task_regs(task)->iasq[0] = task_regs(task)->iasq[1];
  82                 task_regs(task)->iaoq[1] = task_regs(task)->iaoq[0] + 4;
  83                 pa_psw(task)->n = 0;
  84                 pa_psw(task)->x = 0;
  85                 pa_psw(task)->y = 0;
  86                 pa_psw(task)->z = 0;
  87                 pa_psw(task)->b = 0;
  88                 ptrace_disable(task);
  89                 
  90 
  91                 force_sig_fault_to_task(SIGTRAP, TRAP_TRACE,
  92                                         (void __user *) (task_regs(task)->iaoq[0] & ~3),
  93                                         task);
  94                 
  95                 return;
  96         }
  97 
  98         
  99 
 100 
 101 
 102 
 103 
 104 
 105 
 106         pa_psw(task)->r = 1;
 107         pa_psw(task)->t = 0;
 108         pa_psw(task)->h = 0;
 109         pa_psw(task)->l = 0;
 110 }
 111 
 112 void user_enable_block_step(struct task_struct *task)
 113 {
 114         clear_tsk_thread_flag(task, TIF_SINGLESTEP);
 115         set_tsk_thread_flag(task, TIF_BLOCKSTEP);
 116 
 117         
 118         pa_psw(task)->r = 0;
 119         pa_psw(task)->t = 1;
 120         pa_psw(task)->h = 0;
 121         pa_psw(task)->l = 0;
 122 }
 123 
 124 long arch_ptrace(struct task_struct *child, long request,
 125                  unsigned long addr, unsigned long data)
 126 {
 127         unsigned long __user *datap = (unsigned long __user *)data;
 128         unsigned long tmp;
 129         long ret = -EIO;
 130 
 131         switch (request) {
 132 
 133         
 134 
 135         case PTRACE_PEEKUSR:
 136                 if ((addr & (sizeof(unsigned long)-1)) ||
 137                      addr >= sizeof(struct pt_regs))
 138                         break;
 139                 tmp = *(unsigned long *) ((char *) task_regs(child) + addr);
 140                 ret = put_user(tmp, datap);
 141                 break;
 142 
 143         
 144 
 145 
 146 
 147 
 148 
 149         case PTRACE_POKEUSR:
 150                 
 151 
 152 
 153 
 154                 if (addr == PT_PSW) {
 155                         
 156 
 157 
 158 
 159 
 160                         data &= USER_PSW_BITS;
 161                         task_regs(child)->gr[0] &= ~USER_PSW_BITS;
 162                         task_regs(child)->gr[0] |= data;
 163                         ret = 0;
 164                         break;
 165                 }
 166 
 167                 if ((addr & (sizeof(unsigned long)-1)) ||
 168                      addr >= sizeof(struct pt_regs))
 169                         break;
 170                 if (addr == PT_IAOQ0 || addr == PT_IAOQ1) {
 171                         data |= 3; 
 172                 }
 173                 if ((addr >= PT_GR1 && addr <= PT_GR31) ||
 174                                 addr == PT_IAOQ0 || addr == PT_IAOQ1 ||
 175                                 (addr >= PT_FR0 && addr <= PT_FR31 + 4) ||
 176                                 addr == PT_SAR) {
 177                         *(unsigned long *) ((char *) task_regs(child) + addr) = data;
 178                         ret = 0;
 179                 }
 180                 break;
 181 
 182         case PTRACE_GETREGS:    
 183                 return copy_regset_to_user(child,
 184                                            task_user_regset_view(current),
 185                                            REGSET_GENERAL,
 186                                            0, sizeof(struct user_regs_struct),
 187                                            datap);
 188 
 189         case PTRACE_SETREGS:    
 190                 return copy_regset_from_user(child,
 191                                              task_user_regset_view(current),
 192                                              REGSET_GENERAL,
 193                                              0, sizeof(struct user_regs_struct),
 194                                              datap);
 195 
 196         case PTRACE_GETFPREGS:  
 197                 return copy_regset_to_user(child,
 198                                            task_user_regset_view(current),
 199                                            REGSET_FP,
 200                                            0, sizeof(struct user_fp_struct),
 201                                            datap);
 202 
 203         case PTRACE_SETFPREGS:  
 204                 return copy_regset_from_user(child,
 205                                              task_user_regset_view(current),
 206                                              REGSET_FP,
 207                                              0, sizeof(struct user_fp_struct),
 208                                              datap);
 209 
 210         default:
 211                 ret = ptrace_request(child, request, addr, data);
 212                 break;
 213         }
 214 
 215         return ret;
 216 }
 217 
 218 
 219 #ifdef CONFIG_COMPAT
 220 
 221 
 222 
 223 
 224 
 225 
 226 
 227 
 228 
 229 
 230 
 231 
 232 static compat_ulong_t translate_usr_offset(compat_ulong_t offset)
 233 {
 234         compat_ulong_t pos;
 235 
 236         if (offset < 32*4)      
 237                 pos = offset * 2 + 4;
 238         else if (offset < 32*4+32*8)    
 239                 pos = (offset - 32*4) + PT_FR0;
 240         else if (offset < sizeof(struct pt_regs)/2 + 32*4) 
 241                 pos = (offset - 32*4 - 32*8) * 2 + PT_SR0 + 4;
 242         else
 243                 pos = sizeof(struct pt_regs);
 244 
 245         return pos;
 246 }
 247 
 248 long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
 249                         compat_ulong_t addr, compat_ulong_t data)
 250 {
 251         compat_uint_t tmp;
 252         long ret = -EIO;
 253 
 254         switch (request) {
 255 
 256         case PTRACE_PEEKUSR:
 257                 if (addr & (sizeof(compat_uint_t)-1))
 258                         break;
 259                 addr = translate_usr_offset(addr);
 260                 if (addr >= sizeof(struct pt_regs))
 261                         break;
 262 
 263                 tmp = *(compat_uint_t *) ((char *) task_regs(child) + addr);
 264                 ret = put_user(tmp, (compat_uint_t *) (unsigned long) data);
 265                 break;
 266 
 267         
 268 
 269 
 270 
 271 
 272 
 273         case PTRACE_POKEUSR:
 274                 
 275 
 276 
 277 
 278                 if (addr == PT_PSW) {
 279                         
 280 
 281 
 282                         ret = arch_ptrace(child, request, addr, data);
 283                 } else {
 284                         if (addr & (sizeof(compat_uint_t)-1))
 285                                 break;
 286                         addr = translate_usr_offset(addr);
 287                         if (addr >= sizeof(struct pt_regs))
 288                                 break;
 289                         if (addr == PT_IAOQ0+4 || addr == PT_IAOQ1+4) {
 290                                 data |= 3; 
 291                         }
 292                         if (addr >= PT_FR0 && addr <= PT_FR31 + 4) {
 293                                 
 294                                 *(__u32 *) ((char *) task_regs(child) + addr) = data;
 295                                 ret = 0;
 296                         }
 297                         else if ((addr >= PT_GR1+4 && addr <= PT_GR31+4) ||
 298                                         addr == PT_IAOQ0+4 || addr == PT_IAOQ1+4 ||
 299                                         addr == PT_SAR+4) {
 300                                 
 301                                 *(__u32 *) ((char *) task_regs(child) + addr - 4) = 0;
 302                                 *(__u32 *) ((char *) task_regs(child) + addr) = data;
 303                                 ret = 0;
 304                         }
 305                 }
 306                 break;
 307 
 308         default:
 309                 ret = compat_ptrace_request(child, request, addr, data);
 310                 break;
 311         }
 312 
 313         return ret;
 314 }
 315 #endif
 316 
 317 long do_syscall_trace_enter(struct pt_regs *regs)
 318 {
 319         if (test_thread_flag(TIF_SYSCALL_TRACE)) {
 320                 int rc = tracehook_report_syscall_entry(regs);
 321 
 322                 
 323 
 324 
 325 
 326                 regs->gr[28] = -ENOSYS;
 327 
 328                 if (rc) {
 329                         
 330 
 331 
 332 
 333 
 334 
 335 
 336 
 337 
 338 
 339                         regs->gr[20] = -1UL;
 340                         return -1;
 341                 }
 342         }
 343 
 344         
 345         if (secure_computing(NULL) == -1)
 346                 return -1;
 347 
 348 #ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS
 349         if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
 350                 trace_sys_enter(regs, regs->gr[20]);
 351 #endif
 352 
 353 #ifdef CONFIG_64BIT
 354         if (!is_compat_task())
 355                 audit_syscall_entry(regs->gr[20], regs->gr[26], regs->gr[25],
 356                                     regs->gr[24], regs->gr[23]);
 357         else
 358 #endif
 359                 audit_syscall_entry(regs->gr[20] & 0xffffffff,
 360                         regs->gr[26] & 0xffffffff,
 361                         regs->gr[25] & 0xffffffff,
 362                         regs->gr[24] & 0xffffffff,
 363                         regs->gr[23] & 0xffffffff);
 364 
 365         
 366 
 367 
 368 
 369         return (int) ((u32) regs->gr[20]);
 370 }
 371 
 372 void do_syscall_trace_exit(struct pt_regs *regs)
 373 {
 374         int stepping = test_thread_flag(TIF_SINGLESTEP) ||
 375                 test_thread_flag(TIF_BLOCKSTEP);
 376 
 377         audit_syscall_exit(regs);
 378 
 379 #ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS
 380         if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
 381                 trace_sys_exit(regs, regs->gr[20]);
 382 #endif
 383 
 384         if (stepping || test_thread_flag(TIF_SYSCALL_TRACE))
 385                 tracehook_report_syscall_exit(regs, stepping);
 386 }
 387 
 388 
 389 
 390 
 391 
 392 
 393 static int fpr_get(struct task_struct *target,
 394                      const struct user_regset *regset,
 395                      unsigned int pos, unsigned int count,
 396                      void *kbuf, void __user *ubuf)
 397 {
 398         struct pt_regs *regs = task_regs(target);
 399         __u64 *k = kbuf;
 400         __u64 __user *u = ubuf;
 401         __u64 reg;
 402 
 403         pos /= sizeof(reg);
 404         count /= sizeof(reg);
 405 
 406         if (kbuf)
 407                 for (; count > 0 && pos < ELF_NFPREG; --count)
 408                         *k++ = regs->fr[pos++];
 409         else
 410                 for (; count > 0 && pos < ELF_NFPREG; --count)
 411                         if (__put_user(regs->fr[pos++], u++))
 412                                 return -EFAULT;
 413 
 414         kbuf = k;
 415         ubuf = u;
 416         pos *= sizeof(reg);
 417         count *= sizeof(reg);
 418         return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
 419                                         ELF_NFPREG * sizeof(reg), -1);
 420 }
 421 
 422 static int fpr_set(struct task_struct *target,
 423                      const struct user_regset *regset,
 424                      unsigned int pos, unsigned int count,
 425                      const void *kbuf, const void __user *ubuf)
 426 {
 427         struct pt_regs *regs = task_regs(target);
 428         const __u64 *k = kbuf;
 429         const __u64 __user *u = ubuf;
 430         __u64 reg;
 431 
 432         pos /= sizeof(reg);
 433         count /= sizeof(reg);
 434 
 435         if (kbuf)
 436                 for (; count > 0 && pos < ELF_NFPREG; --count)
 437                         regs->fr[pos++] = *k++;
 438         else
 439                 for (; count > 0 && pos < ELF_NFPREG; --count) {
 440                         if (__get_user(reg, u++))
 441                                 return -EFAULT;
 442                         regs->fr[pos++] = reg;
 443                 }
 444 
 445         kbuf = k;
 446         ubuf = u;
 447         pos *= sizeof(reg);
 448         count *= sizeof(reg);
 449         return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
 450                                          ELF_NFPREG * sizeof(reg), -1);
 451 }
 452 
 453 #define RI(reg) (offsetof(struct user_regs_struct,reg) / sizeof(long))
 454 
 455 static unsigned long get_reg(struct pt_regs *regs, int num)
 456 {
 457         switch (num) {
 458         case RI(gr[0]) ... RI(gr[31]):  return regs->gr[num - RI(gr[0])];
 459         case RI(sr[0]) ... RI(sr[7]):   return regs->sr[num - RI(sr[0])];
 460         case RI(iasq[0]):               return regs->iasq[0];
 461         case RI(iasq[1]):               return regs->iasq[1];
 462         case RI(iaoq[0]):               return regs->iaoq[0];
 463         case RI(iaoq[1]):               return regs->iaoq[1];
 464         case RI(sar):                   return regs->sar;
 465         case RI(iir):                   return regs->iir;
 466         case RI(isr):                   return regs->isr;
 467         case RI(ior):                   return regs->ior;
 468         case RI(ipsw):                  return regs->ipsw;
 469         case RI(cr27):                  return regs->cr27;
 470         case RI(cr0):                   return mfctl(0);
 471         case RI(cr24):                  return mfctl(24);
 472         case RI(cr25):                  return mfctl(25);
 473         case RI(cr26):                  return mfctl(26);
 474         case RI(cr28):                  return mfctl(28);
 475         case RI(cr29):                  return mfctl(29);
 476         case RI(cr30):                  return mfctl(30);
 477         case RI(cr31):                  return mfctl(31);
 478         case RI(cr8):                   return mfctl(8);
 479         case RI(cr9):                   return mfctl(9);
 480         case RI(cr12):                  return mfctl(12);
 481         case RI(cr13):                  return mfctl(13);
 482         case RI(cr10):                  return mfctl(10);
 483         case RI(cr15):                  return mfctl(15);
 484         default:                        return 0;
 485         }
 486 }
 487 
 488 static void set_reg(struct pt_regs *regs, int num, unsigned long val)
 489 {
 490         switch (num) {
 491         case RI(gr[0]): 
 492 
 493 
 494 
 495 
 496 
 497 
 498                         val &= USER_PSW_BITS;
 499                         regs->gr[0] &= ~USER_PSW_BITS;
 500                         regs->gr[0] |= val;
 501                         return;
 502         case RI(gr[1]) ... RI(gr[31]):
 503                         regs->gr[num - RI(gr[0])] = val;
 504                         return;
 505         case RI(iaoq[0]):
 506         case RI(iaoq[1]):
 507                         
 508                         regs->iaoq[num - RI(iaoq[0])] = val | 3;
 509                         return;
 510         case RI(sar):   regs->sar = val;
 511                         return;
 512         default:        return;
 513 #if 0
 514         
 515         case RI(sr[0]) ... RI(sr[7]):   return regs->sr[num - RI(sr[0])];
 516         case RI(iasq[0]):               return regs->iasq[0];
 517         case RI(iasq[1]):               return regs->iasq[1];
 518         case RI(iir):                   return regs->iir;
 519         case RI(isr):                   return regs->isr;
 520         case RI(ior):                   return regs->ior;
 521         case RI(ipsw):                  return regs->ipsw;
 522         case RI(cr27):                  return regs->cr27;
 523         case cr0, cr24, cr25, cr26, cr27, cr28, cr29, cr30, cr31;
 524         case cr8, cr9, cr12, cr13, cr10, cr15;
 525 #endif
 526         }
 527 }
 528 
 529 static int gpr_get(struct task_struct *target,
 530                      const struct user_regset *regset,
 531                      unsigned int pos, unsigned int count,
 532                      void *kbuf, void __user *ubuf)
 533 {
 534         struct pt_regs *regs = task_regs(target);
 535         unsigned long *k = kbuf;
 536         unsigned long __user *u = ubuf;
 537         unsigned long reg;
 538 
 539         pos /= sizeof(reg);
 540         count /= sizeof(reg);
 541 
 542         if (kbuf)
 543                 for (; count > 0 && pos < ELF_NGREG; --count)
 544                         *k++ = get_reg(regs, pos++);
 545         else
 546                 for (; count > 0 && pos < ELF_NGREG; --count)
 547                         if (__put_user(get_reg(regs, pos++), u++))
 548                                 return -EFAULT;
 549         kbuf = k;
 550         ubuf = u;
 551         pos *= sizeof(reg);
 552         count *= sizeof(reg);
 553         return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
 554                                         ELF_NGREG * sizeof(reg), -1);
 555 }
 556 
 557 static int gpr_set(struct task_struct *target,
 558                      const struct user_regset *regset,
 559                      unsigned int pos, unsigned int count,
 560                      const void *kbuf, const void __user *ubuf)
 561 {
 562         struct pt_regs *regs = task_regs(target);
 563         const unsigned long *k = kbuf;
 564         const unsigned long __user *u = ubuf;
 565         unsigned long reg;
 566 
 567         pos /= sizeof(reg);
 568         count /= sizeof(reg);
 569 
 570         if (kbuf)
 571                 for (; count > 0 && pos < ELF_NGREG; --count)
 572                         set_reg(regs, pos++, *k++);
 573         else
 574                 for (; count > 0 && pos < ELF_NGREG; --count) {
 575                         if (__get_user(reg, u++))
 576                                 return -EFAULT;
 577                         set_reg(regs, pos++, reg);
 578                 }
 579 
 580         kbuf = k;
 581         ubuf = u;
 582         pos *= sizeof(reg);
 583         count *= sizeof(reg);
 584         return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
 585                                          ELF_NGREG * sizeof(reg), -1);
 586 }
 587 
 588 static const struct user_regset native_regsets[] = {
 589         [REGSET_GENERAL] = {
 590                 .core_note_type = NT_PRSTATUS, .n = ELF_NGREG,
 591                 .size = sizeof(long), .align = sizeof(long),
 592                 .get = gpr_get, .set = gpr_set
 593         },
 594         [REGSET_FP] = {
 595                 .core_note_type = NT_PRFPREG, .n = ELF_NFPREG,
 596                 .size = sizeof(__u64), .align = sizeof(__u64),
 597                 .get = fpr_get, .set = fpr_set
 598         }
 599 };
 600 
 601 static const struct user_regset_view user_parisc_native_view = {
 602         .name = "parisc", .e_machine = ELF_ARCH, .ei_osabi = ELFOSABI_LINUX,
 603         .regsets = native_regsets, .n = ARRAY_SIZE(native_regsets)
 604 };
 605 
 606 #ifdef CONFIG_64BIT
 607 #include <linux/compat.h>
 608 
 609 static int gpr32_get(struct task_struct *target,
 610                      const struct user_regset *regset,
 611                      unsigned int pos, unsigned int count,
 612                      void *kbuf, void __user *ubuf)
 613 {
 614         struct pt_regs *regs = task_regs(target);
 615         compat_ulong_t *k = kbuf;
 616         compat_ulong_t __user *u = ubuf;
 617         compat_ulong_t reg;
 618 
 619         pos /= sizeof(reg);
 620         count /= sizeof(reg);
 621 
 622         if (kbuf)
 623                 for (; count > 0 && pos < ELF_NGREG; --count)
 624                         *k++ = get_reg(regs, pos++);
 625         else
 626                 for (; count > 0 && pos < ELF_NGREG; --count)
 627                         if (__put_user((compat_ulong_t) get_reg(regs, pos++), u++))
 628                                 return -EFAULT;
 629 
 630         kbuf = k;
 631         ubuf = u;
 632         pos *= sizeof(reg);
 633         count *= sizeof(reg);
 634         return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
 635                                         ELF_NGREG * sizeof(reg), -1);
 636 }
 637 
 638 static int gpr32_set(struct task_struct *target,
 639                      const struct user_regset *regset,
 640                      unsigned int pos, unsigned int count,
 641                      const void *kbuf, const void __user *ubuf)
 642 {
 643         struct pt_regs *regs = task_regs(target);
 644         const compat_ulong_t *k = kbuf;
 645         const compat_ulong_t __user *u = ubuf;
 646         compat_ulong_t reg;
 647 
 648         pos /= sizeof(reg);
 649         count /= sizeof(reg);
 650 
 651         if (kbuf)
 652                 for (; count > 0 && pos < ELF_NGREG; --count)
 653                         set_reg(regs, pos++, *k++);
 654         else
 655                 for (; count > 0 && pos < ELF_NGREG; --count) {
 656                         if (__get_user(reg, u++))
 657                                 return -EFAULT;
 658                         set_reg(regs, pos++, reg);
 659                 }
 660 
 661         kbuf = k;
 662         ubuf = u;
 663         pos *= sizeof(reg);
 664         count *= sizeof(reg);
 665         return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
 666                                          ELF_NGREG * sizeof(reg), -1);
 667 }
 668 
 669 
 670 
 671 
 672 static const struct user_regset compat_regsets[] = {
 673         [REGSET_GENERAL] = {
 674                 .core_note_type = NT_PRSTATUS, .n = ELF_NGREG,
 675                 .size = sizeof(compat_long_t), .align = sizeof(compat_long_t),
 676                 .get = gpr32_get, .set = gpr32_set
 677         },
 678         [REGSET_FP] = {
 679                 .core_note_type = NT_PRFPREG, .n = ELF_NFPREG,
 680                 .size = sizeof(__u64), .align = sizeof(__u64),
 681                 .get = fpr_get, .set = fpr_set
 682         }
 683 };
 684 
 685 static const struct user_regset_view user_parisc_compat_view = {
 686         .name = "parisc", .e_machine = EM_PARISC, .ei_osabi = ELFOSABI_LINUX,
 687         .regsets = compat_regsets, .n = ARRAY_SIZE(compat_regsets)
 688 };
 689 #endif  
 690 
 691 const struct user_regset_view *task_user_regset_view(struct task_struct *task)
 692 {
 693         BUILD_BUG_ON(sizeof(struct user_regs_struct)/sizeof(long) != ELF_NGREG);
 694         BUILD_BUG_ON(sizeof(struct user_fp_struct)/sizeof(__u64) != ELF_NFPREG);
 695 #ifdef CONFIG_64BIT
 696         if (is_compat_task())
 697                 return &user_parisc_compat_view;
 698 #endif
 699         return &user_parisc_native_view;
 700 }
 701 
 702 
 703 
 704 
 705 struct pt_regs_offset {
 706         const char *name;
 707         int offset;
 708 };
 709 
 710 #define REG_OFFSET_NAME(r)    {.name = #r, .offset = offsetof(struct pt_regs, r)}
 711 #define REG_OFFSET_INDEX(r,i) {.name = #r#i, .offset = offsetof(struct pt_regs, r[i])}
 712 #define REG_OFFSET_END {.name = NULL, .offset = 0}
 713 
 714 static const struct pt_regs_offset regoffset_table[] = {
 715         REG_OFFSET_INDEX(gr,0),
 716         REG_OFFSET_INDEX(gr,1),
 717         REG_OFFSET_INDEX(gr,2),
 718         REG_OFFSET_INDEX(gr,3),
 719         REG_OFFSET_INDEX(gr,4),
 720         REG_OFFSET_INDEX(gr,5),
 721         REG_OFFSET_INDEX(gr,6),
 722         REG_OFFSET_INDEX(gr,7),
 723         REG_OFFSET_INDEX(gr,8),
 724         REG_OFFSET_INDEX(gr,9),
 725         REG_OFFSET_INDEX(gr,10),
 726         REG_OFFSET_INDEX(gr,11),
 727         REG_OFFSET_INDEX(gr,12),
 728         REG_OFFSET_INDEX(gr,13),
 729         REG_OFFSET_INDEX(gr,14),
 730         REG_OFFSET_INDEX(gr,15),
 731         REG_OFFSET_INDEX(gr,16),
 732         REG_OFFSET_INDEX(gr,17),
 733         REG_OFFSET_INDEX(gr,18),
 734         REG_OFFSET_INDEX(gr,19),
 735         REG_OFFSET_INDEX(gr,20),
 736         REG_OFFSET_INDEX(gr,21),
 737         REG_OFFSET_INDEX(gr,22),
 738         REG_OFFSET_INDEX(gr,23),
 739         REG_OFFSET_INDEX(gr,24),
 740         REG_OFFSET_INDEX(gr,25),
 741         REG_OFFSET_INDEX(gr,26),
 742         REG_OFFSET_INDEX(gr,27),
 743         REG_OFFSET_INDEX(gr,28),
 744         REG_OFFSET_INDEX(gr,29),
 745         REG_OFFSET_INDEX(gr,30),
 746         REG_OFFSET_INDEX(gr,31),
 747         REG_OFFSET_INDEX(sr,0),
 748         REG_OFFSET_INDEX(sr,1),
 749         REG_OFFSET_INDEX(sr,2),
 750         REG_OFFSET_INDEX(sr,3),
 751         REG_OFFSET_INDEX(sr,4),
 752         REG_OFFSET_INDEX(sr,5),
 753         REG_OFFSET_INDEX(sr,6),
 754         REG_OFFSET_INDEX(sr,7),
 755         REG_OFFSET_INDEX(iasq,0),
 756         REG_OFFSET_INDEX(iasq,1),
 757         REG_OFFSET_INDEX(iaoq,0),
 758         REG_OFFSET_INDEX(iaoq,1),
 759         REG_OFFSET_NAME(cr27),
 760         REG_OFFSET_NAME(ksp),
 761         REG_OFFSET_NAME(kpc),
 762         REG_OFFSET_NAME(sar),
 763         REG_OFFSET_NAME(iir),
 764         REG_OFFSET_NAME(isr),
 765         REG_OFFSET_NAME(ior),
 766         REG_OFFSET_NAME(ipsw),
 767         REG_OFFSET_END,
 768 };
 769 
 770 
 771 
 772 
 773 
 774 
 775 
 776 
 777 int regs_query_register_offset(const char *name)
 778 {
 779         const struct pt_regs_offset *roff;
 780         for (roff = regoffset_table; roff->name != NULL; roff++)
 781                 if (!strcmp(roff->name, name))
 782                         return roff->offset;
 783         return -EINVAL;
 784 }
 785 
 786 
 787 
 788 
 789 
 790 
 791 
 792 
 793 const char *regs_query_register_name(unsigned int offset)
 794 {
 795         const struct pt_regs_offset *roff;
 796         for (roff = regoffset_table; roff->name != NULL; roff++)
 797                 if (roff->offset == offset)
 798                         return roff->name;
 799         return NULL;
 800 }
 801 
 802 
 803 
 804 
 805 
 806 
 807 
 808 
 809 
 810 int regs_within_kernel_stack(struct pt_regs *regs, unsigned long addr)
 811 {
 812         return ((addr & ~(THREAD_SIZE - 1))  ==
 813                 (kernel_stack_pointer(regs) & ~(THREAD_SIZE - 1)));
 814 }
 815 
 816 
 817 
 818 
 819 
 820 
 821 
 822 
 823 
 824 
 825 unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, unsigned int n)
 826 {
 827         unsigned long *addr = (unsigned long *)kernel_stack_pointer(regs);
 828 
 829         addr -= n;
 830 
 831         if (!regs_within_kernel_stack(regs, (unsigned long)addr))
 832                 return 0;
 833 
 834         return *addr;
 835 }