diff options
Diffstat (limited to 'arch/blackfin/kernel/process.c')
-rw-r--r-- | arch/blackfin/kernel/process.c | 75 |
1 files changed, 17 insertions, 58 deletions
diff --git a/arch/blackfin/kernel/process.c b/arch/blackfin/kernel/process.c index bb1cc721fcf..da8df0e504a 100644 --- a/arch/blackfin/kernel/process.c +++ b/arch/blackfin/kernel/process.c | |||
@@ -102,40 +102,6 @@ void cpu_idle(void) | |||
102 | } | 102 | } |
103 | 103 | ||
104 | /* | 104 | /* |
105 | * This gets run with P1 containing the | ||
106 | * function to call, and R1 containing | ||
107 | * the "args". Note P0 is clobbered on the way here. | ||
108 | */ | ||
109 | void kernel_thread_helper(void); | ||
110 | __asm__(".section .text\n" | ||
111 | ".align 4\n" | ||
112 | "_kernel_thread_helper:\n\t" | ||
113 | "\tsp += -12;\n\t" | ||
114 | "\tr0 = r1;\n\t" "\tcall (p1);\n\t" "\tcall _do_exit;\n" ".previous"); | ||
115 | |||
116 | /* | ||
117 | * Create a kernel thread. | ||
118 | */ | ||
119 | pid_t kernel_thread(int (*fn) (void *), void *arg, unsigned long flags) | ||
120 | { | ||
121 | struct pt_regs regs; | ||
122 | |||
123 | memset(®s, 0, sizeof(regs)); | ||
124 | |||
125 | regs.r1 = (unsigned long)arg; | ||
126 | regs.p1 = (unsigned long)fn; | ||
127 | regs.pc = (unsigned long)kernel_thread_helper; | ||
128 | regs.orig_p0 = -1; | ||
129 | /* Set bit 2 to tell ret_from_fork we should be returning to kernel | ||
130 | mode. */ | ||
131 | regs.ipend = 0x8002; | ||
132 | __asm__ __volatile__("%0 = syscfg;":"=da"(regs.syscfg):); | ||
133 | return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, | ||
134 | NULL); | ||
135 | } | ||
136 | EXPORT_SYMBOL(kernel_thread); | ||
137 | |||
138 | /* | ||
139 | * Do necessary setup to start up a newly executed thread. | 105 | * Do necessary setup to start up a newly executed thread. |
140 | * | 106 | * |
141 | * pass the data segment into user programs if it exists, | 107 | * pass the data segment into user programs if it exists, |
@@ -193,38 +159,31 @@ copy_thread(unsigned long clone_flags, | |||
193 | struct task_struct *p, struct pt_regs *regs) | 159 | struct task_struct *p, struct pt_regs *regs) |
194 | { | 160 | { |
195 | struct pt_regs *childregs; | 161 | struct pt_regs *childregs; |
162 | unsigned long *v; | ||
196 | 163 | ||
197 | childregs = (struct pt_regs *) (task_stack_page(p) + THREAD_SIZE) - 1; | 164 | childregs = (struct pt_regs *) (task_stack_page(p) + THREAD_SIZE) - 1; |
198 | *childregs = *regs; | 165 | v = ((unsigned long *)childregs) - 2; |
199 | childregs->r0 = 0; | 166 | if (unlikely(!regs)) { |
167 | memset(childregs, 0, sizeof(struct pt_regs)); | ||
168 | v[0] = usp; | ||
169 | v[1] = topstk; | ||
170 | childregs->orig_p0 = -1; | ||
171 | childregs->ipend = 0x8000; | ||
172 | __asm__ __volatile__("%0 = syscfg;":"=da"(childregs->syscfg):); | ||
173 | p->thread.usp = 0; | ||
174 | } else { | ||
175 | *childregs = *regs; | ||
176 | childregs->r0 = 0; | ||
177 | p->thread.usp = usp; | ||
178 | v[0] = v[1] = 0; | ||
179 | } | ||
200 | 180 | ||
201 | p->thread.usp = usp; | 181 | p->thread.ksp = (unsigned long)v; |
202 | p->thread.ksp = (unsigned long)childregs; | ||
203 | p->thread.pc = (unsigned long)ret_from_fork; | 182 | p->thread.pc = (unsigned long)ret_from_fork; |
204 | 183 | ||
205 | return 0; | 184 | return 0; |
206 | } | 185 | } |
207 | 186 | ||
208 | /* | ||
209 | * sys_execve() executes a new program. | ||
210 | */ | ||
211 | asmlinkage int sys_execve(const char __user *name, | ||
212 | const char __user *const __user *argv, | ||
213 | const char __user *const __user *envp) | ||
214 | { | ||
215 | int error; | ||
216 | struct filename *filename; | ||
217 | struct pt_regs *regs = (struct pt_regs *)((&name) + 6); | ||
218 | |||
219 | filename = getname(name); | ||
220 | error = PTR_ERR(filename); | ||
221 | if (IS_ERR(filename)) | ||
222 | return error; | ||
223 | error = do_execve(filename->name, argv, envp, regs); | ||
224 | putname(filename); | ||
225 | return error; | ||
226 | } | ||
227 | |||
228 | unsigned long get_wchan(struct task_struct *p) | 187 | unsigned long get_wchan(struct task_struct *p) |
229 | { | 188 | { |
230 | unsigned long fp, pc; | 189 | unsigned long fp, pc; |