aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc64/kernel')
-rw-r--r--arch/sparc64/kernel/ptrace.c101
-rw-r--r--arch/sparc64/kernel/signal32.c5
-rw-r--r--arch/sparc64/kernel/sys_sparc32.c68
-rw-r--r--arch/sparc64/kernel/systbls.S14
4 files changed, 131 insertions, 57 deletions
diff --git a/arch/sparc64/kernel/ptrace.c b/arch/sparc64/kernel/ptrace.c
index 1722dc51b0d8..5f080cf04b33 100644
--- a/arch/sparc64/kernel/ptrace.c
+++ b/arch/sparc64/kernel/ptrace.c
@@ -103,6 +103,55 @@ void ptrace_disable(struct task_struct *child)
103 /* nothing to do */ 103 /* nothing to do */
104} 104}
105 105
106/* To get the necessary page struct, access_process_vm() first calls
107 * get_user_pages(). This has done a flush_dcache_page() on the
108 * accessed page. Then our caller (copy_{to,from}_user_page()) did
109 * to memcpy to read/write the data from that page.
110 *
111 * Now, the only thing we have to do is:
112 * 1) flush the D-cache if it's possible than an illegal alias
113 * has been created
114 * 2) flush the I-cache if this is pre-cheetah and we did a write
115 */
116void flush_ptrace_access(struct vm_area_struct *vma, struct page *page,
117 unsigned long uaddr, void *kaddr,
118 unsigned long len, int write)
119{
120 BUG_ON(len > PAGE_SIZE);
121
122#ifdef DCACHE_ALIASING_POSSIBLE
123 /* If bit 13 of the kernel address we used to access the
124 * user page is the same as the virtual address that page
125 * is mapped to in the user's address space, we can skip the
126 * D-cache flush.
127 */
128 if ((uaddr ^ kaddr) & (1UL << 13)) {
129 unsigned long start = __pa(kaddr);
130 unsigned long end = start + len;
131
132 if (tlb_type == spitfire) {
133 for (; start < end; start += 32)
134 spitfire_put_dcache_tag(va & 0x3fe0, 0x0);
135 } else {
136 for (; start < end; start += 32)
137 __asm__ __volatile__(
138 "stxa %%g0, [%0] %1\n\t"
139 "membar #Sync"
140 : /* no outputs */
141 : "r" (va),
142 "i" (ASI_DCACHE_INVALIDATE));
143 }
144 }
145#endif
146 if (write && tlb_type == spitfire) {
147 unsigned long start = (unsigned long) kaddr;
148 unsigned long end = start + len;
149
150 for (; start < end; start += 32)
151 flushi(start);
152 }
153}
154
106asmlinkage void do_ptrace(struct pt_regs *regs) 155asmlinkage void do_ptrace(struct pt_regs *regs)
107{ 156{
108 int request = regs->u_regs[UREG_I0]; 157 int request = regs->u_regs[UREG_I0];
@@ -227,7 +276,7 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
227 pt_error_return(regs, -res); 276 pt_error_return(regs, -res);
228 else 277 else
229 pt_os_succ_return(regs, tmp64, (void __user *) data); 278 pt_os_succ_return(regs, tmp64, (void __user *) data);
230 goto flush_and_out; 279 goto out_tsk;
231 } 280 }
232 281
233 case PTRACE_POKETEXT: /* write the word at location addr. */ 282 case PTRACE_POKETEXT: /* write the word at location addr. */
@@ -253,7 +302,7 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
253 pt_error_return(regs, -res); 302 pt_error_return(regs, -res);
254 else 303 else
255 pt_succ_return(regs, res); 304 pt_succ_return(regs, res);
256 goto flush_and_out; 305 goto out_tsk;
257 } 306 }
258 307
259 case PTRACE_GETREGS: { 308 case PTRACE_GETREGS: {
@@ -485,12 +534,12 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
485 (char __user *)addr2, data); 534 (char __user *)addr2, data);
486 if (res == data) { 535 if (res == data) {
487 pt_succ_return(regs, 0); 536 pt_succ_return(regs, 0);
488 goto flush_and_out; 537 goto out_tsk;
489 } 538 }
490 if (res >= 0) 539 if (res >= 0)
491 res = -EIO; 540 res = -EIO;
492 pt_error_return(regs, -res); 541 pt_error_return(regs, -res);
493 goto flush_and_out; 542 goto out_tsk;
494 } 543 }
495 544
496 case PTRACE_WRITETEXT: 545 case PTRACE_WRITETEXT:
@@ -499,12 +548,12 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
499 addr, data); 548 addr, data);
500 if (res == data) { 549 if (res == data) {
501 pt_succ_return(regs, 0); 550 pt_succ_return(regs, 0);
502 goto flush_and_out; 551 goto out_tsk;
503 } 552 }
504 if (res >= 0) 553 if (res >= 0)
505 res = -EIO; 554 res = -EIO;
506 pt_error_return(regs, -res); 555 pt_error_return(regs, -res);
507 goto flush_and_out; 556 goto out_tsk;
508 } 557 }
509 case PTRACE_SYSCALL: /* continue and stop at (return from) syscall */ 558 case PTRACE_SYSCALL: /* continue and stop at (return from) syscall */
510 addr = 1; 559 addr = 1;
@@ -514,25 +563,6 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
514 pt_error_return(regs, EIO); 563 pt_error_return(regs, EIO);
515 goto out_tsk; 564 goto out_tsk;
516 } 565 }
517 if (addr != 1) {
518 unsigned long pc_mask = ~0UL;
519
520 if ((child->thread_info->flags & _TIF_32BIT) != 0)
521 pc_mask = 0xffffffff;
522
523 if (addr & 3) {
524 pt_error_return(regs, EINVAL);
525 goto out_tsk;
526 }
527#ifdef DEBUG_PTRACE
528 printk ("Original: %016lx %016lx\n",
529 child->thread_info->kregs->tpc,
530 child->thread_info->kregs->tnpc);
531 printk ("Continuing with %016lx %016lx\n", addr, addr+4);
532#endif
533 child->thread_info->kregs->tpc = (addr & pc_mask);
534 child->thread_info->kregs->tnpc = ((addr + 4) & pc_mask);
535 }
536 566
537 if (request == PTRACE_SYSCALL) { 567 if (request == PTRACE_SYSCALL) {
538 set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); 568 set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
@@ -590,27 +620,6 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
590 goto out_tsk; 620 goto out_tsk;
591 } 621 }
592 } 622 }
593flush_and_out:
594 {
595 unsigned long va;
596
597 if (tlb_type == cheetah || tlb_type == cheetah_plus) {
598 for (va = 0; va < (1 << 16); va += (1 << 5))
599 spitfire_put_dcache_tag(va, 0x0);
600 /* No need to mess with I-cache on Cheetah. */
601 } else {
602 for (va = 0; va < L1DCACHE_SIZE; va += 32)
603 spitfire_put_dcache_tag(va, 0x0);
604 if (request == PTRACE_PEEKTEXT ||
605 request == PTRACE_POKETEXT ||
606 request == PTRACE_READTEXT ||
607 request == PTRACE_WRITETEXT) {
608 for (va = 0; va < (PAGE_SIZE << 1); va += 32)
609 spitfire_put_icache_tag(va, 0x0);
610 __asm__ __volatile__("flush %g6");
611 }
612 }
613 }
614out_tsk: 623out_tsk:
615 if (child) 624 if (child)
616 put_task_struct(child); 625 put_task_struct(child);
diff --git a/arch/sparc64/kernel/signal32.c b/arch/sparc64/kernel/signal32.c
index 859255cf6762..9a375e975cff 100644
--- a/arch/sparc64/kernel/signal32.c
+++ b/arch/sparc64/kernel/signal32.c
@@ -192,10 +192,13 @@ int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
192 err |= __put_user(from->si_uid, &to->si_uid); 192 err |= __put_user(from->si_uid, &to->si_uid);
193 break; 193 break;
194 case __SI_FAULT >> 16: 194 case __SI_FAULT >> 16:
195 case __SI_POLL >> 16:
196 err |= __put_user(from->si_trapno, &to->si_trapno); 195 err |= __put_user(from->si_trapno, &to->si_trapno);
197 err |= __put_user((unsigned long)from->si_addr, &to->si_addr); 196 err |= __put_user((unsigned long)from->si_addr, &to->si_addr);
198 break; 197 break;
198 case __SI_POLL >> 16:
199 err |= __put_user(from->si_band, &to->si_band);
200 err |= __put_user(from->si_fd, &to->si_fd);
201 break;
199 case __SI_RT >> 16: /* This is not generated by the kernel as of now. */ 202 case __SI_RT >> 16: /* This is not generated by the kernel as of now. */
200 case __SI_MESGQ >> 16: 203 case __SI_MESGQ >> 16:
201 err |= __put_user(from->si_pid, &to->si_pid); 204 err |= __put_user(from->si_pid, &to->si_pid);
diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c
index 567c91c77b20..1d3aa588df8a 100644
--- a/arch/sparc64/kernel/sys_sparc32.c
+++ b/arch/sparc64/kernel/sys_sparc32.c
@@ -352,11 +352,11 @@ int cp_compat_stat(struct kstat *stat, struct compat_stat __user *statbuf)
352 err |= put_user(old_encode_dev(stat->rdev), &statbuf->st_rdev); 352 err |= put_user(old_encode_dev(stat->rdev), &statbuf->st_rdev);
353 err |= put_user(stat->size, &statbuf->st_size); 353 err |= put_user(stat->size, &statbuf->st_size);
354 err |= put_user(stat->atime.tv_sec, &statbuf->st_atime); 354 err |= put_user(stat->atime.tv_sec, &statbuf->st_atime);
355 err |= put_user(0, &statbuf->__unused1); 355 err |= put_user(stat->atime.tv_nsec, &statbuf->st_atime_nsec);
356 err |= put_user(stat->mtime.tv_sec, &statbuf->st_mtime); 356 err |= put_user(stat->mtime.tv_sec, &statbuf->st_mtime);
357 err |= put_user(0, &statbuf->__unused2); 357 err |= put_user(stat->mtime.tv_nsec, &statbuf->st_mtime_nsec);
358 err |= put_user(stat->ctime.tv_sec, &statbuf->st_ctime); 358 err |= put_user(stat->ctime.tv_sec, &statbuf->st_ctime);
359 err |= put_user(0, &statbuf->__unused3); 359 err |= put_user(stat->ctime.tv_nsec, &statbuf->st_ctime_nsec);
360 err |= put_user(stat->blksize, &statbuf->st_blksize); 360 err |= put_user(stat->blksize, &statbuf->st_blksize);
361 err |= put_user(stat->blocks, &statbuf->st_blocks); 361 err |= put_user(stat->blocks, &statbuf->st_blocks);
362 err |= put_user(0, &statbuf->__unused4[0]); 362 err |= put_user(0, &statbuf->__unused4[0]);
@@ -365,6 +365,68 @@ int cp_compat_stat(struct kstat *stat, struct compat_stat __user *statbuf)
365 return err; 365 return err;
366} 366}
367 367
368int cp_compat_stat64(struct kstat *stat, struct compat_stat64 __user *statbuf)
369{
370 int err;
371
372 err = put_user(huge_encode_dev(stat->dev), &statbuf->st_dev);
373 err |= put_user(stat->ino, &statbuf->st_ino);
374 err |= put_user(stat->mode, &statbuf->st_mode);
375 err |= put_user(stat->nlink, &statbuf->st_nlink);
376 err |= put_user(stat->uid, &statbuf->st_uid);
377 err |= put_user(stat->gid, &statbuf->st_gid);
378 err |= put_user(huge_encode_dev(stat->rdev), &statbuf->st_rdev);
379 err |= put_user(0, (unsigned long __user *) &statbuf->__pad3[0]);
380 err |= put_user(stat->size, &statbuf->st_size);
381 err |= put_user(stat->blksize, &statbuf->st_blksize);
382 err |= put_user(0, (unsigned int __user *) &statbuf->__pad4[0]);
383 err |= put_user(0, (unsigned int __user *) &statbuf->__pad4[4]);
384 err |= put_user(stat->blocks, &statbuf->st_blocks);
385 err |= put_user(stat->atime.tv_sec, &statbuf->st_atime);
386 err |= put_user(stat->atime.tv_nsec, &statbuf->st_atime_nsec);
387 err |= put_user(stat->mtime.tv_sec, &statbuf->st_mtime);
388 err |= put_user(stat->mtime.tv_nsec, &statbuf->st_mtime_nsec);
389 err |= put_user(stat->ctime.tv_sec, &statbuf->st_ctime);
390 err |= put_user(stat->ctime.tv_nsec, &statbuf->st_ctime_nsec);
391 err |= put_user(0, &statbuf->__unused4);
392 err |= put_user(0, &statbuf->__unused5);
393
394 return err;
395}
396
397asmlinkage long compat_sys_stat64(char __user * filename,
398 struct compat_stat64 __user *statbuf)
399{
400 struct kstat stat;
401 int error = vfs_stat(filename, &stat);
402
403 if (!error)
404 error = cp_compat_stat64(&stat, statbuf);
405 return error;
406}
407
408asmlinkage long compat_sys_lstat64(char __user * filename,
409 struct compat_stat64 __user *statbuf)
410{
411 struct kstat stat;
412 int error = vfs_lstat(filename, &stat);
413
414 if (!error)
415 error = cp_compat_stat64(&stat, statbuf);
416 return error;
417}
418
419asmlinkage long compat_sys_fstat64(unsigned int fd,
420 struct compat_stat64 __user * statbuf)
421{
422 struct kstat stat;
423 int error = vfs_fstat(fd, &stat);
424
425 if (!error)
426 error = cp_compat_stat64(&stat, statbuf);
427 return error;
428}
429
368asmlinkage long compat_sys_sysfs(int option, u32 arg1, u32 arg2) 430asmlinkage long compat_sys_sysfs(int option, u32 arg1, u32 arg2)
369{ 431{
370 return sys_sysfs(option, arg1, arg2); 432 return sys_sysfs(option, arg1, arg2);
diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S
index 48170f77fff1..a5e36a4c8924 100644
--- a/arch/sparc64/kernel/systbls.S
+++ b/arch/sparc64/kernel/systbls.S
@@ -32,7 +32,7 @@ sys_call_table32:
32 .word sys32_umount, sys32_setgid16, sys32_getgid16, sys32_signal, sys32_geteuid16 32 .word sys32_umount, sys32_setgid16, sys32_getgid16, sys32_signal, sys32_geteuid16
33/*50*/ .word sys32_getegid16, sys_acct, sys_nis_syscall, sys_getgid, compat_sys_ioctl 33/*50*/ .word sys32_getegid16, sys_acct, sys_nis_syscall, sys_getgid, compat_sys_ioctl
34 .word sys32_reboot, sys32_mmap2, sys_symlink, sys32_readlink, sys32_execve 34 .word sys32_reboot, sys32_mmap2, sys_symlink, sys32_readlink, sys32_execve
35/*60*/ .word sys32_umask, sys_chroot, compat_sys_newfstat, sys_fstat64, sys_getpagesize 35/*60*/ .word sys32_umask, sys_chroot, compat_sys_newfstat, compat_sys_fstat64, sys_getpagesize
36 .word sys32_msync, sys_vfork, sys32_pread64, sys32_pwrite64, sys_geteuid 36 .word sys32_msync, sys_vfork, sys32_pread64, sys32_pwrite64, sys_geteuid
37/*70*/ .word sys_getegid, sys_mmap, sys_setreuid, sys_munmap, sys_mprotect 37/*70*/ .word sys_getegid, sys_mmap, sys_setreuid, sys_munmap, sys_mprotect
38 .word sys_madvise, sys_vhangup, sys32_truncate64, sys_mincore, sys32_getgroups16 38 .word sys_madvise, sys_vhangup, sys32_truncate64, sys_mincore, sys32_getgroups16
@@ -46,8 +46,8 @@ sys_call_table32:
46 .word sys32_getgroups, sys32_gettimeofday, sys32_getrusage, sys_nis_syscall, sys_getcwd 46 .word sys32_getgroups, sys32_gettimeofday, sys32_getrusage, sys_nis_syscall, sys_getcwd
47/*120*/ .word compat_sys_readv, compat_sys_writev, sys32_settimeofday, sys32_fchown16, sys_fchmod 47/*120*/ .word compat_sys_readv, compat_sys_writev, sys32_settimeofday, sys32_fchown16, sys_fchmod
48 .word sys_nis_syscall, sys32_setreuid16, sys32_setregid16, sys_rename, sys_truncate 48 .word sys_nis_syscall, sys32_setreuid16, sys32_setregid16, sys_rename, sys_truncate
49/*130*/ .word sys_ftruncate, sys_flock, sys_lstat64, sys_nis_syscall, sys_nis_syscall 49/*130*/ .word sys_ftruncate, sys_flock, compat_sys_lstat64, sys_nis_syscall, sys_nis_syscall
50 .word sys_nis_syscall, sys32_mkdir, sys_rmdir, sys32_utimes, sys_stat64 50 .word sys_nis_syscall, sys32_mkdir, sys_rmdir, sys32_utimes, compat_sys_stat64
51/*140*/ .word sys32_sendfile64, sys_nis_syscall, sys32_futex, sys_gettid, compat_sys_getrlimit 51/*140*/ .word sys32_sendfile64, sys_nis_syscall, sys32_futex, sys_gettid, compat_sys_getrlimit
52 .word compat_sys_setrlimit, sys_pivot_root, sys32_prctl, sys_pciconfig_read, sys_pciconfig_write 52 .word compat_sys_setrlimit, sys_pivot_root, sys32_prctl, sys_pciconfig_read, sys_pciconfig_write
53/*150*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_getdents64 53/*150*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_getdents64
@@ -75,7 +75,7 @@ sys_call_table32:
75/*260*/ .word compat_sys_sched_getaffinity, compat_sys_sched_setaffinity, sys32_timer_settime, compat_sys_timer_gettime, sys_timer_getoverrun 75/*260*/ .word compat_sys_sched_getaffinity, compat_sys_sched_setaffinity, sys32_timer_settime, compat_sys_timer_gettime, sys_timer_getoverrun
76 .word sys_timer_delete, sys32_timer_create, sys_ni_syscall, compat_sys_io_setup, sys_io_destroy 76 .word sys_timer_delete, sys32_timer_create, sys_ni_syscall, compat_sys_io_setup, sys_io_destroy
77/*270*/ .word sys32_io_submit, sys_io_cancel, compat_sys_io_getevents, sys32_mq_open, sys_mq_unlink 77/*270*/ .word sys32_io_submit, sys_io_cancel, compat_sys_io_getevents, sys32_mq_open, sys_mq_unlink
78 .word sys_mq_timedsend, sys_mq_timedreceive, compat_sys_mq_notify, compat_sys_mq_getsetattr, compat_sys_waitid 78 .word compat_sys_mq_timedsend, compat_sys_mq_timedreceive, compat_sys_mq_notify, compat_sys_mq_getsetattr, compat_sys_waitid
79/*280*/ .word sys_ni_syscall, sys_add_key, sys_request_key, sys_keyctl 79/*280*/ .word sys_ni_syscall, sys_add_key, sys_request_key, sys_keyctl
80 80
81#endif /* CONFIG_COMPAT */ 81#endif /* CONFIG_COMPAT */
@@ -98,7 +98,7 @@ sys_call_table:
98 .word sys_umount, sys_setgid, sys_getgid, sys_signal, sys_geteuid 98 .word sys_umount, sys_setgid, sys_getgid, sys_signal, sys_geteuid
99/*50*/ .word sys_getegid, sys_acct, sys_memory_ordering, sys_nis_syscall, sys_ioctl 99/*50*/ .word sys_getegid, sys_acct, sys_memory_ordering, sys_nis_syscall, sys_ioctl
100 .word sys_reboot, sys_nis_syscall, sys_symlink, sys_readlink, sys_execve 100 .word sys_reboot, sys_nis_syscall, sys_symlink, sys_readlink, sys_execve
101/*60*/ .word sys_umask, sys_chroot, sys_newfstat, sys_nis_syscall, sys_getpagesize 101/*60*/ .word sys_umask, sys_chroot, sys_newfstat, sys_stat64, sys_getpagesize
102 .word sys_msync, sys_vfork, sys_pread64, sys_pwrite64, sys_nis_syscall 102 .word sys_msync, sys_vfork, sys_pread64, sys_pwrite64, sys_nis_syscall
103/*70*/ .word sys_nis_syscall, sys_mmap, sys_nis_syscall, sys64_munmap, sys_mprotect 103/*70*/ .word sys_nis_syscall, sys_mmap, sys_nis_syscall, sys64_munmap, sys_mprotect
104 .word sys_madvise, sys_vhangup, sys_nis_syscall, sys_mincore, sys_getgroups 104 .word sys_madvise, sys_vhangup, sys_nis_syscall, sys_mincore, sys_getgroups
@@ -112,8 +112,8 @@ sys_call_table:
112 .word sys_nis_syscall, sys_gettimeofday, sys_getrusage, sys_getsockopt, sys_getcwd 112 .word sys_nis_syscall, sys_gettimeofday, sys_getrusage, sys_getsockopt, sys_getcwd
113/*120*/ .word sys_readv, sys_writev, sys_settimeofday, sys_fchown, sys_fchmod 113/*120*/ .word sys_readv, sys_writev, sys_settimeofday, sys_fchown, sys_fchmod
114 .word sys_recvfrom, sys_setreuid, sys_setregid, sys_rename, sys_truncate 114 .word sys_recvfrom, sys_setreuid, sys_setregid, sys_rename, sys_truncate
115/*130*/ .word sys_ftruncate, sys_flock, sys_nis_syscall, sys_sendto, sys_shutdown 115/*130*/ .word sys_ftruncate, sys_flock, sys_lstat64, sys_sendto, sys_shutdown
116 .word sys_socketpair, sys_mkdir, sys_rmdir, sys_utimes, sys_nis_syscall 116 .word sys_socketpair, sys_mkdir, sys_rmdir, sys_utimes, sys_stat64
117/*140*/ .word sys_sendfile64, sys_getpeername, sys_futex, sys_gettid, sys_getrlimit 117/*140*/ .word sys_sendfile64, sys_getpeername, sys_futex, sys_gettid, sys_getrlimit
118 .word sys_setrlimit, sys_pivot_root, sys_prctl, sys_pciconfig_read, sys_pciconfig_write 118 .word sys_setrlimit, sys_pivot_root, sys_prctl, sys_pciconfig_read, sys_pciconfig_write
119/*150*/ .word sys_getsockname, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_getdents64 119/*150*/ .word sys_getsockname, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_getdents64