diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-11-01 20:48:19 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-11-01 20:48:19 -0400 |
| commit | c660b8f944f1815494a76935148571276fa47462 (patch) | |
| tree | a6b98740870bb455e477782ad46c4a7d3892f1da | |
| parent | 8c23f406c6d86808726ace580657186bc3b44587 (diff) | |
| parent | dc241f2c1761bfdec85915f4bbf7e750663f3442 (diff) | |
Merge tag 'xtensa-next-20121101' of git://github.com/czankel/xtensa-linux
Pull Xtensa fixes from Chris Zankel:
"Some important bug fixes.
With the change to uapi, there was a bug introduced that results in an
empty syscall table (mult-inclusion bug). Switching to the generic
thread/execve allowed us to fix a bug we had in vfork()."
* tag 'xtensa-next-20121101' of git://github.com/czankel/xtensa-linux:
xtensa: switch to generic sys_execve()
xtensa: switch to generic kernel_execve()
xtensa: switch to generic kernel_thread()
xtensa: reset windowbase/windowstart when cloning the VM
xtensa: use physical addresses for bus addresses
xtensa: allow multi-inclusion for uapi/unistd.h
| -rw-r--r-- | arch/xtensa/Kconfig | 2 | ||||
| -rw-r--r-- | arch/xtensa/include/asm/io.h | 4 | ||||
| -rw-r--r-- | arch/xtensa/include/asm/processor.h | 4 | ||||
| -rw-r--r-- | arch/xtensa/include/asm/syscall.h | 2 | ||||
| -rw-r--r-- | arch/xtensa/include/asm/unistd.h | 15 | ||||
| -rw-r--r-- | arch/xtensa/include/uapi/asm/unistd.h | 16 | ||||
| -rw-r--r-- | arch/xtensa/kernel/entry.S | 57 | ||||
| -rw-r--r-- | arch/xtensa/kernel/process.c | 128 | ||||
| -rw-r--r-- | arch/xtensa/kernel/syscall.c | 7 | ||||
| -rw-r--r-- | arch/xtensa/kernel/xtensa_ksyms.c | 1 |
10 files changed, 104 insertions, 132 deletions
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig index cdcb48adee4c..0d1f36a22c98 100644 --- a/arch/xtensa/Kconfig +++ b/arch/xtensa/Kconfig | |||
| @@ -13,6 +13,8 @@ config XTENSA | |||
| 13 | select GENERIC_CPU_DEVICES | 13 | select GENERIC_CPU_DEVICES |
| 14 | select MODULES_USE_ELF_RELA | 14 | select MODULES_USE_ELF_RELA |
| 15 | select GENERIC_PCI_IOMAP | 15 | select GENERIC_PCI_IOMAP |
| 16 | select GENERIC_KERNEL_THREAD | ||
| 17 | select GENERIC_KERNEL_EXECVE | ||
| 16 | select ARCH_WANT_OPTIONAL_GPIOLIB | 18 | select ARCH_WANT_OPTIONAL_GPIOLIB |
| 17 | help | 19 | help |
| 18 | Xtensa processors are 32-bit RISC machines designed by Tensilica | 20 | Xtensa processors are 32-bit RISC machines designed by Tensilica |
diff --git a/arch/xtensa/include/asm/io.h b/arch/xtensa/include/asm/io.h index e6be5b9091c2..700c2e6f2d25 100644 --- a/arch/xtensa/include/asm/io.h +++ b/arch/xtensa/include/asm/io.h | |||
| @@ -62,6 +62,10 @@ static inline void __iomem *ioremap(unsigned long offset, unsigned long size) | |||
| 62 | static inline void iounmap(volatile void __iomem *addr) | 62 | static inline void iounmap(volatile void __iomem *addr) |
| 63 | { | 63 | { |
| 64 | } | 64 | } |
| 65 | |||
| 66 | #define virt_to_bus virt_to_phys | ||
| 67 | #define bus_to_virt phys_to_virt | ||
| 68 | |||
| 65 | #endif /* CONFIG_MMU */ | 69 | #endif /* CONFIG_MMU */ |
| 66 | 70 | ||
| 67 | /* | 71 | /* |
diff --git a/arch/xtensa/include/asm/processor.h b/arch/xtensa/include/asm/processor.h index 5c371d8d4528..2d630e7399ca 100644 --- a/arch/xtensa/include/asm/processor.h +++ b/arch/xtensa/include/asm/processor.h | |||
| @@ -152,6 +152,7 @@ struct thread_struct { | |||
| 152 | 152 | ||
| 153 | /* Clearing a0 terminates the backtrace. */ | 153 | /* Clearing a0 terminates the backtrace. */ |
| 154 | #define start_thread(regs, new_pc, new_sp) \ | 154 | #define start_thread(regs, new_pc, new_sp) \ |
| 155 | memset(regs, 0, sizeof(*regs)); \ | ||
| 155 | regs->pc = new_pc; \ | 156 | regs->pc = new_pc; \ |
| 156 | regs->ps = USER_PS_VALUE; \ | 157 | regs->ps = USER_PS_VALUE; \ |
| 157 | regs->areg[1] = new_sp; \ | 158 | regs->areg[1] = new_sp; \ |
| @@ -168,9 +169,6 @@ struct mm_struct; | |||
| 168 | /* Free all resources held by a thread. */ | 169 | /* Free all resources held by a thread. */ |
| 169 | #define release_thread(thread) do { } while(0) | 170 | #define release_thread(thread) do { } while(0) |
| 170 | 171 | ||
| 171 | /* Create a kernel thread without removing it from tasklists */ | ||
| 172 | extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | ||
| 173 | |||
| 174 | /* Copy and release all segment info associated with a VM */ | 172 | /* Copy and release all segment info associated with a VM */ |
| 175 | #define copy_segments(p, mm) do { } while(0) | 173 | #define copy_segments(p, mm) do { } while(0) |
| 176 | #define release_segments(mm) do { } while(0) | 174 | #define release_segments(mm) do { } while(0) |
diff --git a/arch/xtensa/include/asm/syscall.h b/arch/xtensa/include/asm/syscall.h index c1dacca312f3..124aeee0d381 100644 --- a/arch/xtensa/include/asm/syscall.h +++ b/arch/xtensa/include/asm/syscall.h | |||
| @@ -10,7 +10,7 @@ | |||
| 10 | 10 | ||
| 11 | struct pt_regs; | 11 | struct pt_regs; |
| 12 | struct sigaction; | 12 | struct sigaction; |
| 13 | asmlinkage long xtensa_execve(char*, char**, char**, struct pt_regs*); | 13 | asmlinkage long sys_execve(char*, char**, char**, struct pt_regs*); |
| 14 | asmlinkage long xtensa_clone(unsigned long, unsigned long, struct pt_regs*); | 14 | asmlinkage long xtensa_clone(unsigned long, unsigned long, struct pt_regs*); |
| 15 | asmlinkage long xtensa_ptrace(long, long, long, long); | 15 | asmlinkage long xtensa_ptrace(long, long, long, long); |
| 16 | asmlinkage long xtensa_sigreturn(struct pt_regs*); | 16 | asmlinkage long xtensa_sigreturn(struct pt_regs*); |
diff --git a/arch/xtensa/include/asm/unistd.h b/arch/xtensa/include/asm/unistd.h index 9ef1c31d2c83..f4e6eaa40d1c 100644 --- a/arch/xtensa/include/asm/unistd.h +++ b/arch/xtensa/include/asm/unistd.h | |||
| @@ -1,16 +1,9 @@ | |||
| 1 | /* | 1 | #ifndef _XTENSA_UNISTD_H |
| 2 | * include/asm-xtensa/unistd.h | 2 | #define _XTENSA_UNISTD_H |
| 3 | * | ||
| 4 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 5 | * License. See the file "COPYING" in the main directory of this archive | ||
| 6 | * for more details. | ||
| 7 | * | ||
| 8 | * Copyright (C) 2001 - 2005 Tensilica Inc. | ||
| 9 | */ | ||
| 10 | 3 | ||
| 4 | #define __ARCH_WANT_SYS_EXECVE | ||
| 11 | #include <uapi/asm/unistd.h> | 5 | #include <uapi/asm/unistd.h> |
| 12 | 6 | ||
| 13 | |||
| 14 | /* | 7 | /* |
| 15 | * "Conditional" syscalls | 8 | * "Conditional" syscalls |
| 16 | * | 9 | * |
| @@ -37,3 +30,5 @@ | |||
| 37 | #define __IGNORE_mmap /* use mmap2 */ | 30 | #define __IGNORE_mmap /* use mmap2 */ |
| 38 | #define __IGNORE_vfork /* use clone */ | 31 | #define __IGNORE_vfork /* use clone */ |
| 39 | #define __IGNORE_fadvise64 /* use fadvise64_64 */ | 32 | #define __IGNORE_fadvise64 /* use fadvise64_64 */ |
| 33 | |||
| 34 | #endif /* _XTENSA_UNISTD_H */ | ||
diff --git a/arch/xtensa/include/uapi/asm/unistd.h b/arch/xtensa/include/uapi/asm/unistd.h index 479abaea5aae..9f36d0e3e0ac 100644 --- a/arch/xtensa/include/uapi/asm/unistd.h +++ b/arch/xtensa/include/uapi/asm/unistd.h | |||
| @@ -1,14 +1,4 @@ | |||
| 1 | /* | 1 | #if !defined(_UAPI_XTENSA_UNISTD_H) || defined(__SYSCALL) |
| 2 | * include/asm-xtensa/unistd.h | ||
| 3 | * | ||
| 4 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 5 | * License. See the file "COPYING" in the main directory of this archive | ||
| 6 | * for more details. | ||
| 7 | * | ||
| 8 | * Copyright (C) 2001 - 2012 Tensilica Inc. | ||
| 9 | */ | ||
| 10 | |||
| 11 | #ifndef _UAPI_XTENSA_UNISTD_H | ||
| 12 | #define _UAPI_XTENSA_UNISTD_H | 2 | #define _UAPI_XTENSA_UNISTD_H |
| 13 | 3 | ||
| 14 | #ifndef __SYSCALL | 4 | #ifndef __SYSCALL |
| @@ -272,7 +262,7 @@ __SYSCALL(115, sys_sendmmsg, 4) | |||
| 272 | #define __NR_clone 116 | 262 | #define __NR_clone 116 |
| 273 | __SYSCALL(116, xtensa_clone, 5) | 263 | __SYSCALL(116, xtensa_clone, 5) |
| 274 | #define __NR_execve 117 | 264 | #define __NR_execve 117 |
| 275 | __SYSCALL(117, xtensa_execve, 3) | 265 | __SYSCALL(117, sys_execve, 3) |
| 276 | #define __NR_exit 118 | 266 | #define __NR_exit 118 |
| 277 | __SYSCALL(118, sys_exit, 1) | 267 | __SYSCALL(118, sys_exit, 1) |
| 278 | #define __NR_exit_group 119 | 268 | #define __NR_exit_group 119 |
| @@ -759,4 +749,6 @@ __SYSCALL(331, sys_kcmp, 5) | |||
| 759 | 749 | ||
| 760 | #define SYS_XTENSA_COUNT 5 /* count */ | 750 | #define SYS_XTENSA_COUNT 5 /* count */ |
| 761 | 751 | ||
| 752 | #undef __SYSCALL | ||
| 753 | |||
| 762 | #endif /* _UAPI_XTENSA_UNISTD_H */ | 754 | #endif /* _UAPI_XTENSA_UNISTD_H */ |
diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S index 18453067c258..90bfc1dbc13d 100644 --- a/arch/xtensa/kernel/entry.S +++ b/arch/xtensa/kernel/entry.S | |||
| @@ -1833,50 +1833,6 @@ ENTRY(system_call) | |||
| 1833 | 1833 | ||
| 1834 | 1834 | ||
| 1835 | /* | 1835 | /* |
| 1836 | * Create a kernel thread | ||
| 1837 | * | ||
| 1838 | * int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) | ||
| 1839 | * a2 a2 a3 a4 | ||
| 1840 | */ | ||
| 1841 | |||
| 1842 | ENTRY(kernel_thread) | ||
| 1843 | entry a1, 16 | ||
| 1844 | |||
| 1845 | mov a5, a2 # preserve fn over syscall | ||
| 1846 | mov a7, a3 # preserve args over syscall | ||
| 1847 | |||
| 1848 | movi a3, _CLONE_VM | _CLONE_UNTRACED | ||
| 1849 | movi a2, __NR_clone | ||
| 1850 | or a6, a4, a3 # arg0: flags | ||
| 1851 | mov a3, a1 # arg1: sp | ||
| 1852 | syscall | ||
| 1853 | |||
| 1854 | beq a3, a1, 1f # branch if parent | ||
| 1855 | mov a6, a7 # args | ||
| 1856 | callx4 a5 # fn(args) | ||
| 1857 | |||
| 1858 | movi a2, __NR_exit | ||
| 1859 | syscall # return value of fn(args) still in a6 | ||
| 1860 | |||
| 1861 | 1: retw | ||
| 1862 | |||
| 1863 | /* | ||
| 1864 | * Do a system call from kernel instead of calling sys_execve, so we end up | ||
| 1865 | * with proper pt_regs. | ||
| 1866 | * | ||
| 1867 | * int kernel_execve(const char *fname, char *const argv[], charg *const envp[]) | ||
| 1868 | * a2 a2 a3 a4 | ||
| 1869 | */ | ||
| 1870 | |||
| 1871 | ENTRY(kernel_execve) | ||
| 1872 | entry a1, 16 | ||
| 1873 | mov a6, a2 # arg0 is in a6 | ||
| 1874 | movi a2, __NR_execve | ||
| 1875 | syscall | ||
| 1876 | |||
| 1877 | retw | ||
| 1878 | |||
| 1879 | /* | ||
| 1880 | * Task switch. | 1836 | * Task switch. |
| 1881 | * | 1837 | * |
| 1882 | * struct task* _switch_to (struct task* prev, struct task* next) | 1838 | * struct task* _switch_to (struct task* prev, struct task* next) |
| @@ -1958,3 +1914,16 @@ ENTRY(ret_from_fork) | |||
| 1958 | 1914 | ||
| 1959 | j common_exception_return | 1915 | j common_exception_return |
| 1960 | 1916 | ||
| 1917 | /* | ||
| 1918 | * Kernel thread creation helper | ||
| 1919 | * On entry, set up by copy_thread: a2 = thread_fn, a3 = thread_fn arg | ||
| 1920 | * left from _switch_to: a6 = prev | ||
| 1921 | */ | ||
| 1922 | ENTRY(ret_from_kernel_thread) | ||
| 1923 | |||
| 1924 | call4 schedule_tail | ||
| 1925 | mov a6, a3 | ||
| 1926 | callx4 a2 | ||
| 1927 | j common_exception_return | ||
| 1928 | |||
| 1929 | ENDPROC(ret_from_kernel_thread) | ||
diff --git a/arch/xtensa/kernel/process.c b/arch/xtensa/kernel/process.c index 1908f6642d31..09ae7bfab9a7 100644 --- a/arch/xtensa/kernel/process.c +++ b/arch/xtensa/kernel/process.c | |||
| @@ -45,6 +45,7 @@ | |||
| 45 | #include <asm/regs.h> | 45 | #include <asm/regs.h> |
| 46 | 46 | ||
| 47 | extern void ret_from_fork(void); | 47 | extern void ret_from_fork(void); |
| 48 | extern void ret_from_kernel_thread(void); | ||
| 48 | 49 | ||
| 49 | struct task_struct *current_set[NR_CPUS] = {&init_task, }; | 50 | struct task_struct *current_set[NR_CPUS] = {&init_task, }; |
| 50 | 51 | ||
| @@ -158,18 +159,30 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) | |||
| 158 | /* | 159 | /* |
| 159 | * Copy thread. | 160 | * Copy thread. |
| 160 | * | 161 | * |
| 162 | * There are two modes in which this function is called: | ||
| 163 | * 1) Userspace thread creation, | ||
| 164 | * regs != NULL, usp_thread_fn is userspace stack pointer. | ||
| 165 | * It is expected to copy parent regs (in case CLONE_VM is not set | ||
| 166 | * in the clone_flags) and set up passed usp in the childregs. | ||
| 167 | * 2) Kernel thread creation, | ||
| 168 | * regs == NULL, usp_thread_fn is the function to run in the new thread | ||
| 169 | * and thread_fn_arg is its parameter. | ||
| 170 | * childregs are not used for the kernel threads. | ||
| 171 | * | ||
| 161 | * The stack layout for the new thread looks like this: | 172 | * The stack layout for the new thread looks like this: |
| 162 | * | 173 | * |
| 163 | * +------------------------+ <- sp in childregs (= tos) | 174 | * +------------------------+ |
| 164 | * | childregs | | 175 | * | childregs | |
| 165 | * +------------------------+ <- thread.sp = sp in dummy-frame | 176 | * +------------------------+ <- thread.sp = sp in dummy-frame |
| 166 | * | dummy-frame | (saved in dummy-frame spill-area) | 177 | * | dummy-frame | (saved in dummy-frame spill-area) |
| 167 | * +------------------------+ | 178 | * +------------------------+ |
| 168 | * | 179 | * |
| 169 | * We create a dummy frame to return to ret_from_fork: | 180 | * We create a dummy frame to return to either ret_from_fork or |
| 170 | * a0 points to ret_from_fork (simulating a call4) | 181 | * ret_from_kernel_thread: |
| 182 | * a0 points to ret_from_fork/ret_from_kernel_thread (simulating a call4) | ||
| 171 | * sp points to itself (thread.sp) | 183 | * sp points to itself (thread.sp) |
| 172 | * a2, a3 are unused. | 184 | * a2, a3 are unused for userspace threads, |
| 185 | * a2 points to thread_fn, a3 holds thread_fn arg for kernel threads. | ||
| 173 | * | 186 | * |
| 174 | * Note: This is a pristine frame, so we don't need any spill region on top of | 187 | * Note: This is a pristine frame, so we don't need any spill region on top of |
| 175 | * childregs. | 188 | * childregs. |
| @@ -185,43 +198,63 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) | |||
| 185 | * involved. Much simpler to just not copy those live frames across. | 198 | * involved. Much simpler to just not copy those live frames across. |
| 186 | */ | 199 | */ |
| 187 | 200 | ||
| 188 | int copy_thread(unsigned long clone_flags, unsigned long usp, | 201 | int copy_thread(unsigned long clone_flags, unsigned long usp_thread_fn, |
| 189 | unsigned long unused, | 202 | unsigned long thread_fn_arg, |
| 190 | struct task_struct * p, struct pt_regs * regs) | 203 | struct task_struct *p, struct pt_regs *unused) |
| 191 | { | 204 | { |
| 192 | struct pt_regs *childregs; | 205 | struct pt_regs *childregs = task_pt_regs(p); |
| 193 | unsigned long tos; | ||
| 194 | int user_mode = user_mode(regs); | ||
| 195 | 206 | ||
| 196 | #if (XTENSA_HAVE_COPROCESSORS || XTENSA_HAVE_IO_PORTS) | 207 | #if (XTENSA_HAVE_COPROCESSORS || XTENSA_HAVE_IO_PORTS) |
| 197 | struct thread_info *ti; | 208 | struct thread_info *ti; |
| 198 | #endif | 209 | #endif |
| 199 | 210 | ||
| 200 | /* Set up new TSS. */ | ||
| 201 | tos = (unsigned long)task_stack_page(p) + THREAD_SIZE; | ||
| 202 | if (user_mode) | ||
| 203 | childregs = (struct pt_regs*)(tos - PT_USER_SIZE); | ||
| 204 | else | ||
| 205 | childregs = (struct pt_regs*)tos - 1; | ||
| 206 | |||
| 207 | /* This does not copy all the regs. In a bout of brilliance or madness, | ||
| 208 | ARs beyond a0-a15 exist past the end of the struct. */ | ||
| 209 | *childregs = *regs; | ||
| 210 | |||
| 211 | /* Create a call4 dummy-frame: a0 = 0, a1 = childregs. */ | 211 | /* Create a call4 dummy-frame: a0 = 0, a1 = childregs. */ |
| 212 | *((int*)childregs - 3) = (unsigned long)childregs; | 212 | *((int*)childregs - 3) = (unsigned long)childregs; |
| 213 | *((int*)childregs - 4) = 0; | 213 | *((int*)childregs - 4) = 0; |
| 214 | 214 | ||
| 215 | childregs->areg[2] = 0; | ||
| 216 | p->set_child_tid = p->clear_child_tid = NULL; | ||
| 217 | p->thread.ra = MAKE_RA_FOR_CALL((unsigned long)ret_from_fork, 0x1); | ||
| 218 | p->thread.sp = (unsigned long)childregs; | 215 | p->thread.sp = (unsigned long)childregs; |
| 219 | 216 | ||
| 220 | if (user_mode(regs)) { | 217 | if (!(p->flags & PF_KTHREAD)) { |
| 218 | struct pt_regs *regs = current_pt_regs(); | ||
| 219 | unsigned long usp = usp_thread_fn ? | ||
| 220 | usp_thread_fn : regs->areg[1]; | ||
| 221 | 221 | ||
| 222 | p->thread.ra = MAKE_RA_FOR_CALL( | ||
| 223 | (unsigned long)ret_from_fork, 0x1); | ||
| 224 | |||
| 225 | /* This does not copy all the regs. | ||
| 226 | * In a bout of brilliance or madness, | ||
| 227 | * ARs beyond a0-a15 exist past the end of the struct. | ||
| 228 | */ | ||
| 229 | *childregs = *regs; | ||
| 222 | childregs->areg[1] = usp; | 230 | childregs->areg[1] = usp; |
| 231 | childregs->areg[2] = 0; | ||
| 232 | |||
| 233 | /* When sharing memory with the parent thread, the child | ||
| 234 | usually starts on a pristine stack, so we have to reset | ||
| 235 | windowbase, windowstart and wmask. | ||
| 236 | (Note that such a new thread is required to always create | ||
| 237 | an initial call4 frame) | ||
| 238 | The exception is vfork, where the new thread continues to | ||
| 239 | run on the parent's stack until it calls execve. This could | ||
| 240 | be a call8 or call12, which requires a legal stack frame | ||
| 241 | of the previous caller for the overflow handlers to work. | ||
| 242 | (Note that it's always legal to overflow live registers). | ||
| 243 | In this case, ensure to spill at least the stack pointer | ||
| 244 | of that frame. */ | ||
| 245 | |||
| 223 | if (clone_flags & CLONE_VM) { | 246 | if (clone_flags & CLONE_VM) { |
| 224 | childregs->wmask = 1; /* can't share live windows */ | 247 | /* check that caller window is live and same stack */ |
| 248 | int len = childregs->wmask & ~0xf; | ||
| 249 | if (regs->areg[1] == usp && len != 0) { | ||
| 250 | int callinc = (regs->areg[0] >> 30) & 3; | ||
| 251 | int caller_ars = XCHAL_NUM_AREGS - callinc * 4; | ||
| 252 | put_user(regs->areg[caller_ars+1], | ||
| 253 | (unsigned __user*)(usp - 12)); | ||
| 254 | } | ||
| 255 | childregs->wmask = 1; | ||
| 256 | childregs->windowstart = 1; | ||
| 257 | childregs->windowbase = 0; | ||
| 225 | } else { | 258 | } else { |
| 226 | int len = childregs->wmask & ~0xf; | 259 | int len = childregs->wmask & ~0xf; |
| 227 | memcpy(&childregs->areg[XCHAL_NUM_AREGS - len/4], | 260 | memcpy(&childregs->areg[XCHAL_NUM_AREGS - len/4], |
| @@ -230,11 +263,19 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, | |||
| 230 | // FIXME: we need to set THREADPTR in thread_info... | 263 | // FIXME: we need to set THREADPTR in thread_info... |
| 231 | if (clone_flags & CLONE_SETTLS) | 264 | if (clone_flags & CLONE_SETTLS) |
| 232 | childregs->areg[2] = childregs->areg[6]; | 265 | childregs->areg[2] = childregs->areg[6]; |
| 233 | |||
| 234 | } else { | 266 | } else { |
| 235 | /* In kernel space, we start a new thread with a new stack. */ | 267 | p->thread.ra = MAKE_RA_FOR_CALL( |
| 236 | childregs->wmask = 1; | 268 | (unsigned long)ret_from_kernel_thread, 1); |
| 237 | childregs->areg[1] = tos; | 269 | |
| 270 | /* pass parameters to ret_from_kernel_thread: | ||
| 271 | * a2 = thread_fn, a3 = thread_fn arg | ||
| 272 | */ | ||
| 273 | *((int *)childregs - 1) = thread_fn_arg; | ||
| 274 | *((int *)childregs - 2) = usp_thread_fn; | ||
| 275 | |||
| 276 | /* Childregs are only used when we're going to userspace | ||
| 277 | * in which case start_thread will set them up. | ||
| 278 | */ | ||
| 238 | } | 279 | } |
| 239 | 280 | ||
| 240 | #if (XTENSA_HAVE_COPROCESSORS || XTENSA_HAVE_IO_PORTS) | 281 | #if (XTENSA_HAVE_COPROCESSORS || XTENSA_HAVE_IO_PORTS) |
| @@ -330,32 +371,5 @@ long xtensa_clone(unsigned long clone_flags, unsigned long newsp, | |||
| 330 | void __user *child_tid, long a5, | 371 | void __user *child_tid, long a5, |
| 331 | struct pt_regs *regs) | 372 | struct pt_regs *regs) |
| 332 | { | 373 | { |
| 333 | if (!newsp) | ||
| 334 | newsp = regs->areg[1]; | ||
| 335 | return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid); | 374 | return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid); |
| 336 | } | 375 | } |
| 337 | |||
| 338 | /* | ||
| 339 | * xtensa_execve() executes a new program. | ||
| 340 | */ | ||
| 341 | |||
| 342 | asmlinkage | ||
| 343 | long xtensa_execve(const char __user *name, | ||
| 344 | const char __user *const __user *argv, | ||
| 345 | const char __user *const __user *envp, | ||
| 346 | long a3, long a4, long a5, | ||
| 347 | struct pt_regs *regs) | ||
| 348 | { | ||
| 349 | long error; | ||
| 350 | struct filename *filename; | ||
| 351 | |||
| 352 | filename = getname(name); | ||
| 353 | error = PTR_ERR(filename); | ||
| 354 | if (IS_ERR(filename)) | ||
| 355 | goto out; | ||
| 356 | error = do_execve(filename->name, argv, envp, regs); | ||
| 357 | putname(filename); | ||
| 358 | out: | ||
| 359 | return error; | ||
| 360 | } | ||
| 361 | |||
diff --git a/arch/xtensa/kernel/syscall.c b/arch/xtensa/kernel/syscall.c index a5c01e74d5d5..5702065f472a 100644 --- a/arch/xtensa/kernel/syscall.c +++ b/arch/xtensa/kernel/syscall.c | |||
| @@ -32,10 +32,8 @@ typedef void (*syscall_t)(void); | |||
| 32 | syscall_t sys_call_table[__NR_syscall_count] /* FIXME __cacheline_aligned */= { | 32 | syscall_t sys_call_table[__NR_syscall_count] /* FIXME __cacheline_aligned */= { |
| 33 | [0 ... __NR_syscall_count - 1] = (syscall_t)&sys_ni_syscall, | 33 | [0 ... __NR_syscall_count - 1] = (syscall_t)&sys_ni_syscall, |
| 34 | 34 | ||
| 35 | #undef __SYSCALL | ||
| 36 | #define __SYSCALL(nr,symbol,nargs) [ nr ] = (syscall_t)symbol, | 35 | #define __SYSCALL(nr,symbol,nargs) [ nr ] = (syscall_t)symbol, |
| 37 | #undef __KERNEL_SYSCALLS__ | 36 | #include <uapi/asm/unistd.h> |
| 38 | #include <asm/unistd.h> | ||
| 39 | }; | 37 | }; |
| 40 | 38 | ||
| 41 | asmlinkage long xtensa_shmat(int shmid, char __user *shmaddr, int shmflg) | 39 | asmlinkage long xtensa_shmat(int shmid, char __user *shmaddr, int shmflg) |
| @@ -49,7 +47,8 @@ asmlinkage long xtensa_shmat(int shmid, char __user *shmaddr, int shmflg) | |||
| 49 | return (long)ret; | 47 | return (long)ret; |
| 50 | } | 48 | } |
| 51 | 49 | ||
| 52 | asmlinkage long xtensa_fadvise64_64(int fd, int advice, unsigned long long offset, unsigned long long len) | 50 | asmlinkage long xtensa_fadvise64_64(int fd, int advice, |
| 51 | unsigned long long offset, unsigned long long len) | ||
| 53 | { | 52 | { |
| 54 | return sys_fadvise64_64(fd, offset, len, advice); | 53 | return sys_fadvise64_64(fd, offset, len, advice); |
| 55 | } | 54 | } |
diff --git a/arch/xtensa/kernel/xtensa_ksyms.c b/arch/xtensa/kernel/xtensa_ksyms.c index a8b9f1fd1e17..afe058b24e6e 100644 --- a/arch/xtensa/kernel/xtensa_ksyms.c +++ b/arch/xtensa/kernel/xtensa_ksyms.c | |||
| @@ -43,7 +43,6 @@ EXPORT_SYMBOL(__strncpy_user); | |||
| 43 | EXPORT_SYMBOL(clear_page); | 43 | EXPORT_SYMBOL(clear_page); |
| 44 | EXPORT_SYMBOL(copy_page); | 44 | EXPORT_SYMBOL(copy_page); |
| 45 | 45 | ||
| 46 | EXPORT_SYMBOL(kernel_thread); | ||
| 47 | EXPORT_SYMBOL(empty_zero_page); | 46 | EXPORT_SYMBOL(empty_zero_page); |
| 48 | 47 | ||
| 49 | /* | 48 | /* |
