diff options
Diffstat (limited to 'arch/tile')
25 files changed, 291 insertions, 412 deletions
diff --git a/arch/tile/include/asm/Kbuild b/arch/tile/include/asm/Kbuild index 6948015e08a2..b17b9b8e53cd 100644 --- a/arch/tile/include/asm/Kbuild +++ b/arch/tile/include/asm/Kbuild | |||
| @@ -34,5 +34,6 @@ generic-y += sockios.h | |||
| 34 | generic-y += statfs.h | 34 | generic-y += statfs.h |
| 35 | generic-y += termbits.h | 35 | generic-y += termbits.h |
| 36 | generic-y += termios.h | 36 | generic-y += termios.h |
| 37 | generic-y += trace_clock.h | ||
| 37 | generic-y += types.h | 38 | generic-y += types.h |
| 38 | generic-y += xor.h | 39 | generic-y += xor.h |
diff --git a/arch/tile/include/asm/compat.h b/arch/tile/include/asm/compat.h index 3063e6fc8daa..88f3c227afd9 100644 --- a/arch/tile/include/asm/compat.h +++ b/arch/tile/include/asm/compat.h | |||
| @@ -275,18 +275,14 @@ extern int compat_setup_rt_frame(int sig, struct k_sigaction *ka, | |||
| 275 | struct compat_sigaction; | 275 | struct compat_sigaction; |
| 276 | struct compat_siginfo; | 276 | struct compat_siginfo; |
| 277 | struct compat_sigaltstack; | 277 | struct compat_sigaltstack; |
| 278 | long compat_sys_execve(const char __user *path, | ||
| 279 | compat_uptr_t __user *argv, | ||
| 280 | compat_uptr_t __user *envp, struct pt_regs *); | ||
| 281 | long compat_sys_rt_sigaction(int sig, struct compat_sigaction __user *act, | 278 | long compat_sys_rt_sigaction(int sig, struct compat_sigaction __user *act, |
| 282 | struct compat_sigaction __user *oact, | 279 | struct compat_sigaction __user *oact, |
| 283 | size_t sigsetsize); | 280 | size_t sigsetsize); |
| 284 | long compat_sys_rt_sigqueueinfo(int pid, int sig, | 281 | long compat_sys_rt_sigqueueinfo(int pid, int sig, |
| 285 | struct compat_siginfo __user *uinfo); | 282 | struct compat_siginfo __user *uinfo); |
| 286 | long compat_sys_rt_sigreturn(struct pt_regs *); | 283 | long compat_sys_rt_sigreturn(void); |
| 287 | long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr, | 284 | long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr, |
| 288 | struct compat_sigaltstack __user *uoss_ptr, | 285 | struct compat_sigaltstack __user *uoss_ptr); |
| 289 | struct pt_regs *); | ||
| 290 | long compat_sys_truncate64(char __user *filename, u32 dummy, u32 low, u32 high); | 286 | long compat_sys_truncate64(char __user *filename, u32 dummy, u32 low, u32 high); |
| 291 | long compat_sys_ftruncate64(unsigned int fd, u32 dummy, u32 low, u32 high); | 287 | long compat_sys_ftruncate64(unsigned int fd, u32 dummy, u32 low, u32 high); |
| 292 | long compat_sys_pread64(unsigned int fd, char __user *ubuf, size_t count, | 288 | long compat_sys_pread64(unsigned int fd, char __user *ubuf, size_t count, |
| @@ -300,15 +296,8 @@ long compat_sys_sync_file_range2(int fd, unsigned int flags, | |||
| 300 | long compat_sys_fallocate(int fd, int mode, | 296 | long compat_sys_fallocate(int fd, int mode, |
| 301 | u32 offset_lo, u32 offset_hi, | 297 | u32 offset_lo, u32 offset_hi, |
| 302 | u32 len_lo, u32 len_hi); | 298 | u32 len_lo, u32 len_hi); |
| 303 | long compat_sys_sched_rr_get_interval(compat_pid_t pid, | 299 | |
| 304 | struct compat_timespec __user *interval); | 300 | /* Assembly trampoline to avoid clobbering r0. */ |
| 305 | |||
| 306 | /* These are the intvec_64.S trampolines. */ | ||
| 307 | long _compat_sys_execve(const char __user *path, | ||
| 308 | const compat_uptr_t __user *argv, | ||
| 309 | const compat_uptr_t __user *envp); | ||
| 310 | long _compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr, | ||
| 311 | struct compat_sigaltstack __user *uoss_ptr); | ||
| 312 | long _compat_sys_rt_sigreturn(void); | 301 | long _compat_sys_rt_sigreturn(void); |
| 313 | 302 | ||
| 314 | #endif /* _ASM_TILE_COMPAT_H */ | 303 | #endif /* _ASM_TILE_COMPAT_H */ |
diff --git a/arch/tile/include/asm/dma-mapping.h b/arch/tile/include/asm/dma-mapping.h index 4b6247d1a315..f2ff191376b4 100644 --- a/arch/tile/include/asm/dma-mapping.h +++ b/arch/tile/include/asm/dma-mapping.h | |||
| @@ -72,6 +72,7 @@ static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size) | |||
| 72 | static inline int | 72 | static inline int |
| 73 | dma_mapping_error(struct device *dev, dma_addr_t dma_addr) | 73 | dma_mapping_error(struct device *dev, dma_addr_t dma_addr) |
| 74 | { | 74 | { |
| 75 | debug_dma_mapping_error(dev, dma_addr); | ||
| 75 | return get_dma_ops(dev)->mapping_error(dev, dma_addr); | 76 | return get_dma_ops(dev)->mapping_error(dev, dma_addr); |
| 76 | } | 77 | } |
| 77 | 78 | ||
diff --git a/arch/tile/include/asm/elf.h b/arch/tile/include/asm/elf.h index f8ccf08f6934..ff8a93408823 100644 --- a/arch/tile/include/asm/elf.h +++ b/arch/tile/include/asm/elf.h | |||
| @@ -148,6 +148,7 @@ extern int arch_setup_additional_pages(struct linux_binprm *bprm, | |||
| 148 | #define compat_start_thread(regs, ip, usp) do { \ | 148 | #define compat_start_thread(regs, ip, usp) do { \ |
| 149 | regs->pc = ptr_to_compat_reg((void *)(ip)); \ | 149 | regs->pc = ptr_to_compat_reg((void *)(ip)); \ |
| 150 | regs->sp = ptr_to_compat_reg((void *)(usp)); \ | 150 | regs->sp = ptr_to_compat_reg((void *)(usp)); \ |
| 151 | single_step_execve(); \ | ||
| 151 | } while (0) | 152 | } while (0) |
| 152 | 153 | ||
| 153 | /* | 154 | /* |
| @@ -169,4 +170,6 @@ do { \ | |||
| 169 | 170 | ||
| 170 | #endif /* CONFIG_COMPAT */ | 171 | #endif /* CONFIG_COMPAT */ |
| 171 | 172 | ||
| 173 | #define CORE_DUMP_USE_REGSET | ||
| 174 | |||
| 172 | #endif /* _ASM_TILE_ELF_H */ | 175 | #endif /* _ASM_TILE_ELF_H */ |
diff --git a/arch/tile/include/asm/pci.h b/arch/tile/include/asm/pci.h index 302cdf71ceed..54a924208d3c 100644 --- a/arch/tile/include/asm/pci.h +++ b/arch/tile/include/asm/pci.h | |||
| @@ -188,7 +188,7 @@ extern void pci_iounmap(struct pci_dev *dev, void __iomem *); | |||
| 188 | int __init tile_pci_init(void); | 188 | int __init tile_pci_init(void); |
| 189 | int __init pcibios_init(void); | 189 | int __init pcibios_init(void); |
| 190 | 190 | ||
| 191 | void __devinit pcibios_fixup_bus(struct pci_bus *bus); | 191 | void pcibios_fixup_bus(struct pci_bus *bus); |
| 192 | 192 | ||
| 193 | #define pci_domain_nr(bus) (((struct pci_controller *)(bus)->sysdata)->index) | 193 | #define pci_domain_nr(bus) (((struct pci_controller *)(bus)->sysdata)->index) |
| 194 | 194 | ||
diff --git a/arch/tile/include/asm/processor.h b/arch/tile/include/asm/processor.h index 8c4dd9ff91eb..2b70dfb1442e 100644 --- a/arch/tile/include/asm/processor.h +++ b/arch/tile/include/asm/processor.h | |||
| @@ -211,6 +211,7 @@ static inline void start_thread(struct pt_regs *regs, | |||
| 211 | { | 211 | { |
| 212 | regs->pc = pc; | 212 | regs->pc = pc; |
| 213 | regs->sp = usp; | 213 | regs->sp = usp; |
| 214 | single_step_execve(); | ||
| 214 | } | 215 | } |
| 215 | 216 | ||
| 216 | /* Free all resources held by a thread. */ | 217 | /* Free all resources held by a thread. */ |
| @@ -219,8 +220,6 @@ static inline void release_thread(struct task_struct *dead_task) | |||
| 219 | /* Nothing for now */ | 220 | /* Nothing for now */ |
| 220 | } | 221 | } |
| 221 | 222 | ||
| 222 | extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); | ||
| 223 | |||
| 224 | extern int do_work_pending(struct pt_regs *regs, u32 flags); | 223 | extern int do_work_pending(struct pt_regs *regs, u32 flags); |
| 225 | 224 | ||
| 226 | 225 | ||
| @@ -239,6 +238,9 @@ unsigned long get_wchan(struct task_struct *p); | |||
| 239 | #define KSTK_TOP(task) (task_ksp0(task) - STACK_TOP_DELTA) | 238 | #define KSTK_TOP(task) (task_ksp0(task) - STACK_TOP_DELTA) |
| 240 | #define task_pt_regs(task) \ | 239 | #define task_pt_regs(task) \ |
| 241 | ((struct pt_regs *)(task_ksp0(task) - KSTK_PTREGS_GAP) - 1) | 240 | ((struct pt_regs *)(task_ksp0(task) - KSTK_PTREGS_GAP) - 1) |
| 241 | #define current_pt_regs() \ | ||
| 242 | ((struct pt_regs *)((stack_pointer | (THREAD_SIZE - 1)) - \ | ||
| 243 | (KSTK_PTREGS_GAP - 1)) - 1) | ||
| 242 | #define task_sp(task) (task_pt_regs(task)->sp) | 244 | #define task_sp(task) (task_pt_regs(task)->sp) |
| 243 | #define task_pc(task) (task_pt_regs(task)->pc) | 245 | #define task_pc(task) (task_pt_regs(task)->pc) |
| 244 | /* Aliases for pc and sp (used in fs/proc/array.c) */ | 246 | /* Aliases for pc and sp (used in fs/proc/array.c) */ |
diff --git a/arch/tile/include/asm/ptrace.h b/arch/tile/include/asm/ptrace.h index 1a4fd9ab0ee1..2e83fc1b9467 100644 --- a/arch/tile/include/asm/ptrace.h +++ b/arch/tile/include/asm/ptrace.h | |||
| @@ -24,8 +24,7 @@ typedef unsigned long pt_reg_t; | |||
| 24 | #include <uapi/asm/ptrace.h> | 24 | #include <uapi/asm/ptrace.h> |
| 25 | 25 | ||
| 26 | #define PTRACE_O_MASK_TILE (PTRACE_O_TRACEMIGRATE) | 26 | #define PTRACE_O_MASK_TILE (PTRACE_O_TRACEMIGRATE) |
| 27 | #define PT_TRACE_MIGRATE 0x00080000 | 27 | #define PT_TRACE_MIGRATE PT_EVENT_FLAG(PTRACE_EVENT_MIGRATE) |
| 28 | #define PT_TRACE_MASK_TILE (PT_TRACE_MIGRATE) | ||
| 29 | 28 | ||
| 30 | /* Flag bits in pt_regs.flags */ | 29 | /* Flag bits in pt_regs.flags */ |
| 31 | #define PT_FLAGS_DISABLE_IRQ 1 /* on return to kernel, disable irqs */ | 30 | #define PT_FLAGS_DISABLE_IRQ 1 /* on return to kernel, disable irqs */ |
| @@ -36,6 +35,7 @@ typedef unsigned long pt_reg_t; | |||
| 36 | 35 | ||
| 37 | #define instruction_pointer(regs) ((regs)->pc) | 36 | #define instruction_pointer(regs) ((regs)->pc) |
| 38 | #define profile_pc(regs) instruction_pointer(regs) | 37 | #define profile_pc(regs) instruction_pointer(regs) |
| 38 | #define user_stack_pointer(regs) ((regs)->sp) | ||
| 39 | 39 | ||
| 40 | /* Does the process account for user or for system time? */ | 40 | /* Does the process account for user or for system time? */ |
| 41 | #define user_mode(regs) (EX1_PL((regs)->ex1) == USER_PL) | 41 | #define user_mode(regs) (EX1_PL((regs)->ex1) == USER_PL) |
diff --git a/arch/tile/include/asm/switch_to.h b/arch/tile/include/asm/switch_to.h index 1d48c5fee8b7..b8f888cbe6b0 100644 --- a/arch/tile/include/asm/switch_to.h +++ b/arch/tile/include/asm/switch_to.h | |||
| @@ -68,7 +68,10 @@ extern unsigned long get_switch_to_pc(void); | |||
| 68 | /* Support function for forking a new task. */ | 68 | /* Support function for forking a new task. */ |
| 69 | void ret_from_fork(void); | 69 | void ret_from_fork(void); |
| 70 | 70 | ||
| 71 | /* Called from ret_from_fork() when a new process starts up. */ | 71 | /* Support function for forking a new kernel thread. */ |
| 72 | void ret_from_kernel_thread(void *fn, void *arg); | ||
| 73 | |||
| 74 | /* Called from ret_from_xxx() when a new process starts up. */ | ||
| 72 | struct task_struct *sim_notify_fork(struct task_struct *prev); | 75 | struct task_struct *sim_notify_fork(struct task_struct *prev); |
| 73 | 76 | ||
| 74 | #endif /* !__ASSEMBLY__ */ | 77 | #endif /* !__ASSEMBLY__ */ |
diff --git a/arch/tile/include/asm/syscalls.h b/arch/tile/include/asm/syscalls.h index 06f0464cfed9..4c8462a62cb6 100644 --- a/arch/tile/include/asm/syscalls.h +++ b/arch/tile/include/asm/syscalls.h | |||
| @@ -51,8 +51,7 @@ long sys_cacheflush(unsigned long addr, unsigned long len, | |||
| 51 | 51 | ||
| 52 | #ifndef __tilegx__ | 52 | #ifndef __tilegx__ |
| 53 | /* mm/fault.c */ | 53 | /* mm/fault.c */ |
| 54 | long sys_cmpxchg_badaddr(unsigned long address, struct pt_regs *); | 54 | long sys_cmpxchg_badaddr(unsigned long address); |
| 55 | long _sys_cmpxchg_badaddr(unsigned long address); | ||
| 56 | #endif | 55 | #endif |
| 57 | 56 | ||
| 58 | #ifdef CONFIG_COMPAT | 57 | #ifdef CONFIG_COMPAT |
| @@ -63,14 +62,16 @@ long sys_truncate64(const char __user *path, loff_t length); | |||
| 63 | long sys_ftruncate64(unsigned int fd, loff_t length); | 62 | long sys_ftruncate64(unsigned int fd, loff_t length); |
| 64 | #endif | 63 | #endif |
| 65 | 64 | ||
| 65 | /* Provide versions of standard syscalls that use current_pt_regs(). */ | ||
| 66 | long sys_rt_sigreturn(void); | ||
| 67 | long sys_sigaltstack(const stack_t __user *, stack_t __user *); | ||
| 68 | #define sys_rt_sigreturn sys_rt_sigreturn | ||
| 69 | #define sys_sigaltstack sys_sigaltstack | ||
| 70 | |||
| 66 | /* These are the intvec*.S trampolines. */ | 71 | /* These are the intvec*.S trampolines. */ |
| 67 | long _sys_sigaltstack(const stack_t __user *, stack_t __user *); | ||
| 68 | long _sys_rt_sigreturn(void); | 72 | long _sys_rt_sigreturn(void); |
| 69 | long _sys_clone(unsigned long clone_flags, unsigned long newsp, | 73 | long _sys_clone(unsigned long clone_flags, unsigned long newsp, |
| 70 | void __user *parent_tid, void __user *child_tid); | 74 | void __user *parent_tid, void __user *child_tid); |
| 71 | long _sys_execve(const char __user *filename, | ||
| 72 | const char __user *const __user *argv, | ||
| 73 | const char __user *const __user *envp); | ||
| 74 | 75 | ||
| 75 | #include <asm-generic/syscalls.h> | 76 | #include <asm-generic/syscalls.h> |
| 76 | 77 | ||
diff --git a/arch/tile/include/asm/unistd.h b/arch/tile/include/asm/unistd.h index 6e032a0a268e..6ac21034f69a 100644 --- a/arch/tile/include/asm/unistd.h +++ b/arch/tile/include/asm/unistd.h | |||
| @@ -14,6 +14,8 @@ | |||
| 14 | /* In compat mode, we use sys_llseek() for compat_sys_llseek(). */ | 14 | /* In compat mode, we use sys_llseek() for compat_sys_llseek(). */ |
| 15 | #ifdef CONFIG_COMPAT | 15 | #ifdef CONFIG_COMPAT |
| 16 | #define __ARCH_WANT_SYS_LLSEEK | 16 | #define __ARCH_WANT_SYS_LLSEEK |
| 17 | #define __ARCH_WANT_COMPAT_SYS_SCHED_RR_GET_INTERVAL | ||
| 17 | #endif | 18 | #endif |
| 18 | #define __ARCH_WANT_SYS_NEWFSTATAT | 19 | #define __ARCH_WANT_SYS_NEWFSTATAT |
| 20 | #define __ARCH_WANT_SYS_CLONE | ||
| 19 | #include <uapi/asm/unistd.h> | 21 | #include <uapi/asm/unistd.h> |
diff --git a/arch/tile/include/uapi/asm/ptrace.h b/arch/tile/include/uapi/asm/ptrace.h index c717d0fec72e..7757e1985fb6 100644 --- a/arch/tile/include/uapi/asm/ptrace.h +++ b/arch/tile/include/uapi/asm/ptrace.h | |||
| @@ -81,8 +81,14 @@ struct pt_regs { | |||
| 81 | #define PTRACE_SETFPREGS 15 | 81 | #define PTRACE_SETFPREGS 15 |
| 82 | 82 | ||
| 83 | /* Support TILE-specific ptrace options, with events starting at 16. */ | 83 | /* Support TILE-specific ptrace options, with events starting at 16. */ |
| 84 | #define PTRACE_O_TRACEMIGRATE 0x00010000 | ||
| 85 | #define PTRACE_EVENT_MIGRATE 16 | 84 | #define PTRACE_EVENT_MIGRATE 16 |
| 85 | #define PTRACE_O_TRACEMIGRATE (1 << PTRACE_EVENT_MIGRATE) | ||
| 86 | 86 | ||
| 87 | /* | ||
| 88 | * Flag bits in pt_regs.flags that are part of the ptrace API. | ||
| 89 | * We start our numbering higher up to avoid confusion with the | ||
| 90 | * non-ABI kernel-internal values that use the low 16 bits. | ||
| 91 | */ | ||
| 92 | #define PT_FLAGS_COMPAT 0x10000 /* process is an -m32 compat process */ | ||
| 87 | 93 | ||
| 88 | #endif /* _UAPI_ASM_TILE_PTRACE_H */ | 94 | #endif /* _UAPI_ASM_TILE_PTRACE_H */ |
diff --git a/arch/tile/kernel/compat.c b/arch/tile/kernel/compat.c index d67459b9ac2a..7f72401b4f45 100644 --- a/arch/tile/kernel/compat.c +++ b/arch/tile/kernel/compat.c | |||
| @@ -76,24 +76,6 @@ long compat_sys_fallocate(int fd, int mode, | |||
| 76 | ((loff_t)len_hi << 32) | len_lo); | 76 | ((loff_t)len_hi << 32) | len_lo); |
| 77 | } | 77 | } |
| 78 | 78 | ||
| 79 | |||
| 80 | |||
| 81 | long compat_sys_sched_rr_get_interval(compat_pid_t pid, | ||
| 82 | struct compat_timespec __user *interval) | ||
| 83 | { | ||
| 84 | struct timespec t; | ||
| 85 | int ret; | ||
| 86 | mm_segment_t old_fs = get_fs(); | ||
| 87 | |||
| 88 | set_fs(KERNEL_DS); | ||
| 89 | ret = sys_sched_rr_get_interval(pid, | ||
| 90 | (struct timespec __force __user *)&t); | ||
| 91 | set_fs(old_fs); | ||
| 92 | if (put_compat_timespec(&t, interval)) | ||
| 93 | return -EFAULT; | ||
| 94 | return ret; | ||
| 95 | } | ||
| 96 | |||
| 97 | /* Provide the compat syscall number to call mapping. */ | 79 | /* Provide the compat syscall number to call mapping. */ |
| 98 | #undef __SYSCALL | 80 | #undef __SYSCALL |
| 99 | #define __SYSCALL(nr, call) [nr] = (call), | 81 | #define __SYSCALL(nr, call) [nr] = (call), |
| @@ -102,9 +84,7 @@ long compat_sys_sched_rr_get_interval(compat_pid_t pid, | |||
| 102 | #define compat_sys_fadvise64_64 sys32_fadvise64_64 | 84 | #define compat_sys_fadvise64_64 sys32_fadvise64_64 |
| 103 | #define compat_sys_readahead sys32_readahead | 85 | #define compat_sys_readahead sys32_readahead |
| 104 | 86 | ||
| 105 | /* Call the trampolines to manage pt_regs where necessary. */ | 87 | /* Call the assembly trampolines where necessary. */ |
| 106 | #define compat_sys_execve _compat_sys_execve | ||
| 107 | #define compat_sys_sigaltstack _compat_sys_sigaltstack | ||
| 108 | #define compat_sys_rt_sigreturn _compat_sys_rt_sigreturn | 88 | #define compat_sys_rt_sigreturn _compat_sys_rt_sigreturn |
| 109 | #define sys_clone _sys_clone | 89 | #define sys_clone _sys_clone |
| 110 | 90 | ||
diff --git a/arch/tile/kernel/compat_signal.c b/arch/tile/kernel/compat_signal.c index 08b4fe1717bb..2e4cc69224a6 100644 --- a/arch/tile/kernel/compat_signal.c +++ b/arch/tile/kernel/compat_signal.c | |||
| @@ -197,8 +197,7 @@ int copy_siginfo_from_user32(siginfo_t *to, struct compat_siginfo __user *from) | |||
| 197 | } | 197 | } |
| 198 | 198 | ||
| 199 | long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr, | 199 | long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr, |
| 200 | struct compat_sigaltstack __user *uoss_ptr, | 200 | struct compat_sigaltstack __user *uoss_ptr) |
| 201 | struct pt_regs *regs) | ||
| 202 | { | 201 | { |
| 203 | stack_t uss, uoss; | 202 | stack_t uss, uoss; |
| 204 | int ret; | 203 | int ret; |
| @@ -219,7 +218,7 @@ long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr, | |||
| 219 | set_fs(KERNEL_DS); | 218 | set_fs(KERNEL_DS); |
| 220 | ret = do_sigaltstack(uss_ptr ? (stack_t __user __force *)&uss : NULL, | 219 | ret = do_sigaltstack(uss_ptr ? (stack_t __user __force *)&uss : NULL, |
| 221 | (stack_t __user __force *)&uoss, | 220 | (stack_t __user __force *)&uoss, |
| 222 | (unsigned long)compat_ptr(regs->sp)); | 221 | (unsigned long)compat_ptr(current_pt_regs()->sp)); |
| 223 | set_fs(seg); | 222 | set_fs(seg); |
| 224 | if (ret >= 0 && uoss_ptr) { | 223 | if (ret >= 0 && uoss_ptr) { |
| 225 | if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(*uoss_ptr)) || | 224 | if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(*uoss_ptr)) || |
| @@ -232,8 +231,9 @@ long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr, | |||
| 232 | } | 231 | } |
| 233 | 232 | ||
| 234 | /* The assembly shim for this function arranges to ignore the return value. */ | 233 | /* The assembly shim for this function arranges to ignore the return value. */ |
| 235 | long compat_sys_rt_sigreturn(struct pt_regs *regs) | 234 | long compat_sys_rt_sigreturn(void) |
| 236 | { | 235 | { |
| 236 | struct pt_regs *regs = current_pt_regs(); | ||
| 237 | struct compat_rt_sigframe __user *frame = | 237 | struct compat_rt_sigframe __user *frame = |
| 238 | (struct compat_rt_sigframe __user *) compat_ptr(regs->sp); | 238 | (struct compat_rt_sigframe __user *) compat_ptr(regs->sp); |
| 239 | sigset_t set; | 239 | sigset_t set; |
| @@ -248,7 +248,7 @@ long compat_sys_rt_sigreturn(struct pt_regs *regs) | |||
| 248 | if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) | 248 | if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) |
| 249 | goto badframe; | 249 | goto badframe; |
| 250 | 250 | ||
| 251 | if (compat_sys_sigaltstack(&frame->uc.uc_stack, NULL, regs) != 0) | 251 | if (compat_sys_sigaltstack(&frame->uc.uc_stack, NULL) == -EFAULT) |
| 252 | goto badframe; | 252 | goto badframe; |
| 253 | 253 | ||
| 254 | return 0; | 254 | return 0; |
diff --git a/arch/tile/kernel/entry.S b/arch/tile/kernel/entry.S index c31637baff28..f116cb0bce20 100644 --- a/arch/tile/kernel/entry.S +++ b/arch/tile/kernel/entry.S | |||
| @@ -28,17 +28,6 @@ STD_ENTRY(current_text_addr) | |||
| 28 | STD_ENDPROC(current_text_addr) | 28 | STD_ENDPROC(current_text_addr) |
| 29 | 29 | ||
| 30 | /* | 30 | /* |
| 31 | * Implement execve(). The i386 code has a note that forking from kernel | ||
| 32 | * space results in no copy on write until the execve, so we should be | ||
| 33 | * careful not to write to the stack here. | ||
| 34 | */ | ||
| 35 | STD_ENTRY(kernel_execve) | ||
| 36 | moveli TREG_SYSCALL_NR_NAME, __NR_execve | ||
| 37 | swint1 | ||
| 38 | jrp lr | ||
| 39 | STD_ENDPROC(kernel_execve) | ||
| 40 | |||
| 41 | /* | ||
| 42 | * We don't run this function directly, but instead copy it to a page | 31 | * We don't run this function directly, but instead copy it to a page |
| 43 | * we map into every user process. See vdso_setup(). | 32 | * we map into every user process. See vdso_setup(). |
| 44 | * | 33 | * |
diff --git a/arch/tile/kernel/intvec_32.S b/arch/tile/kernel/intvec_32.S index 6943515100f8..f212bf7cea86 100644 --- a/arch/tile/kernel/intvec_32.S +++ b/arch/tile/kernel/intvec_32.S | |||
| @@ -1291,6 +1291,21 @@ STD_ENTRY(ret_from_fork) | |||
| 1291 | } | 1291 | } |
| 1292 | STD_ENDPROC(ret_from_fork) | 1292 | STD_ENDPROC(ret_from_fork) |
| 1293 | 1293 | ||
| 1294 | STD_ENTRY(ret_from_kernel_thread) | ||
| 1295 | jal sim_notify_fork | ||
| 1296 | jal schedule_tail | ||
| 1297 | FEEDBACK_REENTER(ret_from_fork) | ||
| 1298 | { | ||
| 1299 | move r0, r31 | ||
| 1300 | jalr r30 | ||
| 1301 | } | ||
| 1302 | FEEDBACK_REENTER(ret_from_kernel_thread) | ||
| 1303 | { | ||
| 1304 | movei r30, 0 /* not an NMI */ | ||
| 1305 | j .Lresume_userspace /* jump into middle of interrupt_return */ | ||
| 1306 | } | ||
| 1307 | STD_ENDPROC(ret_from_kernel_thread) | ||
| 1308 | |||
| 1294 | /* | 1309 | /* |
| 1295 | * Code for ill interrupt. | 1310 | * Code for ill interrupt. |
| 1296 | */ | 1311 | */ |
| @@ -1437,15 +1452,6 @@ STD_ENTRY_LOCAL(bad_intr) | |||
| 1437 | panic "Unhandled interrupt %#x: PC %#lx" | 1452 | panic "Unhandled interrupt %#x: PC %#lx" |
| 1438 | STD_ENDPROC(bad_intr) | 1453 | STD_ENDPROC(bad_intr) |
| 1439 | 1454 | ||
| 1440 | /* Put address of pt_regs in reg and jump. */ | ||
| 1441 | #define PTREGS_SYSCALL(x, reg) \ | ||
| 1442 | STD_ENTRY(_##x); \ | ||
| 1443 | { \ | ||
| 1444 | PTREGS_PTR(reg, PTREGS_OFFSET_BASE); \ | ||
| 1445 | j x \ | ||
| 1446 | }; \ | ||
| 1447 | STD_ENDPROC(_##x) | ||
| 1448 | |||
| 1449 | /* | 1455 | /* |
| 1450 | * Special-case sigreturn to not write r0 to the stack on return. | 1456 | * Special-case sigreturn to not write r0 to the stack on return. |
| 1451 | * This is technically more efficient, but it also avoids difficulties | 1457 | * This is technically more efficient, but it also avoids difficulties |
| @@ -1461,12 +1467,9 @@ STD_ENTRY_LOCAL(bad_intr) | |||
| 1461 | }; \ | 1467 | }; \ |
| 1462 | STD_ENDPROC(_##x) | 1468 | STD_ENDPROC(_##x) |
| 1463 | 1469 | ||
| 1464 | PTREGS_SYSCALL(sys_execve, r3) | ||
| 1465 | PTREGS_SYSCALL(sys_sigaltstack, r2) | ||
| 1466 | PTREGS_SYSCALL_SIGRETURN(sys_rt_sigreturn, r0) | 1470 | PTREGS_SYSCALL_SIGRETURN(sys_rt_sigreturn, r0) |
| 1467 | PTREGS_SYSCALL(sys_cmpxchg_badaddr, r1) | ||
| 1468 | 1471 | ||
| 1469 | /* Save additional callee-saves to pt_regs, put address in r4 and jump. */ | 1472 | /* Save additional callee-saves to pt_regs and jump to standard function. */ |
| 1470 | STD_ENTRY(_sys_clone) | 1473 | STD_ENTRY(_sys_clone) |
| 1471 | push_extra_callee_saves r4 | 1474 | push_extra_callee_saves r4 |
| 1472 | j sys_clone | 1475 | j sys_clone |
diff --git a/arch/tile/kernel/intvec_64.S b/arch/tile/kernel/intvec_64.S index 7c06d597ffd0..54bc9a6678e8 100644 --- a/arch/tile/kernel/intvec_64.S +++ b/arch/tile/kernel/intvec_64.S | |||
| @@ -1150,6 +1150,21 @@ STD_ENTRY(ret_from_fork) | |||
| 1150 | } | 1150 | } |
| 1151 | STD_ENDPROC(ret_from_fork) | 1151 | STD_ENDPROC(ret_from_fork) |
| 1152 | 1152 | ||
| 1153 | STD_ENTRY(ret_from_kernel_thread) | ||
| 1154 | jal sim_notify_fork | ||
| 1155 | jal schedule_tail | ||
| 1156 | FEEDBACK_REENTER(ret_from_fork) | ||
| 1157 | { | ||
| 1158 | move r0, r31 | ||
| 1159 | jalr r30 | ||
| 1160 | } | ||
| 1161 | FEEDBACK_REENTER(ret_from_kernel_thread) | ||
| 1162 | { | ||
| 1163 | movei r30, 0 /* not an NMI */ | ||
| 1164 | j .Lresume_userspace /* jump into middle of interrupt_return */ | ||
| 1165 | } | ||
| 1166 | STD_ENDPROC(ret_from_kernel_thread) | ||
| 1167 | |||
| 1153 | /* Various stub interrupt handlers and syscall handlers */ | 1168 | /* Various stub interrupt handlers and syscall handlers */ |
| 1154 | 1169 | ||
| 1155 | STD_ENTRY_LOCAL(_kernel_double_fault) | 1170 | STD_ENTRY_LOCAL(_kernel_double_fault) |
| @@ -1166,15 +1181,6 @@ STD_ENTRY_LOCAL(bad_intr) | |||
| 1166 | panic "Unhandled interrupt %#x: PC %#lx" | 1181 | panic "Unhandled interrupt %#x: PC %#lx" |
| 1167 | STD_ENDPROC(bad_intr) | 1182 | STD_ENDPROC(bad_intr) |
| 1168 | 1183 | ||
| 1169 | /* Put address of pt_regs in reg and jump. */ | ||
| 1170 | #define PTREGS_SYSCALL(x, reg) \ | ||
| 1171 | STD_ENTRY(_##x); \ | ||
| 1172 | { \ | ||
| 1173 | PTREGS_PTR(reg, PTREGS_OFFSET_BASE); \ | ||
| 1174 | j x \ | ||
| 1175 | }; \ | ||
| 1176 | STD_ENDPROC(_##x) | ||
| 1177 | |||
| 1178 | /* | 1184 | /* |
| 1179 | * Special-case sigreturn to not write r0 to the stack on return. | 1185 | * Special-case sigreturn to not write r0 to the stack on return. |
| 1180 | * This is technically more efficient, but it also avoids difficulties | 1186 | * This is technically more efficient, but it also avoids difficulties |
| @@ -1190,16 +1196,12 @@ STD_ENTRY_LOCAL(bad_intr) | |||
| 1190 | }; \ | 1196 | }; \ |
| 1191 | STD_ENDPROC(_##x) | 1197 | STD_ENDPROC(_##x) |
| 1192 | 1198 | ||
| 1193 | PTREGS_SYSCALL(sys_execve, r3) | ||
| 1194 | PTREGS_SYSCALL(sys_sigaltstack, r2) | ||
| 1195 | PTREGS_SYSCALL_SIGRETURN(sys_rt_sigreturn, r0) | 1199 | PTREGS_SYSCALL_SIGRETURN(sys_rt_sigreturn, r0) |
| 1196 | #ifdef CONFIG_COMPAT | 1200 | #ifdef CONFIG_COMPAT |
| 1197 | PTREGS_SYSCALL(compat_sys_execve, r3) | ||
| 1198 | PTREGS_SYSCALL(compat_sys_sigaltstack, r2) | ||
| 1199 | PTREGS_SYSCALL_SIGRETURN(compat_sys_rt_sigreturn, r0) | 1201 | PTREGS_SYSCALL_SIGRETURN(compat_sys_rt_sigreturn, r0) |
| 1200 | #endif | 1202 | #endif |
| 1201 | 1203 | ||
| 1202 | /* Save additional callee-saves to pt_regs, put address in r4 and jump. */ | 1204 | /* Save additional callee-saves to pt_regs and jump to standard function. */ |
| 1203 | STD_ENTRY(_sys_clone) | 1205 | STD_ENTRY(_sys_clone) |
| 1204 | push_extra_callee_saves r4 | 1206 | push_extra_callee_saves r4 |
| 1205 | j sys_clone | 1207 | j sys_clone |
diff --git a/arch/tile/kernel/module.c b/arch/tile/kernel/module.c index 243ffebe38d6..4918d91bc3a6 100644 --- a/arch/tile/kernel/module.c +++ b/arch/tile/kernel/module.c | |||
| @@ -42,8 +42,6 @@ void *module_alloc(unsigned long size) | |||
| 42 | int i = 0; | 42 | int i = 0; |
| 43 | int npages; | 43 | int npages; |
| 44 | 44 | ||
| 45 | if (size == 0) | ||
| 46 | return NULL; | ||
| 47 | npages = (size + PAGE_SIZE - 1) / PAGE_SIZE; | 45 | npages = (size + PAGE_SIZE - 1) / PAGE_SIZE; |
| 48 | pages = kmalloc(npages * sizeof(struct page *), GFP_KERNEL); | 46 | pages = kmalloc(npages * sizeof(struct page *), GFP_KERNEL); |
| 49 | if (pages == NULL) | 47 | if (pages == NULL) |
diff --git a/arch/tile/kernel/pci.c b/arch/tile/kernel/pci.c index 759822687e8f..67237d34c2e2 100644 --- a/arch/tile/kernel/pci.c +++ b/arch/tile/kernel/pci.c | |||
| @@ -81,7 +81,7 @@ EXPORT_SYMBOL(pcibios_align_resource); | |||
| 81 | * controller_id is the controller number, config type is 0 or 1 for | 81 | * controller_id is the controller number, config type is 0 or 1 for |
| 82 | * config0 or config1 operations. | 82 | * config0 or config1 operations. |
| 83 | */ | 83 | */ |
| 84 | static int __devinit tile_pcie_open(int controller_id, int config_type) | 84 | static int tile_pcie_open(int controller_id, int config_type) |
| 85 | { | 85 | { |
| 86 | char filename[32]; | 86 | char filename[32]; |
| 87 | int fd; | 87 | int fd; |
| @@ -97,8 +97,7 @@ static int __devinit tile_pcie_open(int controller_id, int config_type) | |||
| 97 | /* | 97 | /* |
| 98 | * Get the IRQ numbers from the HV and set up the handlers for them. | 98 | * Get the IRQ numbers from the HV and set up the handlers for them. |
| 99 | */ | 99 | */ |
| 100 | static int __devinit tile_init_irqs(int controller_id, | 100 | static int tile_init_irqs(int controller_id, struct pci_controller *controller) |
| 101 | struct pci_controller *controller) | ||
| 102 | { | 101 | { |
| 103 | char filename[32]; | 102 | char filename[32]; |
| 104 | int fd; | 103 | int fd; |
| @@ -237,7 +236,7 @@ static int tile_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) | |||
| 237 | } | 236 | } |
| 238 | 237 | ||
| 239 | 238 | ||
| 240 | static void __devinit fixup_read_and_payload_sizes(void) | 239 | static void fixup_read_and_payload_sizes(void) |
| 241 | { | 240 | { |
| 242 | struct pci_dev *dev = NULL; | 241 | struct pci_dev *dev = NULL; |
| 243 | int smallest_max_payload = 0x1; /* Tile maxes out at 256 bytes. */ | 242 | int smallest_max_payload = 0x1; /* Tile maxes out at 256 bytes. */ |
| @@ -245,7 +244,7 @@ static void __devinit fixup_read_and_payload_sizes(void) | |||
| 245 | u16 new_values; | 244 | u16 new_values; |
| 246 | 245 | ||
| 247 | /* Scan for the smallest maximum payload size. */ | 246 | /* Scan for the smallest maximum payload size. */ |
| 248 | while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { | 247 | for_each_pci_dev(dev) { |
| 249 | u32 devcap; | 248 | u32 devcap; |
| 250 | int max_payload; | 249 | int max_payload; |
| 251 | 250 | ||
| @@ -260,7 +259,7 @@ static void __devinit fixup_read_and_payload_sizes(void) | |||
| 260 | 259 | ||
| 261 | /* Now, set the max_payload_size for all devices to that value. */ | 260 | /* Now, set the max_payload_size for all devices to that value. */ |
| 262 | new_values = (max_read_size << 12) | (smallest_max_payload << 5); | 261 | new_values = (max_read_size << 12) | (smallest_max_payload << 5); |
| 263 | while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) | 262 | for_each_pci_dev(dev) |
| 264 | pcie_capability_clear_and_set_word(dev, PCI_EXP_DEVCTL, | 263 | pcie_capability_clear_and_set_word(dev, PCI_EXP_DEVCTL, |
| 265 | PCI_EXP_DEVCTL_PAYLOAD | PCI_EXP_DEVCTL_READRQ, | 264 | PCI_EXP_DEVCTL_PAYLOAD | PCI_EXP_DEVCTL_READRQ, |
| 266 | new_values); | 265 | new_values); |
| @@ -379,7 +378,7 @@ subsys_initcall(pcibios_init); | |||
| 379 | /* | 378 | /* |
| 380 | * No bus fixups needed. | 379 | * No bus fixups needed. |
| 381 | */ | 380 | */ |
| 382 | void __devinit pcibios_fixup_bus(struct pci_bus *bus) | 381 | void pcibios_fixup_bus(struct pci_bus *bus) |
| 383 | { | 382 | { |
| 384 | /* Nothing needs to be done. */ | 383 | /* Nothing needs to be done. */ |
| 385 | } | 384 | } |
| @@ -458,11 +457,8 @@ int pcibios_enable_device(struct pci_dev *dev, int mask) | |||
| 458 | * specified bus & slot. | 457 | * specified bus & slot. |
| 459 | */ | 458 | */ |
| 460 | 459 | ||
| 461 | static int __devinit tile_cfg_read(struct pci_bus *bus, | 460 | static int tile_cfg_read(struct pci_bus *bus, unsigned int devfn, int offset, |
| 462 | unsigned int devfn, | 461 | int size, u32 *val) |
| 463 | int offset, | ||
| 464 | int size, | ||
| 465 | u32 *val) | ||
| 466 | { | 462 | { |
| 467 | struct pci_controller *controller = bus->sysdata; | 463 | struct pci_controller *controller = bus->sysdata; |
| 468 | int busnum = bus->number & 0xff; | 464 | int busnum = bus->number & 0xff; |
| @@ -504,11 +500,8 @@ static int __devinit tile_cfg_read(struct pci_bus *bus, | |||
| 504 | * See tile_cfg_read() for relevant comments. | 500 | * See tile_cfg_read() for relevant comments. |
| 505 | * Note that "val" is the value to write, not a pointer to that value. | 501 | * Note that "val" is the value to write, not a pointer to that value. |
| 506 | */ | 502 | */ |
| 507 | static int __devinit tile_cfg_write(struct pci_bus *bus, | 503 | static int tile_cfg_write(struct pci_bus *bus, unsigned int devfn, int offset, |
| 508 | unsigned int devfn, | 504 | int size, u32 val) |
| 509 | int offset, | ||
| 510 | int size, | ||
| 511 | u32 val) | ||
| 512 | { | 505 | { |
| 513 | struct pci_controller *controller = bus->sysdata; | 506 | struct pci_controller *controller = bus->sysdata; |
| 514 | int busnum = bus->number & 0xff; | 507 | int busnum = bus->number & 0xff; |
diff --git a/arch/tile/kernel/pci_gx.c b/arch/tile/kernel/pci_gx.c index 2ba6d052f85d..11425633b2d7 100644 --- a/arch/tile/kernel/pci_gx.c +++ b/arch/tile/kernel/pci_gx.c | |||
| @@ -58,10 +58,10 @@ | |||
| 58 | #define TRACE_CFG_RD(...) | 58 | #define TRACE_CFG_RD(...) |
| 59 | #endif | 59 | #endif |
| 60 | 60 | ||
| 61 | static int __devinitdata pci_probe = 1; | 61 | static int pci_probe = 1; |
| 62 | 62 | ||
| 63 | /* Information on the PCIe RC ports configuration. */ | 63 | /* Information on the PCIe RC ports configuration. */ |
| 64 | static int __devinitdata pcie_rc[TILEGX_NUM_TRIO][TILEGX_TRIO_PCIES]; | 64 | static int pcie_rc[TILEGX_NUM_TRIO][TILEGX_TRIO_PCIES]; |
| 65 | 65 | ||
| 66 | /* | 66 | /* |
| 67 | * On some platforms with one or more Gx endpoint ports, we need to | 67 | * On some platforms with one or more Gx endpoint ports, we need to |
| @@ -72,7 +72,7 @@ static int __devinitdata pcie_rc[TILEGX_NUM_TRIO][TILEGX_TRIO_PCIES]; | |||
| 72 | * the delay in seconds. If the delay is not provided, the value | 72 | * the delay in seconds. If the delay is not provided, the value |
| 73 | * will be DEFAULT_RC_DELAY. | 73 | * will be DEFAULT_RC_DELAY. |
| 74 | */ | 74 | */ |
| 75 | static int __devinitdata rc_delay[TILEGX_NUM_TRIO][TILEGX_TRIO_PCIES]; | 75 | static int rc_delay[TILEGX_NUM_TRIO][TILEGX_TRIO_PCIES]; |
| 76 | 76 | ||
| 77 | /* Default number of seconds that the PCIe RC port probe can be delayed. */ | 77 | /* Default number of seconds that the PCIe RC port probe can be delayed. */ |
| 78 | #define DEFAULT_RC_DELAY 10 | 78 | #define DEFAULT_RC_DELAY 10 |
| @@ -137,7 +137,7 @@ static int tile_irq_cpu(int irq) | |||
| 137 | /* | 137 | /* |
| 138 | * Open a file descriptor to the TRIO shim. | 138 | * Open a file descriptor to the TRIO shim. |
| 139 | */ | 139 | */ |
| 140 | static int __devinit tile_pcie_open(int trio_index) | 140 | static int tile_pcie_open(int trio_index) |
| 141 | { | 141 | { |
| 142 | gxio_trio_context_t *context = &trio_contexts[trio_index]; | 142 | gxio_trio_context_t *context = &trio_contexts[trio_index]; |
| 143 | int ret; | 143 | int ret; |
| @@ -265,7 +265,7 @@ trio_handle_level_irq(unsigned int irq, struct irq_desc *desc) | |||
| 265 | * Create kernel irqs and set up the handlers for the legacy interrupts. | 265 | * Create kernel irqs and set up the handlers for the legacy interrupts. |
| 266 | * Also some minimum initialization for the MSI support. | 266 | * Also some minimum initialization for the MSI support. |
| 267 | */ | 267 | */ |
| 268 | static int __devinit tile_init_irqs(struct pci_controller *controller) | 268 | static int tile_init_irqs(struct pci_controller *controller) |
| 269 | { | 269 | { |
| 270 | int i; | 270 | int i; |
| 271 | int j; | 271 | int j; |
| @@ -459,8 +459,7 @@ static int tile_map_irq(const struct pci_dev *dev, u8 device, u8 pin) | |||
| 459 | } | 459 | } |
| 460 | 460 | ||
| 461 | 461 | ||
| 462 | static void __devinit fixup_read_and_payload_sizes(struct pci_controller * | 462 | static void fixup_read_and_payload_sizes(struct pci_controller *controller) |
| 463 | controller) | ||
| 464 | { | 463 | { |
| 465 | gxio_trio_context_t *trio_context = controller->trio; | 464 | gxio_trio_context_t *trio_context = controller->trio; |
| 466 | struct pci_bus *root_bus = controller->root_bus; | 465 | struct pci_bus *root_bus = controller->root_bus; |
| @@ -541,7 +540,7 @@ static void __devinit fixup_read_and_payload_sizes(struct pci_controller * | |||
| 541 | } | 540 | } |
| 542 | } | 541 | } |
| 543 | 542 | ||
| 544 | static int __devinit setup_pcie_rc_delay(char *str) | 543 | static int setup_pcie_rc_delay(char *str) |
| 545 | { | 544 | { |
| 546 | unsigned long delay = 0; | 545 | unsigned long delay = 0; |
| 547 | unsigned long trio_index; | 546 | unsigned long trio_index; |
| @@ -1016,7 +1015,7 @@ alloc_mem_map_failed: | |||
| 1016 | subsys_initcall(pcibios_init); | 1015 | subsys_initcall(pcibios_init); |
| 1017 | 1016 | ||
| 1018 | /* Note: to be deleted after Linux 3.6 merge. */ | 1017 | /* Note: to be deleted after Linux 3.6 merge. */ |
| 1019 | void __devinit pcibios_fixup_bus(struct pci_bus *bus) | 1018 | void pcibios_fixup_bus(struct pci_bus *bus) |
| 1020 | { | 1019 | { |
| 1021 | } | 1020 | } |
| 1022 | 1021 | ||
| @@ -1024,7 +1023,7 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus) | |||
| 1024 | * This can be called from the generic PCI layer, but doesn't need to | 1023 | * This can be called from the generic PCI layer, but doesn't need to |
| 1025 | * do anything. | 1024 | * do anything. |
| 1026 | */ | 1025 | */ |
| 1027 | char __devinit *pcibios_setup(char *str) | 1026 | char *pcibios_setup(char *str) |
| 1028 | { | 1027 | { |
| 1029 | if (!strcmp(str, "off")) { | 1028 | if (!strcmp(str, "off")) { |
| 1030 | pci_probe = 0; | 1029 | pci_probe = 0; |
| @@ -1047,8 +1046,7 @@ int pcibios_enable_device(struct pci_dev *dev, int mask) | |||
| 1047 | } | 1046 | } |
| 1048 | 1047 | ||
| 1049 | /* Called for each device after PCI setup is done. */ | 1048 | /* Called for each device after PCI setup is done. */ |
| 1050 | static void __init | 1049 | static void pcibios_fixup_final(struct pci_dev *pdev) |
| 1051 | pcibios_fixup_final(struct pci_dev *pdev) | ||
| 1052 | { | 1050 | { |
| 1053 | set_dma_ops(&pdev->dev, gx_pci_dma_map_ops); | 1051 | set_dma_ops(&pdev->dev, gx_pci_dma_map_ops); |
| 1054 | set_dma_offset(&pdev->dev, TILE_PCI_MEM_MAP_BASE_OFFSET); | 1052 | set_dma_offset(&pdev->dev, TILE_PCI_MEM_MAP_BASE_OFFSET); |
| @@ -1144,11 +1142,8 @@ EXPORT_SYMBOL(pci_iounmap); | |||
| 1144 | * specified bus & device. | 1142 | * specified bus & device. |
| 1145 | */ | 1143 | */ |
| 1146 | 1144 | ||
| 1147 | static int __devinit tile_cfg_read(struct pci_bus *bus, | 1145 | static int tile_cfg_read(struct pci_bus *bus, unsigned int devfn, int offset, |
| 1148 | unsigned int devfn, | 1146 | int size, u32 *val) |
| 1149 | int offset, | ||
| 1150 | int size, | ||
| 1151 | u32 *val) | ||
| 1152 | { | 1147 | { |
| 1153 | struct pci_controller *controller = bus->sysdata; | 1148 | struct pci_controller *controller = bus->sysdata; |
| 1154 | gxio_trio_context_t *trio_context = controller->trio; | 1149 | gxio_trio_context_t *trio_context = controller->trio; |
| @@ -1272,11 +1267,8 @@ invalid_device: | |||
| 1272 | * See tile_cfg_read() for relevent comments. | 1267 | * See tile_cfg_read() for relevent comments. |
| 1273 | * Note that "val" is the value to write, not a pointer to that value. | 1268 | * Note that "val" is the value to write, not a pointer to that value. |
| 1274 | */ | 1269 | */ |
| 1275 | static int __devinit tile_cfg_write(struct pci_bus *bus, | 1270 | static int tile_cfg_write(struct pci_bus *bus, unsigned int devfn, int offset, |
| 1276 | unsigned int devfn, | 1271 | int size, u32 val) |
| 1277 | int offset, | ||
| 1278 | int size, | ||
| 1279 | u32 val) | ||
| 1280 | { | 1272 | { |
| 1281 | struct pci_controller *controller = bus->sysdata; | 1273 | struct pci_controller *controller = bus->sysdata; |
| 1282 | gxio_trio_context_t *trio_context = controller->trio; | 1274 | gxio_trio_context_t *trio_context = controller->trio; |
diff --git a/arch/tile/kernel/process.c b/arch/tile/kernel/process.c index 307d010696c9..0e5661e7d00d 100644 --- a/arch/tile/kernel/process.c +++ b/arch/tile/kernel/process.c | |||
| @@ -157,24 +157,43 @@ void arch_release_thread_info(struct thread_info *info) | |||
| 157 | static void save_arch_state(struct thread_struct *t); | 157 | static void save_arch_state(struct thread_struct *t); |
| 158 | 158 | ||
| 159 | int copy_thread(unsigned long clone_flags, unsigned long sp, | 159 | int copy_thread(unsigned long clone_flags, unsigned long sp, |
| 160 | unsigned long stack_size, | 160 | unsigned long arg, struct task_struct *p) |
| 161 | struct task_struct *p, struct pt_regs *regs) | ||
| 162 | { | 161 | { |
| 163 | struct pt_regs *childregs; | 162 | struct pt_regs *childregs = task_pt_regs(p), *regs = current_pt_regs(); |
| 164 | unsigned long ksp; | 163 | unsigned long ksp; |
| 164 | unsigned long *callee_regs; | ||
| 165 | 165 | ||
| 166 | /* | 166 | /* |
| 167 | * When creating a new kernel thread we pass sp as zero. | 167 | * Set up the stack and stack pointer appropriately for the |
| 168 | * Assign it to a reasonable value now that we have the stack. | 168 | * new child to find itself woken up in __switch_to(). |
| 169 | * The callee-saved registers must be on the stack to be read; | ||
| 170 | * the new task will then jump to assembly support to handle | ||
| 171 | * calling schedule_tail(), etc., and (for userspace tasks) | ||
| 172 | * returning to the context set up in the pt_regs. | ||
| 169 | */ | 173 | */ |
| 170 | if (sp == 0 && regs->ex1 == PL_ICS_EX1(KERNEL_PL, 0)) | 174 | ksp = (unsigned long) childregs; |
| 171 | sp = KSTK_TOP(p); | 175 | ksp -= C_ABI_SAVE_AREA_SIZE; /* interrupt-entry save area */ |
| 176 | ((long *)ksp)[0] = ((long *)ksp)[1] = 0; | ||
| 177 | ksp -= CALLEE_SAVED_REGS_COUNT * sizeof(unsigned long); | ||
| 178 | callee_regs = (unsigned long *)ksp; | ||
| 179 | ksp -= C_ABI_SAVE_AREA_SIZE; /* __switch_to() save area */ | ||
| 180 | ((long *)ksp)[0] = ((long *)ksp)[1] = 0; | ||
| 181 | p->thread.ksp = ksp; | ||
| 172 | 182 | ||
| 173 | /* | 183 | /* Record the pid of the task that created this one. */ |
| 174 | * Do not clone step state from the parent; each thread | 184 | p->thread.creator_pid = current->pid; |
| 175 | * must make its own lazily. | 185 | |
| 176 | */ | 186 | if (unlikely(p->flags & PF_KTHREAD)) { |
| 177 | task_thread_info(p)->step_state = NULL; | 187 | /* kernel thread */ |
| 188 | memset(childregs, 0, sizeof(struct pt_regs)); | ||
| 189 | memset(&callee_regs[2], 0, | ||
| 190 | (CALLEE_SAVED_REGS_COUNT - 2) * sizeof(unsigned long)); | ||
| 191 | callee_regs[0] = sp; /* r30 = function */ | ||
| 192 | callee_regs[1] = arg; /* r31 = arg */ | ||
| 193 | childregs->ex1 = PL_ICS_EX1(KERNEL_PL, 0); | ||
| 194 | p->thread.pc = (unsigned long) ret_from_kernel_thread; | ||
| 195 | return 0; | ||
| 196 | } | ||
| 178 | 197 | ||
| 179 | /* | 198 | /* |
| 180 | * Start new thread in ret_from_fork so it schedules properly | 199 | * Start new thread in ret_from_fork so it schedules properly |
| @@ -182,46 +201,33 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, | |||
| 182 | */ | 201 | */ |
| 183 | p->thread.pc = (unsigned long) ret_from_fork; | 202 | p->thread.pc = (unsigned long) ret_from_fork; |
| 184 | 203 | ||
| 185 | /* Save user stack top pointer so we can ID the stack vm area later. */ | 204 | /* |
| 186 | p->thread.usp0 = sp; | 205 | * Do not clone step state from the parent; each thread |
| 187 | 206 | * must make its own lazily. | |
| 188 | /* Record the pid of the process that created this one. */ | 207 | */ |
| 189 | p->thread.creator_pid = current->pid; | 208 | task_thread_info(p)->step_state = NULL; |
| 190 | 209 | ||
| 191 | /* | 210 | /* |
| 192 | * Copy the registers onto the kernel stack so the | 211 | * Copy the registers onto the kernel stack so the |
| 193 | * return-from-interrupt code will reload it into registers. | 212 | * return-from-interrupt code will reload it into registers. |
| 194 | */ | 213 | */ |
| 195 | childregs = task_pt_regs(p); | 214 | *childregs = *current_pt_regs(); |
| 196 | *childregs = *regs; | ||
| 197 | childregs->regs[0] = 0; /* return value is zero */ | 215 | childregs->regs[0] = 0; /* return value is zero */ |
| 198 | childregs->sp = sp; /* override with new user stack pointer */ | 216 | if (sp) |
| 217 | childregs->sp = sp; /* override with new user stack pointer */ | ||
| 218 | memcpy(callee_regs, &childregs->regs[CALLEE_SAVED_FIRST_REG], | ||
| 219 | CALLEE_SAVED_REGS_COUNT * sizeof(unsigned long)); | ||
| 220 | |||
| 221 | /* Save user stack top pointer so we can ID the stack vm area later. */ | ||
| 222 | p->thread.usp0 = childregs->sp; | ||
| 199 | 223 | ||
| 200 | /* | 224 | /* |
| 201 | * If CLONE_SETTLS is set, set "tp" in the new task to "r4", | 225 | * If CLONE_SETTLS is set, set "tp" in the new task to "r4", |
| 202 | * which is passed in as arg #5 to sys_clone(). | 226 | * which is passed in as arg #5 to sys_clone(). |
| 203 | */ | 227 | */ |
| 204 | if (clone_flags & CLONE_SETTLS) | 228 | if (clone_flags & CLONE_SETTLS) |
| 205 | childregs->tp = regs->regs[4]; | 229 | childregs->tp = childregs->regs[4]; |
| 206 | 230 | ||
| 207 | /* | ||
| 208 | * Copy the callee-saved registers from the passed pt_regs struct | ||
| 209 | * into the context-switch callee-saved registers area. | ||
| 210 | * This way when we start the interrupt-return sequence, the | ||
| 211 | * callee-save registers will be correctly in registers, which | ||
| 212 | * is how we assume the compiler leaves them as we start doing | ||
| 213 | * the normal return-from-interrupt path after calling C code. | ||
| 214 | * Zero out the C ABI save area to mark the top of the stack. | ||
| 215 | */ | ||
| 216 | ksp = (unsigned long) childregs; | ||
| 217 | ksp -= C_ABI_SAVE_AREA_SIZE; /* interrupt-entry save area */ | ||
| 218 | ((long *)ksp)[0] = ((long *)ksp)[1] = 0; | ||
| 219 | ksp -= CALLEE_SAVED_REGS_COUNT * sizeof(unsigned long); | ||
| 220 | memcpy((void *)ksp, ®s->regs[CALLEE_SAVED_FIRST_REG], | ||
| 221 | CALLEE_SAVED_REGS_COUNT * sizeof(unsigned long)); | ||
| 222 | ksp -= C_ABI_SAVE_AREA_SIZE; /* __switch_to() save area */ | ||
| 223 | ((long *)ksp)[0] = ((long *)ksp)[1] = 0; | ||
| 224 | p->thread.ksp = ksp; | ||
| 225 | 231 | ||
| 226 | #if CHIP_HAS_TILE_DMA() | 232 | #if CHIP_HAS_TILE_DMA() |
| 227 | /* | 233 | /* |
| @@ -577,62 +583,6 @@ int do_work_pending(struct pt_regs *regs, u32 thread_info_flags) | |||
| 577 | panic("work_pending: bad flags %#x\n", thread_info_flags); | 583 | panic("work_pending: bad flags %#x\n", thread_info_flags); |
| 578 | } | 584 | } |
| 579 | 585 | ||
| 580 | /* Note there is an implicit fifth argument if (clone_flags & CLONE_SETTLS). */ | ||
| 581 | SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp, | ||
| 582 | void __user *, parent_tidptr, void __user *, child_tidptr, | ||
| 583 | struct pt_regs *, regs) | ||
| 584 | { | ||
| 585 | if (!newsp) | ||
| 586 | newsp = regs->sp; | ||
| 587 | return do_fork(clone_flags, newsp, regs, 0, | ||
| 588 | parent_tidptr, child_tidptr); | ||
| 589 | } | ||
| 590 | |||
| 591 | /* | ||
| 592 | * sys_execve() executes a new program. | ||
| 593 | */ | ||
| 594 | SYSCALL_DEFINE4(execve, const char __user *, path, | ||
| 595 | const char __user *const __user *, argv, | ||
| 596 | const char __user *const __user *, envp, | ||
| 597 | struct pt_regs *, regs) | ||
| 598 | { | ||
| 599 | long error; | ||
| 600 | struct filename *filename; | ||
| 601 | |||
| 602 | filename = getname(path); | ||
| 603 | error = PTR_ERR(filename); | ||
| 604 | if (IS_ERR(filename)) | ||
| 605 | goto out; | ||
| 606 | error = do_execve(filename->name, argv, envp, regs); | ||
| 607 | putname(filename); | ||
| 608 | if (error == 0) | ||
| 609 | single_step_execve(); | ||
| 610 | out: | ||
| 611 | return error; | ||
| 612 | } | ||
| 613 | |||
| 614 | #ifdef CONFIG_COMPAT | ||
| 615 | long compat_sys_execve(const char __user *path, | ||
| 616 | compat_uptr_t __user *argv, | ||
| 617 | compat_uptr_t __user *envp, | ||
| 618 | struct pt_regs *regs) | ||
| 619 | { | ||
| 620 | long error; | ||
| 621 | struct filename *filename; | ||
| 622 | |||
| 623 | filename = getname(path); | ||
| 624 | error = PTR_ERR(filename); | ||
| 625 | if (IS_ERR(filename)) | ||
| 626 | goto out; | ||
| 627 | error = compat_do_execve(filename->name, argv, envp, regs); | ||
| 628 | putname(filename); | ||
| 629 | if (error == 0) | ||
| 630 | single_step_execve(); | ||
| 631 | out: | ||
| 632 | return error; | ||
| 633 | } | ||
| 634 | #endif | ||
| 635 | |||
| 636 | unsigned long get_wchan(struct task_struct *p) | 586 | unsigned long get_wchan(struct task_struct *p) |
| 637 | { | 587 | { |
| 638 | struct KBacktraceIterator kbt; | 588 | struct KBacktraceIterator kbt; |
| @@ -650,37 +600,6 @@ unsigned long get_wchan(struct task_struct *p) | |||
| 650 | return 0; | 600 | return 0; |
| 651 | } | 601 | } |
| 652 | 602 | ||
| 653 | /* | ||
| 654 | * We pass in lr as zero (cleared in kernel_thread) and the caller | ||
| 655 | * part of the backtrace ABI on the stack also zeroed (in copy_thread) | ||
| 656 | * so that backtraces will stop with this function. | ||
| 657 | * Note that we don't use r0, since copy_thread() clears it. | ||
| 658 | */ | ||
| 659 | static void start_kernel_thread(int dummy, int (*fn)(int), int arg) | ||
| 660 | { | ||
| 661 | do_exit(fn(arg)); | ||
| 662 | } | ||
| 663 | |||
| 664 | /* | ||
| 665 | * Create a kernel thread | ||
| 666 | */ | ||
| 667 | int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | ||
| 668 | { | ||
| 669 | struct pt_regs regs; | ||
| 670 | |||
| 671 | memset(®s, 0, sizeof(regs)); | ||
| 672 | regs.ex1 = PL_ICS_EX1(KERNEL_PL, 0); /* run at kernel PL, no ICS */ | ||
| 673 | regs.pc = (long) start_kernel_thread; | ||
| 674 | regs.flags = PT_FLAGS_CALLER_SAVES; /* need to restore r1 and r2 */ | ||
| 675 | regs.regs[1] = (long) fn; /* function pointer */ | ||
| 676 | regs.regs[2] = (long) arg; /* parameter register */ | ||
| 677 | |||
| 678 | /* Ok, create the new process.. */ | ||
| 679 | return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, | ||
| 680 | 0, NULL, NULL); | ||
| 681 | } | ||
| 682 | EXPORT_SYMBOL(kernel_thread); | ||
| 683 | |||
| 684 | /* Flush thread state. */ | 603 | /* Flush thread state. */ |
| 685 | void flush_thread(void) | 604 | void flush_thread(void) |
| 686 | { | 605 | { |
diff --git a/arch/tile/kernel/ptrace.c b/arch/tile/kernel/ptrace.c index e92e40527d6d..9835312d5a91 100644 --- a/arch/tile/kernel/ptrace.c +++ b/arch/tile/kernel/ptrace.c | |||
| @@ -19,7 +19,10 @@ | |||
| 19 | #include <linux/kprobes.h> | 19 | #include <linux/kprobes.h> |
| 20 | #include <linux/compat.h> | 20 | #include <linux/compat.h> |
| 21 | #include <linux/uaccess.h> | 21 | #include <linux/uaccess.h> |
| 22 | #include <linux/regset.h> | ||
| 23 | #include <linux/elf.h> | ||
| 22 | #include <asm/traps.h> | 24 | #include <asm/traps.h> |
| 25 | #include <arch/chip.h> | ||
| 23 | 26 | ||
| 24 | void user_enable_single_step(struct task_struct *child) | 27 | void user_enable_single_step(struct task_struct *child) |
| 25 | { | 28 | { |
| @@ -45,6 +48,100 @@ void ptrace_disable(struct task_struct *child) | |||
| 45 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | 48 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); |
| 46 | } | 49 | } |
| 47 | 50 | ||
| 51 | /* | ||
| 52 | * Get registers from task and ready the result for userspace. | ||
| 53 | * Note that we localize the API issues to getregs() and putregs() at | ||
| 54 | * some cost in performance, e.g. we need a full pt_regs copy for | ||
| 55 | * PEEKUSR, and two copies for POKEUSR. But in general we expect | ||
| 56 | * GETREGS/PUTREGS to be the API of choice anyway. | ||
| 57 | */ | ||
| 58 | static char *getregs(struct task_struct *child, struct pt_regs *uregs) | ||
| 59 | { | ||
| 60 | *uregs = *task_pt_regs(child); | ||
| 61 | |||
| 62 | /* Set up flags ABI bits. */ | ||
| 63 | uregs->flags = 0; | ||
| 64 | #ifdef CONFIG_COMPAT | ||
| 65 | if (task_thread_info(child)->status & TS_COMPAT) | ||
| 66 | uregs->flags |= PT_FLAGS_COMPAT; | ||
| 67 | #endif | ||
| 68 | |||
| 69 | return (char *)uregs; | ||
| 70 | } | ||
| 71 | |||
| 72 | /* Put registers back to task. */ | ||
| 73 | static void putregs(struct task_struct *child, struct pt_regs *uregs) | ||
| 74 | { | ||
| 75 | struct pt_regs *regs = task_pt_regs(child); | ||
| 76 | |||
| 77 | /* Don't allow overwriting the kernel-internal flags word. */ | ||
| 78 | uregs->flags = regs->flags; | ||
| 79 | |||
| 80 | /* Only allow setting the ICS bit in the ex1 word. */ | ||
| 81 | uregs->ex1 = PL_ICS_EX1(USER_PL, EX1_ICS(uregs->ex1)); | ||
| 82 | |||
| 83 | *regs = *uregs; | ||
| 84 | } | ||
| 85 | |||
| 86 | enum tile_regset { | ||
| 87 | REGSET_GPR, | ||
| 88 | }; | ||
| 89 | |||
| 90 | static int tile_gpr_get(struct task_struct *target, | ||
| 91 | const struct user_regset *regset, | ||
| 92 | unsigned int pos, unsigned int count, | ||
| 93 | void *kbuf, void __user *ubuf) | ||
| 94 | { | ||
| 95 | struct pt_regs regs; | ||
| 96 | |||
| 97 | getregs(target, ®s); | ||
| 98 | |||
| 99 | return user_regset_copyout(&pos, &count, &kbuf, &ubuf, ®s, 0, | ||
| 100 | sizeof(regs)); | ||
| 101 | } | ||
| 102 | |||
| 103 | static int tile_gpr_set(struct task_struct *target, | ||
| 104 | const struct user_regset *regset, | ||
| 105 | unsigned int pos, unsigned int count, | ||
| 106 | const void *kbuf, const void __user *ubuf) | ||
| 107 | { | ||
| 108 | int ret; | ||
| 109 | struct pt_regs regs; | ||
| 110 | |||
| 111 | ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, ®s, 0, | ||
| 112 | sizeof(regs)); | ||
| 113 | if (ret) | ||
| 114 | return ret; | ||
| 115 | |||
| 116 | putregs(target, ®s); | ||
| 117 | |||
| 118 | return 0; | ||
| 119 | } | ||
| 120 | |||
| 121 | static const struct user_regset tile_user_regset[] = { | ||
| 122 | [REGSET_GPR] = { | ||
| 123 | .core_note_type = NT_PRSTATUS, | ||
| 124 | .n = ELF_NGREG, | ||
| 125 | .size = sizeof(elf_greg_t), | ||
| 126 | .align = sizeof(elf_greg_t), | ||
| 127 | .get = tile_gpr_get, | ||
| 128 | .set = tile_gpr_set, | ||
| 129 | }, | ||
| 130 | }; | ||
| 131 | |||
| 132 | static const struct user_regset_view tile_user_regset_view = { | ||
| 133 | .name = CHIP_ARCH_NAME, | ||
| 134 | .e_machine = ELF_ARCH, | ||
| 135 | .ei_osabi = ELF_OSABI, | ||
| 136 | .regsets = tile_user_regset, | ||
| 137 | .n = ARRAY_SIZE(tile_user_regset), | ||
| 138 | }; | ||
| 139 | |||
| 140 | const struct user_regset_view *task_user_regset_view(struct task_struct *task) | ||
| 141 | { | ||
| 142 | return &tile_user_regset_view; | ||
| 143 | } | ||
| 144 | |||
| 48 | long arch_ptrace(struct task_struct *child, long request, | 145 | long arch_ptrace(struct task_struct *child, long request, |
| 49 | unsigned long addr, unsigned long data) | 146 | unsigned long addr, unsigned long data) |
| 50 | { | 147 | { |
| @@ -53,14 +150,13 @@ long arch_ptrace(struct task_struct *child, long request, | |||
| 53 | long ret = -EIO; | 150 | long ret = -EIO; |
| 54 | char *childreg; | 151 | char *childreg; |
| 55 | struct pt_regs copyregs; | 152 | struct pt_regs copyregs; |
| 56 | int ex1_offset; | ||
| 57 | 153 | ||
| 58 | switch (request) { | 154 | switch (request) { |
| 59 | 155 | ||
| 60 | case PTRACE_PEEKUSR: /* Read register from pt_regs. */ | 156 | case PTRACE_PEEKUSR: /* Read register from pt_regs. */ |
| 61 | if (addr >= PTREGS_SIZE) | 157 | if (addr >= PTREGS_SIZE) |
| 62 | break; | 158 | break; |
| 63 | childreg = (char *)task_pt_regs(child) + addr; | 159 | childreg = getregs(child, ©regs) + addr; |
| 64 | #ifdef CONFIG_COMPAT | 160 | #ifdef CONFIG_COMPAT |
| 65 | if (is_compat_task()) { | 161 | if (is_compat_task()) { |
| 66 | if (addr & (sizeof(compat_long_t)-1)) | 162 | if (addr & (sizeof(compat_long_t)-1)) |
| @@ -79,17 +175,7 @@ long arch_ptrace(struct task_struct *child, long request, | |||
| 79 | case PTRACE_POKEUSR: /* Write register in pt_regs. */ | 175 | case PTRACE_POKEUSR: /* Write register in pt_regs. */ |
| 80 | if (addr >= PTREGS_SIZE) | 176 | if (addr >= PTREGS_SIZE) |
| 81 | break; | 177 | break; |
| 82 | childreg = (char *)task_pt_regs(child) + addr; | 178 | childreg = getregs(child, ©regs) + addr; |
| 83 | |||
| 84 | /* Guard against overwrites of the privilege level. */ | ||
| 85 | ex1_offset = PTREGS_OFFSET_EX1; | ||
| 86 | #if defined(CONFIG_COMPAT) && defined(__BIG_ENDIAN) | ||
| 87 | if (is_compat_task()) /* point at low word */ | ||
| 88 | ex1_offset += sizeof(compat_long_t); | ||
| 89 | #endif | ||
| 90 | if (addr == ex1_offset) | ||
| 91 | data = PL_ICS_EX1(USER_PL, EX1_ICS(data)); | ||
| 92 | |||
| 93 | #ifdef CONFIG_COMPAT | 179 | #ifdef CONFIG_COMPAT |
| 94 | if (is_compat_task()) { | 180 | if (is_compat_task()) { |
| 95 | if (addr & (sizeof(compat_long_t)-1)) | 181 | if (addr & (sizeof(compat_long_t)-1)) |
| @@ -102,24 +188,20 @@ long arch_ptrace(struct task_struct *child, long request, | |||
| 102 | break; | 188 | break; |
| 103 | *(long *)childreg = data; | 189 | *(long *)childreg = data; |
| 104 | } | 190 | } |
| 191 | putregs(child, ©regs); | ||
| 105 | ret = 0; | 192 | ret = 0; |
| 106 | break; | 193 | break; |
| 107 | 194 | ||
| 108 | case PTRACE_GETREGS: /* Get all registers from the child. */ | 195 | case PTRACE_GETREGS: /* Get all registers from the child. */ |
| 109 | if (copy_to_user(datap, task_pt_regs(child), | 196 | ret = copy_regset_to_user(child, &tile_user_regset_view, |
| 110 | sizeof(struct pt_regs)) == 0) { | 197 | REGSET_GPR, 0, |
| 111 | ret = 0; | 198 | sizeof(struct pt_regs), datap); |
| 112 | } | ||
| 113 | break; | 199 | break; |
| 114 | 200 | ||
| 115 | case PTRACE_SETREGS: /* Set all registers in the child. */ | 201 | case PTRACE_SETREGS: /* Set all registers in the child. */ |
| 116 | if (copy_from_user(©regs, datap, | 202 | ret = copy_regset_from_user(child, &tile_user_regset_view, |
| 117 | sizeof(struct pt_regs)) == 0) { | 203 | REGSET_GPR, 0, |
| 118 | copyregs.ex1 = | 204 | sizeof(struct pt_regs), datap); |
| 119 | PL_ICS_EX1(USER_PL, EX1_ICS(copyregs.ex1)); | ||
| 120 | *task_pt_regs(child) = copyregs; | ||
| 121 | ret = 0; | ||
| 122 | } | ||
| 123 | break; | 205 | break; |
| 124 | 206 | ||
| 125 | case PTRACE_GETFPREGS: /* Get the child FPU state. */ | 207 | case PTRACE_GETFPREGS: /* Get the child FPU state. */ |
| @@ -128,12 +210,16 @@ long arch_ptrace(struct task_struct *child, long request, | |||
| 128 | 210 | ||
| 129 | case PTRACE_SETOPTIONS: | 211 | case PTRACE_SETOPTIONS: |
| 130 | /* Support TILE-specific ptrace options. */ | 212 | /* Support TILE-specific ptrace options. */ |
| 131 | child->ptrace &= ~PT_TRACE_MASK_TILE; | 213 | BUILD_BUG_ON(PTRACE_O_MASK_TILE & PTRACE_O_MASK); |
| 132 | tmp = data & PTRACE_O_MASK_TILE; | 214 | tmp = data & PTRACE_O_MASK_TILE; |
| 133 | data &= ~PTRACE_O_MASK_TILE; | 215 | data &= ~PTRACE_O_MASK_TILE; |
| 134 | ret = ptrace_request(child, request, addr, data); | 216 | ret = ptrace_request(child, request, addr, data); |
| 135 | if (tmp & PTRACE_O_TRACEMIGRATE) | 217 | if (ret == 0) { |
| 136 | child->ptrace |= PT_TRACE_MIGRATE; | 218 | unsigned int flags = child->ptrace; |
| 219 | flags &= ~(PTRACE_O_MASK_TILE << PT_OPT_FLAG_SHIFT); | ||
| 220 | flags |= (tmp << PT_OPT_FLAG_SHIFT); | ||
| 221 | child->ptrace = flags; | ||
| 222 | } | ||
| 137 | break; | 223 | break; |
| 138 | 224 | ||
| 139 | default: | 225 | default: |
diff --git a/arch/tile/kernel/signal.c b/arch/tile/kernel/signal.c index 67efb656d104..657a7ace4ab4 100644 --- a/arch/tile/kernel/signal.c +++ b/arch/tile/kernel/signal.c | |||
| @@ -37,10 +37,10 @@ | |||
| 37 | 37 | ||
| 38 | #define DEBUG_SIG 0 | 38 | #define DEBUG_SIG 0 |
| 39 | 39 | ||
| 40 | SYSCALL_DEFINE3(sigaltstack, const stack_t __user *, uss, | 40 | SYSCALL_DEFINE2(sigaltstack, const stack_t __user *, uss, |
| 41 | stack_t __user *, uoss, struct pt_regs *, regs) | 41 | stack_t __user *, uoss) |
| 42 | { | 42 | { |
| 43 | return do_sigaltstack(uss, uoss, regs->sp); | 43 | return do_sigaltstack(uss, uoss, current_pt_regs()->sp); |
| 44 | } | 44 | } |
| 45 | 45 | ||
| 46 | 46 | ||
| @@ -83,8 +83,9 @@ void signal_fault(const char *type, struct pt_regs *regs, | |||
| 83 | } | 83 | } |
| 84 | 84 | ||
| 85 | /* The assembly shim for this function arranges to ignore the return value. */ | 85 | /* The assembly shim for this function arranges to ignore the return value. */ |
| 86 | SYSCALL_DEFINE1(rt_sigreturn, struct pt_regs *, regs) | 86 | SYSCALL_DEFINE0(rt_sigreturn) |
| 87 | { | 87 | { |
| 88 | struct pt_regs *regs = current_pt_regs(); | ||
| 88 | struct rt_sigframe __user *frame = | 89 | struct rt_sigframe __user *frame = |
| 89 | (struct rt_sigframe __user *)(regs->sp); | 90 | (struct rt_sigframe __user *)(regs->sp); |
| 90 | sigset_t set; | 91 | sigset_t set; |
diff --git a/arch/tile/kernel/sys.c b/arch/tile/kernel/sys.c index b08095b402d6..b881a7be24bd 100644 --- a/arch/tile/kernel/sys.c +++ b/arch/tile/kernel/sys.c | |||
| @@ -106,14 +106,10 @@ SYSCALL_DEFINE6(mmap, unsigned long, addr, unsigned long, len, | |||
| 106 | #define sys_readahead sys32_readahead | 106 | #define sys_readahead sys32_readahead |
| 107 | #endif | 107 | #endif |
| 108 | 108 | ||
| 109 | /* Call the trampolines to manage pt_regs where necessary. */ | 109 | /* Call the assembly trampolines where necessary. */ |
| 110 | #define sys_execve _sys_execve | 110 | #undef sys_rt_sigreturn |
| 111 | #define sys_sigaltstack _sys_sigaltstack | ||
| 112 | #define sys_rt_sigreturn _sys_rt_sigreturn | 111 | #define sys_rt_sigreturn _sys_rt_sigreturn |
| 113 | #define sys_clone _sys_clone | 112 | #define sys_clone _sys_clone |
| 114 | #ifndef __tilegx__ | ||
| 115 | #define sys_cmpxchg_badaddr _sys_cmpxchg_badaddr | ||
| 116 | #endif | ||
| 117 | 113 | ||
| 118 | /* | 114 | /* |
| 119 | * Note that we can't include <linux/unistd.h> here since the header | 115 | * Note that we can't include <linux/unistd.h> here since the header |
diff --git a/arch/tile/mm/fault.c b/arch/tile/mm/fault.c index fe811fa5f1b9..3d2b81c163a6 100644 --- a/arch/tile/mm/fault.c +++ b/arch/tile/mm/fault.c | |||
| @@ -70,9 +70,10 @@ static noinline void force_sig_info_fault(const char *type, int si_signo, | |||
| 70 | * Synthesize the fault a PL0 process would get by doing a word-load of | 70 | * Synthesize the fault a PL0 process would get by doing a word-load of |
| 71 | * an unaligned address or a high kernel address. | 71 | * an unaligned address or a high kernel address. |
| 72 | */ | 72 | */ |
| 73 | SYSCALL_DEFINE2(cmpxchg_badaddr, unsigned long, address, | 73 | SYSCALL_DEFINE1(cmpxchg_badaddr, unsigned long, address) |
| 74 | struct pt_regs *, regs) | ||
| 75 | { | 74 | { |
| 75 | struct pt_regs *regs = current_pt_regs(); | ||
| 76 | |||
| 76 | if (address >= PAGE_OFFSET) | 77 | if (address >= PAGE_OFFSET) |
| 77 | force_sig_info_fault("atomic segfault", SIGSEGV, SEGV_MAPERR, | 78 | force_sig_info_fault("atomic segfault", SIGSEGV, SEGV_MAPERR, |
| 78 | address, INT_DTLB_MISS, current, regs); | 79 | address, INT_DTLB_MISS, current, regs); |
diff --git a/arch/tile/mm/hugetlbpage.c b/arch/tile/mm/hugetlbpage.c index 812e2d037972..650ccff8378c 100644 --- a/arch/tile/mm/hugetlbpage.c +++ b/arch/tile/mm/hugetlbpage.c | |||
| @@ -231,42 +231,15 @@ static unsigned long hugetlb_get_unmapped_area_bottomup(struct file *file, | |||
| 231 | unsigned long pgoff, unsigned long flags) | 231 | unsigned long pgoff, unsigned long flags) |
| 232 | { | 232 | { |
| 233 | struct hstate *h = hstate_file(file); | 233 | struct hstate *h = hstate_file(file); |
| 234 | struct mm_struct *mm = current->mm; | 234 | struct vm_unmapped_area_info info; |
| 235 | struct vm_area_struct *vma; | 235 | |
| 236 | unsigned long start_addr; | 236 | info.flags = 0; |
| 237 | 237 | info.length = len; | |
| 238 | if (len > mm->cached_hole_size) { | 238 | info.low_limit = TASK_UNMAPPED_BASE; |
| 239 | start_addr = mm->free_area_cache; | 239 | info.high_limit = TASK_SIZE; |
| 240 | } else { | 240 | info.align_mask = PAGE_MASK & ~huge_page_mask(h); |
| 241 | start_addr = TASK_UNMAPPED_BASE; | 241 | info.align_offset = 0; |
| 242 | mm->cached_hole_size = 0; | 242 | return vm_unmapped_area(&info); |
| 243 | } | ||
| 244 | |||
| 245 | full_search: | ||
| 246 | addr = ALIGN(start_addr, huge_page_size(h)); | ||
| 247 | |||
| 248 | for (vma = find_vma(mm, addr); ; vma = vma->vm_next) { | ||
| 249 | /* At this point: (!vma || addr < vma->vm_end). */ | ||
| 250 | if (TASK_SIZE - len < addr) { | ||
| 251 | /* | ||
| 252 | * Start a new search - just in case we missed | ||
| 253 | * some holes. | ||
| 254 | */ | ||
| 255 | if (start_addr != TASK_UNMAPPED_BASE) { | ||
| 256 | start_addr = TASK_UNMAPPED_BASE; | ||
| 257 | mm->cached_hole_size = 0; | ||
| 258 | goto full_search; | ||
| 259 | } | ||
| 260 | return -ENOMEM; | ||
| 261 | } | ||
| 262 | if (!vma || addr + len <= vma->vm_start) { | ||
| 263 | mm->free_area_cache = addr + len; | ||
| 264 | return addr; | ||
| 265 | } | ||
| 266 | if (addr + mm->cached_hole_size < vma->vm_start) | ||
| 267 | mm->cached_hole_size = vma->vm_start - addr; | ||
| 268 | addr = ALIGN(vma->vm_end, huge_page_size(h)); | ||
| 269 | } | ||
| 270 | } | 243 | } |
| 271 | 244 | ||
| 272 | static unsigned long hugetlb_get_unmapped_area_topdown(struct file *file, | 245 | static unsigned long hugetlb_get_unmapped_area_topdown(struct file *file, |
| @@ -274,92 +247,30 @@ static unsigned long hugetlb_get_unmapped_area_topdown(struct file *file, | |||
| 274 | unsigned long pgoff, unsigned long flags) | 247 | unsigned long pgoff, unsigned long flags) |
| 275 | { | 248 | { |
| 276 | struct hstate *h = hstate_file(file); | 249 | struct hstate *h = hstate_file(file); |
| 277 | struct mm_struct *mm = current->mm; | 250 | struct vm_unmapped_area_info info; |
| 278 | struct vm_area_struct *vma, *prev_vma; | 251 | unsigned long addr; |
| 279 | unsigned long base = mm->mmap_base, addr = addr0; | ||
| 280 | unsigned long largest_hole = mm->cached_hole_size; | ||
| 281 | int first_time = 1; | ||
| 282 | |||
| 283 | /* don't allow allocations above current base */ | ||
| 284 | if (mm->free_area_cache > base) | ||
| 285 | mm->free_area_cache = base; | ||
| 286 | |||
| 287 | if (len <= largest_hole) { | ||
| 288 | largest_hole = 0; | ||
| 289 | mm->free_area_cache = base; | ||
| 290 | } | ||
| 291 | try_again: | ||
| 292 | /* make sure it can fit in the remaining address space */ | ||
| 293 | if (mm->free_area_cache < len) | ||
| 294 | goto fail; | ||
| 295 | |||
| 296 | /* either no address requested or can't fit in requested address hole */ | ||
| 297 | addr = (mm->free_area_cache - len) & huge_page_mask(h); | ||
| 298 | do { | ||
| 299 | /* | ||
| 300 | * Lookup failure means no vma is above this address, | ||
| 301 | * i.e. return with success: | ||
| 302 | */ | ||
| 303 | vma = find_vma_prev(mm, addr, &prev_vma); | ||
| 304 | if (!vma) { | ||
| 305 | return addr; | ||
| 306 | break; | ||
| 307 | } | ||
| 308 | |||
| 309 | /* | ||
| 310 | * new region fits between prev_vma->vm_end and | ||
| 311 | * vma->vm_start, use it: | ||
| 312 | */ | ||
| 313 | if (addr + len <= vma->vm_start && | ||
| 314 | (!prev_vma || (addr >= prev_vma->vm_end))) { | ||
| 315 | /* remember the address as a hint for next time */ | ||
| 316 | mm->cached_hole_size = largest_hole; | ||
| 317 | mm->free_area_cache = addr; | ||
| 318 | return addr; | ||
| 319 | } else { | ||
| 320 | /* pull free_area_cache down to the first hole */ | ||
| 321 | if (mm->free_area_cache == vma->vm_end) { | ||
| 322 | mm->free_area_cache = vma->vm_start; | ||
| 323 | mm->cached_hole_size = largest_hole; | ||
| 324 | } | ||
| 325 | } | ||
| 326 | 252 | ||
| 327 | /* remember the largest hole we saw so far */ | 253 | info.flags = VM_UNMAPPED_AREA_TOPDOWN; |
| 328 | if (addr + largest_hole < vma->vm_start) | 254 | info.length = len; |
| 329 | largest_hole = vma->vm_start - addr; | 255 | info.low_limit = PAGE_SIZE; |
| 256 | info.high_limit = current->mm->mmap_base; | ||
| 257 | info.align_mask = PAGE_MASK & ~huge_page_mask(h); | ||
| 258 | info.align_offset = 0; | ||
| 259 | addr = vm_unmapped_area(&info); | ||
| 330 | 260 | ||
| 331 | /* try just below the current vma->vm_start */ | ||
| 332 | addr = (vma->vm_start - len) & huge_page_mask(h); | ||
| 333 | |||
| 334 | } while (len <= vma->vm_start); | ||
| 335 | |||
| 336 | fail: | ||
| 337 | /* | ||
| 338 | * if hint left us with no space for the requested | ||
| 339 | * mapping then try again: | ||
| 340 | */ | ||
| 341 | if (first_time) { | ||
| 342 | mm->free_area_cache = base; | ||
| 343 | largest_hole = 0; | ||
| 344 | first_time = 0; | ||
| 345 | goto try_again; | ||
| 346 | } | ||
| 347 | /* | 261 | /* |
| 348 | * A failed mmap() very likely causes application failure, | 262 | * A failed mmap() very likely causes application failure, |
| 349 | * so fall back to the bottom-up function here. This scenario | 263 | * so fall back to the bottom-up function here. This scenario |
| 350 | * can happen with large stack limits and large mmap() | 264 | * can happen with large stack limits and large mmap() |
| 351 | * allocations. | 265 | * allocations. |
| 352 | */ | 266 | */ |
| 353 | mm->free_area_cache = TASK_UNMAPPED_BASE; | 267 | if (addr & ~PAGE_MASK) { |
| 354 | mm->cached_hole_size = ~0UL; | 268 | VM_BUG_ON(addr != -ENOMEM); |
| 355 | addr = hugetlb_get_unmapped_area_bottomup(file, addr0, | 269 | info.flags = 0; |
| 356 | len, pgoff, flags); | 270 | info.low_limit = TASK_UNMAPPED_BASE; |
| 357 | 271 | info.high_limit = TASK_SIZE; | |
| 358 | /* | 272 | addr = vm_unmapped_area(&info); |
| 359 | * Restore the topdown base: | 273 | } |
| 360 | */ | ||
| 361 | mm->free_area_cache = base; | ||
| 362 | mm->cached_hole_size = ~0UL; | ||
| 363 | 274 | ||
| 364 | return addr; | 275 | return addr; |
| 365 | } | 276 | } |
