aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc')
-rw-r--r--arch/sparc/Kconfig2
-rw-r--r--arch/sparc/boot/piggyback.c12
-rw-r--r--arch/sparc/include/asm/Kbuild1
-rw-r--r--arch/sparc/include/asm/processor_32.h1
-rw-r--r--arch/sparc/include/asm/processor_64.h11
-rw-r--r--arch/sparc/include/asm/ptrace.h10
-rw-r--r--arch/sparc/include/asm/signal.h2
-rw-r--r--arch/sparc/include/asm/switch_to_64.h2
-rw-r--r--arch/sparc/include/asm/syscalls.h2
-rw-r--r--arch/sparc/include/asm/thread_info_64.h25
-rw-r--r--arch/sparc/include/asm/uaccess_64.h4
-rw-r--r--arch/sparc/include/asm/unistd.h2
-rw-r--r--arch/sparc/include/uapi/asm/ioctls.h3
-rw-r--r--arch/sparc/include/uapi/asm/socket.h1
-rw-r--r--arch/sparc/kernel/entry.S51
-rw-r--r--arch/sparc/kernel/etrap_64.S8
-rw-r--r--arch/sparc/kernel/pci_impl.h2
-rw-r--r--arch/sparc/kernel/process_32.c158
-rw-r--r--arch/sparc/kernel/process_64.c148
-rw-r--r--arch/sparc/kernel/sys32.S2
-rw-r--r--arch/sparc/kernel/sys_sparc32.c50
-rw-r--r--arch/sparc/kernel/sys_sparc_32.c51
-rw-r--r--arch/sparc/kernel/sys_sparc_64.c172
-rw-r--r--arch/sparc/kernel/syscalls.S44
-rw-r--r--arch/sparc/kernel/systbls_64.S4
-rw-r--r--arch/sparc/kernel/traps_64.c4
-rw-r--r--arch/sparc/mm/hugetlbpage.c124
-rw-r--r--arch/sparc/mm/init_64.c2
-rw-r--r--arch/sparc/net/bpf_jit_comp.c19
29 files changed, 278 insertions, 639 deletions
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index 9f2edb5c5551..0c7d365fa402 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -41,6 +41,8 @@ config SPARC
41 select GENERIC_STRNCPY_FROM_USER 41 select GENERIC_STRNCPY_FROM_USER
42 select GENERIC_STRNLEN_USER 42 select GENERIC_STRNLEN_USER
43 select MODULES_USE_ELF_RELA 43 select MODULES_USE_ELF_RELA
44 select GENERIC_KERNEL_THREAD
45 select GENERIC_KERNEL_EXECVE
44 46
45config SPARC32 47config SPARC32
46 def_bool !64BIT 48 def_bool !64BIT
diff --git a/arch/sparc/boot/piggyback.c b/arch/sparc/boot/piggyback.c
index c0a798fcf030..bb7c95161d71 100644
--- a/arch/sparc/boot/piggyback.c
+++ b/arch/sparc/boot/piggyback.c
@@ -81,18 +81,18 @@ static void usage(void)
81 81
82static int start_line(const char *line) 82static int start_line(const char *line)
83{ 83{
84 if (strcmp(line + 8, " T _start\n") == 0) 84 if (strcmp(line + 10, " _start\n") == 0)
85 return 1; 85 return 1;
86 else if (strcmp(line + 16, " T _start\n") == 0) 86 else if (strcmp(line + 18, " _start\n") == 0)
87 return 1; 87 return 1;
88 return 0; 88 return 0;
89} 89}
90 90
91static int end_line(const char *line) 91static int end_line(const char *line)
92{ 92{
93 if (strcmp(line + 8, " A _end\n") == 0) 93 if (strcmp(line + 10, " _end\n") == 0)
94 return 1; 94 return 1;
95 else if (strcmp (line + 16, " A _end\n") == 0) 95 else if (strcmp (line + 18, " _end\n") == 0)
96 return 1; 96 return 1;
97 return 0; 97 return 0;
98} 98}
@@ -100,8 +100,8 @@ static int end_line(const char *line)
100/* 100/*
101 * Find address for start and end in System.map. 101 * Find address for start and end in System.map.
102 * The file looks like this: 102 * The file looks like this:
103 * f0004000 T _start 103 * f0004000 ... _start
104 * f0379f79 A _end 104 * f0379f79 ... _end
105 * 1234567890123456 105 * 1234567890123456
106 * ^coloumn 1 106 * ^coloumn 1
107 * There is support for 64 bit addresses too. 107 * There is support for 64 bit addresses too.
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild
index 645a58da0e86..e26d430ce2fd 100644
--- a/arch/sparc/include/asm/Kbuild
+++ b/arch/sparc/include/asm/Kbuild
@@ -8,4 +8,5 @@ generic-y += local64.h
8generic-y += irq_regs.h 8generic-y += irq_regs.h
9generic-y += local.h 9generic-y += local.h
10generic-y += module.h 10generic-y += module.h
11generic-y += trace_clock.h
11generic-y += word-at-a-time.h 12generic-y += word-at-a-time.h
diff --git a/arch/sparc/include/asm/processor_32.h b/arch/sparc/include/asm/processor_32.h
index f74ac9ee33a8..c1e01914fd98 100644
--- a/arch/sparc/include/asm/processor_32.h
+++ b/arch/sparc/include/asm/processor_32.h
@@ -106,7 +106,6 @@ static inline void start_thread(struct pt_regs * regs, unsigned long pc,
106 106
107/* Free all resources held by a thread. */ 107/* Free all resources held by a thread. */
108#define release_thread(tsk) do { } while(0) 108#define release_thread(tsk) do { } while(0)
109extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
110 109
111extern unsigned long get_wchan(struct task_struct *); 110extern unsigned long get_wchan(struct task_struct *);
112 111
diff --git a/arch/sparc/include/asm/processor_64.h b/arch/sparc/include/asm/processor_64.h
index 721e25f0e2ea..cce72ce4c334 100644
--- a/arch/sparc/include/asm/processor_64.h
+++ b/arch/sparc/include/asm/processor_64.h
@@ -94,6 +94,7 @@ struct thread_struct {
94#ifndef __ASSEMBLY__ 94#ifndef __ASSEMBLY__
95 95
96#include <linux/types.h> 96#include <linux/types.h>
97#include <asm/fpumacro.h>
97 98
98/* Return saved PC of a blocked thread. */ 99/* Return saved PC of a blocked thread. */
99struct task_struct; 100struct task_struct;
@@ -143,6 +144,10 @@ do { \
143 : \ 144 : \
144 : "r" (regs), "r" (sp - sizeof(struct reg_window) - STACK_BIAS), \ 145 : "r" (regs), "r" (sp - sizeof(struct reg_window) - STACK_BIAS), \
145 "i" ((const unsigned long)(&((struct pt_regs *)0)->u_regs[0]))); \ 146 "i" ((const unsigned long)(&((struct pt_regs *)0)->u_regs[0]))); \
147 fprs_write(0); \
148 current_thread_info()->xfsr[0] = 0; \
149 current_thread_info()->fpsaved[0] = 0; \
150 regs->tstate &= ~TSTATE_PEF; \
146} while (0) 151} while (0)
147 152
148#define start_thread32(regs, pc, sp) \ 153#define start_thread32(regs, pc, sp) \
@@ -183,13 +188,15 @@ do { \
183 : \ 188 : \
184 : "r" (regs), "r" (sp - sizeof(struct reg_window32)), \ 189 : "r" (regs), "r" (sp - sizeof(struct reg_window32)), \
185 "i" ((const unsigned long)(&((struct pt_regs *)0)->u_regs[0]))); \ 190 "i" ((const unsigned long)(&((struct pt_regs *)0)->u_regs[0]))); \
191 fprs_write(0); \
192 current_thread_info()->xfsr[0] = 0; \
193 current_thread_info()->fpsaved[0] = 0; \
194 regs->tstate &= ~TSTATE_PEF; \
186} while (0) 195} while (0)
187 196
188/* Free all resources held by a thread. */ 197/* Free all resources held by a thread. */
189#define release_thread(tsk) do { } while (0) 198#define release_thread(tsk) do { } while (0)
190 199
191extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
192
193extern unsigned long get_wchan(struct task_struct *task); 200extern unsigned long get_wchan(struct task_struct *task);
194 201
195#define task_pt_regs(tsk) (task_thread_info(tsk)->kregs) 202#define task_pt_regs(tsk) (task_thread_info(tsk)->kregs)
diff --git a/arch/sparc/include/asm/ptrace.h b/arch/sparc/include/asm/ptrace.h
index da43bdc62294..bdfafd7af46f 100644
--- a/arch/sparc/include/asm/ptrace.h
+++ b/arch/sparc/include/asm/ptrace.h
@@ -32,6 +32,9 @@ static inline bool pt_regs_clear_syscall(struct pt_regs *regs)
32#define arch_ptrace_stop(exit_code, info) \ 32#define arch_ptrace_stop(exit_code, info) \
33 synchronize_user_stack() 33 synchronize_user_stack()
34 34
35#define current_pt_regs() \
36 ((struct pt_regs *)((unsigned long)current_thread_info() + THREAD_SIZE) - 1)
37
35struct global_reg_snapshot { 38struct global_reg_snapshot {
36 unsigned long tstate; 39 unsigned long tstate;
37 unsigned long tpc; 40 unsigned long tpc;
@@ -55,9 +58,7 @@ union global_cpu_snapshot {
55 58
56extern union global_cpu_snapshot global_cpu_snapshot[NR_CPUS]; 59extern union global_cpu_snapshot global_cpu_snapshot[NR_CPUS];
57 60
58#define force_successful_syscall_return() \ 61#define force_successful_syscall_return() set_thread_noerror(1)
59do { current_thread_info()->syscall_noerror = 1; \
60} while (0)
61#define user_mode(regs) (!((regs)->tstate & TSTATE_PRIV)) 62#define user_mode(regs) (!((regs)->tstate & TSTATE_PRIV))
62#define instruction_pointer(regs) ((regs)->tpc) 63#define instruction_pointer(regs) ((regs)->tpc)
63#define instruction_pointer_set(regs, val) ((regs)->tpc = (val)) 64#define instruction_pointer_set(regs, val) ((regs)->tpc = (val))
@@ -100,6 +101,9 @@ static inline bool pt_regs_clear_syscall(struct pt_regs *regs)
100#define arch_ptrace_stop(exit_code, info) \ 101#define arch_ptrace_stop(exit_code, info) \
101 synchronize_user_stack() 102 synchronize_user_stack()
102 103
104#define current_pt_regs() \
105 ((struct pt_regs *)((unsigned long)current_thread_info() + THREAD_SIZE) - 1)
106
103#define user_mode(regs) (!((regs)->psr & PSR_PS)) 107#define user_mode(regs) (!((regs)->psr & PSR_PS))
104#define instruction_pointer(regs) ((regs)->pc) 108#define instruction_pointer(regs) ((regs)->pc)
105#define user_stack_pointer(regs) ((regs)->u_regs[UREG_FP]) 109#define user_stack_pointer(regs) ((regs)->u_regs[UREG_FP])
diff --git a/arch/sparc/include/asm/signal.h b/arch/sparc/include/asm/signal.h
index d243c2ae02d2..77b85850d543 100644
--- a/arch/sparc/include/asm/signal.h
+++ b/arch/sparc/include/asm/signal.h
@@ -26,7 +26,5 @@ struct k_sigaction {
26 void __user *ka_restorer; 26 void __user *ka_restorer;
27}; 27};
28 28
29#define ptrace_signal_deliver(regs, cookie) do { } while (0)
30
31#endif /* !(__ASSEMBLY__) */ 29#endif /* !(__ASSEMBLY__) */
32#endif /* !(__SPARC_SIGNAL_H) */ 30#endif /* !(__SPARC_SIGNAL_H) */
diff --git a/arch/sparc/include/asm/switch_to_64.h b/arch/sparc/include/asm/switch_to_64.h
index 7923c4a2be38..cad36f56fa03 100644
--- a/arch/sparc/include/asm/switch_to_64.h
+++ b/arch/sparc/include/asm/switch_to_64.h
@@ -23,7 +23,7 @@ do { flush_tlb_pending(); \
23 /* If you are tempted to conditionalize the following */ \ 23 /* If you are tempted to conditionalize the following */ \
24 /* so that ASI is only written if it changes, think again. */ \ 24 /* so that ASI is only written if it changes, think again. */ \
25 __asm__ __volatile__("wr %%g0, %0, %%asi" \ 25 __asm__ __volatile__("wr %%g0, %0, %%asi" \
26 : : "r" (__thread_flag_byte_ptr(task_thread_info(next))[TI_FLAG_BYTE_CURRENT_DS]));\ 26 : : "r" (task_thread_info(next)->current_ds));\
27 trap_block[current_thread_info()->cpu].thread = \ 27 trap_block[current_thread_info()->cpu].thread = \
28 task_thread_info(next); \ 28 task_thread_info(next); \
29 __asm__ __volatile__( \ 29 __asm__ __volatile__( \
diff --git a/arch/sparc/include/asm/syscalls.h b/arch/sparc/include/asm/syscalls.h
index 45a43f637a14..bf8972adea17 100644
--- a/arch/sparc/include/asm/syscalls.h
+++ b/arch/sparc/include/asm/syscalls.h
@@ -8,6 +8,4 @@ extern asmlinkage long sparc_do_fork(unsigned long clone_flags,
8 struct pt_regs *regs, 8 struct pt_regs *regs,
9 unsigned long stack_size); 9 unsigned long stack_size);
10 10
11extern asmlinkage int sparc_execve(struct pt_regs *regs);
12
13#endif /* _SPARC64_SYSCALLS_H */ 11#endif /* _SPARC64_SYSCALLS_H */
diff --git a/arch/sparc/include/asm/thread_info_64.h b/arch/sparc/include/asm/thread_info_64.h
index a3fe4dcc0aa6..269bd92313df 100644
--- a/arch/sparc/include/asm/thread_info_64.h
+++ b/arch/sparc/include/asm/thread_info_64.h
@@ -14,12 +14,12 @@
14#define TI_FLAG_FAULT_CODE_SHIFT 56 14#define TI_FLAG_FAULT_CODE_SHIFT 56
15#define TI_FLAG_BYTE_WSTATE 1 15#define TI_FLAG_BYTE_WSTATE 1
16#define TI_FLAG_WSTATE_SHIFT 48 16#define TI_FLAG_WSTATE_SHIFT 48
17#define TI_FLAG_BYTE_CWP 2 17#define TI_FLAG_BYTE_NOERROR 2
18#define TI_FLAG_CWP_SHIFT 40 18#define TI_FLAG_BYTE_NOERROR_SHIFT 40
19#define TI_FLAG_BYTE_CURRENT_DS 3 19#define TI_FLAG_BYTE_FPDEPTH 3
20#define TI_FLAG_CURRENT_DS_SHIFT 32 20#define TI_FLAG_FPDEPTH_SHIFT 32
21#define TI_FLAG_BYTE_FPDEPTH 4 21#define TI_FLAG_BYTE_CWP 4
22#define TI_FLAG_FPDEPTH_SHIFT 24 22#define TI_FLAG_CWP_SHIFT 24
23#define TI_FLAG_BYTE_WSAVED 5 23#define TI_FLAG_BYTE_WSAVED 5
24#define TI_FLAG_WSAVED_SHIFT 16 24#define TI_FLAG_WSAVED_SHIFT 16
25 25
@@ -47,7 +47,7 @@ struct thread_info {
47 struct exec_domain *exec_domain; 47 struct exec_domain *exec_domain;
48 int preempt_count; /* 0 => preemptable, <0 => BUG */ 48 int preempt_count; /* 0 => preemptable, <0 => BUG */
49 __u8 new_child; 49 __u8 new_child;
50 __u8 syscall_noerror; 50 __u8 current_ds;
51 __u16 cpu; 51 __u16 cpu;
52 52
53 unsigned long *utraps; 53 unsigned long *utraps;
@@ -74,9 +74,9 @@ struct thread_info {
74#define TI_FAULT_CODE (TI_FLAGS + TI_FLAG_BYTE_FAULT_CODE) 74#define TI_FAULT_CODE (TI_FLAGS + TI_FLAG_BYTE_FAULT_CODE)
75#define TI_WSTATE (TI_FLAGS + TI_FLAG_BYTE_WSTATE) 75#define TI_WSTATE (TI_FLAGS + TI_FLAG_BYTE_WSTATE)
76#define TI_CWP (TI_FLAGS + TI_FLAG_BYTE_CWP) 76#define TI_CWP (TI_FLAGS + TI_FLAG_BYTE_CWP)
77#define TI_CURRENT_DS (TI_FLAGS + TI_FLAG_BYTE_CURRENT_DS)
78#define TI_FPDEPTH (TI_FLAGS + TI_FLAG_BYTE_FPDEPTH) 77#define TI_FPDEPTH (TI_FLAGS + TI_FLAG_BYTE_FPDEPTH)
79#define TI_WSAVED (TI_FLAGS + TI_FLAG_BYTE_WSAVED) 78#define TI_WSAVED (TI_FLAGS + TI_FLAG_BYTE_WSAVED)
79#define TI_SYS_NOERROR (TI_FLAGS + TI_FLAG_BYTE_NOERROR)
80#define TI_FPSAVED 0x00000010 80#define TI_FPSAVED 0x00000010
81#define TI_KSP 0x00000018 81#define TI_KSP 0x00000018
82#define TI_FAULT_ADDR 0x00000020 82#define TI_FAULT_ADDR 0x00000020
@@ -84,7 +84,7 @@ struct thread_info {
84#define TI_EXEC_DOMAIN 0x00000030 84#define TI_EXEC_DOMAIN 0x00000030
85#define TI_PRE_COUNT 0x00000038 85#define TI_PRE_COUNT 0x00000038
86#define TI_NEW_CHILD 0x0000003c 86#define TI_NEW_CHILD 0x0000003c
87#define TI_SYS_NOERROR 0x0000003d 87#define TI_CURRENT_DS 0x0000003d
88#define TI_CPU 0x0000003e 88#define TI_CPU 0x0000003e
89#define TI_UTRAPS 0x00000040 89#define TI_UTRAPS 0x00000040
90#define TI_REG_WINDOW 0x00000048 90#define TI_REG_WINDOW 0x00000048
@@ -121,7 +121,7 @@ struct thread_info {
121#define INIT_THREAD_INFO(tsk) \ 121#define INIT_THREAD_INFO(tsk) \
122{ \ 122{ \
123 .task = &tsk, \ 123 .task = &tsk, \
124 .flags = ((unsigned long)ASI_P) << TI_FLAG_CURRENT_DS_SHIFT, \ 124 .current_ds = ASI_P, \
125 .exec_domain = &default_exec_domain, \ 125 .exec_domain = &default_exec_domain, \
126 .preempt_count = INIT_PREEMPT_COUNT, \ 126 .preempt_count = INIT_PREEMPT_COUNT, \
127 .restart_block = { \ 127 .restart_block = { \
@@ -153,13 +153,12 @@ register struct thread_info *current_thread_info_reg asm("g6");
153#define set_thread_wstate(val) (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_WSTATE] = (val)) 153#define set_thread_wstate(val) (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_WSTATE] = (val))
154#define get_thread_cwp() (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_CWP]) 154#define get_thread_cwp() (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_CWP])
155#define set_thread_cwp(val) (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_CWP] = (val)) 155#define set_thread_cwp(val) (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_CWP] = (val))
156#define get_thread_current_ds() (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_CURRENT_DS]) 156#define get_thread_noerror() (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_NOERROR])
157#define set_thread_current_ds(val) (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_CURRENT_DS] = (val)) 157#define set_thread_noerror(val) (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_NOERROR] = (val))
158#define get_thread_fpdepth() (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_FPDEPTH]) 158#define get_thread_fpdepth() (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_FPDEPTH])
159#define set_thread_fpdepth(val) (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_FPDEPTH] = (val)) 159#define set_thread_fpdepth(val) (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_FPDEPTH] = (val))
160#define get_thread_wsaved() (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_WSAVED]) 160#define get_thread_wsaved() (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_WSAVED])
161#define set_thread_wsaved(val) (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_WSAVED] = (val)) 161#define set_thread_wsaved(val) (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_WSAVED] = (val))
162
163#endif /* !(__ASSEMBLY__) */ 162#endif /* !(__ASSEMBLY__) */
164 163
165/* 164/*
diff --git a/arch/sparc/include/asm/uaccess_64.h b/arch/sparc/include/asm/uaccess_64.h
index 73083e1d38d9..e562d3caee57 100644
--- a/arch/sparc/include/asm/uaccess_64.h
+++ b/arch/sparc/include/asm/uaccess_64.h
@@ -38,14 +38,14 @@
38#define VERIFY_READ 0 38#define VERIFY_READ 0
39#define VERIFY_WRITE 1 39#define VERIFY_WRITE 1
40 40
41#define get_fs() ((mm_segment_t) { get_thread_current_ds() }) 41#define get_fs() ((mm_segment_t){(current_thread_info()->current_ds)})
42#define get_ds() (KERNEL_DS) 42#define get_ds() (KERNEL_DS)
43 43
44#define segment_eq(a,b) ((a).seg == (b).seg) 44#define segment_eq(a,b) ((a).seg == (b).seg)
45 45
46#define set_fs(val) \ 46#define set_fs(val) \
47do { \ 47do { \
48 set_thread_current_ds((val).seg); \ 48 current_thread_info()->current_ds =(val).seg; \
49 __asm__ __volatile__ ("wr %%g0, %0, %%asi" : : "r" ((val).seg)); \ 49 __asm__ __volatile__ ("wr %%g0, %0, %%asi" : : "r" ((val).seg)); \
50} while(0) 50} while(0)
51 51
diff --git a/arch/sparc/include/asm/unistd.h b/arch/sparc/include/asm/unistd.h
index 0ecea6ed943e..497386a7ed28 100644
--- a/arch/sparc/include/asm/unistd.h
+++ b/arch/sparc/include/asm/unistd.h
@@ -45,7 +45,9 @@
45#define __ARCH_WANT_COMPAT_SYS_TIME 45#define __ARCH_WANT_COMPAT_SYS_TIME
46#define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND 46#define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
47#define __ARCH_WANT_COMPAT_SYS_SENDFILE 47#define __ARCH_WANT_COMPAT_SYS_SENDFILE
48#define __ARCH_WANT_COMPAT_SYS_SCHED_RR_GET_INTERVAL
48#endif 49#endif
50#define __ARCH_WANT_SYS_EXECVE
49 51
50/* 52/*
51 * "Conditional" syscalls 53 * "Conditional" syscalls
diff --git a/arch/sparc/include/uapi/asm/ioctls.h b/arch/sparc/include/uapi/asm/ioctls.h
index 9155f7041d44..897d1723fa14 100644
--- a/arch/sparc/include/uapi/asm/ioctls.h
+++ b/arch/sparc/include/uapi/asm/ioctls.h
@@ -21,6 +21,9 @@
21#define TCSETSF2 _IOW('T', 15, struct termios2) 21#define TCSETSF2 _IOW('T', 15, struct termios2)
22#define TIOCGDEV _IOR('T',0x32, unsigned int) /* Get primary device node of /dev/console */ 22#define TIOCGDEV _IOR('T',0x32, unsigned int) /* Get primary device node of /dev/console */
23#define TIOCVHANGUP _IO('T', 0x37) 23#define TIOCVHANGUP _IO('T', 0x37)
24#define TIOCGPKT _IOR('T', 0x38, int) /* Get packet mode state */
25#define TIOCGPTLCK _IOR('T', 0x39, int) /* Get Pty lock state */
26#define TIOCGEXCL _IOR('T', 0x40, int) /* Get exclusive mode state */
24 27
25/* Note that all the ioctls that are not available in Linux have a 28/* Note that all the ioctls that are not available in Linux have a
26 * double underscore on the front to: a) avoid some programs to 29 * double underscore on the front to: a) avoid some programs to
diff --git a/arch/sparc/include/uapi/asm/socket.h b/arch/sparc/include/uapi/asm/socket.h
index bea1568ae4af..c83a937ead00 100644
--- a/arch/sparc/include/uapi/asm/socket.h
+++ b/arch/sparc/include/uapi/asm/socket.h
@@ -41,6 +41,7 @@
41 41
42#define SO_ATTACH_FILTER 0x001a 42#define SO_ATTACH_FILTER 0x001a
43#define SO_DETACH_FILTER 0x001b 43#define SO_DETACH_FILTER 0x001b
44#define SO_GET_FILTER SO_ATTACH_FILTER
44 45
45#define SO_PEERNAME 0x001c 46#define SO_PEERNAME 0x001c
46#define SO_TIMESTAMP 0x001d 47#define SO_TIMESTAMP 0x001d
diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S
index dcaa1cf0de40..21fd1a8f47d2 100644
--- a/arch/sparc/kernel/entry.S
+++ b/arch/sparc/kernel/entry.S
@@ -806,23 +806,10 @@ sys_nis_syscall:
806 call c_sys_nis_syscall 806 call c_sys_nis_syscall
807 mov %l5, %o7 807 mov %l5, %o7
808 808
809 .align 4
810 .globl sys_execve
811sys_execve:
812 mov %o7, %l5
813 add %sp, STACKFRAME_SZ, %o0 ! pt_regs *regs arg
814 call sparc_execve
815 mov %l5, %o7
816
817 .globl sunos_execv
818sunos_execv: 809sunos_execv:
819 st %g0, [%sp + STACKFRAME_SZ + PT_I2] 810 .globl sunos_execv
820 811 b sys_execve
821 call sparc_execve 812 clr %i2
822 add %sp, STACKFRAME_SZ, %o0
823
824 b ret_sys_call
825 ld [%sp + STACKFRAME_SZ + PT_I0], %o0
826 813
827 .align 4 814 .align 4
828 .globl sys_sparc_pipe 815 .globl sys_sparc_pipe
@@ -959,17 +946,9 @@ flush_patch_four:
959 .align 4 946 .align 4
960linux_sparc_ni_syscall: 947linux_sparc_ni_syscall:
961 sethi %hi(sys_ni_syscall), %l7 948 sethi %hi(sys_ni_syscall), %l7
962 b syscall_is_too_hard 949 b do_syscall
963 or %l7, %lo(sys_ni_syscall), %l7 950 or %l7, %lo(sys_ni_syscall), %l7
964 951
965linux_fast_syscall:
966 andn %l7, 3, %l7
967 mov %i0, %o0
968 mov %i1, %o1
969 mov %i2, %o2
970 jmpl %l7 + %g0, %g0
971 mov %i3, %o3
972
973linux_syscall_trace: 952linux_syscall_trace:
974 add %sp, STACKFRAME_SZ, %o0 953 add %sp, STACKFRAME_SZ, %o0
975 call syscall_trace 954 call syscall_trace
@@ -991,6 +970,23 @@ ret_from_fork:
991 b ret_sys_call 970 b ret_sys_call
992 ld [%sp + STACKFRAME_SZ + PT_I0], %o0 971 ld [%sp + STACKFRAME_SZ + PT_I0], %o0
993 972
973 .globl ret_from_kernel_thread
974ret_from_kernel_thread:
975 call schedule_tail
976 ld [%g3 + TI_TASK], %o0
977 ld [%sp + STACKFRAME_SZ + PT_G1], %l0
978 call %l0
979 ld [%sp + STACKFRAME_SZ + PT_G2], %o0
980 rd %psr, %l1
981 ld [%sp + STACKFRAME_SZ + PT_PSR], %l0
982 andn %l0, PSR_CWP, %l0
983 nop
984 and %l1, PSR_CWP, %l1
985 or %l0, %l1, %l0
986 st %l0, [%sp + STACKFRAME_SZ + PT_PSR]
987 b ret_sys_call
988 mov 0, %o0
989
994 /* Linux native system calls enter here... */ 990 /* Linux native system calls enter here... */
995 .align 4 991 .align 4
996 .globl linux_sparc_syscall 992 .globl linux_sparc_syscall
@@ -1002,11 +998,8 @@ linux_sparc_syscall:
1002 bgeu linux_sparc_ni_syscall 998 bgeu linux_sparc_ni_syscall
1003 sll %g1, 2, %l4 999 sll %g1, 2, %l4
1004 ld [%l7 + %l4], %l7 1000 ld [%l7 + %l4], %l7
1005 andcc %l7, 1, %g0
1006 bne linux_fast_syscall
1007 /* Just do first insn from SAVE_ALL in the delay slot */
1008 1001
1009syscall_is_too_hard: 1002do_syscall:
1010 SAVE_ALL_HEAD 1003 SAVE_ALL_HEAD
1011 rd %wim, %l3 1004 rd %wim, %l3
1012 1005
diff --git a/arch/sparc/kernel/etrap_64.S b/arch/sparc/kernel/etrap_64.S
index 786b185e6e3f..1276ca2567ba 100644
--- a/arch/sparc/kernel/etrap_64.S
+++ b/arch/sparc/kernel/etrap_64.S
@@ -92,8 +92,10 @@ etrap_save: save %g2, -STACK_BIAS, %sp
92 rdpr %wstate, %g2 92 rdpr %wstate, %g2
93 wrpr %g0, 0, %canrestore 93 wrpr %g0, 0, %canrestore
94 sll %g2, 3, %g2 94 sll %g2, 3, %g2
95
96 /* Set TI_SYS_FPDEPTH to 1 and clear TI_SYS_NOERROR. */
95 mov 1, %l5 97 mov 1, %l5
96 stb %l5, [%l6 + TI_FPDEPTH] 98 sth %l5, [%l6 + TI_SYS_NOERROR]
97 99
98 wrpr %g3, 0, %otherwin 100 wrpr %g3, 0, %otherwin
99 wrpr %g2, 0, %wstate 101 wrpr %g2, 0, %wstate
@@ -152,7 +154,9 @@ etrap_save: save %g2, -STACK_BIAS, %sp
152 add %l6, TI_FPSAVED + 1, %l4 154 add %l6, TI_FPSAVED + 1, %l4
153 srl %l5, 1, %l3 155 srl %l5, 1, %l3
154 add %l5, 2, %l5 156 add %l5, 2, %l5
155 stb %l5, [%l6 + TI_FPDEPTH] 157
158 /* Set TI_SYS_FPDEPTH to %l5 and clear TI_SYS_NOERROR. */
159 sth %l5, [%l6 + TI_SYS_NOERROR]
156 ba,pt %xcc, 2b 160 ba,pt %xcc, 2b
157 stb %g0, [%l4 + %l3] 161 stb %g0, [%l4 + %l3]
158 nop 162 nop
diff --git a/arch/sparc/kernel/pci_impl.h b/arch/sparc/kernel/pci_impl.h
index 918a2031c8bb..5f688531f48c 100644
--- a/arch/sparc/kernel/pci_impl.h
+++ b/arch/sparc/kernel/pci_impl.h
@@ -88,7 +88,7 @@ struct pci_pbm_info {
88 int chip_revision; 88 int chip_revision;
89 89
90 /* Name used for top-level resources. */ 90 /* Name used for top-level resources. */
91 char *name; 91 const char *name;
92 92
93 /* OBP specific information. */ 93 /* OBP specific information. */
94 struct platform_device *op; 94 struct platform_device *op;
diff --git a/arch/sparc/kernel/process_32.c b/arch/sparc/kernel/process_32.c
index 487bffb36f5e..be8e862badaf 100644
--- a/arch/sparc/kernel/process_32.c
+++ b/arch/sparc/kernel/process_32.c
@@ -286,8 +286,7 @@ asmlinkage int sparc_do_fork(unsigned long clone_flags,
286 parent_tid_ptr = regs->u_regs[UREG_I2]; 286 parent_tid_ptr = regs->u_regs[UREG_I2];
287 child_tid_ptr = regs->u_regs[UREG_I4]; 287 child_tid_ptr = regs->u_regs[UREG_I4];
288 288
289 ret = do_fork(clone_flags, stack_start, 289 ret = do_fork(clone_flags, stack_start, stack_size,
290 regs, stack_size,
291 (int __user *) parent_tid_ptr, 290 (int __user *) parent_tid_ptr,
292 (int __user *) child_tid_ptr); 291 (int __user *) child_tid_ptr);
293 292
@@ -316,13 +315,13 @@ asmlinkage int sparc_do_fork(unsigned long clone_flags,
316 * XXX See comment above sys_vfork in sparc64. todo. 315 * XXX See comment above sys_vfork in sparc64. todo.
317 */ 316 */
318extern void ret_from_fork(void); 317extern void ret_from_fork(void);
318extern void ret_from_kernel_thread(void);
319 319
320int copy_thread(unsigned long clone_flags, unsigned long sp, 320int copy_thread(unsigned long clone_flags, unsigned long sp,
321 unsigned long unused, 321 unsigned long arg, struct task_struct *p)
322 struct task_struct *p, struct pt_regs *regs)
323{ 322{
324 struct thread_info *ti = task_thread_info(p); 323 struct thread_info *ti = task_thread_info(p);
325 struct pt_regs *childregs; 324 struct pt_regs *childregs, *regs = current_pt_regs();
326 char *new_stack; 325 char *new_stack;
327 326
328#ifndef CONFIG_SMP 327#ifndef CONFIG_SMP
@@ -336,16 +335,13 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
336 } 335 }
337 336
338 /* 337 /*
339 * p->thread_info new_stack childregs 338 * p->thread_info new_stack childregs stack bottom
340 * ! ! ! {if(PSR_PS) } 339 * ! ! ! !
341 * V V (stk.fr.) V (pt_regs) { (stk.fr.) } 340 * V V (stk.fr.) V (pt_regs) V
342 * +----- - - - - - ------+===========+============={+==========}+ 341 * +----- - - - - - ------+===========+=============+
343 */ 342 */
344 new_stack = task_stack_page(p) + THREAD_SIZE; 343 new_stack = task_stack_page(p) + THREAD_SIZE;
345 if (regs->psr & PSR_PS)
346 new_stack -= STACKFRAME_SZ;
347 new_stack -= STACKFRAME_SZ + TRACEREG_SZ; 344 new_stack -= STACKFRAME_SZ + TRACEREG_SZ;
348 memcpy(new_stack, (char *)regs - STACKFRAME_SZ, STACKFRAME_SZ + TRACEREG_SZ);
349 childregs = (struct pt_regs *) (new_stack + STACKFRAME_SZ); 345 childregs = (struct pt_regs *) (new_stack + STACKFRAME_SZ);
350 346
351 /* 347 /*
@@ -356,55 +352,58 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
356 * Thus, kpsr|=PSR_PIL. 352 * Thus, kpsr|=PSR_PIL.
357 */ 353 */
358 ti->ksp = (unsigned long) new_stack; 354 ti->ksp = (unsigned long) new_stack;
355 p->thread.kregs = childregs;
356
357 if (unlikely(p->flags & PF_KTHREAD)) {
358 extern int nwindows;
359 unsigned long psr;
360 memset(new_stack, 0, STACKFRAME_SZ + TRACEREG_SZ);
361 p->thread.flags |= SPARC_FLAG_KTHREAD;
362 p->thread.current_ds = KERNEL_DS;
363 ti->kpc = (((unsigned long) ret_from_kernel_thread) - 0x8);
364 childregs->u_regs[UREG_G1] = sp; /* function */
365 childregs->u_regs[UREG_G2] = arg;
366 psr = childregs->psr = get_psr();
367 ti->kpsr = psr | PSR_PIL;
368 ti->kwim = 1 << (((psr & PSR_CWP) + 1) % nwindows);
369 return 0;
370 }
371 memcpy(new_stack, (char *)regs - STACKFRAME_SZ, STACKFRAME_SZ + TRACEREG_SZ);
372 childregs->u_regs[UREG_FP] = sp;
373 p->thread.flags &= ~SPARC_FLAG_KTHREAD;
374 p->thread.current_ds = USER_DS;
359 ti->kpc = (((unsigned long) ret_from_fork) - 0x8); 375 ti->kpc = (((unsigned long) ret_from_fork) - 0x8);
360 ti->kpsr = current->thread.fork_kpsr | PSR_PIL; 376 ti->kpsr = current->thread.fork_kpsr | PSR_PIL;
361 ti->kwim = current->thread.fork_kwim; 377 ti->kwim = current->thread.fork_kwim;
362 378
363 if(regs->psr & PSR_PS) { 379 if (sp != regs->u_regs[UREG_FP]) {
364 extern struct pt_regs fake_swapper_regs; 380 struct sparc_stackf __user *childstack;
381 struct sparc_stackf __user *parentstack;
365 382
366 p->thread.kregs = &fake_swapper_regs; 383 /*
367 new_stack += STACKFRAME_SZ + TRACEREG_SZ; 384 * This is a clone() call with supplied user stack.
368 childregs->u_regs[UREG_FP] = (unsigned long) new_stack; 385 * Set some valid stack frames to give to the child.
369 p->thread.flags |= SPARC_FLAG_KTHREAD; 386 */
370 p->thread.current_ds = KERNEL_DS; 387 childstack = (struct sparc_stackf __user *)
371 memcpy(new_stack, (void *)regs->u_regs[UREG_FP], STACKFRAME_SZ); 388 (sp & ~0xfUL);
372 childregs->u_regs[UREG_G6] = (unsigned long) ti; 389 parentstack = (struct sparc_stackf __user *)
373 } else { 390 regs->u_regs[UREG_FP];
374 p->thread.kregs = childregs;
375 childregs->u_regs[UREG_FP] = sp;
376 p->thread.flags &= ~SPARC_FLAG_KTHREAD;
377 p->thread.current_ds = USER_DS;
378
379 if (sp != regs->u_regs[UREG_FP]) {
380 struct sparc_stackf __user *childstack;
381 struct sparc_stackf __user *parentstack;
382
383 /*
384 * This is a clone() call with supplied user stack.
385 * Set some valid stack frames to give to the child.
386 */
387 childstack = (struct sparc_stackf __user *)
388 (sp & ~0xfUL);
389 parentstack = (struct sparc_stackf __user *)
390 regs->u_regs[UREG_FP];
391 391
392#if 0 392#if 0
393 printk("clone: parent stack:\n"); 393 printk("clone: parent stack:\n");
394 show_stackframe(parentstack); 394 show_stackframe(parentstack);
395#endif 395#endif
396 396
397 childstack = clone_stackframe(childstack, parentstack); 397 childstack = clone_stackframe(childstack, parentstack);
398 if (!childstack) 398 if (!childstack)
399 return -EFAULT; 399 return -EFAULT;
400 400
401#if 0 401#if 0
402 printk("clone: child stack:\n"); 402 printk("clone: child stack:\n");
403 show_stackframe(childstack); 403 show_stackframe(childstack);
404#endif 404#endif
405 405
406 childregs->u_regs[UREG_FP] = (unsigned long)childstack; 406 childregs->u_regs[UREG_FP] = (unsigned long)childstack;
407 }
408 } 407 }
409 408
410#ifdef CONFIG_SMP 409#ifdef CONFIG_SMP
@@ -475,69 +474,6 @@ int dump_fpu (struct pt_regs * regs, elf_fpregset_t * fpregs)
475 return 1; 474 return 1;
476} 475}
477 476
478/*
479 * sparc_execve() executes a new program after the asm stub has set
480 * things up for us. This should basically do what I want it to.
481 */
482asmlinkage int sparc_execve(struct pt_regs *regs)
483{
484 int error, base = 0;
485 struct filename *filename;
486
487 /* Check for indirect call. */
488 if(regs->u_regs[UREG_G1] == 0)
489 base = 1;
490
491 filename = getname((char __user *)regs->u_regs[base + UREG_I0]);
492 error = PTR_ERR(filename);
493 if(IS_ERR(filename))
494 goto out;
495 error = do_execve(filename->name,
496 (const char __user *const __user *)
497 regs->u_regs[base + UREG_I1],
498 (const char __user *const __user *)
499 regs->u_regs[base + UREG_I2],
500 regs);
501 putname(filename);
502out:
503 return error;
504}
505
506/*
507 * This is the mechanism for creating a new kernel thread.
508 *
509 * NOTE! Only a kernel-only process(ie the swapper or direct descendants
510 * who haven't done an "execve()") should use this: it will work within
511 * a system call from a "real" process, but the process memory space will
512 * not be freed until both the parent and the child have exited.
513 */
514pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
515{
516 long retval;
517
518 __asm__ __volatile__("mov %4, %%g2\n\t" /* Set aside fn ptr... */
519 "mov %5, %%g3\n\t" /* and arg. */
520 "mov %1, %%g1\n\t"
521 "mov %2, %%o0\n\t" /* Clone flags. */
522 "mov 0, %%o1\n\t" /* usp arg == 0 */
523 "t 0x10\n\t" /* Linux/Sparc clone(). */
524 "cmp %%o1, 0\n\t"
525 "be 1f\n\t" /* The parent, just return. */
526 " nop\n\t" /* Delay slot. */
527 "jmpl %%g2, %%o7\n\t" /* Call the function. */
528 " mov %%g3, %%o0\n\t" /* Get back the arg in delay. */
529 "mov %3, %%g1\n\t"
530 "t 0x10\n\t" /* Linux/Sparc exit(). */
531 /* Notreached by child. */
532 "1: mov %%o0, %0\n\t" :
533 "=r" (retval) :
534 "i" (__NR_clone), "r" (flags | CLONE_VM | CLONE_UNTRACED),
535 "i" (__NR_exit), "r" (fn), "r" (arg) :
536 "g1", "g2", "g3", "o0", "o1", "memory", "cc");
537 return retval;
538}
539EXPORT_SYMBOL(kernel_thread);
540
541unsigned long get_wchan(struct task_struct *task) 477unsigned long get_wchan(struct task_struct *task)
542{ 478{
543 unsigned long pc, fp, bias = 0; 479 unsigned long pc, fp, bias = 0;
diff --git a/arch/sparc/kernel/process_64.c b/arch/sparc/kernel/process_64.c
index c6e0c2910043..cdb80b2adbe0 100644
--- a/arch/sparc/kernel/process_64.c
+++ b/arch/sparc/kernel/process_64.c
@@ -601,8 +601,7 @@ asmlinkage long sparc_do_fork(unsigned long clone_flags,
601 child_tid_ptr = (int __user *) regs->u_regs[UREG_I4]; 601 child_tid_ptr = (int __user *) regs->u_regs[UREG_I4];
602 } 602 }
603 603
604 ret = do_fork(clone_flags, stack_start, 604 ret = do_fork(clone_flags, stack_start, stack_size,
605 regs, stack_size,
606 parent_tid_ptr, child_tid_ptr); 605 parent_tid_ptr, child_tid_ptr);
607 606
608 /* If we get an error and potentially restart the system 607 /* If we get an error and potentially restart the system
@@ -622,64 +621,55 @@ asmlinkage long sparc_do_fork(unsigned long clone_flags,
622 * Child --> %o0 == parents pid, %o1 == 1 621 * Child --> %o0 == parents pid, %o1 == 1
623 */ 622 */
624int copy_thread(unsigned long clone_flags, unsigned long sp, 623int copy_thread(unsigned long clone_flags, unsigned long sp,
625 unsigned long unused, 624 unsigned long arg, struct task_struct *p)
626 struct task_struct *p, struct pt_regs *regs)
627{ 625{
628 struct thread_info *t = task_thread_info(p); 626 struct thread_info *t = task_thread_info(p);
627 struct pt_regs *regs = current_pt_regs();
629 struct sparc_stackf *parent_sf; 628 struct sparc_stackf *parent_sf;
630 unsigned long child_stack_sz; 629 unsigned long child_stack_sz;
631 char *child_trap_frame; 630 char *child_trap_frame;
632 int kernel_thread;
633
634 kernel_thread = (regs->tstate & TSTATE_PRIV) ? 1 : 0;
635 parent_sf = ((struct sparc_stackf *) regs) - 1;
636 631
637 /* Calculate offset to stack_frame & pt_regs */ 632 /* Calculate offset to stack_frame & pt_regs */
638 child_stack_sz = ((STACKFRAME_SZ + TRACEREG_SZ) + 633 child_stack_sz = (STACKFRAME_SZ + TRACEREG_SZ);
639 (kernel_thread ? STACKFRAME_SZ : 0));
640 child_trap_frame = (task_stack_page(p) + 634 child_trap_frame = (task_stack_page(p) +
641 (THREAD_SIZE - child_stack_sz)); 635 (THREAD_SIZE - child_stack_sz));
642 memcpy(child_trap_frame, parent_sf, child_stack_sz);
643 636
644 t->flags = (t->flags & ~((0xffUL << TI_FLAG_CWP_SHIFT) |
645 (0xffUL << TI_FLAG_CURRENT_DS_SHIFT))) |
646 (((regs->tstate + 1) & TSTATE_CWP) << TI_FLAG_CWP_SHIFT);
647 t->new_child = 1; 637 t->new_child = 1;
648 t->ksp = ((unsigned long) child_trap_frame) - STACK_BIAS; 638 t->ksp = ((unsigned long) child_trap_frame) - STACK_BIAS;
649 t->kregs = (struct pt_regs *) (child_trap_frame + 639 t->kregs = (struct pt_regs *) (child_trap_frame +
650 sizeof(struct sparc_stackf)); 640 sizeof(struct sparc_stackf));
651 t->fpsaved[0] = 0; 641 t->fpsaved[0] = 0;
652 642
653 if (kernel_thread) { 643 if (unlikely(p->flags & PF_KTHREAD)) {
654 struct sparc_stackf *child_sf = (struct sparc_stackf *) 644 memset(child_trap_frame, 0, child_stack_sz);
655 (child_trap_frame + (STACKFRAME_SZ + TRACEREG_SZ)); 645 __thread_flag_byte_ptr(t)[TI_FLAG_BYTE_CWP] =
656 646 (current_pt_regs()->tstate + 1) & TSTATE_CWP;
657 /* Zero terminate the stack backtrace. */ 647 t->current_ds = ASI_P;
658 child_sf->fp = NULL; 648 t->kregs->u_regs[UREG_G1] = sp; /* function */
659 t->kregs->u_regs[UREG_FP] = 649 t->kregs->u_regs[UREG_G2] = arg;
660 ((unsigned long) child_sf) - STACK_BIAS; 650 return 0;
651 }
661 652
662 t->flags |= ((long)ASI_P << TI_FLAG_CURRENT_DS_SHIFT); 653 parent_sf = ((struct sparc_stackf *) regs) - 1;
663 t->kregs->u_regs[UREG_G6] = (unsigned long) t; 654 memcpy(child_trap_frame, parent_sf, child_stack_sz);
664 t->kregs->u_regs[UREG_G4] = (unsigned long) t->task; 655 if (t->flags & _TIF_32BIT) {
665 } else { 656 sp &= 0x00000000ffffffffUL;
666 if (t->flags & _TIF_32BIT) { 657 regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL;
667 sp &= 0x00000000ffffffffUL;
668 regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL;
669 }
670 t->kregs->u_regs[UREG_FP] = sp;
671 t->flags |= ((long)ASI_AIUS << TI_FLAG_CURRENT_DS_SHIFT);
672 if (sp != regs->u_regs[UREG_FP]) {
673 unsigned long csp;
674
675 csp = clone_stackframe(sp, regs->u_regs[UREG_FP]);
676 if (!csp)
677 return -EFAULT;
678 t->kregs->u_regs[UREG_FP] = csp;
679 }
680 if (t->utraps)
681 t->utraps[0]++;
682 } 658 }
659 t->kregs->u_regs[UREG_FP] = sp;
660 __thread_flag_byte_ptr(t)[TI_FLAG_BYTE_CWP] =
661 (regs->tstate + 1) & TSTATE_CWP;
662 t->current_ds = ASI_AIUS;
663 if (sp != regs->u_regs[UREG_FP]) {
664 unsigned long csp;
665
666 csp = clone_stackframe(sp, regs->u_regs[UREG_FP]);
667 if (!csp)
668 return -EFAULT;
669 t->kregs->u_regs[UREG_FP] = csp;
670 }
671 if (t->utraps)
672 t->utraps[0]++;
683 673
684 /* Set the return value for the child. */ 674 /* Set the return value for the child. */
685 t->kregs->u_regs[UREG_I0] = current->pid; 675 t->kregs->u_regs[UREG_I0] = current->pid;
@@ -694,45 +684,6 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
694 return 0; 684 return 0;
695} 685}
696 686
697/*
698 * This is the mechanism for creating a new kernel thread.
699 *
700 * NOTE! Only a kernel-only process(ie the swapper or direct descendants
701 * who haven't done an "execve()") should use this: it will work within
702 * a system call from a "real" process, but the process memory space will
703 * not be freed until both the parent and the child have exited.
704 */
705pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
706{
707 long retval;
708
709 /* If the parent runs before fn(arg) is called by the child,
710 * the input registers of this function can be clobbered.
711 * So we stash 'fn' and 'arg' into global registers which
712 * will not be modified by the parent.
713 */
714 __asm__ __volatile__("mov %4, %%g2\n\t" /* Save FN into global */
715 "mov %5, %%g3\n\t" /* Save ARG into global */
716 "mov %1, %%g1\n\t" /* Clone syscall nr. */
717 "mov %2, %%o0\n\t" /* Clone flags. */
718 "mov 0, %%o1\n\t" /* usp arg == 0 */
719 "t 0x6d\n\t" /* Linux/Sparc clone(). */
720 "brz,a,pn %%o1, 1f\n\t" /* Parent, just return. */
721 " mov %%o0, %0\n\t"
722 "jmpl %%g2, %%o7\n\t" /* Call the function. */
723 " mov %%g3, %%o0\n\t" /* Set arg in delay. */
724 "mov %3, %%g1\n\t"
725 "t 0x6d\n\t" /* Linux/Sparc exit(). */
726 /* Notreached by child. */
727 "1:" :
728 "=r" (retval) :
729 "i" (__NR_clone), "r" (flags | CLONE_VM | CLONE_UNTRACED),
730 "i" (__NR_exit), "r" (fn), "r" (arg) :
731 "g1", "g2", "g3", "o0", "o1", "memory", "cc");
732 return retval;
733}
734EXPORT_SYMBOL(kernel_thread);
735
736typedef struct { 687typedef struct {
737 union { 688 union {
738 unsigned int pr_regs[32]; 689 unsigned int pr_regs[32];
@@ -799,41 +750,6 @@ int dump_fpu (struct pt_regs * regs, elf_fpregset_t * fpregs)
799} 750}
800EXPORT_SYMBOL(dump_fpu); 751EXPORT_SYMBOL(dump_fpu);
801 752
802/*
803 * sparc_execve() executes a new program after the asm stub has set
804 * things up for us. This should basically do what I want it to.
805 */
806asmlinkage int sparc_execve(struct pt_regs *regs)
807{
808 int error, base = 0;
809 struct filename *filename;
810
811 /* User register window flush is done by entry.S */
812
813 /* Check for indirect call. */
814 if (regs->u_regs[UREG_G1] == 0)
815 base = 1;
816
817 filename = getname((char __user *)regs->u_regs[base + UREG_I0]);
818 error = PTR_ERR(filename);
819 if (IS_ERR(filename))
820 goto out;
821 error = do_execve(filename->name,
822 (const char __user *const __user *)
823 regs->u_regs[base + UREG_I1],
824 (const char __user *const __user *)
825 regs->u_regs[base + UREG_I2], regs);
826 putname(filename);
827 if (!error) {
828 fprs_write(0);
829 current_thread_info()->xfsr[0] = 0;
830 current_thread_info()->fpsaved[0] = 0;
831 regs->tstate &= ~TSTATE_PEF;
832 }
833out:
834 return error;
835}
836
837unsigned long get_wchan(struct task_struct *task) 753unsigned long get_wchan(struct task_struct *task)
838{ 754{
839 unsigned long pc, fp, bias = 0; 755 unsigned long pc, fp, bias = 0;
diff --git a/arch/sparc/kernel/sys32.S b/arch/sparc/kernel/sys32.S
index 44025f4ba41f..8475a474273a 100644
--- a/arch/sparc/kernel/sys32.S
+++ b/arch/sparc/kernel/sys32.S
@@ -47,7 +47,7 @@ STUB: sra REG1, 0, REG1; \
47 sra REG4, 0, REG4 47 sra REG4, 0, REG4
48 48
49SIGN1(sys32_exit, sparc_exit, %o0) 49SIGN1(sys32_exit, sparc_exit, %o0)
50SIGN1(sys32_exit_group, sys_exit_group, %o0) 50SIGN1(sys32_exit_group, sparc_exit_group, %o0)
51SIGN1(sys32_wait4, compat_sys_wait4, %o2) 51SIGN1(sys32_wait4, compat_sys_wait4, %o2)
52SIGN1(sys32_creat, sys_creat, %o1) 52SIGN1(sys32_creat, sys_creat, %o1)
53SIGN1(sys32_mknod, sys_mknod, %o1) 53SIGN1(sys32_mknod, sys_mknod, %o1)
diff --git a/arch/sparc/kernel/sys_sparc32.c b/arch/sparc/kernel/sys_sparc32.c
index c3239811a1b5..4a4cdc633f6b 100644
--- a/arch/sparc/kernel/sys_sparc32.c
+++ b/arch/sparc/kernel/sys_sparc32.c
@@ -211,20 +211,6 @@ asmlinkage long compat_sys_sysfs(int option, u32 arg1, u32 arg2)
211 return sys_sysfs(option, arg1, arg2); 211 return sys_sysfs(option, arg1, arg2);
212} 212}
213 213
214asmlinkage long compat_sys_sched_rr_get_interval(compat_pid_t pid, struct compat_timespec __user *interval)
215{
216 struct timespec t;
217 int ret;
218 mm_segment_t old_fs = get_fs ();
219
220 set_fs (KERNEL_DS);
221 ret = sys_sched_rr_get_interval(pid, (struct timespec __user *) &t);
222 set_fs (old_fs);
223 if (put_compat_timespec(&t, interval))
224 return -EFAULT;
225 return ret;
226}
227
228asmlinkage long compat_sys_rt_sigprocmask(int how, 214asmlinkage long compat_sys_rt_sigprocmask(int how,
229 compat_sigset_t __user *set, 215 compat_sigset_t __user *set,
230 compat_sigset_t __user *oset, 216 compat_sigset_t __user *oset,
@@ -396,42 +382,6 @@ asmlinkage long compat_sys_rt_sigaction(int sig,
396 return ret; 382 return ret;
397} 383}
398 384
399/*
400 * sparc32_execve() executes a new program after the asm stub has set
401 * things up for us. This should basically do what I want it to.
402 */
403asmlinkage long sparc32_execve(struct pt_regs *regs)
404{
405 int error, base = 0;
406 struct filename *filename;
407
408 /* User register window flush is done by entry.S */
409
410 /* Check for indirect call. */
411 if ((u32)regs->u_regs[UREG_G1] == 0)
412 base = 1;
413
414 filename = getname(compat_ptr(regs->u_regs[base + UREG_I0]));
415 error = PTR_ERR(filename);
416 if (IS_ERR(filename))
417 goto out;
418
419 error = compat_do_execve(filename->name,
420 compat_ptr(regs->u_regs[base + UREG_I1]),
421 compat_ptr(regs->u_regs[base + UREG_I2]), regs);
422
423 putname(filename);
424
425 if (!error) {
426 fprs_write(0);
427 current_thread_info()->xfsr[0] = 0;
428 current_thread_info()->fpsaved[0] = 0;
429 regs->tstate &= ~TSTATE_PEF;
430 }
431out:
432 return error;
433}
434
435#ifdef CONFIG_MODULES 385#ifdef CONFIG_MODULES
436 386
437asmlinkage long sys32_init_module(void __user *umod, u32 len, 387asmlinkage long sys32_init_module(void __user *umod, u32 len,
diff --git a/arch/sparc/kernel/sys_sparc_32.c b/arch/sparc/kernel/sys_sparc_32.c
index 0c9b31b22e07..2da0bdcae52f 100644
--- a/arch/sparc/kernel/sys_sparc_32.c
+++ b/arch/sparc/kernel/sys_sparc_32.c
@@ -34,11 +34,9 @@ asmlinkage unsigned long sys_getpagesize(void)
34 return PAGE_SIZE; /* Possibly older binaries want 8192 on sun4's? */ 34 return PAGE_SIZE; /* Possibly older binaries want 8192 on sun4's? */
35} 35}
36 36
37#define COLOUR_ALIGN(addr) (((addr)+SHMLBA-1)&~(SHMLBA-1))
38
39unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags) 37unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags)
40{ 38{
41 struct vm_area_struct * vmm; 39 struct vm_unmapped_area_info info;
42 40
43 if (flags & MAP_FIXED) { 41 if (flags & MAP_FIXED) {
44 /* We do not accept a shared mapping if it would violate 42 /* We do not accept a shared mapping if it would violate
@@ -56,21 +54,14 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi
56 if (!addr) 54 if (!addr)
57 addr = TASK_UNMAPPED_BASE; 55 addr = TASK_UNMAPPED_BASE;
58 56
59 if (flags & MAP_SHARED) 57 info.flags = 0;
60 addr = COLOUR_ALIGN(addr); 58 info.length = len;
61 else 59 info.low_limit = addr;
62 addr = PAGE_ALIGN(addr); 60 info.high_limit = TASK_SIZE;
63 61 info.align_mask = (flags & MAP_SHARED) ?
64 for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) { 62 (PAGE_MASK & (SHMLBA - 1)) : 0;
65 /* At this point: (!vmm || addr < vmm->vm_end). */ 63 info.align_offset = pgoff << PAGE_SHIFT;
66 if (TASK_SIZE - PAGE_SIZE - len < addr) 64 return vm_unmapped_area(&info);
67 return -ENOMEM;
68 if (!vmm || addr + len <= vmm->vm_start)
69 return addr;
70 addr = vmm->vm_end;
71 if (flags & MAP_SHARED)
72 addr = COLOUR_ALIGN(addr);
73 }
74} 65}
75 66
76/* 67/*
@@ -258,27 +249,3 @@ out:
258 up_read(&uts_sem); 249 up_read(&uts_sem);
259 return err; 250 return err;
260} 251}
261
262/*
263 * Do a system call from kernel instead of calling sys_execve so we
264 * end up with proper pt_regs.
265 */
266int kernel_execve(const char *filename,
267 const char *const argv[],
268 const char *const envp[])
269{
270 long __res;
271 register long __g1 __asm__ ("g1") = __NR_execve;
272 register long __o0 __asm__ ("o0") = (long)(filename);
273 register long __o1 __asm__ ("o1") = (long)(argv);
274 register long __o2 __asm__ ("o2") = (long)(envp);
275 asm volatile ("t 0x10\n\t"
276 "bcc 1f\n\t"
277 "mov %%o0, %0\n\t"
278 "sub %%g0, %%o0, %0\n\t"
279 "1:\n\t"
280 : "=r" (__res), "=&r" (__o0)
281 : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__g1)
282 : "cc");
283 return __res;
284}
diff --git a/arch/sparc/kernel/sys_sparc_64.c b/arch/sparc/kernel/sys_sparc_64.c
index 878ef3d5fec5..708bc29d36a8 100644
--- a/arch/sparc/kernel/sys_sparc_64.c
+++ b/arch/sparc/kernel/sys_sparc_64.c
@@ -75,7 +75,7 @@ static inline int invalid_64bit_range(unsigned long addr, unsigned long len)
75 * the spitfire/niagara VA-hole. 75 * the spitfire/niagara VA-hole.
76 */ 76 */
77 77
78static inline unsigned long COLOUR_ALIGN(unsigned long addr, 78static inline unsigned long COLOR_ALIGN(unsigned long addr,
79 unsigned long pgoff) 79 unsigned long pgoff)
80{ 80{
81 unsigned long base = (addr+SHMLBA-1)&~(SHMLBA-1); 81 unsigned long base = (addr+SHMLBA-1)&~(SHMLBA-1);
@@ -84,24 +84,13 @@ static inline unsigned long COLOUR_ALIGN(unsigned long addr,
84 return base + off; 84 return base + off;
85} 85}
86 86
87static inline unsigned long COLOUR_ALIGN_DOWN(unsigned long addr,
88 unsigned long pgoff)
89{
90 unsigned long base = addr & ~(SHMLBA-1);
91 unsigned long off = (pgoff<<PAGE_SHIFT) & (SHMLBA-1);
92
93 if (base + off <= addr)
94 return base + off;
95 return base - off;
96}
97
98unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags) 87unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags)
99{ 88{
100 struct mm_struct *mm = current->mm; 89 struct mm_struct *mm = current->mm;
101 struct vm_area_struct * vma; 90 struct vm_area_struct * vma;
102 unsigned long task_size = TASK_SIZE; 91 unsigned long task_size = TASK_SIZE;
103 unsigned long start_addr;
104 int do_color_align; 92 int do_color_align;
93 struct vm_unmapped_area_info info;
105 94
106 if (flags & MAP_FIXED) { 95 if (flags & MAP_FIXED) {
107 /* We do not accept a shared mapping if it would violate 96 /* We do not accept a shared mapping if it would violate
@@ -124,7 +113,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi
124 113
125 if (addr) { 114 if (addr) {
126 if (do_color_align) 115 if (do_color_align)
127 addr = COLOUR_ALIGN(addr, pgoff); 116 addr = COLOR_ALIGN(addr, pgoff);
128 else 117 else
129 addr = PAGE_ALIGN(addr); 118 addr = PAGE_ALIGN(addr);
130 119
@@ -134,50 +123,22 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi
134 return addr; 123 return addr;
135 } 124 }
136 125
137 if (len > mm->cached_hole_size) { 126 info.flags = 0;
138 start_addr = addr = mm->free_area_cache; 127 info.length = len;
139 } else { 128 info.low_limit = TASK_UNMAPPED_BASE;
140 start_addr = addr = TASK_UNMAPPED_BASE; 129 info.high_limit = min(task_size, VA_EXCLUDE_START);
141 mm->cached_hole_size = 0; 130 info.align_mask = do_color_align ? (PAGE_MASK & (SHMLBA - 1)) : 0;
131 info.align_offset = pgoff << PAGE_SHIFT;
132 addr = vm_unmapped_area(&info);
133
134 if ((addr & ~PAGE_MASK) && task_size > VA_EXCLUDE_END) {
135 VM_BUG_ON(addr != -ENOMEM);
136 info.low_limit = VA_EXCLUDE_END;
137 info.high_limit = task_size;
138 addr = vm_unmapped_area(&info);
142 } 139 }
143 140
144 task_size -= len; 141 return addr;
145
146full_search:
147 if (do_color_align)
148 addr = COLOUR_ALIGN(addr, pgoff);
149 else
150 addr = PAGE_ALIGN(addr);
151
152 for (vma = find_vma(mm, addr); ; vma = vma->vm_next) {
153 /* At this point: (!vma || addr < vma->vm_end). */
154 if (addr < VA_EXCLUDE_START &&
155 (addr + len) >= VA_EXCLUDE_START) {
156 addr = VA_EXCLUDE_END;
157 vma = find_vma(mm, VA_EXCLUDE_END);
158 }
159 if (unlikely(task_size < addr)) {
160 if (start_addr != TASK_UNMAPPED_BASE) {
161 start_addr = addr = TASK_UNMAPPED_BASE;
162 mm->cached_hole_size = 0;
163 goto full_search;
164 }
165 return -ENOMEM;
166 }
167 if (likely(!vma || addr + len <= vma->vm_start)) {
168 /*
169 * Remember the place where we stopped the search:
170 */
171 mm->free_area_cache = addr + len;
172 return addr;
173 }
174 if (addr + mm->cached_hole_size < vma->vm_start)
175 mm->cached_hole_size = vma->vm_start - addr;
176
177 addr = vma->vm_end;
178 if (do_color_align)
179 addr = COLOUR_ALIGN(addr, pgoff);
180 }
181} 142}
182 143
183unsigned long 144unsigned long
@@ -190,6 +151,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
190 unsigned long task_size = STACK_TOP32; 151 unsigned long task_size = STACK_TOP32;
191 unsigned long addr = addr0; 152 unsigned long addr = addr0;
192 int do_color_align; 153 int do_color_align;
154 struct vm_unmapped_area_info info;
193 155
194 /* This should only ever run for 32-bit processes. */ 156 /* This should only ever run for 32-bit processes. */
195 BUG_ON(!test_thread_flag(TIF_32BIT)); 157 BUG_ON(!test_thread_flag(TIF_32BIT));
@@ -214,7 +176,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
214 /* requesting a specific address */ 176 /* requesting a specific address */
215 if (addr) { 177 if (addr) {
216 if (do_color_align) 178 if (do_color_align)
217 addr = COLOUR_ALIGN(addr, pgoff); 179 addr = COLOR_ALIGN(addr, pgoff);
218 else 180 else
219 addr = PAGE_ALIGN(addr); 181 addr = PAGE_ALIGN(addr);
220 182
@@ -224,73 +186,27 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
224 return addr; 186 return addr;
225 } 187 }
226 188
227 /* check if free_area_cache is useful for us */ 189 info.flags = VM_UNMAPPED_AREA_TOPDOWN;
228 if (len <= mm->cached_hole_size) { 190 info.length = len;
229 mm->cached_hole_size = 0; 191 info.low_limit = PAGE_SIZE;
230 mm->free_area_cache = mm->mmap_base; 192 info.high_limit = mm->mmap_base;
231 } 193 info.align_mask = do_color_align ? (PAGE_MASK & (SHMLBA - 1)) : 0;
232 194 info.align_offset = pgoff << PAGE_SHIFT;
233 /* either no address requested or can't fit in requested address hole */ 195 addr = vm_unmapped_area(&info);
234 addr = mm->free_area_cache;
235 if (do_color_align) {
236 unsigned long base = COLOUR_ALIGN_DOWN(addr-len, pgoff);
237
238 addr = base + len;
239 }
240
241 /* make sure it can fit in the remaining address space */
242 if (likely(addr > len)) {
243 vma = find_vma(mm, addr-len);
244 if (!vma || addr <= vma->vm_start) {
245 /* remember the address as a hint for next time */
246 return (mm->free_area_cache = addr-len);
247 }
248 }
249
250 if (unlikely(mm->mmap_base < len))
251 goto bottomup;
252
253 addr = mm->mmap_base-len;
254 if (do_color_align)
255 addr = COLOUR_ALIGN_DOWN(addr, pgoff);
256
257 do {
258 /*
259 * Lookup failure means no vma is above this address,
260 * else if new region fits below vma->vm_start,
261 * return with success:
262 */
263 vma = find_vma(mm, addr);
264 if (likely(!vma || addr+len <= vma->vm_start)) {
265 /* remember the address as a hint for next time */
266 return (mm->free_area_cache = addr);
267 }
268
269 /* remember the largest hole we saw so far */
270 if (addr + mm->cached_hole_size < vma->vm_start)
271 mm->cached_hole_size = vma->vm_start - addr;
272 196
273 /* try just below the current vma->vm_start */
274 addr = vma->vm_start-len;
275 if (do_color_align)
276 addr = COLOUR_ALIGN_DOWN(addr, pgoff);
277 } while (likely(len < vma->vm_start));
278
279bottomup:
280 /* 197 /*
281 * A failed mmap() very likely causes application failure, 198 * A failed mmap() very likely causes application failure,
282 * so fall back to the bottom-up function here. This scenario 199 * so fall back to the bottom-up function here. This scenario
283 * can happen with large stack limits and large mmap() 200 * can happen with large stack limits and large mmap()
284 * allocations. 201 * allocations.
285 */ 202 */
286 mm->cached_hole_size = ~0UL; 203 if (addr & ~PAGE_MASK) {
287 mm->free_area_cache = TASK_UNMAPPED_BASE; 204 VM_BUG_ON(addr != -ENOMEM);
288 addr = arch_get_unmapped_area(filp, addr0, len, pgoff, flags); 205 info.flags = 0;
289 /* 206 info.low_limit = TASK_UNMAPPED_BASE;
290 * Restore the topdown base: 207 info.high_limit = STACK_TOP32;
291 */ 208 addr = vm_unmapped_area(&info);
292 mm->free_area_cache = mm->mmap_base; 209 }
293 mm->cached_hole_size = ~0UL;
294 210
295 return addr; 211 return addr;
296} 212}
@@ -730,28 +646,6 @@ SYSCALL_DEFINE5(rt_sigaction, int, sig, const struct sigaction __user *, act,
730 return ret; 646 return ret;
731} 647}
732 648
733/*
734 * Do a system call from kernel instead of calling sys_execve so we
735 * end up with proper pt_regs.
736 */
737int kernel_execve(const char *filename,
738 const char *const argv[],
739 const char *const envp[])
740{
741 long __res;
742 register long __g1 __asm__ ("g1") = __NR_execve;
743 register long __o0 __asm__ ("o0") = (long)(filename);
744 register long __o1 __asm__ ("o1") = (long)(argv);
745 register long __o2 __asm__ ("o2") = (long)(envp);
746 asm volatile ("t 0x6d\n\t"
747 "sub %%g0, %%o0, %0\n\t"
748 "movcc %%xcc, %%o0, %0\n\t"
749 : "=r" (__res), "=&r" (__o0)
750 : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__g1)
751 : "cc");
752 return __res;
753}
754
755asmlinkage long sys_kern_features(void) 649asmlinkage long sys_kern_features(void)
756{ 650{
757 return KERN_FEATURE_MIXED_MODE_STACK; 651 return KERN_FEATURE_MIXED_MODE_STACK;
diff --git a/arch/sparc/kernel/syscalls.S b/arch/sparc/kernel/syscalls.S
index 7f5f65d0b3fd..e0fed7711a94 100644
--- a/arch/sparc/kernel/syscalls.S
+++ b/arch/sparc/kernel/syscalls.S
@@ -1,23 +1,19 @@
1 /* SunOS's execv() call only specifies the argv argument, the 1 /* SunOS's execv() call only specifies the argv argument, the
2 * environment settings are the same as the calling processes. 2 * environment settings are the same as the calling processes.
3 */ 3 */
4sys_execve: 4sys64_execve:
5 sethi %hi(sparc_execve), %g1 5 set sys_execve, %g1
6 ba,pt %xcc, execve_merge 6 jmpl %g1, %g0
7 or %g1, %lo(sparc_execve), %g1 7 flushw
8 8
9#ifdef CONFIG_COMPAT 9#ifdef CONFIG_COMPAT
10sunos_execv: 10sunos_execv:
11 stx %g0, [%sp + PTREGS_OFF + PT_V9_I2] 11 mov %g0, %o2
12sys32_execve: 12sys32_execve:
13 sethi %hi(sparc32_execve), %g1 13 set compat_sys_execve, %g1
14 or %g1, %lo(sparc32_execve), %g1
15#endif
16
17execve_merge:
18 flushw
19 jmpl %g1, %g0 14 jmpl %g1, %g0
20 add %sp, PTREGS_OFF, %o0 15 flushw
16#endif
21 17
22 .align 32 18 .align 32
23sys_sparc_pipe: 19sys_sparc_pipe:
@@ -112,16 +108,31 @@ sys_clone:
112ret_from_syscall: 108ret_from_syscall:
113 /* Clear current_thread_info()->new_child. */ 109 /* Clear current_thread_info()->new_child. */
114 stb %g0, [%g6 + TI_NEW_CHILD] 110 stb %g0, [%g6 + TI_NEW_CHILD]
115 ldx [%g6 + TI_FLAGS], %l0
116 call schedule_tail 111 call schedule_tail
117 mov %g7, %o0 112 mov %g7, %o0
113 ldx [%sp + PTREGS_OFF + PT_V9_I0], %o0
114 brnz,pt %o0, ret_sys_call
115 ldx [%g6 + TI_FLAGS], %l0
116 ldx [%sp + PTREGS_OFF + PT_V9_G1], %l1
117 call %l1
118 ldx [%sp + PTREGS_OFF + PT_V9_G2], %o0
118 ba,pt %xcc, ret_sys_call 119 ba,pt %xcc, ret_sys_call
119 ldx [%sp + PTREGS_OFF + PT_V9_I0], %o0 120 mov 0, %o0
121
122 .globl sparc_exit_group
123 .type sparc_exit_group,#function
124sparc_exit_group:
125 sethi %hi(sys_exit_group), %g7
126 ba,pt %xcc, 1f
127 or %g7, %lo(sys_exit_group), %g7
128 .size sparc_exit_group,.-sparc_exit_group
120 129
121 .globl sparc_exit 130 .globl sparc_exit
122 .type sparc_exit,#function 131 .type sparc_exit,#function
123sparc_exit: 132sparc_exit:
124 rdpr %pstate, %g2 133 sethi %hi(sys_exit), %g7
134 or %g7, %lo(sys_exit), %g7
1351: rdpr %pstate, %g2
125 wrpr %g2, PSTATE_IE, %pstate 136 wrpr %g2, PSTATE_IE, %pstate
126 rdpr %otherwin, %g1 137 rdpr %otherwin, %g1
127 rdpr %cansave, %g3 138 rdpr %cansave, %g3
@@ -129,7 +140,7 @@ sparc_exit:
129 wrpr %g3, 0x0, %cansave 140 wrpr %g3, 0x0, %cansave
130 wrpr %g0, 0x0, %otherwin 141 wrpr %g0, 0x0, %otherwin
131 wrpr %g2, 0x0, %pstate 142 wrpr %g2, 0x0, %pstate
132 ba,pt %xcc, sys_exit 143 jmpl %g7, %g0
133 stb %g0, [%g6 + TI_WSAVED] 144 stb %g0, [%g6 + TI_WSAVED]
134 .size sparc_exit,.-sparc_exit 145 .size sparc_exit,.-sparc_exit
135 146
@@ -222,7 +233,6 @@ ret_sys_call:
222 ldx [%sp + PTREGS_OFF + PT_V9_TNPC], %l1 ! pc = npc 233 ldx [%sp + PTREGS_OFF + PT_V9_TNPC], %l1 ! pc = npc
223 234
2242: 2352:
225 stb %g0, [%g6 + TI_SYS_NOERROR]
226 /* System call success, clear Carry condition code. */ 236 /* System call success, clear Carry condition code. */
227 andn %g3, %g2, %g3 237 andn %g3, %g2, %g3
2283: 2383:
diff --git a/arch/sparc/kernel/systbls_64.S b/arch/sparc/kernel/systbls_64.S
index 1c9af9fa38e9..cdbd9b817751 100644
--- a/arch/sparc/kernel/systbls_64.S
+++ b/arch/sparc/kernel/systbls_64.S
@@ -107,7 +107,7 @@ sys_call_table:
107/*40*/ .word sys_newlstat, sys_dup, sys_sparc_pipe, sys_times, sys_nis_syscall 107/*40*/ .word sys_newlstat, sys_dup, sys_sparc_pipe, sys_times, sys_nis_syscall
108 .word sys_umount, sys_setgid, sys_getgid, sys_signal, sys_geteuid 108 .word sys_umount, sys_setgid, sys_getgid, sys_signal, sys_geteuid
109/*50*/ .word sys_getegid, sys_acct, sys_memory_ordering, sys_nis_syscall, sys_ioctl 109/*50*/ .word sys_getegid, sys_acct, sys_memory_ordering, sys_nis_syscall, sys_ioctl
110 .word sys_reboot, sys_nis_syscall, sys_symlink, sys_readlink, sys_execve 110 .word sys_reboot, sys_nis_syscall, sys_symlink, sys_readlink, sys64_execve
111/*60*/ .word sys_umask, sys_chroot, sys_newfstat, sys_fstat64, sys_getpagesize 111/*60*/ .word sys_umask, sys_chroot, sys_newfstat, sys_fstat64, sys_getpagesize
112 .word sys_msync, sys_vfork, sys_pread64, sys_pwrite64, sys_nis_syscall 112 .word sys_msync, sys_vfork, sys_pread64, sys_pwrite64, sys_nis_syscall
113/*70*/ .word sys_nis_syscall, sys_mmap, sys_nis_syscall, sys_64_munmap, sys_mprotect 113/*70*/ .word sys_nis_syscall, sys_mmap, sys_nis_syscall, sys_64_munmap, sys_mprotect
@@ -133,7 +133,7 @@ sys_call_table:
133/*170*/ .word sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, sys_getdents 133/*170*/ .word sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, sys_getdents
134 .word sys_setsid, sys_fchdir, sys_fgetxattr, sys_listxattr, sys_llistxattr 134 .word sys_setsid, sys_fchdir, sys_fgetxattr, sys_listxattr, sys_llistxattr
135/*180*/ .word sys_flistxattr, sys_removexattr, sys_lremovexattr, sys_nis_syscall, sys_ni_syscall 135/*180*/ .word sys_flistxattr, sys_removexattr, sys_lremovexattr, sys_nis_syscall, sys_ni_syscall
136 .word sys_setpgid, sys_fremovexattr, sys_tkill, sys_exit_group, sys_newuname 136 .word sys_setpgid, sys_fremovexattr, sys_tkill, sparc_exit_group, sys_newuname
137/*190*/ .word sys_init_module, sys_sparc64_personality, sys_remap_file_pages, sys_epoll_create, sys_epoll_ctl 137/*190*/ .word sys_init_module, sys_sparc64_personality, sys_remap_file_pages, sys_epoll_create, sys_epoll_ctl
138 .word sys_epoll_wait, sys_ioprio_set, sys_getppid, sys_nis_syscall, sys_sgetmask 138 .word sys_epoll_wait, sys_ioprio_set, sys_getppid, sys_nis_syscall, sys_sgetmask
139/*200*/ .word sys_ssetmask, sys_nis_syscall, sys_newlstat, sys_uselib, sys_nis_syscall 139/*200*/ .word sys_ssetmask, sys_nis_syscall, sys_newlstat, sys_uselib, sys_nis_syscall
diff --git a/arch/sparc/kernel/traps_64.c b/arch/sparc/kernel/traps_64.c
index b66a77968f35..e7ecf1507d90 100644
--- a/arch/sparc/kernel/traps_64.c
+++ b/arch/sparc/kernel/traps_64.c
@@ -2688,8 +2688,8 @@ void __init trap_init(void)
2688 TI_PRE_COUNT != offsetof(struct thread_info, 2688 TI_PRE_COUNT != offsetof(struct thread_info,
2689 preempt_count) || 2689 preempt_count) ||
2690 TI_NEW_CHILD != offsetof(struct thread_info, new_child) || 2690 TI_NEW_CHILD != offsetof(struct thread_info, new_child) ||
2691 TI_SYS_NOERROR != offsetof(struct thread_info, 2691 TI_CURRENT_DS != offsetof(struct thread_info,
2692 syscall_noerror) || 2692 current_ds) ||
2693 TI_RESTART_BLOCK != offsetof(struct thread_info, 2693 TI_RESTART_BLOCK != offsetof(struct thread_info,
2694 restart_block) || 2694 restart_block) ||
2695 TI_KUNA_REGS != offsetof(struct thread_info, 2695 TI_KUNA_REGS != offsetof(struct thread_info,
diff --git a/arch/sparc/mm/hugetlbpage.c b/arch/sparc/mm/hugetlbpage.c
index f76f83d5ac63..d2b59441ebdd 100644
--- a/arch/sparc/mm/hugetlbpage.c
+++ b/arch/sparc/mm/hugetlbpage.c
@@ -30,55 +30,28 @@ static unsigned long hugetlb_get_unmapped_area_bottomup(struct file *filp,
30 unsigned long pgoff, 30 unsigned long pgoff,
31 unsigned long flags) 31 unsigned long flags)
32{ 32{
33 struct mm_struct *mm = current->mm;
34 struct vm_area_struct * vma;
35 unsigned long task_size = TASK_SIZE; 33 unsigned long task_size = TASK_SIZE;
36 unsigned long start_addr; 34 struct vm_unmapped_area_info info;
37 35
38 if (test_thread_flag(TIF_32BIT)) 36 if (test_thread_flag(TIF_32BIT))
39 task_size = STACK_TOP32; 37 task_size = STACK_TOP32;
40 if (unlikely(len >= VA_EXCLUDE_START))
41 return -ENOMEM;
42 38
43 if (len > mm->cached_hole_size) { 39 info.flags = 0;
44 start_addr = addr = mm->free_area_cache; 40 info.length = len;
45 } else { 41 info.low_limit = TASK_UNMAPPED_BASE;
46 start_addr = addr = TASK_UNMAPPED_BASE; 42 info.high_limit = min(task_size, VA_EXCLUDE_START);
47 mm->cached_hole_size = 0; 43 info.align_mask = PAGE_MASK & ~HPAGE_MASK;
44 info.align_offset = 0;
45 addr = vm_unmapped_area(&info);
46
47 if ((addr & ~PAGE_MASK) && task_size > VA_EXCLUDE_END) {
48 VM_BUG_ON(addr != -ENOMEM);
49 info.low_limit = VA_EXCLUDE_END;
50 info.high_limit = task_size;
51 addr = vm_unmapped_area(&info);
48 } 52 }
49 53
50 task_size -= len; 54 return addr;
51
52full_search:
53 addr = ALIGN(addr, HPAGE_SIZE);
54
55 for (vma = find_vma(mm, addr); ; vma = vma->vm_next) {
56 /* At this point: (!vma || addr < vma->vm_end). */
57 if (addr < VA_EXCLUDE_START &&
58 (addr + len) >= VA_EXCLUDE_START) {
59 addr = VA_EXCLUDE_END;
60 vma = find_vma(mm, VA_EXCLUDE_END);
61 }
62 if (unlikely(task_size < addr)) {
63 if (start_addr != TASK_UNMAPPED_BASE) {
64 start_addr = addr = TASK_UNMAPPED_BASE;
65 mm->cached_hole_size = 0;
66 goto full_search;
67 }
68 return -ENOMEM;
69 }
70 if (likely(!vma || addr + len <= vma->vm_start)) {
71 /*
72 * Remember the place where we stopped the search:
73 */
74 mm->free_area_cache = addr + len;
75 return addr;
76 }
77 if (addr + mm->cached_hole_size < vma->vm_start)
78 mm->cached_hole_size = vma->vm_start - addr;
79
80 addr = ALIGN(vma->vm_end, HPAGE_SIZE);
81 }
82} 55}
83 56
84static unsigned long 57static unsigned long
@@ -87,71 +60,34 @@ hugetlb_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
87 const unsigned long pgoff, 60 const unsigned long pgoff,
88 const unsigned long flags) 61 const unsigned long flags)
89{ 62{
90 struct vm_area_struct *vma;
91 struct mm_struct *mm = current->mm; 63 struct mm_struct *mm = current->mm;
92 unsigned long addr = addr0; 64 unsigned long addr = addr0;
65 struct vm_unmapped_area_info info;
93 66
94 /* This should only ever run for 32-bit processes. */ 67 /* This should only ever run for 32-bit processes. */
95 BUG_ON(!test_thread_flag(TIF_32BIT)); 68 BUG_ON(!test_thread_flag(TIF_32BIT));
96 69
97 /* check if free_area_cache is useful for us */ 70 info.flags = VM_UNMAPPED_AREA_TOPDOWN;
98 if (len <= mm->cached_hole_size) { 71 info.length = len;
99 mm->cached_hole_size = 0; 72 info.low_limit = PAGE_SIZE;
100 mm->free_area_cache = mm->mmap_base; 73 info.high_limit = mm->mmap_base;
101 } 74 info.align_mask = PAGE_MASK & ~HPAGE_MASK;
102 75 info.align_offset = 0;
103 /* either no address requested or can't fit in requested address hole */ 76 addr = vm_unmapped_area(&info);
104 addr = mm->free_area_cache & HPAGE_MASK;
105
106 /* make sure it can fit in the remaining address space */
107 if (likely(addr > len)) {
108 vma = find_vma(mm, addr-len);
109 if (!vma || addr <= vma->vm_start) {
110 /* remember the address as a hint for next time */
111 return (mm->free_area_cache = addr-len);
112 }
113 }
114
115 if (unlikely(mm->mmap_base < len))
116 goto bottomup;
117
118 addr = (mm->mmap_base-len) & HPAGE_MASK;
119
120 do {
121 /*
122 * Lookup failure means no vma is above this address,
123 * else if new region fits below vma->vm_start,
124 * return with success:
125 */
126 vma = find_vma(mm, addr);
127 if (likely(!vma || addr+len <= vma->vm_start)) {
128 /* remember the address as a hint for next time */
129 return (mm->free_area_cache = addr);
130 }
131
132 /* remember the largest hole we saw so far */
133 if (addr + mm->cached_hole_size < vma->vm_start)
134 mm->cached_hole_size = vma->vm_start - addr;
135
136 /* try just below the current vma->vm_start */
137 addr = (vma->vm_start-len) & HPAGE_MASK;
138 } while (likely(len < vma->vm_start));
139 77
140bottomup:
141 /* 78 /*
142 * A failed mmap() very likely causes application failure, 79 * A failed mmap() very likely causes application failure,
143 * so fall back to the bottom-up function here. This scenario 80 * so fall back to the bottom-up function here. This scenario
144 * can happen with large stack limits and large mmap() 81 * can happen with large stack limits and large mmap()
145 * allocations. 82 * allocations.
146 */ 83 */
147 mm->cached_hole_size = ~0UL; 84 if (addr & ~PAGE_MASK) {
148 mm->free_area_cache = TASK_UNMAPPED_BASE; 85 VM_BUG_ON(addr != -ENOMEM);
149 addr = arch_get_unmapped_area(filp, addr0, len, pgoff, flags); 86 info.flags = 0;
150 /* 87 info.low_limit = TASK_UNMAPPED_BASE;
151 * Restore the topdown base: 88 info.high_limit = STACK_TOP32;
152 */ 89 addr = vm_unmapped_area(&info);
153 mm->free_area_cache = mm->mmap_base; 90 }
154 mm->cached_hole_size = ~0UL;
155 91
156 return addr; 92 return addr;
157} 93}
diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
index 9e28a118e6a4..85be1ca539b2 100644
--- a/arch/sparc/mm/init_64.c
+++ b/arch/sparc/mm/init_64.c
@@ -624,7 +624,7 @@ static void __init inherit_prom_mappings(void)
624void prom_world(int enter) 624void prom_world(int enter)
625{ 625{
626 if (!enter) 626 if (!enter)
627 set_fs((mm_segment_t) { get_thread_current_ds() }); 627 set_fs(get_fs());
628 628
629 __asm__ __volatile__("flushw"); 629 __asm__ __volatile__("flushw");
630} 630}
diff --git a/arch/sparc/net/bpf_jit_comp.c b/arch/sparc/net/bpf_jit_comp.c
index 28368701ef79..3109ca684a99 100644
--- a/arch/sparc/net/bpf_jit_comp.c
+++ b/arch/sparc/net/bpf_jit_comp.c
@@ -3,6 +3,7 @@
3#include <linux/netdevice.h> 3#include <linux/netdevice.h>
4#include <linux/filter.h> 4#include <linux/filter.h>
5#include <linux/cache.h> 5#include <linux/cache.h>
6#include <linux/if_vlan.h>
6 7
7#include <asm/cacheflush.h> 8#include <asm/cacheflush.h>
8#include <asm/ptrace.h> 9#include <asm/ptrace.h>
@@ -312,6 +313,12 @@ do { *prog++ = BR_OPC | WDISP22(OFF); \
312#define emit_addi(R1, IMM, R3) \ 313#define emit_addi(R1, IMM, R3) \
313 *prog++ = (ADD | IMMED | RS1(R1) | S13(IMM) | RD(R3)) 314 *prog++ = (ADD | IMMED | RS1(R1) | S13(IMM) | RD(R3))
314 315
316#define emit_and(R1, R2, R3) \
317 *prog++ = (AND | RS1(R1) | RS2(R2) | RD(R3))
318
319#define emit_andi(R1, IMM, R3) \
320 *prog++ = (AND | IMMED | RS1(R1) | S13(IMM) | RD(R3))
321
315#define emit_alloc_stack(SZ) \ 322#define emit_alloc_stack(SZ) \
316 *prog++ = (SUB | IMMED | RS1(SP) | S13(SZ) | RD(SP)) 323 *prog++ = (SUB | IMMED | RS1(SP) | S13(SZ) | RD(SP))
317 324
@@ -415,6 +422,8 @@ void bpf_jit_compile(struct sk_filter *fp)
415 case BPF_S_ANC_IFINDEX: 422 case BPF_S_ANC_IFINDEX:
416 case BPF_S_ANC_MARK: 423 case BPF_S_ANC_MARK:
417 case BPF_S_ANC_RXHASH: 424 case BPF_S_ANC_RXHASH:
425 case BPF_S_ANC_VLAN_TAG:
426 case BPF_S_ANC_VLAN_TAG_PRESENT:
418 case BPF_S_ANC_CPU: 427 case BPF_S_ANC_CPU:
419 case BPF_S_ANC_QUEUE: 428 case BPF_S_ANC_QUEUE:
420 case BPF_S_LD_W_ABS: 429 case BPF_S_LD_W_ABS:
@@ -600,6 +609,16 @@ void bpf_jit_compile(struct sk_filter *fp)
600 case BPF_S_ANC_RXHASH: 609 case BPF_S_ANC_RXHASH:
601 emit_skb_load32(rxhash, r_A); 610 emit_skb_load32(rxhash, r_A);
602 break; 611 break;
612 case BPF_S_ANC_VLAN_TAG:
613 case BPF_S_ANC_VLAN_TAG_PRESENT:
614 emit_skb_load16(vlan_tci, r_A);
615 if (filter[i].code == BPF_S_ANC_VLAN_TAG) {
616 emit_andi(r_A, VLAN_VID_MASK, r_A);
617 } else {
618 emit_loadimm(VLAN_TAG_PRESENT, r_TMP);
619 emit_and(r_A, r_TMP, r_A);
620 }
621 break;
603 622
604 case BPF_S_LD_IMM: 623 case BPF_S_LD_IMM:
605 emit_loadimm(K, r_A); 624 emit_loadimm(K, r_A);