diff options
Diffstat (limited to 'arch/sparc64')
| -rw-r--r-- | arch/sparc64/kernel/power.c | 2 | ||||
| -rw-r--r-- | arch/sparc64/kernel/process.c | 4 | ||||
| -rw-r--r-- | arch/sparc64/kernel/systbls.S | 8 | ||||
| -rw-r--r-- | arch/sparc64/mm/init.c | 23 | ||||
| -rw-r--r-- | arch/sparc64/solaris/socket.c | 193 |
5 files changed, 140 insertions, 90 deletions
diff --git a/arch/sparc64/kernel/power.c b/arch/sparc64/kernel/power.c index 533104c7907d..946cee0257ea 100644 --- a/arch/sparc64/kernel/power.c +++ b/arch/sparc64/kernel/power.c @@ -69,8 +69,6 @@ void machine_power_off(void) machine_halt(); } -EXPORT_SYMBOL(machine_power_off); - #ifdef CONFIG_PCI static int powerd(void *__unused) { diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c index cffb1c8ab4fc..07424b075938 100644 --- a/arch/sparc64/kernel/process.c +++ b/arch/sparc64/kernel/process.c @@ -124,8 +124,6 @@ void machine_halt(void) panic("Halt failed!"); } -EXPORT_SYMBOL(machine_halt); - void machine_alt_power_off(void) { if (!serial_console && prom_palette) @@ -154,8 +152,6 @@ void machine_restart(char * cmd) panic("Reboot failed!"); } -EXPORT_SYMBOL(machine_restart); - static void show_regwindow32(struct pt_regs *regs) { struct reg_window32 __user *rw; diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S index bceb91a8a2bd..53eaf2345fe9 100644 --- a/arch/sparc64/kernel/systbls.S +++ b/arch/sparc64/kernel/systbls.S @@ -50,8 +50,8 @@ sys_call_table32: .word sys_nis_syscall, sys32_mkdir, sys_rmdir, sys32_utimes, compat_sys_stat64 /*140*/ .word sys32_sendfile64, sys_nis_syscall, sys32_futex, sys_gettid, compat_sys_getrlimit .word compat_sys_setrlimit, sys_pivot_root, sys32_prctl, sys_pciconfig_read, sys_pciconfig_write -/*150*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_getdents64 - .word compat_sys_fcntl64, sys_ni_syscall, compat_sys_statfs, compat_sys_fstatfs, sys_oldumount +/*150*/ .word sys_nis_syscall, sys_inotify_init, sys_inotify_add_watch, sys_poll, sys_getdents64 + .word compat_sys_fcntl64, sys_inotify_rm_watch, compat_sys_statfs, compat_sys_fstatfs, sys_oldumount /*160*/ .word compat_sys_sched_setaffinity, compat_sys_sched_getaffinity, sys32_getdomainname, sys32_setdomainname, sys_nis_syscall .word sys_quotactl, sys_set_tid_address, compat_sys_mount, sys_ustat, sys32_setxattr /*170*/ .word sys32_lsetxattr, sys32_fsetxattr, sys_getxattr, sys_lgetxattr, compat_sys_getdents @@ -116,8 +116,8 @@ sys_call_table: .word sys_socketpair, sys_mkdir, sys_rmdir, sys_utimes, sys_stat64 /*140*/ .word sys_sendfile64, sys_getpeername, sys_futex, sys_gettid, sys_getrlimit .word sys_setrlimit, sys_pivot_root, sys_prctl, sys_pciconfig_read, sys_pciconfig_write -/*150*/ .word sys_getsockname, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_getdents64 - .word sys_nis_syscall, sys_ni_syscall, sys_statfs, sys_fstatfs, sys_oldumount +/*150*/ .word sys_getsockname, sys_inotify_init, sys_inotify_add_watch, sys_poll, sys_getdents64 + .word sys_nis_syscall, sys_inotify_rm_watch, sys_statfs, sys_fstatfs, sys_oldumount /*160*/ .word sys_sched_setaffinity, sys_sched_getaffinity, sys_getdomainname, sys_setdomainname, sys_utrap_install .word sys_quotactl, sys_set_tid_address, sys_mount, sys_ustat, sys_setxattr /*170*/ .word sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, sys_getdents diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c index 8fc413cb6acd..3fbaf342a452 100644 --- a/arch/sparc64/mm/init.c +++ b/arch/sparc64/mm/init.c @@ -121,15 +121,24 @@ __inline__ void flush_dcache_page_impl(struct page *page) } #define PG_dcache_dirty PG_arch_1 +#define PG_dcache_cpu_shift 24 +#define PG_dcache_cpu_mask (256 - 1) + +#if NR_CPUS > 256 +#error D-cache dirty tracking and thread_info->cpu need fixing for > 256 cpus +#endif #define dcache_dirty_cpu(page) \ - (((page)->flags >> 24) & (NR_CPUS - 1UL)) + (((page)->flags >> PG_dcache_cpu_shift) & PG_dcache_cpu_mask) static __inline__ void set_dcache_dirty(struct page *page, int this_cpu) { unsigned long mask = this_cpu; - unsigned long non_cpu_bits = ~((NR_CPUS - 1UL) << 24UL); - mask = (mask << 24) | (1UL << PG_dcache_dirty); + unsigned long non_cpu_bits; + + non_cpu_bits = ~(PG_dcache_cpu_mask << PG_dcache_cpu_shift); + mask = (mask << PG_dcache_cpu_shift) | (1UL << PG_dcache_dirty); + __asm__ __volatile__("1:\n\t" "ldx [%2], %%g7\n\t" "and %%g7, %1, %%g1\n\t" @@ -151,7 +160,7 @@ static __inline__ void clear_dcache_dirty_cpu(struct page *page, unsigned long c __asm__ __volatile__("! test_and_clear_dcache_dirty\n" "1:\n\t" "ldx [%2], %%g7\n\t" - "srlx %%g7, 24, %%g1\n\t" + "srlx %%g7, %4, %%g1\n\t" "and %%g1, %3, %%g1\n\t" "cmp %%g1, %0\n\t" "bne,pn %%icc, 2f\n\t" @@ -164,7 +173,8 @@ static __inline__ void clear_dcache_dirty_cpu(struct page *page, unsigned long c "2:" : /* no outputs */ : "r" (cpu), "r" (mask), "r" (&page->flags), - "i" (NR_CPUS - 1UL) + "i" (PG_dcache_cpu_mask), + "i" (PG_dcache_cpu_shift) : "g1", "g7"); } @@ -180,7 +190,8 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t p if (pfn_valid(pfn) && (page = pfn_to_page(pfn), page_mapping(page)) && ((pg_flags = page->flags) & (1UL << PG_dcache_dirty))) { - int cpu = ((pg_flags >> 24) & (NR_CPUS - 1UL)); + int cpu = ((pg_flags >> PG_dcache_cpu_shift) & + PG_dcache_cpu_mask); int this_cpu = get_cpu(); /* This is just to optimize away some function calls diff --git a/arch/sparc64/solaris/socket.c b/arch/sparc64/solaris/socket.c index 06740582717e..d3a66ea74a7f 100644 --- a/arch/sparc64/solaris/socket.c +++ b/arch/sparc64/solaris/socket.c @@ -16,6 +16,7 @@ #include <linux/net.h> #include <linux/compat.h> #include <net/compat.h> +#include <net/sock.h> #include <asm/uaccess.h> #include <asm/string.h> @@ -297,121 +298,165 @@ asmlinkage int solaris_sendmsg(int fd, struct sol_nmsghdr __user *user_msg, unsi { struct socket *sock; char address[MAX_SOCK_ADDR]; - struct iovec iov[UIO_FASTIOV]; + struct iovec iovstack[UIO_FASTIOV], *iov = iovstack; unsigned char ctl[sizeof(struct cmsghdr) + 20]; unsigned char *ctl_buf = ctl; - struct msghdr kern_msg; - int err, total_len; + struct msghdr msg_sys; + int err, ctl_len, iov_size, total_len; - if(msghdr_from_user32_to_kern(&kern_msg, user_msg)) - return -EFAULT; - if(kern_msg.msg_iovlen > UIO_MAXIOV) - return -EINVAL; - err = verify_compat_iovec(&kern_msg, iov, address, VERIFY_READ); - if (err < 0) + err = -EFAULT; + if (msghdr_from_user32_to_kern(&msg_sys, user_msg)) + goto out; + + sock = sockfd_lookup(fd, &err); + if (!sock) goto out; + + /* do not move before msg_sys is valid */ + err = -EMSGSIZE; + if (msg_sys.msg_iovlen > UIO_MAXIOV) + goto out_put; + + /* Check whether to allocate the iovec area*/ + err = -ENOMEM; + iov_size = msg_sys.msg_iovlen * sizeof(struct iovec); + if (msg_sys.msg_iovlen > UIO_FASTIOV) { + iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL); + if (!iov) + goto out_put; + } + + err = verify_compat_iovec(&msg_sys, iov, address, VERIFY_READ); + if (err < 0) + goto out_freeiov; total_len = err; - if(kern_msg.msg_controllen) { - struct sol_cmsghdr __user *ucmsg = kern_msg.msg_control; + err = -ENOBUFS; + if (msg_sys.msg_controllen > INT_MAX) + goto out_freeiov; + + ctl_len = msg_sys.msg_controllen; + if (ctl_len) { + struct sol_cmsghdr __user *ucmsg = msg_sys.msg_control; unsigned long *kcmsg; compat_size_t cmlen; - if (kern_msg.msg_controllen <= sizeof(compat_size_t)) - return -EINVAL; + err = -EINVAL; + if (ctl_len <= sizeof(compat_size_t)) + goto out_freeiov; - if(kern_msg.msg_controllen > sizeof(ctl)) { + if (ctl_len > sizeof(ctl)) { err = -ENOBUFS; - ctl_buf = kmalloc(kern_msg.msg_controllen, GFP_KERNEL); - if(!ctl_buf) + ctl_buf = kmalloc(ctl_len, GFP_KERNEL); + if (!ctl_buf) goto out_freeiov; } __get_user(cmlen, &ucmsg->cmsg_len); kcmsg = (unsigned long *) ctl_buf; *kcmsg++ = (unsigned long)cmlen; err = -EFAULT; - if(copy_from_user(kcmsg, &ucmsg->cmsg_level, - kern_msg.msg_controllen - sizeof(compat_size_t))) + if (copy_from_user(kcmsg, &ucmsg->cmsg_level, + ctl_len - sizeof(compat_size_t))) goto out_freectl; - kern_msg.msg_control = ctl_buf; + msg_sys.msg_control = ctl_buf; } - kern_msg.msg_flags = solaris_to_linux_msgflags(user_flags); + msg_sys.msg_flags = solaris_to_linux_msgflags(user_flags); - lock_kernel(); - sock = sockfd_lookup(fd, &err); - if (sock != NULL) { - if (sock->file->f_flags & O_NONBLOCK) - kern_msg.msg_flags |= MSG_DONTWAIT; - err = sock_sendmsg(sock, &kern_msg, total_len); - sockfd_put(sock); - } - unlock_kernel(); + if (sock->file->f_flags & O_NONBLOCK) + msg_sys.msg_flags |= MSG_DONTWAIT; + err = sock_sendmsg(sock, &msg_sys, total_len); out_freectl: - /* N.B. Use kfree here, as kern_msg.msg_controllen might change? */ - if(ctl_buf != ctl) - kfree(ctl_buf); + if (ctl_buf != ctl) + sock_kfree_s(sock->sk, ctl_buf, ctl_len); out_freeiov: - if(kern_msg.msg_iov != iov) - kfree(kern_msg.msg_iov); -out: + if (iov != iovstack) + sock_kfree_s(sock->sk, iov, iov_size); +out_put: + sockfd_put(sock); +out: return err; } asmlinkage int solaris_recvmsg(int fd, struct sol_nmsghdr __user *user_msg, unsigned int user_flags) { - struct iovec iovstack[UIO_FASTIOV]; - struct msghdr kern_msg; - char addr[MAX_SOCK_ADDR]; struct socket *sock; + struct iovec iovstack[UIO_FASTIOV]; struct iovec *iov = iovstack; + struct msghdr msg_sys; + unsigned long cmsg_ptr; + int err, iov_size, total_len, len; + + /* kernel mode address */ + char addr[MAX_SOCK_ADDR]; + + /* user mode address pointers */ struct sockaddr __user *uaddr; int __user *uaddr_len; - unsigned long cmsg_ptr; - int err, total_len, len = 0; - if(msghdr_from_user32_to_kern(&kern_msg, user_msg)) + if (msghdr_from_user32_to_kern(&msg_sys, user_msg)) return -EFAULT; - if(kern_msg.msg_iovlen > UIO_MAXIOV) - return -EINVAL; - uaddr = kern_msg.msg_name; + sock = sockfd_lookup(fd, &err); + if (!sock) + goto out; + + err = -EMSGSIZE; + if (msg_sys.msg_iovlen > UIO_MAXIOV) + goto out_put; + + /* Check whether to allocate the iovec area*/ + err = -ENOMEM; + iov_size = msg_sys.msg_iovlen * sizeof(struct iovec); + if (msg_sys.msg_iovlen > UIO_FASTIOV) { + iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL); + if (!iov) + goto out_put; + } + + /* + * Save the user-mode address (verify_iovec will change the + * kernel msghdr to use the kernel address space) + */ + + uaddr = (void __user *) msg_sys.msg_name; uaddr_len = &user_msg->msg_namelen; - err = verify_compat_iovec(&kern_msg, iov, addr, VERIFY_WRITE); + err = verify_compat_iovec(&msg_sys, iov, addr, VERIFY_WRITE); if (err < 0) - goto out; + goto out_freeiov; total_len = err; - cmsg_ptr = (unsigned long) kern_msg.msg_control; - kern_msg.msg_flags = 0; + cmsg_ptr = (unsigned long) msg_sys.msg_control; + msg_sys.msg_flags = MSG_CMSG_COMPAT; - lock_kernel(); - sock = sockfd_lookup(fd, &err); - if (sock != NULL) { - if (sock->file->f_flags & O_NONBLOCK) - user_flags |= MSG_DONTWAIT; - err = sock_recvmsg(sock, &kern_msg, total_len, user_flags); - if(err >= 0) - len = err; - sockfd_put(sock); - } - unlock_kernel(); - - if(uaddr != NULL && err >= 0) - err = move_addr_to_user(addr, kern_msg.msg_namelen, uaddr, uaddr_len); - if(err >= 0) { - err = __put_user(linux_to_solaris_msgflags(kern_msg.msg_flags), &user_msg->msg_flags); - if(!err) { - /* XXX Convert cmsg back into userspace 32-bit format... */ - err = __put_user((unsigned long)kern_msg.msg_control - cmsg_ptr, - &user_msg->msg_controllen); - } + if (sock->file->f_flags & O_NONBLOCK) + user_flags |= MSG_DONTWAIT; + + err = sock_recvmsg(sock, &msg_sys, total_len, user_flags); + if(err < 0) + goto out_freeiov; + + len = err; + + if (uaddr != NULL) { + err = move_addr_to_user(addr, msg_sys.msg_namelen, uaddr, uaddr_len); + if (err < 0) + goto out_freeiov; } + err = __put_user(linux_to_solaris_msgflags(msg_sys.msg_flags), &user_msg->msg_flags); + if (err) + goto out_freeiov; + err = __put_user((unsigned long)msg_sys.msg_control - cmsg_ptr, + &user_msg->msg_controllen); + if (err) + goto out_freeiov; + err = len; - if(kern_msg.msg_iov != iov) - kfree(kern_msg.msg_iov); +out_freeiov: + if (iov != iovstack) + sock_kfree_s(sock->sk, iov, iov_size); +out_put: + sockfd_put(sock); out: - if(err < 0) - return err; - return len; + return err; } |
