Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6:
[SPARC32]: Use regsets in arch_ptrace().
[SPARC64]: Use regsets in arch_ptrace().
[SPARC32]: Use regsets for ELF core dumping.
[SPARC64]: Use regsets for ELF core dumping.
[SPARC64]: Remove unintentional ptrace debugging messages.
[SPARC]: Move over to arch_ptrace().
[SPARC]: Remove PTRACE_SUN* handling.
[SPARC]: Kill DEBUG_PTRACE code.
[SPARC32]: Add user regset support.
[SPARC64]: Add user regsets.
[SPARC64]: Fix booting on non-zero cpu.

+1096 -1019
-17
arch/sparc/kernel/entry.S
··· 1224 1224 call c_sys_nis_syscall 1225 1225 mov %l5, %o7 1226 1226 1227 - .align 4 1228 - .globl sys_ptrace 1229 - sys_ptrace: 1230 - call do_ptrace 1231 - add %sp, STACKFRAME_SZ, %o0 1232 - 1233 - ld [%curptr + TI_FLAGS], %l5 1234 - andcc %l5, _TIF_SYSCALL_TRACE, %g0 1235 - be 1f 1236 - nop 1237 - 1238 - call syscall_trace 1239 - nop 1240 - 1241 - 1: 1242 - RESTORE_ALL 1243 - 1244 1227 .align 4 1245 1228 .globl sys_execve 1246 1229 sys_execve:
+351 -484
arch/sparc/kernel/ptrace.c
··· 1 1 /* ptrace.c: Sparc process tracing support. 2 2 * 3 - * Copyright (C) 1996 David S. Miller (davem@caipfs.rutgers.edu) 3 + * Copyright (C) 1996, 2008 David S. Miller (davem@davemloft.net) 4 4 * 5 5 * Based upon code written by Ross Biro, Linus Torvalds, Bob Manson, 6 6 * and David Mosberger. ··· 19 19 #include <linux/smp_lock.h> 20 20 #include <linux/security.h> 21 21 #include <linux/signal.h> 22 + #include <linux/regset.h> 23 + #include <linux/elf.h> 22 24 23 25 #include <asm/pgtable.h> 24 26 #include <asm/system.h> 25 27 #include <asm/uaccess.h> 26 28 27 - #define MAGIC_CONSTANT 0x80000000 28 - 29 - 30 - /* Returning from ptrace is a bit tricky because the syscall return 31 - * low level code assumes any value returned which is negative and 32 - * is a valid errno will mean setting the condition codes to indicate 33 - * an error return. This doesn't work, so we have this hook. 34 - */ 35 - static inline void pt_error_return(struct pt_regs *regs, unsigned long error) 36 - { 37 - regs->u_regs[UREG_I0] = error; 38 - regs->psr |= PSR_C; 39 - regs->pc = regs->npc; 40 - regs->npc += 4; 41 - } 42 - 43 - static inline void pt_succ_return(struct pt_regs *regs, unsigned long value) 44 - { 45 - regs->u_regs[UREG_I0] = value; 46 - regs->psr &= ~PSR_C; 47 - regs->pc = regs->npc; 48 - regs->npc += 4; 49 - } 50 - 51 - static void 52 - pt_succ_return_linux(struct pt_regs *regs, unsigned long value, long __user *addr) 53 - { 54 - if (put_user(value, addr)) { 55 - pt_error_return(regs, EFAULT); 56 - return; 57 - } 58 - regs->u_regs[UREG_I0] = 0; 59 - regs->psr &= ~PSR_C; 60 - regs->pc = regs->npc; 61 - regs->npc += 4; 62 - } 63 - 64 - static void 65 - pt_os_succ_return (struct pt_regs *regs, unsigned long val, long __user *addr) 66 - { 67 - if (current->personality == PER_SUNOS) 68 - pt_succ_return (regs, val); 69 - else 70 - pt_succ_return_linux (regs, val, addr); 71 - } 72 - 73 - /* Fuck me gently with a chainsaw... */ 74 - static inline void read_sunos_user(struct pt_regs *regs, unsigned long offset, 75 - struct task_struct *tsk, long __user *addr) 76 - { 77 - struct pt_regs *cregs = tsk->thread.kregs; 78 - struct thread_info *t = task_thread_info(tsk); 79 - int v; 80 - 81 - if(offset >= 1024) 82 - offset -= 1024; /* whee... */ 83 - if(offset & ((sizeof(unsigned long) - 1))) { 84 - pt_error_return(regs, EIO); 85 - return; 86 - } 87 - if(offset >= 16 && offset < 784) { 88 - offset -= 16; offset >>= 2; 89 - pt_os_succ_return(regs, *(((unsigned long *)(&t->reg_window[0]))+offset), addr); 90 - return; 91 - } 92 - if(offset >= 784 && offset < 832) { 93 - offset -= 784; offset >>= 2; 94 - pt_os_succ_return(regs, *(((unsigned long *)(&t->rwbuf_stkptrs[0]))+offset), addr); 95 - return; 96 - } 97 - switch(offset) { 98 - case 0: 99 - v = t->ksp; 100 - break; 101 - case 4: 102 - v = t->kpc; 103 - break; 104 - case 8: 105 - v = t->kpsr; 106 - break; 107 - case 12: 108 - v = t->uwinmask; 109 - break; 110 - case 832: 111 - v = t->w_saved; 112 - break; 113 - case 896: 114 - v = cregs->u_regs[UREG_I0]; 115 - break; 116 - case 900: 117 - v = cregs->u_regs[UREG_I1]; 118 - break; 119 - case 904: 120 - v = cregs->u_regs[UREG_I2]; 121 - break; 122 - case 908: 123 - v = cregs->u_regs[UREG_I3]; 124 - break; 125 - case 912: 126 - v = cregs->u_regs[UREG_I4]; 127 - break; 128 - case 916: 129 - v = cregs->u_regs[UREG_I5]; 130 - break; 131 - case 920: 132 - v = cregs->u_regs[UREG_I6]; 133 - break; 134 - case 924: 135 - if(tsk->thread.flags & MAGIC_CONSTANT) 136 - v = cregs->u_regs[UREG_G1]; 137 - else 138 - v = 0; 139 - break; 140 - case 940: 141 - v = cregs->u_regs[UREG_I0]; 142 - break; 143 - case 944: 144 - v = cregs->u_regs[UREG_I1]; 145 - break; 146 - 147 - case 948: 148 - /* Isn't binary compatibility _fun_??? */ 149 - if(cregs->psr & PSR_C) 150 - v = cregs->u_regs[UREG_I0] << 24; 151 - else 152 - v = 0; 153 - break; 154 - 155 - /* Rest of them are completely unsupported. */ 156 - default: 157 - printk("%s [%d]: Wants to read user offset %ld\n", 158 - current->comm, task_pid_nr(current), offset); 159 - pt_error_return(regs, EIO); 160 - return; 161 - } 162 - if (current->personality == PER_SUNOS) 163 - pt_succ_return (regs, v); 164 - else 165 - pt_succ_return_linux (regs, v, addr); 166 - return; 167 - } 168 - 169 - static inline void write_sunos_user(struct pt_regs *regs, unsigned long offset, 170 - struct task_struct *tsk) 171 - { 172 - struct pt_regs *cregs = tsk->thread.kregs; 173 - struct thread_info *t = task_thread_info(tsk); 174 - unsigned long value = regs->u_regs[UREG_I3]; 175 - 176 - if(offset >= 1024) 177 - offset -= 1024; /* whee... */ 178 - if(offset & ((sizeof(unsigned long) - 1))) 179 - goto failure; 180 - if(offset >= 16 && offset < 784) { 181 - offset -= 16; offset >>= 2; 182 - *(((unsigned long *)(&t->reg_window[0]))+offset) = value; 183 - goto success; 184 - } 185 - if(offset >= 784 && offset < 832) { 186 - offset -= 784; offset >>= 2; 187 - *(((unsigned long *)(&t->rwbuf_stkptrs[0]))+offset) = value; 188 - goto success; 189 - } 190 - switch(offset) { 191 - case 896: 192 - cregs->u_regs[UREG_I0] = value; 193 - break; 194 - case 900: 195 - cregs->u_regs[UREG_I1] = value; 196 - break; 197 - case 904: 198 - cregs->u_regs[UREG_I2] = value; 199 - break; 200 - case 908: 201 - cregs->u_regs[UREG_I3] = value; 202 - break; 203 - case 912: 204 - cregs->u_regs[UREG_I4] = value; 205 - break; 206 - case 916: 207 - cregs->u_regs[UREG_I5] = value; 208 - break; 209 - case 920: 210 - cregs->u_regs[UREG_I6] = value; 211 - break; 212 - case 924: 213 - cregs->u_regs[UREG_I7] = value; 214 - break; 215 - case 940: 216 - cregs->u_regs[UREG_I0] = value; 217 - break; 218 - case 944: 219 - cregs->u_regs[UREG_I1] = value; 220 - break; 221 - 222 - /* Rest of them are completely unsupported or "no-touch". */ 223 - default: 224 - printk("%s [%d]: Wants to write user offset %ld\n", 225 - current->comm, task_pid_nr(current), offset); 226 - goto failure; 227 - } 228 - success: 229 - pt_succ_return(regs, 0); 230 - return; 231 - failure: 232 - pt_error_return(regs, EIO); 233 - return; 234 - } 235 - 236 29 /* #define ALLOW_INIT_TRACING */ 237 - /* #define DEBUG_PTRACE */ 238 - 239 - #ifdef DEBUG_PTRACE 240 - char *pt_rq [] = { 241 - /* 0 */ "TRACEME", "PEEKTEXT", "PEEKDATA", "PEEKUSR", 242 - /* 4 */ "POKETEXT", "POKEDATA", "POKEUSR", "CONT", 243 - /* 8 */ "KILL", "SINGLESTEP", "SUNATTACH", "SUNDETACH", 244 - /* 12 */ "GETREGS", "SETREGS", "GETFPREGS", "SETFPREGS", 245 - /* 16 */ "READDATA", "WRITEDATA", "READTEXT", "WRITETEXT", 246 - /* 20 */ "GETFPAREGS", "SETFPAREGS", "unknown", "unknown", 247 - /* 24 */ "SYSCALL", "" 248 - }; 249 - #endif 250 30 251 31 /* 252 32 * Called by kernel/ptrace.c when detaching.. ··· 38 258 /* nothing to do */ 39 259 } 40 260 41 - asmlinkage void do_ptrace(struct pt_regs *regs) 261 + enum sparc_regset { 262 + REGSET_GENERAL, 263 + REGSET_FP, 264 + }; 265 + 266 + static int genregs32_get(struct task_struct *target, 267 + const struct user_regset *regset, 268 + unsigned int pos, unsigned int count, 269 + void *kbuf, void __user *ubuf) 42 270 { 43 - unsigned long request = regs->u_regs[UREG_I0]; 44 - unsigned long pid = regs->u_regs[UREG_I1]; 45 - unsigned long addr = regs->u_regs[UREG_I2]; 46 - unsigned long data = regs->u_regs[UREG_I3]; 47 - unsigned long addr2 = regs->u_regs[UREG_I4]; 48 - struct task_struct *child; 271 + const struct pt_regs *regs = target->thread.kregs; 272 + unsigned long __user *reg_window; 273 + unsigned long *k = kbuf; 274 + unsigned long __user *u = ubuf; 275 + unsigned long reg; 276 + 277 + if (target == current) 278 + flush_user_windows(); 279 + 280 + pos /= sizeof(reg); 281 + count /= sizeof(reg); 282 + 283 + if (kbuf) { 284 + for (; count > 0 && pos < 16; count--) 285 + *k++ = regs->u_regs[pos++]; 286 + 287 + reg_window = (unsigned long __user *) regs->u_regs[UREG_I6]; 288 + for (; count > 0 && pos < 32; count--) { 289 + if (get_user(*k++, &reg_window[pos++])) 290 + return -EFAULT; 291 + } 292 + } else { 293 + for (; count > 0 && pos < 16; count--) { 294 + if (put_user(regs->u_regs[pos++], u++)) 295 + return -EFAULT; 296 + } 297 + 298 + reg_window = (unsigned long __user *) regs->u_regs[UREG_I6]; 299 + for (; count > 0 && pos < 32; count--) { 300 + if (get_user(reg, &reg_window[pos++]) || 301 + put_user(reg, u++)) 302 + return -EFAULT; 303 + } 304 + } 305 + while (count > 0) { 306 + switch (pos) { 307 + case 32: /* PSR */ 308 + reg = regs->psr; 309 + break; 310 + case 33: /* PC */ 311 + reg = regs->pc; 312 + break; 313 + case 34: /* NPC */ 314 + reg = regs->npc; 315 + break; 316 + case 35: /* Y */ 317 + reg = regs->y; 318 + break; 319 + case 36: /* WIM */ 320 + case 37: /* TBR */ 321 + reg = 0; 322 + break; 323 + default: 324 + goto finish; 325 + } 326 + 327 + if (kbuf) 328 + *k++ = reg; 329 + else if (put_user(reg, u++)) 330 + return -EFAULT; 331 + pos++; 332 + count--; 333 + } 334 + finish: 335 + pos *= sizeof(reg); 336 + count *= sizeof(reg); 337 + 338 + return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, 339 + 38 * sizeof(reg), -1); 340 + } 341 + 342 + static int genregs32_set(struct task_struct *target, 343 + const struct user_regset *regset, 344 + unsigned int pos, unsigned int count, 345 + const void *kbuf, const void __user *ubuf) 346 + { 347 + struct pt_regs *regs = target->thread.kregs; 348 + unsigned long __user *reg_window; 349 + const unsigned long *k = kbuf; 350 + const unsigned long __user *u = ubuf; 351 + unsigned long reg; 352 + 353 + if (target == current) 354 + flush_user_windows(); 355 + 356 + pos /= sizeof(reg); 357 + count /= sizeof(reg); 358 + 359 + if (kbuf) { 360 + for (; count > 0 && pos < 16; count--) 361 + regs->u_regs[pos++] = *k++; 362 + 363 + reg_window = (unsigned long __user *) regs->u_regs[UREG_I6]; 364 + for (; count > 0 && pos < 32; count--) { 365 + if (put_user(*k++, &reg_window[pos++])) 366 + return -EFAULT; 367 + } 368 + } else { 369 + for (; count > 0 && pos < 16; count--) { 370 + if (get_user(reg, u++)) 371 + return -EFAULT; 372 + regs->u_regs[pos++] = reg; 373 + } 374 + 375 + reg_window = (unsigned long __user *) regs->u_regs[UREG_I6]; 376 + for (; count > 0 && pos < 32; count--) { 377 + if (get_user(reg, u++) || 378 + put_user(reg, &reg_window[pos++])) 379 + return -EFAULT; 380 + } 381 + } 382 + while (count > 0) { 383 + unsigned long psr; 384 + 385 + if (kbuf) 386 + reg = *k++; 387 + else if (get_user(reg, u++)) 388 + return -EFAULT; 389 + 390 + switch (pos) { 391 + case 32: /* PSR */ 392 + psr = regs->psr; 393 + psr &= ~PSR_ICC; 394 + psr |= (reg & PSR_ICC); 395 + regs->psr = psr; 396 + break; 397 + case 33: /* PC */ 398 + regs->pc = reg; 399 + break; 400 + case 34: /* NPC */ 401 + regs->npc = reg; 402 + break; 403 + case 35: /* Y */ 404 + regs->y = reg; 405 + break; 406 + case 36: /* WIM */ 407 + case 37: /* TBR */ 408 + break; 409 + default: 410 + goto finish; 411 + } 412 + 413 + pos++; 414 + count--; 415 + } 416 + finish: 417 + pos *= sizeof(reg); 418 + count *= sizeof(reg); 419 + 420 + return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 421 + 38 * sizeof(reg), -1); 422 + } 423 + 424 + static int fpregs32_get(struct task_struct *target, 425 + const struct user_regset *regset, 426 + unsigned int pos, unsigned int count, 427 + void *kbuf, void __user *ubuf) 428 + { 429 + const unsigned long *fpregs = target->thread.float_regs; 430 + int ret = 0; 431 + 432 + #if 0 433 + if (target == current) 434 + save_and_clear_fpu(); 435 + #endif 436 + 437 + ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, 438 + fpregs, 439 + 0, 32 * sizeof(u32)); 440 + 441 + if (!ret) 442 + ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, 443 + 32 * sizeof(u32), 444 + 33 * sizeof(u32)); 445 + if (!ret) 446 + ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, 447 + &target->thread.fsr, 448 + 33 * sizeof(u32), 449 + 34 * sizeof(u32)); 450 + 451 + if (!ret) { 452 + unsigned long val; 453 + 454 + val = (1 << 8) | (8 << 16); 455 + ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, 456 + &val, 457 + 34 * sizeof(u32), 458 + 35 * sizeof(u32)); 459 + } 460 + 461 + if (!ret) 462 + ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, 463 + 35 * sizeof(u32), -1); 464 + 465 + return ret; 466 + } 467 + 468 + static int fpregs32_set(struct task_struct *target, 469 + const struct user_regset *regset, 470 + unsigned int pos, unsigned int count, 471 + const void *kbuf, const void __user *ubuf) 472 + { 473 + unsigned long *fpregs = target->thread.float_regs; 49 474 int ret; 50 475 51 - lock_kernel(); 52 - #ifdef DEBUG_PTRACE 53 - { 54 - char *s; 55 - 56 - if ((request >= 0) && (request <= 24)) 57 - s = pt_rq [request]; 58 - else 59 - s = "unknown"; 60 - 61 - if (request == PTRACE_POKEDATA && data == 0x91d02001){ 62 - printk ("do_ptrace: breakpoint pid=%d, addr=%08lx addr2=%08lx\n", 63 - pid, addr, addr2); 64 - } else 65 - printk("do_ptrace: rq=%s(%d) pid=%d addr=%08lx data=%08lx addr2=%08lx\n", 66 - s, (int) request, (int) pid, addr, data, addr2); 67 - } 476 + #if 0 477 + if (target == current) 478 + save_and_clear_fpu(); 68 479 #endif 69 - 70 - if (request == PTRACE_TRACEME) { 71 - ret = ptrace_traceme(); 72 - if (ret < 0) 73 - pt_error_return(regs, -ret); 74 - else 75 - pt_succ_return(regs, 0); 76 - goto out; 480 + ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 481 + fpregs, 482 + 0, 32 * sizeof(u32)); 483 + if (!ret) 484 + user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 485 + 32 * sizeof(u32), 486 + 33 * sizeof(u32)); 487 + if (!ret && count > 0) { 488 + ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 489 + &target->thread.fsr, 490 + 33 * sizeof(u32), 491 + 34 * sizeof(u32)); 77 492 } 78 493 79 - child = ptrace_get_task_struct(pid); 80 - if (IS_ERR(child)) { 81 - ret = PTR_ERR(child); 82 - pt_error_return(regs, -ret); 83 - goto out; 84 - } 494 + if (!ret) 495 + ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 496 + 34 * sizeof(u32), -1); 497 + return ret; 498 + } 85 499 86 - if ((current->personality == PER_SUNOS && request == PTRACE_SUNATTACH) 87 - || (current->personality != PER_SUNOS && request == PTRACE_ATTACH)) { 88 - if (ptrace_attach(child)) { 89 - pt_error_return(regs, EPERM); 90 - goto out_tsk; 91 - } 92 - pt_succ_return(regs, 0); 93 - goto out_tsk; 94 - } 500 + static const struct user_regset sparc32_regsets[] = { 501 + /* Format is: 502 + * G0 --> G7 503 + * O0 --> O7 504 + * L0 --> L7 505 + * I0 --> I7 506 + * PSR, PC, nPC, Y, WIM, TBR 507 + */ 508 + [REGSET_GENERAL] = { 509 + .core_note_type = NT_PRSTATUS, 510 + .n = 38 * sizeof(u32), 511 + .size = sizeof(u32), .align = sizeof(u32), 512 + .get = genregs32_get, .set = genregs32_set 513 + }, 514 + /* Format is: 515 + * F0 --> F31 516 + * empty 32-bit word 517 + * FSR (32--bit word) 518 + * FPU QUEUE COUNT (8-bit char) 519 + * FPU QUEUE ENTRYSIZE (8-bit char) 520 + * FPU ENABLED (8-bit char) 521 + * empty 8-bit char 522 + * FPU QUEUE (64 32-bit ints) 523 + */ 524 + [REGSET_FP] = { 525 + .core_note_type = NT_PRFPREG, 526 + .n = 99 * sizeof(u32), 527 + .size = sizeof(u32), .align = sizeof(u32), 528 + .get = fpregs32_get, .set = fpregs32_set 529 + }, 530 + }; 95 531 96 - ret = ptrace_check_attach(child, request == PTRACE_KILL); 97 - if (ret < 0) { 98 - pt_error_return(regs, -ret); 99 - goto out_tsk; 100 - } 532 + static const struct user_regset_view user_sparc32_view = { 533 + .name = "sparc", .e_machine = EM_SPARC, 534 + .regsets = sparc32_regsets, .n = ARRAY_SIZE(sparc32_regsets) 535 + }; 536 + 537 + const struct user_regset_view *task_user_regset_view(struct task_struct *task) 538 + { 539 + return &user_sparc32_view; 540 + } 541 + 542 + long arch_ptrace(struct task_struct *child, long request, long addr, long data) 543 + { 544 + unsigned long addr2 = current->thread.kregs->u_regs[UREG_I4]; 545 + const struct user_regset_view *view; 546 + int ret; 547 + 548 + view = task_user_regset_view(child); 101 549 102 550 switch(request) { 103 - case PTRACE_PEEKTEXT: /* read word at location addr. */ 104 - case PTRACE_PEEKDATA: { 105 - unsigned long tmp; 106 - 107 - if (access_process_vm(child, addr, 108 - &tmp, sizeof(tmp), 0) == sizeof(tmp)) 109 - pt_os_succ_return(regs, tmp, (long __user *)data); 110 - else 111 - pt_error_return(regs, EIO); 112 - goto out_tsk; 113 - } 114 - 115 - case PTRACE_PEEKUSR: 116 - read_sunos_user(regs, addr, child, (long __user *) data); 117 - goto out_tsk; 118 - 119 - case PTRACE_POKEUSR: 120 - write_sunos_user(regs, addr, child); 121 - goto out_tsk; 122 - 123 - case PTRACE_POKETEXT: /* write the word at location addr. */ 124 - case PTRACE_POKEDATA: { 125 - if (access_process_vm(child, addr, 126 - &data, sizeof(data), 1) == sizeof(data)) 127 - pt_succ_return(regs, 0); 128 - else 129 - pt_error_return(regs, EIO); 130 - goto out_tsk; 131 - } 132 - 133 551 case PTRACE_GETREGS: { 134 552 struct pt_regs __user *pregs = (struct pt_regs __user *) addr; 135 - struct pt_regs *cregs = child->thread.kregs; 136 - int rval; 137 553 138 - if (!access_ok(VERIFY_WRITE, pregs, sizeof(struct pt_regs))) { 139 - rval = -EFAULT; 140 - pt_error_return(regs, -rval); 141 - goto out_tsk; 142 - } 143 - __put_user(cregs->psr, (&pregs->psr)); 144 - __put_user(cregs->pc, (&pregs->pc)); 145 - __put_user(cregs->npc, (&pregs->npc)); 146 - __put_user(cregs->y, (&pregs->y)); 147 - for(rval = 1; rval < 16; rval++) 148 - __put_user(cregs->u_regs[rval], (&pregs->u_regs[rval - 1])); 149 - pt_succ_return(regs, 0); 150 - #ifdef DEBUG_PTRACE 151 - printk ("PC=%x nPC=%x o7=%x\n", cregs->pc, cregs->npc, cregs->u_regs [15]); 152 - #endif 153 - goto out_tsk; 554 + ret = copy_regset_to_user(child, view, REGSET_GENERAL, 555 + 32 * sizeof(u32), 556 + 4 * sizeof(u32), 557 + &pregs->psr); 558 + if (!ret) 559 + copy_regset_to_user(child, view, REGSET_GENERAL, 560 + 1 * sizeof(u32), 561 + 15 * sizeof(u32), 562 + &pregs->u_regs[0]); 563 + break; 154 564 } 155 565 156 566 case PTRACE_SETREGS: { 157 567 struct pt_regs __user *pregs = (struct pt_regs __user *) addr; 158 - struct pt_regs *cregs = child->thread.kregs; 159 - unsigned long psr, pc, npc, y; 160 - int i; 161 568 162 - /* Must be careful, tracing process can only set certain 163 - * bits in the psr. 164 - */ 165 - if (!access_ok(VERIFY_READ, pregs, sizeof(struct pt_regs))) { 166 - pt_error_return(regs, EFAULT); 167 - goto out_tsk; 168 - } 169 - __get_user(psr, (&pregs->psr)); 170 - __get_user(pc, (&pregs->pc)); 171 - __get_user(npc, (&pregs->npc)); 172 - __get_user(y, (&pregs->y)); 173 - psr &= PSR_ICC; 174 - cregs->psr &= ~PSR_ICC; 175 - cregs->psr |= psr; 176 - if (!((pc | npc) & 3)) { 177 - cregs->pc = pc; 178 - cregs->npc =npc; 179 - } 180 - cregs->y = y; 181 - for(i = 1; i < 16; i++) 182 - __get_user(cregs->u_regs[i], (&pregs->u_regs[i-1])); 183 - pt_succ_return(regs, 0); 184 - goto out_tsk; 569 + ret = copy_regset_from_user(child, view, REGSET_GENERAL, 570 + 32 * sizeof(u32), 571 + 4 * sizeof(u32), 572 + &pregs->psr); 573 + if (!ret) 574 + copy_regset_from_user(child, view, REGSET_GENERAL, 575 + 1 * sizeof(u32), 576 + 15 * sizeof(u32), 577 + &pregs->u_regs[0]); 578 + break; 185 579 } 186 580 187 581 case PTRACE_GETFPREGS: { ··· 371 417 } fpq[16]; 372 418 }; 373 419 struct fps __user *fps = (struct fps __user *) addr; 374 - int i; 375 420 376 - if (!access_ok(VERIFY_WRITE, fps, sizeof(struct fps))) { 377 - i = -EFAULT; 378 - pt_error_return(regs, -i); 379 - goto out_tsk; 421 + ret = copy_regset_to_user(child, view, REGSET_FP, 422 + 0 * sizeof(u32), 423 + 32 * sizeof(u32), 424 + &fps->regs[0]); 425 + if (!ret) 426 + ret = copy_regset_to_user(child, view, REGSET_FP, 427 + 33 * sizeof(u32), 428 + 1 * sizeof(u32), 429 + &fps->fsr); 430 + 431 + if (!ret) { 432 + if (__put_user(0, &fps->fpqd) || 433 + __put_user(0, &fps->flags) || 434 + __put_user(0, &fps->extra) || 435 + clear_user(fps->fpq, sizeof(fps->fpq))) 436 + ret = -EFAULT; 380 437 } 381 - for(i = 0; i < 32; i++) 382 - __put_user(child->thread.float_regs[i], (&fps->regs[i])); 383 - __put_user(child->thread.fsr, (&fps->fsr)); 384 - __put_user(child->thread.fpqdepth, (&fps->fpqd)); 385 - __put_user(0, (&fps->flags)); 386 - __put_user(0, (&fps->extra)); 387 - for(i = 0; i < 16; i++) { 388 - __put_user(child->thread.fpqueue[i].insn_addr, 389 - (&fps->fpq[i].insnaddr)); 390 - __put_user(child->thread.fpqueue[i].insn, (&fps->fpq[i].insn)); 391 - } 392 - pt_succ_return(regs, 0); 393 - goto out_tsk; 438 + break; 394 439 } 395 440 396 441 case PTRACE_SETFPREGS: { ··· 405 452 } fpq[16]; 406 453 }; 407 454 struct fps __user *fps = (struct fps __user *) addr; 408 - int i; 409 455 410 - if (!access_ok(VERIFY_READ, fps, sizeof(struct fps))) { 411 - i = -EFAULT; 412 - pt_error_return(regs, -i); 413 - goto out_tsk; 414 - } 415 - copy_from_user(&child->thread.float_regs[0], &fps->regs[0], (32 * sizeof(unsigned long))); 416 - __get_user(child->thread.fsr, (&fps->fsr)); 417 - __get_user(child->thread.fpqdepth, (&fps->fpqd)); 418 - for(i = 0; i < 16; i++) { 419 - __get_user(child->thread.fpqueue[i].insn_addr, 420 - (&fps->fpq[i].insnaddr)); 421 - __get_user(child->thread.fpqueue[i].insn, (&fps->fpq[i].insn)); 422 - } 423 - pt_succ_return(regs, 0); 424 - goto out_tsk; 456 + ret = copy_regset_from_user(child, view, REGSET_FP, 457 + 0 * sizeof(u32), 458 + 32 * sizeof(u32), 459 + &fps->regs[0]); 460 + if (!ret) 461 + ret = copy_regset_from_user(child, view, REGSET_FP, 462 + 33 * sizeof(u32), 463 + 1 * sizeof(u32), 464 + &fps->fsr); 465 + break; 425 466 } 426 467 427 468 case PTRACE_READTEXT: 428 - case PTRACE_READDATA: { 429 - int res = ptrace_readdata(child, addr, 430 - (void __user *) addr2, data); 469 + case PTRACE_READDATA: 470 + ret = ptrace_readdata(child, addr, 471 + (void __user *) addr2, data); 431 472 432 - if (res == data) { 433 - pt_succ_return(regs, 0); 434 - goto out_tsk; 435 - } 436 - /* Partial read is an IO failure */ 437 - if (res >= 0) 438 - res = -EIO; 439 - pt_error_return(regs, -res); 440 - goto out_tsk; 441 - } 473 + if (ret == data) 474 + ret = 0; 475 + else if (ret >= 0) 476 + ret = -EIO; 477 + break; 442 478 443 479 case PTRACE_WRITETEXT: 444 - case PTRACE_WRITEDATA: { 445 - int res = ptrace_writedata(child, (void __user *) addr2, 446 - addr, data); 480 + case PTRACE_WRITEDATA: 481 + ret = ptrace_writedata(child, (void __user *) addr2, 482 + addr, data); 447 483 448 - if (res == data) { 449 - pt_succ_return(regs, 0); 450 - goto out_tsk; 451 - } 452 - /* Partial write is an IO failure */ 453 - if (res >= 0) 454 - res = -EIO; 455 - pt_error_return(regs, -res); 456 - goto out_tsk; 484 + if (ret == data) 485 + ret = 0; 486 + else if (ret >= 0) 487 + ret = -EIO; 488 + break; 489 + 490 + default: 491 + ret = ptrace_request(child, request, addr, data); 492 + break; 457 493 } 458 494 459 - case PTRACE_SYSCALL: /* continue and stop at (return from) syscall */ 460 - addr = 1; 461 - 462 - case PTRACE_CONT: { /* restart after signal. */ 463 - if (!valid_signal(data)) { 464 - pt_error_return(regs, EIO); 465 - goto out_tsk; 466 - } 467 - 468 - if (request == PTRACE_SYSCALL) 469 - set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); 470 - else 471 - clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); 472 - 473 - child->exit_code = data; 474 - #ifdef DEBUG_PTRACE 475 - printk("CONT: %s [%d]: set exit_code = %x %lx %lx\n", 476 - child->comm, child->pid, child->exit_code, 477 - child->thread.kregs->pc, 478 - child->thread.kregs->npc); 479 - #endif 480 - wake_up_process(child); 481 - pt_succ_return(regs, 0); 482 - goto out_tsk; 483 - } 484 - 485 - /* 486 - * make the child exit. Best I can do is send it a sigkill. 487 - * perhaps it should be put in the status that it wants to 488 - * exit. 489 - */ 490 - case PTRACE_KILL: { 491 - if (child->exit_state == EXIT_ZOMBIE) { /* already dead */ 492 - pt_succ_return(regs, 0); 493 - goto out_tsk; 494 - } 495 - wake_up_process(child); 496 - child->exit_code = SIGKILL; 497 - pt_succ_return(regs, 0); 498 - goto out_tsk; 499 - } 500 - 501 - case PTRACE_SUNDETACH: { /* detach a process that was attached. */ 502 - int err = ptrace_detach(child, data); 503 - if (err) { 504 - pt_error_return(regs, EIO); 505 - goto out_tsk; 506 - } 507 - pt_succ_return(regs, 0); 508 - goto out_tsk; 509 - } 510 - 511 - /* PTRACE_DUMPCORE unsupported... */ 512 - 513 - default: { 514 - int err = ptrace_request(child, request, addr, data); 515 - if (err) 516 - pt_error_return(regs, -err); 517 - else 518 - pt_succ_return(regs, 0); 519 - goto out_tsk; 520 - } 521 - } 522 - out_tsk: 523 - if (child) 524 - put_task_struct(child); 525 - out: 526 - unlock_kernel(); 495 + return ret; 527 496 } 528 497 529 498 asmlinkage void syscall_trace(void) 530 499 { 531 - #ifdef DEBUG_PTRACE 532 - printk("%s [%d]: syscall_trace\n", current->comm, current->pid); 533 - #endif 534 500 if (!test_thread_flag(TIF_SYSCALL_TRACE)) 535 501 return; 536 502 if (!(current->ptrace & PT_PTRACED)) 537 503 return; 538 - current->thread.flags ^= MAGIC_CONSTANT; 539 504 ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) 540 505 ? 0x80 : 0)); 541 506 /* ··· 461 590 * for normal use. strace only continues with a signal if the 462 591 * stopping signal is not SIGTRAP. -brl 463 592 */ 464 - #ifdef DEBUG_PTRACE 465 - printk("%s [%d]: syscall_trace exit= %x\n", current->comm, 466 - current->pid, current->exit_code); 467 - #endif 468 593 if (current->exit_code) { 469 594 send_sig (current->exit_code, current, 1); 470 595 current->exit_code = 0;
+4 -27
arch/sparc64/kernel/binfmt_elf32.c
··· 1 1 /* 2 2 * binfmt_elf32.c: Support 32-bit Sparc ELF binaries on Ultra. 3 3 * 4 - * Copyright (C) 1995, 1996, 1997, 1998 David S. Miller (davem@davemloft.net) 4 + * Copyright (C) 1995, 1996, 1997, 1998, 2008 David S. Miller (davem@davemloft.net) 5 5 * Copyright (C) 1995, 1996, 1997, 1998 Jakub Jelinek (jj@ultra.linux.cz) 6 6 */ 7 7 8 8 #define ELF_ARCH EM_SPARC 9 9 #define ELF_CLASS ELFCLASS32 10 10 #define ELF_DATA ELFDATA2MSB; 11 - 12 - /* For the most part we present code dumps in the format 13 - * Solaris does. 14 - */ 15 - typedef unsigned int elf_greg_t; 16 - #define ELF_NGREG 38 17 - typedef elf_greg_t elf_gregset_t[ELF_NGREG]; 18 11 19 12 /* Format is: 20 13 * G0 --> G7 ··· 16 23 * I0 --> I7 17 24 * PSR, PC, nPC, Y, WIM, TBR 18 25 */ 19 - #include <asm/psrcompat.h> 20 - #define ELF_CORE_COPY_REGS(__elf_regs, __pt_regs) \ 21 - do { unsigned int *dest = &(__elf_regs[0]); \ 22 - struct pt_regs *src = (__pt_regs); \ 23 - unsigned int __user *sp; \ 24 - int i; \ 25 - for(i = 0; i < 16; i++) \ 26 - dest[i] = (unsigned int) src->u_regs[i];\ 27 - /* Don't try this at home kids... */ \ 28 - sp = (unsigned int __user *) (src->u_regs[14] & \ 29 - 0x00000000fffffffc); \ 30 - for(i = 0; i < 16; i++) \ 31 - __get_user(dest[i+16], &sp[i]); \ 32 - dest[32] = tstate_to_psr(src->tstate); \ 33 - dest[33] = (unsigned int) src->tpc; \ 34 - dest[34] = (unsigned int) src->tnpc; \ 35 - dest[35] = src->y; \ 36 - dest[36] = dest[37] = 0; /* XXX */ \ 37 - } while(0); 26 + typedef unsigned int elf_greg_t; 27 + #define ELF_NGREG 38 28 + typedef elf_greg_t elf_gregset_t[ELF_NGREG]; 38 29 39 30 typedef struct { 40 31 union {
-4
arch/sparc64/kernel/entry.S
··· 1477 1477 add %o7, 1f-.-4, %o7 1478 1478 nop 1479 1479 #endif 1480 - sys_ptrace: add %sp, PTREGS_OFF, %o0 1481 - call do_ptrace 1482 - add %o7, 1f-.-4, %o7 1483 - nop 1484 1480 .align 32 1485 1481 1: ldx [%curptr + TI_FLAGS], %l5 1486 1482 andcc %l5, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT), %g0
+25
arch/sparc64/kernel/head.S
··· 632 632 /* Not reached... */ 633 633 634 634 1: 635 + /* If we boot on a non-zero cpu, all of the per-cpu 636 + * variable references we make before setting up the 637 + * per-cpu areas will use a bogus offset. Put a 638 + * compensating factor into __per_cpu_base to handle 639 + * this cleanly. 640 + * 641 + * What the per-cpu code calculates is: 642 + * 643 + * __per_cpu_base + (cpu << __per_cpu_shift) 644 + * 645 + * These two variables are zero initially, so to 646 + * make it all cancel out to zero we need to put 647 + * "0 - (cpu << 0)" into __per_cpu_base so that the 648 + * above formula evaluates to zero. 649 + * 650 + * We cannot even perform a printk() until this stuff 651 + * is setup as that calls cpu_clock() which uses 652 + * per-cpu variables. 653 + */ 654 + sub %g0, %o0, %o1 655 + sethi %hi(__per_cpu_base), %o2 656 + stx %o1, [%o2 + %lo(__per_cpu_base)] 635 657 #else 636 658 mov 0, %o0 637 659 #endif 638 660 sth %o0, [%g6 + TI_CPU] 661 + 662 + call prom_init_report 663 + nop 639 664 640 665 /* Off we go.... */ 641 666 call start_kernel
+700 -407
arch/sparc64/kernel/ptrace.c
··· 1 1 /* ptrace.c: Sparc process tracing support. 2 2 * 3 - * Copyright (C) 1996 David S. Miller (davem@caipfs.rutgers.edu) 3 + * Copyright (C) 1996, 2008 David S. Miller (davem@davemloft.net) 4 4 * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) 5 5 * 6 6 * Based upon code written by Ross Biro, Linus Torvalds, Bob Manson, ··· 22 22 #include <linux/seccomp.h> 23 23 #include <linux/audit.h> 24 24 #include <linux/signal.h> 25 + #include <linux/regset.h> 26 + #include <linux/compat.h> 27 + #include <linux/elf.h> 25 28 26 29 #include <asm/asi.h> 27 30 #include <asm/pgtable.h> ··· 36 33 #include <asm/page.h> 37 34 #include <asm/cpudata.h> 38 35 39 - /* Returning from ptrace is a bit tricky because the syscall return 40 - * low level code assumes any value returned which is negative and 41 - * is a valid errno will mean setting the condition codes to indicate 42 - * an error return. This doesn't work, so we have this hook. 43 - */ 44 - static inline void pt_error_return(struct pt_regs *regs, unsigned long error) 45 - { 46 - regs->u_regs[UREG_I0] = error; 47 - regs->tstate |= (TSTATE_ICARRY | TSTATE_XCARRY); 48 - regs->tpc = regs->tnpc; 49 - regs->tnpc += 4; 50 - } 51 - 52 - static inline void pt_succ_return(struct pt_regs *regs, unsigned long value) 53 - { 54 - regs->u_regs[UREG_I0] = value; 55 - regs->tstate &= ~(TSTATE_ICARRY | TSTATE_XCARRY); 56 - regs->tpc = regs->tnpc; 57 - regs->tnpc += 4; 58 - } 59 - 60 - static inline void 61 - pt_succ_return_linux(struct pt_regs *regs, unsigned long value, void __user *addr) 62 - { 63 - if (test_thread_flag(TIF_32BIT)) { 64 - if (put_user(value, (unsigned int __user *) addr)) { 65 - pt_error_return(regs, EFAULT); 66 - return; 67 - } 68 - } else { 69 - if (put_user(value, (long __user *) addr)) { 70 - pt_error_return(regs, EFAULT); 71 - return; 72 - } 73 - } 74 - regs->u_regs[UREG_I0] = 0; 75 - regs->tstate &= ~(TSTATE_ICARRY | TSTATE_XCARRY); 76 - regs->tpc = regs->tnpc; 77 - regs->tnpc += 4; 78 - } 79 - 80 - static void 81 - pt_os_succ_return (struct pt_regs *regs, unsigned long val, void __user *addr) 82 - { 83 - if (current->personality == PER_SUNOS) 84 - pt_succ_return (regs, val); 85 - else 86 - pt_succ_return_linux (regs, val, addr); 87 - } 88 - 89 36 /* #define ALLOW_INIT_TRACING */ 90 - /* #define DEBUG_PTRACE */ 91 - 92 - #ifdef DEBUG_PTRACE 93 - char *pt_rq [] = { 94 - /* 0 */ "TRACEME", "PEEKTEXT", "PEEKDATA", "PEEKUSR", 95 - /* 4 */ "POKETEXT", "POKEDATA", "POKEUSR", "CONT", 96 - /* 8 */ "KILL", "SINGLESTEP", "SUNATTACH", "SUNDETACH", 97 - /* 12 */ "GETREGS", "SETREGS", "GETFPREGS", "SETFPREGS", 98 - /* 16 */ "READDATA", "WRITEDATA", "READTEXT", "WRITETEXT", 99 - /* 20 */ "GETFPAREGS", "SETFPAREGS", "unknown", "unknown", 100 - /* 24 */ "SYSCALL", "" 101 - }; 102 - #endif 103 37 104 38 /* 105 39 * Called by kernel/ptrace.c when detaching.. ··· 107 167 } 108 168 } 109 169 110 - asmlinkage void do_ptrace(struct pt_regs *regs) 170 + enum sparc_regset { 171 + REGSET_GENERAL, 172 + REGSET_FP, 173 + }; 174 + 175 + static int genregs64_get(struct task_struct *target, 176 + const struct user_regset *regset, 177 + unsigned int pos, unsigned int count, 178 + void *kbuf, void __user *ubuf) 111 179 { 112 - int request = regs->u_regs[UREG_I0]; 113 - pid_t pid = regs->u_regs[UREG_I1]; 114 - unsigned long addr = regs->u_regs[UREG_I2]; 115 - unsigned long data = regs->u_regs[UREG_I3]; 116 - unsigned long addr2 = regs->u_regs[UREG_I4]; 117 - struct task_struct *child; 180 + const struct pt_regs *regs = task_pt_regs(target); 118 181 int ret; 119 182 120 - if (test_thread_flag(TIF_32BIT)) { 121 - addr &= 0xffffffffUL; 122 - data &= 0xffffffffUL; 123 - addr2 &= 0xffffffffUL; 124 - } 125 - lock_kernel(); 126 - #ifdef DEBUG_PTRACE 127 - { 128 - char *s; 183 + if (target == current) 184 + flushw_user(); 129 185 130 - if ((request >= 0) && (request <= 24)) 131 - s = pt_rq [request]; 132 - else 133 - s = "unknown"; 186 + ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, 187 + regs->u_regs, 188 + 0, 16 * sizeof(u64)); 189 + if (!ret) { 190 + unsigned long __user *reg_window = (unsigned long __user *) 191 + (regs->u_regs[UREG_I6] + STACK_BIAS); 192 + unsigned long window[16]; 134 193 135 - if (request == PTRACE_POKEDATA && data == 0x91d02001){ 136 - printk ("do_ptrace: breakpoint pid=%d, addr=%016lx addr2=%016lx\n", 137 - pid, addr, addr2); 138 - } else 139 - printk("do_ptrace: rq=%s(%d) pid=%d addr=%016lx data=%016lx addr2=%016lx\n", 140 - s, request, pid, addr, data, addr2); 141 - } 142 - #endif 143 - if (request == PTRACE_TRACEME) { 144 - ret = ptrace_traceme(); 145 - if (ret < 0) 146 - pt_error_return(regs, -ret); 147 - else 148 - pt_succ_return(regs, 0); 149 - goto out; 194 + if (copy_from_user(window, reg_window, sizeof(window))) 195 + return -EFAULT; 196 + 197 + ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, 198 + window, 199 + 16 * sizeof(u64), 200 + 32 * sizeof(u64)); 150 201 } 151 202 152 - child = ptrace_get_task_struct(pid); 153 - if (IS_ERR(child)) { 154 - ret = PTR_ERR(child); 155 - pt_error_return(regs, -ret); 156 - goto out; 203 + if (!ret) { 204 + /* TSTATE, TPC, TNPC */ 205 + ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, 206 + &regs->tstate, 207 + 32 * sizeof(u64), 208 + 35 * sizeof(u64)); 157 209 } 158 210 159 - if ((current->personality == PER_SUNOS && request == PTRACE_SUNATTACH) 160 - || (current->personality != PER_SUNOS && request == PTRACE_ATTACH)) { 161 - if (ptrace_attach(child)) { 162 - pt_error_return(regs, EPERM); 163 - goto out_tsk; 211 + if (!ret) { 212 + unsigned long y = regs->y; 213 + 214 + ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, 215 + &y, 216 + 35 * sizeof(u64), 217 + 36 * sizeof(u64)); 218 + } 219 + 220 + if (!ret) 221 + ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, 222 + 36 * sizeof(u64), -1); 223 + 224 + return ret; 225 + } 226 + 227 + static int genregs64_set(struct task_struct *target, 228 + const struct user_regset *regset, 229 + unsigned int pos, unsigned int count, 230 + const void *kbuf, const void __user *ubuf) 231 + { 232 + struct pt_regs *regs = task_pt_regs(target); 233 + int ret; 234 + 235 + if (target == current) 236 + flushw_user(); 237 + 238 + ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 239 + regs->u_regs, 240 + 0, 16 * sizeof(u64)); 241 + if (!ret && count > 0) { 242 + unsigned long __user *reg_window = (unsigned long __user *) 243 + (regs->u_regs[UREG_I6] + STACK_BIAS); 244 + unsigned long window[16]; 245 + 246 + if (copy_from_user(window, reg_window, sizeof(window))) 247 + return -EFAULT; 248 + 249 + ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 250 + window, 251 + 16 * sizeof(u64), 252 + 32 * sizeof(u64)); 253 + if (!ret && 254 + copy_to_user(reg_window, window, sizeof(window))) 255 + return -EFAULT; 256 + } 257 + 258 + if (!ret && count > 0) { 259 + unsigned long tstate; 260 + 261 + /* TSTATE */ 262 + ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 263 + &tstate, 264 + 32 * sizeof(u64), 265 + 33 * sizeof(u64)); 266 + if (!ret) { 267 + /* Only the condition codes can be modified 268 + * in the %tstate register. 269 + */ 270 + tstate &= (TSTATE_ICC | TSTATE_XCC); 271 + regs->tstate &= ~(TSTATE_ICC | TSTATE_XCC); 272 + regs->tstate |= tstate; 164 273 } 165 - pt_succ_return(regs, 0); 166 - goto out_tsk; 167 274 } 168 275 169 - ret = ptrace_check_attach(child, request == PTRACE_KILL); 170 - if (ret < 0) { 171 - pt_error_return(regs, -ret); 172 - goto out_tsk; 276 + if (!ret) { 277 + /* TPC, TNPC */ 278 + ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 279 + &regs->tpc, 280 + 33 * sizeof(u64), 281 + 35 * sizeof(u64)); 173 282 } 174 283 175 - if (!(test_thread_flag(TIF_32BIT)) && 176 - ((request == PTRACE_READDATA64) || 177 - (request == PTRACE_WRITEDATA64) || 178 - (request == PTRACE_READTEXT64) || 179 - (request == PTRACE_WRITETEXT64) || 180 - (request == PTRACE_PEEKTEXT64) || 181 - (request == PTRACE_POKETEXT64) || 182 - (request == PTRACE_PEEKDATA64) || 183 - (request == PTRACE_POKEDATA64))) { 184 - addr = regs->u_regs[UREG_G2]; 185 - addr2 = regs->u_regs[UREG_G3]; 186 - request -= 30; /* wheee... */ 284 + if (!ret) { 285 + unsigned long y; 286 + 287 + ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 288 + &y, 289 + 35 * sizeof(u64), 290 + 36 * sizeof(u64)); 291 + if (!ret) 292 + regs->y = y; 187 293 } 294 + 295 + if (!ret) 296 + ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 297 + 36 * sizeof(u64), -1); 298 + 299 + return ret; 300 + } 301 + 302 + static int fpregs64_get(struct task_struct *target, 303 + const struct user_regset *regset, 304 + unsigned int pos, unsigned int count, 305 + void *kbuf, void __user *ubuf) 306 + { 307 + const unsigned long *fpregs = task_thread_info(target)->fpregs; 308 + unsigned long fprs, fsr, gsr; 309 + int ret; 310 + 311 + if (target == current) 312 + save_and_clear_fpu(); 313 + 314 + fprs = task_thread_info(target)->fpsaved[0]; 315 + 316 + if (fprs & FPRS_DL) 317 + ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, 318 + fpregs, 319 + 0, 16 * sizeof(u64)); 320 + else 321 + ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, 322 + 0, 323 + 16 * sizeof(u64)); 324 + 325 + if (!ret) { 326 + if (fprs & FPRS_DU) 327 + ret = user_regset_copyout(&pos, &count, 328 + &kbuf, &ubuf, 329 + fpregs + 16, 330 + 16 * sizeof(u64), 331 + 32 * sizeof(u64)); 332 + else 333 + ret = user_regset_copyout_zero(&pos, &count, 334 + &kbuf, &ubuf, 335 + 16 * sizeof(u64), 336 + 32 * sizeof(u64)); 337 + } 338 + 339 + if (fprs & FPRS_FEF) { 340 + fsr = task_thread_info(target)->xfsr[0]; 341 + gsr = task_thread_info(target)->gsr[0]; 342 + } else { 343 + fsr = gsr = 0; 344 + } 345 + 346 + if (!ret) 347 + ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, 348 + &fsr, 349 + 32 * sizeof(u64), 350 + 33 * sizeof(u64)); 351 + if (!ret) 352 + ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, 353 + &gsr, 354 + 33 * sizeof(u64), 355 + 34 * sizeof(u64)); 356 + if (!ret) 357 + ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, 358 + &fprs, 359 + 34 * sizeof(u64), 360 + 35 * sizeof(u64)); 361 + 362 + if (!ret) 363 + ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, 364 + 35 * sizeof(u64), -1); 365 + 366 + return ret; 367 + } 368 + 369 + static int fpregs64_set(struct task_struct *target, 370 + const struct user_regset *regset, 371 + unsigned int pos, unsigned int count, 372 + const void *kbuf, const void __user *ubuf) 373 + { 374 + unsigned long *fpregs = task_thread_info(target)->fpregs; 375 + unsigned long fprs; 376 + int ret; 377 + 378 + if (target == current) 379 + save_and_clear_fpu(); 380 + 381 + ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 382 + fpregs, 383 + 0, 32 * sizeof(u64)); 384 + if (!ret) 385 + ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 386 + task_thread_info(target)->xfsr, 387 + 32 * sizeof(u64), 388 + 33 * sizeof(u64)); 389 + if (!ret) 390 + ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 391 + task_thread_info(target)->gsr, 392 + 33 * sizeof(u64), 393 + 34 * sizeof(u64)); 394 + 395 + fprs = task_thread_info(target)->fpsaved[0]; 396 + if (!ret && count > 0) { 397 + ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 398 + &fprs, 399 + 34 * sizeof(u64), 400 + 35 * sizeof(u64)); 401 + } 402 + 403 + fprs |= (FPRS_FEF | FPRS_DL | FPRS_DU); 404 + task_thread_info(target)->fpsaved[0] = fprs; 405 + 406 + if (!ret) 407 + ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 408 + 35 * sizeof(u64), -1); 409 + return ret; 410 + } 411 + 412 + static const struct user_regset sparc64_regsets[] = { 413 + /* Format is: 414 + * G0 --> G7 415 + * O0 --> O7 416 + * L0 --> L7 417 + * I0 --> I7 418 + * TSTATE, TPC, TNPC, Y 419 + */ 420 + [REGSET_GENERAL] = { 421 + .core_note_type = NT_PRSTATUS, 422 + .n = 36 * sizeof(u64), 423 + .size = sizeof(u64), .align = sizeof(u64), 424 + .get = genregs64_get, .set = genregs64_set 425 + }, 426 + /* Format is: 427 + * F0 --> F63 428 + * FSR 429 + * GSR 430 + * FPRS 431 + */ 432 + [REGSET_FP] = { 433 + .core_note_type = NT_PRFPREG, 434 + .n = 35 * sizeof(u64), 435 + .size = sizeof(u64), .align = sizeof(u64), 436 + .get = fpregs64_get, .set = fpregs64_set 437 + }, 438 + }; 439 + 440 + static const struct user_regset_view user_sparc64_view = { 441 + .name = "sparc64", .e_machine = EM_SPARCV9, 442 + .regsets = sparc64_regsets, .n = ARRAY_SIZE(sparc64_regsets) 443 + }; 444 + 445 + static int genregs32_get(struct task_struct *target, 446 + const struct user_regset *regset, 447 + unsigned int pos, unsigned int count, 448 + void *kbuf, void __user *ubuf) 449 + { 450 + const struct pt_regs *regs = task_pt_regs(target); 451 + compat_ulong_t __user *reg_window; 452 + compat_ulong_t *k = kbuf; 453 + compat_ulong_t __user *u = ubuf; 454 + compat_ulong_t reg; 455 + 456 + if (target == current) 457 + flushw_user(); 458 + 459 + pos /= sizeof(reg); 460 + count /= sizeof(reg); 461 + 462 + if (kbuf) { 463 + for (; count > 0 && pos < 16; count--) 464 + *k++ = regs->u_regs[pos++]; 465 + 466 + reg_window = (compat_ulong_t __user *) regs->u_regs[UREG_I6]; 467 + for (; count > 0 && pos < 32; count--) { 468 + if (get_user(*k++, &reg_window[pos++])) 469 + return -EFAULT; 470 + } 471 + } else { 472 + for (; count > 0 && pos < 16; count--) { 473 + if (put_user((compat_ulong_t) regs->u_regs[pos++], u++)) 474 + return -EFAULT; 475 + } 476 + 477 + reg_window = (compat_ulong_t __user *) regs->u_regs[UREG_I6]; 478 + for (; count > 0 && pos < 32; count--) { 479 + if (get_user(reg, &reg_window[pos++]) || 480 + put_user(reg, u++)) 481 + return -EFAULT; 482 + } 483 + } 484 + while (count > 0) { 485 + switch (pos) { 486 + case 32: /* PSR */ 487 + reg = tstate_to_psr(regs->tstate); 488 + break; 489 + case 33: /* PC */ 490 + reg = regs->tpc; 491 + break; 492 + case 34: /* NPC */ 493 + reg = regs->tnpc; 494 + break; 495 + case 35: /* Y */ 496 + reg = regs->y; 497 + break; 498 + case 36: /* WIM */ 499 + case 37: /* TBR */ 500 + reg = 0; 501 + break; 502 + default: 503 + goto finish; 504 + } 505 + 506 + if (kbuf) 507 + *k++ = reg; 508 + else if (put_user(reg, u++)) 509 + return -EFAULT; 510 + pos++; 511 + count--; 512 + } 513 + finish: 514 + pos *= sizeof(reg); 515 + count *= sizeof(reg); 516 + 517 + return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, 518 + 38 * sizeof(reg), -1); 519 + } 520 + 521 + static int genregs32_set(struct task_struct *target, 522 + const struct user_regset *regset, 523 + unsigned int pos, unsigned int count, 524 + const void *kbuf, const void __user *ubuf) 525 + { 526 + struct pt_regs *regs = task_pt_regs(target); 527 + compat_ulong_t __user *reg_window; 528 + const compat_ulong_t *k = kbuf; 529 + const compat_ulong_t __user *u = ubuf; 530 + compat_ulong_t reg; 531 + 532 + if (target == current) 533 + flushw_user(); 534 + 535 + pos /= sizeof(reg); 536 + count /= sizeof(reg); 537 + 538 + if (kbuf) { 539 + for (; count > 0 && pos < 16; count--) 540 + regs->u_regs[pos++] = *k++; 541 + 542 + reg_window = (compat_ulong_t __user *) regs->u_regs[UREG_I6]; 543 + for (; count > 0 && pos < 32; count--) { 544 + if (put_user(*k++, &reg_window[pos++])) 545 + return -EFAULT; 546 + } 547 + } else { 548 + for (; count > 0 && pos < 16; count--) { 549 + if (get_user(reg, u++)) 550 + return -EFAULT; 551 + regs->u_regs[pos++] = reg; 552 + } 553 + 554 + reg_window = (compat_ulong_t __user *) regs->u_regs[UREG_I6]; 555 + for (; count > 0 && pos < 32; count--) { 556 + if (get_user(reg, u++) || 557 + put_user(reg, &reg_window[pos++])) 558 + return -EFAULT; 559 + } 560 + } 561 + while (count > 0) { 562 + unsigned long tstate; 563 + 564 + if (kbuf) 565 + reg = *k++; 566 + else if (get_user(reg, u++)) 567 + return -EFAULT; 568 + 569 + switch (pos) { 570 + case 32: /* PSR */ 571 + tstate = regs->tstate; 572 + tstate &= ~(TSTATE_ICC | TSTATE_XCC); 573 + tstate |= psr_to_tstate_icc(reg); 574 + regs->tstate = tstate; 575 + break; 576 + case 33: /* PC */ 577 + regs->tpc = reg; 578 + break; 579 + case 34: /* NPC */ 580 + regs->tnpc = reg; 581 + break; 582 + case 35: /* Y */ 583 + regs->y = reg; 584 + break; 585 + case 36: /* WIM */ 586 + case 37: /* TBR */ 587 + break; 588 + default: 589 + goto finish; 590 + } 591 + 592 + pos++; 593 + count--; 594 + } 595 + finish: 596 + pos *= sizeof(reg); 597 + count *= sizeof(reg); 598 + 599 + return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 600 + 38 * sizeof(reg), -1); 601 + } 602 + 603 + static int fpregs32_get(struct task_struct *target, 604 + const struct user_regset *regset, 605 + unsigned int pos, unsigned int count, 606 + void *kbuf, void __user *ubuf) 607 + { 608 + const unsigned long *fpregs = task_thread_info(target)->fpregs; 609 + compat_ulong_t enabled; 610 + unsigned long fprs; 611 + compat_ulong_t fsr; 612 + int ret = 0; 613 + 614 + if (target == current) 615 + save_and_clear_fpu(); 616 + 617 + fprs = task_thread_info(target)->fpsaved[0]; 618 + if (fprs & FPRS_FEF) { 619 + fsr = task_thread_info(target)->xfsr[0]; 620 + enabled = 1; 621 + } else { 622 + fsr = 0; 623 + enabled = 0; 624 + } 625 + 626 + ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, 627 + fpregs, 628 + 0, 32 * sizeof(u32)); 629 + 630 + if (!ret) 631 + ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, 632 + 32 * sizeof(u32), 633 + 33 * sizeof(u32)); 634 + if (!ret) 635 + ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, 636 + &fsr, 637 + 33 * sizeof(u32), 638 + 34 * sizeof(u32)); 639 + 640 + if (!ret) { 641 + compat_ulong_t val; 642 + 643 + val = (enabled << 8) | (8 << 16); 644 + ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, 645 + &val, 646 + 34 * sizeof(u32), 647 + 35 * sizeof(u32)); 648 + } 649 + 650 + if (!ret) 651 + ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, 652 + 35 * sizeof(u32), -1); 653 + 654 + return ret; 655 + } 656 + 657 + static int fpregs32_set(struct task_struct *target, 658 + const struct user_regset *regset, 659 + unsigned int pos, unsigned int count, 660 + const void *kbuf, const void __user *ubuf) 661 + { 662 + unsigned long *fpregs = task_thread_info(target)->fpregs; 663 + unsigned long fprs; 664 + int ret; 665 + 666 + if (target == current) 667 + save_and_clear_fpu(); 668 + 669 + fprs = task_thread_info(target)->fpsaved[0]; 670 + 671 + ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 672 + fpregs, 673 + 0, 32 * sizeof(u32)); 674 + if (!ret) 675 + user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 676 + 32 * sizeof(u32), 677 + 33 * sizeof(u32)); 678 + if (!ret && count > 0) { 679 + compat_ulong_t fsr; 680 + unsigned long val; 681 + 682 + ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 683 + &fsr, 684 + 33 * sizeof(u32), 685 + 34 * sizeof(u32)); 686 + if (!ret) { 687 + val = task_thread_info(target)->xfsr[0]; 688 + val &= 0xffffffff00000000UL; 689 + val |= fsr; 690 + task_thread_info(target)->xfsr[0] = val; 691 + } 692 + } 693 + 694 + fprs |= (FPRS_FEF | FPRS_DL); 695 + task_thread_info(target)->fpsaved[0] = fprs; 696 + 697 + if (!ret) 698 + ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 699 + 34 * sizeof(u32), -1); 700 + return ret; 701 + } 702 + 703 + static const struct user_regset sparc32_regsets[] = { 704 + /* Format is: 705 + * G0 --> G7 706 + * O0 --> O7 707 + * L0 --> L7 708 + * I0 --> I7 709 + * PSR, PC, nPC, Y, WIM, TBR 710 + */ 711 + [REGSET_GENERAL] = { 712 + .core_note_type = NT_PRSTATUS, 713 + .n = 38 * sizeof(u32), 714 + .size = sizeof(u32), .align = sizeof(u32), 715 + .get = genregs32_get, .set = genregs32_set 716 + }, 717 + /* Format is: 718 + * F0 --> F31 719 + * empty 32-bit word 720 + * FSR (32--bit word) 721 + * FPU QUEUE COUNT (8-bit char) 722 + * FPU QUEUE ENTRYSIZE (8-bit char) 723 + * FPU ENABLED (8-bit char) 724 + * empty 8-bit char 725 + * FPU QUEUE (64 32-bit ints) 726 + */ 727 + [REGSET_FP] = { 728 + .core_note_type = NT_PRFPREG, 729 + .n = 99 * sizeof(u32), 730 + .size = sizeof(u32), .align = sizeof(u32), 731 + .get = fpregs32_get, .set = fpregs32_set 732 + }, 733 + }; 734 + 735 + static const struct user_regset_view user_sparc32_view = { 736 + .name = "sparc", .e_machine = EM_SPARC, 737 + .regsets = sparc32_regsets, .n = ARRAY_SIZE(sparc32_regsets) 738 + }; 739 + 740 + const struct user_regset_view *task_user_regset_view(struct task_struct *task) 741 + { 742 + if (test_tsk_thread_flag(task, TIF_32BIT)) 743 + return &user_sparc32_view; 744 + return &user_sparc64_view; 745 + } 746 + 747 + long arch_ptrace(struct task_struct *child, long request, long addr, long data) 748 + { 749 + long addr2 = task_pt_regs(current)->u_regs[UREG_I4]; 750 + const struct user_regset_view *view; 751 + int ret; 752 + 753 + if (test_thread_flag(TIF_32BIT)) 754 + addr2 &= 0xffffffffUL; 755 + 756 + view = task_user_regset_view(child); 188 757 189 758 switch(request) { 190 759 case PTRACE_PEEKUSR: 191 - if (addr != 0) 192 - pt_error_return(regs, EIO); 193 - else 194 - pt_succ_return(regs, 0); 195 - goto out_tsk; 760 + ret = (addr != 0) ? -EIO : 0; 761 + break; 196 762 197 763 case PTRACE_PEEKTEXT: /* read word at location addr. */ 198 764 case PTRACE_PEEKDATA: { 199 765 unsigned long tmp64; 200 766 unsigned int tmp32; 201 - int res, copied; 767 + int copied; 202 768 203 - res = -EIO; 769 + ret = -EIO; 204 770 if (test_thread_flag(TIF_32BIT)) { 205 771 copied = access_process_vm(child, addr, 206 772 &tmp32, sizeof(tmp32), 0); 207 - tmp64 = (unsigned long) tmp32; 208 773 if (copied == sizeof(tmp32)) 209 - res = 0; 774 + ret = put_user(tmp32, 775 + (unsigned int __user *) data); 210 776 } else { 211 777 copied = access_process_vm(child, addr, 212 778 &tmp64, sizeof(tmp64), 0); 213 779 if (copied == sizeof(tmp64)) 214 - res = 0; 780 + ret = put_user(tmp64, 781 + (unsigned long __user *) data); 215 782 } 216 - if (res < 0) 217 - pt_error_return(regs, -res); 218 - else 219 - pt_os_succ_return(regs, tmp64, (void __user *) data); 220 - goto out_tsk; 783 + break; 221 784 } 222 785 223 786 case PTRACE_POKETEXT: /* write the word at location addr. */ 224 787 case PTRACE_POKEDATA: { 225 788 unsigned long tmp64; 226 789 unsigned int tmp32; 227 - int copied, res = -EIO; 790 + int copied; 228 791 792 + ret = -EIO; 229 793 if (test_thread_flag(TIF_32BIT)) { 230 794 tmp32 = data; 231 795 copied = access_process_vm(child, addr, 232 796 &tmp32, sizeof(tmp32), 1); 233 797 if (copied == sizeof(tmp32)) 234 - res = 0; 798 + ret = 0; 235 799 } else { 236 800 tmp64 = data; 237 801 copied = access_process_vm(child, addr, 238 802 &tmp64, sizeof(tmp64), 1); 239 803 if (copied == sizeof(tmp64)) 240 - res = 0; 804 + ret = 0; 241 805 } 242 - if (res < 0) 243 - pt_error_return(regs, -res); 244 - else 245 - pt_succ_return(regs, res); 246 - goto out_tsk; 806 + break; 247 807 } 248 808 249 809 case PTRACE_GETREGS: { 250 810 struct pt_regs32 __user *pregs = 251 811 (struct pt_regs32 __user *) addr; 252 - struct pt_regs *cregs = task_pt_regs(child); 253 - int rval; 254 812 255 - if (__put_user(tstate_to_psr(cregs->tstate), (&pregs->psr)) || 256 - __put_user(cregs->tpc, (&pregs->pc)) || 257 - __put_user(cregs->tnpc, (&pregs->npc)) || 258 - __put_user(cregs->y, (&pregs->y))) { 259 - pt_error_return(regs, EFAULT); 260 - goto out_tsk; 261 - } 262 - for (rval = 1; rval < 16; rval++) 263 - if (__put_user(cregs->u_regs[rval], (&pregs->u_regs[rval - 1]))) { 264 - pt_error_return(regs, EFAULT); 265 - goto out_tsk; 266 - } 267 - pt_succ_return(regs, 0); 268 - #ifdef DEBUG_PTRACE 269 - printk ("PC=%lx nPC=%lx o7=%lx\n", cregs->tpc, cregs->tnpc, cregs->u_regs [15]); 270 - #endif 271 - goto out_tsk; 813 + ret = copy_regset_to_user(child, view, REGSET_GENERAL, 814 + 32 * sizeof(u32), 815 + 4 * sizeof(u32), 816 + &pregs->psr); 817 + if (!ret) 818 + ret = copy_regset_to_user(child, view, REGSET_GENERAL, 819 + 1 * sizeof(u32), 820 + 15 * sizeof(u32), 821 + &pregs->u_regs[0]); 822 + break; 272 823 } 273 824 274 825 case PTRACE_GETREGS64: { 275 826 struct pt_regs __user *pregs = (struct pt_regs __user *) addr; 276 - struct pt_regs *cregs = task_pt_regs(child); 277 - unsigned long tpc = cregs->tpc; 278 - int rval; 279 827 280 - if ((task_thread_info(child)->flags & _TIF_32BIT) != 0) 281 - tpc &= 0xffffffff; 282 - if (__put_user(cregs->tstate, (&pregs->tstate)) || 283 - __put_user(tpc, (&pregs->tpc)) || 284 - __put_user(cregs->tnpc, (&pregs->tnpc)) || 285 - __put_user(cregs->y, (&pregs->y))) { 286 - pt_error_return(regs, EFAULT); 287 - goto out_tsk; 828 + ret = copy_regset_to_user(child, view, REGSET_GENERAL, 829 + 1 * sizeof(u64), 830 + 15 * sizeof(u64), 831 + &pregs->u_regs[0]); 832 + if (!ret) { 833 + /* XXX doesn't handle 'y' register correctly XXX */ 834 + ret = copy_regset_to_user(child, view, REGSET_GENERAL, 835 + 32 * sizeof(u64), 836 + 4 * sizeof(u64), 837 + &pregs->tstate); 288 838 } 289 - for (rval = 1; rval < 16; rval++) 290 - if (__put_user(cregs->u_regs[rval], (&pregs->u_regs[rval - 1]))) { 291 - pt_error_return(regs, EFAULT); 292 - goto out_tsk; 293 - } 294 - pt_succ_return(regs, 0); 295 - #ifdef DEBUG_PTRACE 296 - printk ("PC=%lx nPC=%lx o7=%lx\n", cregs->tpc, cregs->tnpc, cregs->u_regs [15]); 297 - #endif 298 - goto out_tsk; 839 + break; 299 840 } 300 841 301 842 case PTRACE_SETREGS: { 302 843 struct pt_regs32 __user *pregs = 303 844 (struct pt_regs32 __user *) addr; 304 - struct pt_regs *cregs = task_pt_regs(child); 305 - unsigned int psr, pc, npc, y; 306 - int i; 307 845 308 - /* Must be careful, tracing process can only set certain 309 - * bits in the psr. 310 - */ 311 - if (__get_user(psr, (&pregs->psr)) || 312 - __get_user(pc, (&pregs->pc)) || 313 - __get_user(npc, (&pregs->npc)) || 314 - __get_user(y, (&pregs->y))) { 315 - pt_error_return(regs, EFAULT); 316 - goto out_tsk; 317 - } 318 - cregs->tstate &= ~(TSTATE_ICC); 319 - cregs->tstate |= psr_to_tstate_icc(psr); 320 - if (!((pc | npc) & 3)) { 321 - cregs->tpc = pc; 322 - cregs->tnpc = npc; 323 - } 324 - cregs->y = y; 325 - for (i = 1; i < 16; i++) { 326 - if (__get_user(cregs->u_regs[i], (&pregs->u_regs[i-1]))) { 327 - pt_error_return(regs, EFAULT); 328 - goto out_tsk; 329 - } 330 - } 331 - pt_succ_return(regs, 0); 332 - goto out_tsk; 846 + ret = copy_regset_from_user(child, view, REGSET_GENERAL, 847 + 32 * sizeof(u32), 848 + 4 * sizeof(u32), 849 + &pregs->psr); 850 + if (!ret) 851 + ret = copy_regset_from_user(child, view, REGSET_GENERAL, 852 + 1 * sizeof(u32), 853 + 15 * sizeof(u32), 854 + &pregs->u_regs[0]); 855 + break; 333 856 } 334 857 335 858 case PTRACE_SETREGS64: { 336 859 struct pt_regs __user *pregs = (struct pt_regs __user *) addr; 337 - struct pt_regs *cregs = task_pt_regs(child); 338 - unsigned long tstate, tpc, tnpc, y; 339 - int i; 340 860 341 - /* Must be careful, tracing process can only set certain 342 - * bits in the psr. 343 - */ 344 - if (__get_user(tstate, (&pregs->tstate)) || 345 - __get_user(tpc, (&pregs->tpc)) || 346 - __get_user(tnpc, (&pregs->tnpc)) || 347 - __get_user(y, (&pregs->y))) { 348 - pt_error_return(regs, EFAULT); 349 - goto out_tsk; 861 + ret = copy_regset_from_user(child, view, REGSET_GENERAL, 862 + 1 * sizeof(u64), 863 + 15 * sizeof(u64), 864 + &pregs->u_regs[0]); 865 + if (!ret) { 866 + /* XXX doesn't handle 'y' register correctly XXX */ 867 + ret = copy_regset_from_user(child, view, REGSET_GENERAL, 868 + 32 * sizeof(u64), 869 + 4 * sizeof(u64), 870 + &pregs->tstate); 350 871 } 351 - if ((task_thread_info(child)->flags & _TIF_32BIT) != 0) { 352 - tpc &= 0xffffffff; 353 - tnpc &= 0xffffffff; 354 - } 355 - tstate &= (TSTATE_ICC | TSTATE_XCC); 356 - cregs->tstate &= ~(TSTATE_ICC | TSTATE_XCC); 357 - cregs->tstate |= tstate; 358 - if (!((tpc | tnpc) & 3)) { 359 - cregs->tpc = tpc; 360 - cregs->tnpc = tnpc; 361 - } 362 - cregs->y = y; 363 - for (i = 1; i < 16; i++) { 364 - if (__get_user(cregs->u_regs[i], (&pregs->u_regs[i-1]))) { 365 - pt_error_return(regs, EFAULT); 366 - goto out_tsk; 367 - } 368 - } 369 - pt_succ_return(regs, 0); 370 - goto out_tsk; 872 + break; 371 873 } 372 874 373 875 case PTRACE_GETFPREGS: { ··· 825 443 } fpq[16]; 826 444 }; 827 445 struct fps __user *fps = (struct fps __user *) addr; 828 - unsigned long *fpregs = task_thread_info(child)->fpregs; 829 446 830 - if (copy_to_user(&fps->regs[0], fpregs, 831 - (32 * sizeof(unsigned int))) || 832 - __put_user(task_thread_info(child)->xfsr[0], (&fps->fsr)) || 833 - __put_user(0, (&fps->fpqd)) || 834 - __put_user(0, (&fps->flags)) || 835 - __put_user(0, (&fps->extra)) || 836 - clear_user(&fps->fpq[0], 32 * sizeof(unsigned int))) { 837 - pt_error_return(regs, EFAULT); 838 - goto out_tsk; 447 + ret = copy_regset_to_user(child, view, REGSET_FP, 448 + 0 * sizeof(u32), 449 + 32 * sizeof(u32), 450 + &fps->regs[0]); 451 + if (!ret) 452 + ret = copy_regset_to_user(child, view, REGSET_FP, 453 + 33 * sizeof(u32), 454 + 1 * sizeof(u32), 455 + &fps->fsr); 456 + if (!ret) { 457 + if (__put_user(0, &fps->flags) || 458 + __put_user(0, &fps->extra) || 459 + __put_user(0, &fps->fpqd) || 460 + clear_user(&fps->fpq[0], 32 * sizeof(unsigned int))) 461 + ret = -EFAULT; 839 462 } 840 - pt_succ_return(regs, 0); 841 - goto out_tsk; 463 + break; 842 464 } 843 465 844 466 case PTRACE_GETFPREGS64: { ··· 851 465 unsigned long fsr; 852 466 }; 853 467 struct fps __user *fps = (struct fps __user *) addr; 854 - unsigned long *fpregs = task_thread_info(child)->fpregs; 855 468 856 - if (copy_to_user(&fps->regs[0], fpregs, 857 - (64 * sizeof(unsigned int))) || 858 - __put_user(task_thread_info(child)->xfsr[0], (&fps->fsr))) { 859 - pt_error_return(regs, EFAULT); 860 - goto out_tsk; 861 - } 862 - pt_succ_return(regs, 0); 863 - goto out_tsk; 469 + ret = copy_regset_to_user(child, view, REGSET_FP, 470 + 0 * sizeof(u64), 471 + 33 * sizeof(u64), 472 + fps); 473 + break; 864 474 } 865 475 866 476 case PTRACE_SETFPREGS: { ··· 872 490 } fpq[16]; 873 491 }; 874 492 struct fps __user *fps = (struct fps __user *) addr; 875 - unsigned long *fpregs = task_thread_info(child)->fpregs; 876 - unsigned fsr; 877 493 878 - if (copy_from_user(fpregs, &fps->regs[0], 879 - (32 * sizeof(unsigned int))) || 880 - __get_user(fsr, (&fps->fsr))) { 881 - pt_error_return(regs, EFAULT); 882 - goto out_tsk; 883 - } 884 - task_thread_info(child)->xfsr[0] &= 0xffffffff00000000UL; 885 - task_thread_info(child)->xfsr[0] |= fsr; 886 - if (!(task_thread_info(child)->fpsaved[0] & FPRS_FEF)) 887 - task_thread_info(child)->gsr[0] = 0; 888 - task_thread_info(child)->fpsaved[0] |= (FPRS_FEF | FPRS_DL); 889 - pt_succ_return(regs, 0); 890 - goto out_tsk; 494 + ret = copy_regset_from_user(child, view, REGSET_FP, 495 + 0 * sizeof(u32), 496 + 32 * sizeof(u32), 497 + &fps->regs[0]); 498 + if (!ret) 499 + ret = copy_regset_from_user(child, view, REGSET_FP, 500 + 33 * sizeof(u32), 501 + 1 * sizeof(u32), 502 + &fps->fsr); 503 + break; 891 504 } 892 505 893 506 case PTRACE_SETFPREGS64: { ··· 891 514 unsigned long fsr; 892 515 }; 893 516 struct fps __user *fps = (struct fps __user *) addr; 894 - unsigned long *fpregs = task_thread_info(child)->fpregs; 895 517 896 - if (copy_from_user(fpregs, &fps->regs[0], 897 - (64 * sizeof(unsigned int))) || 898 - __get_user(task_thread_info(child)->xfsr[0], (&fps->fsr))) { 899 - pt_error_return(regs, EFAULT); 900 - goto out_tsk; 901 - } 902 - if (!(task_thread_info(child)->fpsaved[0] & FPRS_FEF)) 903 - task_thread_info(child)->gsr[0] = 0; 904 - task_thread_info(child)->fpsaved[0] |= (FPRS_FEF | FPRS_DL | FPRS_DU); 905 - pt_succ_return(regs, 0); 906 - goto out_tsk; 907 - } 908 - 909 - case PTRACE_READTEXT: 910 - case PTRACE_READDATA: { 911 - int res = ptrace_readdata(child, addr, 912 - (char __user *)addr2, data); 913 - if (res == data) { 914 - pt_succ_return(regs, 0); 915 - goto out_tsk; 916 - } 917 - if (res >= 0) 918 - res = -EIO; 919 - pt_error_return(regs, -res); 920 - goto out_tsk; 921 - } 922 - 923 - case PTRACE_WRITETEXT: 924 - case PTRACE_WRITEDATA: { 925 - int res = ptrace_writedata(child, (char __user *) addr2, 926 - addr, data); 927 - if (res == data) { 928 - pt_succ_return(regs, 0); 929 - goto out_tsk; 930 - } 931 - if (res >= 0) 932 - res = -EIO; 933 - pt_error_return(regs, -res); 934 - goto out_tsk; 935 - } 936 - case PTRACE_SYSCALL: /* continue and stop at (return from) syscall */ 937 - addr = 1; 938 - 939 - case PTRACE_CONT: { /* restart after signal. */ 940 - if (!valid_signal(data)) { 941 - pt_error_return(regs, EIO); 942 - goto out_tsk; 943 - } 944 - 945 - if (request == PTRACE_SYSCALL) { 946 - set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); 947 - } else { 948 - clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); 949 - } 950 - 951 - child->exit_code = data; 952 - #ifdef DEBUG_PTRACE 953 - printk("CONT: %s [%d]: set exit_code = %x %lx %lx\n", child->comm, 954 - child->pid, child->exit_code, 955 - task_pt_regs(child)->tpc, 956 - task_pt_regs(child)->tnpc); 957 - 958 - #endif 959 - wake_up_process(child); 960 - pt_succ_return(regs, 0); 961 - goto out_tsk; 962 - } 963 - 964 - /* 965 - * make the child exit. Best I can do is send it a sigkill. 966 - * perhaps it should be put in the status that it wants to 967 - * exit. 968 - */ 969 - case PTRACE_KILL: { 970 - if (child->exit_state == EXIT_ZOMBIE) { /* already dead */ 971 - pt_succ_return(regs, 0); 972 - goto out_tsk; 973 - } 974 - child->exit_code = SIGKILL; 975 - wake_up_process(child); 976 - pt_succ_return(regs, 0); 977 - goto out_tsk; 978 - } 979 - 980 - case PTRACE_SUNDETACH: { /* detach a process that was attached. */ 981 - int error = ptrace_detach(child, data); 982 - if (error) { 983 - pt_error_return(regs, EIO); 984 - goto out_tsk; 985 - } 986 - pt_succ_return(regs, 0); 987 - goto out_tsk; 988 - } 989 - 990 - /* PTRACE_DUMPCORE unsupported... */ 991 - 992 - case PTRACE_GETEVENTMSG: { 993 - int err; 994 - 995 - if (test_thread_flag(TIF_32BIT)) 996 - err = put_user(child->ptrace_message, 997 - (unsigned int __user *) data); 998 - else 999 - err = put_user(child->ptrace_message, 1000 - (unsigned long __user *) data); 1001 - if (err) 1002 - pt_error_return(regs, -err); 1003 - else 1004 - pt_succ_return(regs, 0); 518 + ret = copy_regset_to_user(child, view, REGSET_FP, 519 + 0 * sizeof(u64), 520 + 33 * sizeof(u64), 521 + fps); 1005 522 break; 1006 523 } 1007 524 1008 - default: { 1009 - int err = ptrace_request(child, request, addr, data); 1010 - if (err) 1011 - pt_error_return(regs, -err); 525 + case PTRACE_READTEXT: 526 + case PTRACE_READDATA: 527 + ret = ptrace_readdata(child, addr, 528 + (char __user *)addr2, data); 529 + if (ret == data) 530 + ret = 0; 531 + else if (ret >= 0) 532 + ret = -EIO; 533 + break; 534 + 535 + case PTRACE_WRITETEXT: 536 + case PTRACE_WRITEDATA: 537 + ret = ptrace_writedata(child, (char __user *) addr2, 538 + addr, data); 539 + if (ret == data) 540 + ret = 0; 541 + else if (ret >= 0) 542 + ret = -EIO; 543 + break; 544 + 545 + case PTRACE_GETEVENTMSG: { 546 + if (test_thread_flag(TIF_32BIT)) 547 + ret = put_user(child->ptrace_message, 548 + (unsigned int __user *) data); 1012 549 else 1013 - pt_succ_return(regs, 0); 1014 - goto out_tsk; 550 + ret = put_user(child->ptrace_message, 551 + (unsigned long __user *) data); 552 + break; 1015 553 } 554 + 555 + default: 556 + ret = ptrace_request(child, request, addr, data); 557 + break; 1016 558 } 1017 - out_tsk: 1018 - if (child) 1019 - put_task_struct(child); 1020 - out: 1021 - unlock_kernel(); 559 + 560 + return ret; 1022 561 } 1023 562 1024 563 asmlinkage void syscall_trace(struct pt_regs *regs, int syscall_exit_p)
+3
arch/sparc64/prom/init.c
··· 48 48 prom_getstring(node, "version", prom_version, sizeof(prom_version)); 49 49 50 50 prom_printf("\n"); 51 + } 51 52 53 + void __init prom_init_report(void) 54 + { 52 55 printk("PROMLIB: Sun IEEE Boot Prom '%s'\n", prom_version); 53 56 printk("PROMLIB: Root node compatible: %s\n", prom_root_compatible); 54 57 }
+8 -30
include/asm-sparc/elf.h
··· 65 65 #define HWCAP_SPARC_V9 16 66 66 #define HWCAP_SPARC_ULTRA3 32 67 67 68 - /* For the most part we present code dumps in the format 69 - * Solaris does. 68 + #define CORE_DUMP_USE_REGSET 69 + 70 + /* Format is: 71 + * G0 --> G7 72 + * O0 --> O7 73 + * L0 --> L7 74 + * I0 --> I7 75 + * PSR, PC, nPC, Y, WIM, TBR 70 76 */ 71 77 typedef unsigned long elf_greg_t; 72 78 #define ELF_NGREG 38 ··· 92 86 } elf_fpregset_t; 93 87 94 88 #include <asm/mbus.h> 95 - #include <asm/uaccess.h> 96 - 97 - /* Format is: 98 - * G0 --> G7 99 - * O0 --> O7 100 - * L0 --> L7 101 - * I0 --> I7 102 - * PSR, PC, nPC, Y, WIM, TBR 103 - */ 104 - #define ELF_CORE_COPY_REGS(__elf_regs, __pt_regs) \ 105 - do { unsigned long *dest = &(__elf_regs[0]); \ 106 - struct pt_regs *src = (__pt_regs); \ 107 - unsigned long __user *sp; \ 108 - memcpy(&dest[0], &src->u_regs[0], \ 109 - sizeof(unsigned long) * 16); \ 110 - /* Don't try this at home kids... */ \ 111 - sp = (unsigned long __user *) src->u_regs[14]; \ 112 - copy_from_user(&dest[16], sp, \ 113 - sizeof(unsigned long) * 16); \ 114 - dest[32] = src->psr; \ 115 - dest[33] = src->pc; \ 116 - dest[34] = src->npc; \ 117 - dest[35] = src->y; \ 118 - dest[36] = dest[37] = 0; /* XXX */ \ 119 - } while(0); /* Janitors: Don't touch this semicolon. */ 120 - 121 - #define ELF_CORE_COPY_TASK_REGS(__tsk, __elf_regs) \ 122 - ({ ELF_CORE_COPY_REGS((*(__elf_regs)), (__tsk)->thread.kregs); 1; }) 123 89 124 90 /* 125 91 * This is used to ensure we don't load something for the wrong architecture.
-7
include/asm-sparc/ptrace.h
··· 61 61 62 62 #ifdef __KERNEL__ 63 63 64 - #define __ARCH_SYS_PTRACE 1 65 - 66 64 #define user_mode(regs) (!((regs)->psr & PSR_PS)) 67 65 #define instruction_pointer(regs) ((regs)->pc) 68 66 unsigned long profile_pc(struct pt_regs *); ··· 149 151 #define SF_XXARG 0x5c 150 152 151 153 /* Stuff for the ptrace system call */ 152 - #define PTRACE_SUNATTACH 10 153 - #define PTRACE_SUNDETACH 11 154 154 #define PTRACE_GETREGS 12 155 155 #define PTRACE_SETREGS 13 156 156 #define PTRACE_GETFPREGS 14 ··· 159 163 #define PTRACE_WRITETEXT 19 160 164 #define PTRACE_GETFPAREGS 20 161 165 #define PTRACE_SETFPAREGS 21 162 - 163 - #define PTRACE_GETUCODE 29 /* stupid bsd-ism */ 164 - 165 166 166 167 #endif /* !(_SPARC_PTRACE_H) */
+5 -25
include/asm-sparc64/elf.h
··· 70 70 #define HWCAP_SPARC_BLKINIT 64 71 71 #define HWCAP_SPARC_N2 128 72 72 73 + #define CORE_DUMP_USE_REGSET 74 + 73 75 /* 74 76 * These are used to set parameters in the core dumps. 75 77 */ ··· 80 78 #define ELF_CLASS ELFCLASS64 81 79 #define ELF_DATA ELFDATA2MSB 82 80 83 - typedef unsigned long elf_greg_t; 84 - 85 - #define ELF_NGREG 36 86 - typedef elf_greg_t elf_gregset_t[ELF_NGREG]; 87 81 /* Format of 64-bit elf_gregset_t is: 88 82 * G0 --> G7 89 83 * O0 --> O7 ··· 90 92 * TNPC 91 93 * Y 92 94 */ 93 - #define ELF_CORE_COPY_REGS(__elf_regs, __pt_regs) \ 94 - do { unsigned long *dest = &(__elf_regs[0]); \ 95 - struct pt_regs *src = (__pt_regs); \ 96 - unsigned long __user *sp; \ 97 - int i; \ 98 - for(i = 0; i < 16; i++) \ 99 - dest[i] = src->u_regs[i]; \ 100 - /* Don't try this at home kids... */ \ 101 - sp = (unsigned long __user *) \ 102 - ((src->u_regs[14] + STACK_BIAS) \ 103 - & 0xfffffffffffffff8UL); \ 104 - for(i = 0; i < 16; i++) \ 105 - __get_user(dest[i+16], &sp[i]); \ 106 - dest[32] = src->tstate; \ 107 - dest[33] = src->tpc; \ 108 - dest[34] = src->tnpc; \ 109 - dest[35] = src->y; \ 110 - } while (0); 95 + typedef unsigned long elf_greg_t; 96 + #define ELF_NGREG 36 97 + typedef elf_greg_t elf_gregset_t[ELF_NGREG]; 111 98 112 99 typedef struct { 113 100 unsigned long pr_regs[32]; ··· 101 118 unsigned long pr_fprs; 102 119 } elf_fpregset_t; 103 120 #endif 104 - 105 - #define ELF_CORE_COPY_TASK_REGS(__tsk, __elf_regs) \ 106 - ({ ELF_CORE_COPY_REGS((*(__elf_regs)), task_pt_regs(__tsk)); 1; }) 107 121 108 122 /* 109 123 * This is used to ensure we don't load something for the wrong architecture.
-18
include/asm-sparc64/ptrace.h
··· 95 95 96 96 #ifdef __KERNEL__ 97 97 98 - #define __ARCH_SYS_PTRACE 1 99 - 100 98 #define force_successful_syscall_return() \ 101 99 do { current_thread_info()->syscall_noerror = 1; \ 102 100 } while (0) ··· 259 261 #define SF_XXARG 0x5c 260 262 261 263 /* Stuff for the ptrace system call */ 262 - #define PTRACE_SUNATTACH 10 263 - #define PTRACE_SUNDETACH 11 264 264 #define PTRACE_GETREGS 12 265 265 #define PTRACE_SETREGS 13 266 266 #define PTRACE_GETFPREGS 14 ··· 279 283 /* PTRACE_SYSCALL is 24 */ 280 284 #define PTRACE_GETFPREGS64 25 281 285 #define PTRACE_SETFPREGS64 26 282 - 283 - #define PTRACE_GETUCODE 29 /* stupid bsd-ism */ 284 - 285 - /* These are for 32-bit processes debugging 64-bit ones. 286 - * Here addr and addr2 are passed in %g2 and %g3 respectively. 287 - */ 288 - #define PTRACE_PEEKTEXT64 (30 + PTRACE_PEEKTEXT) 289 - #define PTRACE_POKETEXT64 (30 + PTRACE_POKETEXT) 290 - #define PTRACE_PEEKDATA64 (30 + PTRACE_PEEKDATA) 291 - #define PTRACE_POKEDATA64 (30 + PTRACE_POKEDATA) 292 - #define PTRACE_READDATA64 (30 + PTRACE_READDATA) 293 - #define PTRACE_WRITEDATA64 (30 + PTRACE_WRITEDATA) 294 - #define PTRACE_READTEXT64 (30 + PTRACE_READTEXT) 295 - #define PTRACE_WRITETEXT64 (30 + PTRACE_WRITETEXT) 296 286 297 287 #endif /* !(_SPARC64_PTRACE_H) */