Blame view

arch/um/kernel/process.c 8.51 KB
995473aec   Jeff Dike   [PATCH] uml: file...
1
  /*
ba180fd43   Jeff Dike   uml: style fixes ...
2
   * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3
4
5
   * Copyright 2003 PathScale, Inc.
   * Licensed under the GPL
   */
c5d4bb171   Jeff Dike   uml: style fixes ...
6
7
8
  #include <linux/stddef.h>
  #include <linux/err.h>
  #include <linux/hardirq.h>
c5d4bb171   Jeff Dike   uml: style fixes ...
9
  #include <linux/mm.h>
6613c5e86   Alexey Dobriyan   uml: convert to s...
10
  #include <linux/module.h>
c5d4bb171   Jeff Dike   uml: style fixes ...
11
12
13
14
  #include <linux/personality.h>
  #include <linux/proc_fs.h>
  #include <linux/ptrace.h>
  #include <linux/random.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
15
  #include <linux/slab.h>
c5d4bb171   Jeff Dike   uml: style fixes ...
16
  #include <linux/sched.h>
6613c5e86   Alexey Dobriyan   uml: convert to s...
17
  #include <linux/seq_file.h>
c5d4bb171   Jeff Dike   uml: style fixes ...
18
19
  #include <linux/tick.h>
  #include <linux/threads.h>
d50349b0c   Al Viro   um: add TIF_NOTIF...
20
  #include <linux/tracehook.h>
c5d4bb171   Jeff Dike   uml: style fixes ...
21
22
  #include <asm/current.h>
  #include <asm/pgtable.h>
445c5786c   Al Viro   um: kill shared/t...
23
  #include <asm/mmu_context.h>
c5d4bb171   Jeff Dike   uml: style fixes ...
24
  #include <asm/uaccess.h>
37185b332   Al Viro   um: get rid of po...
25
26
27
28
  #include <as-layout.h>
  #include <kern_util.h>
  #include <os.h>
  #include <skas.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
29

ba180fd43   Jeff Dike   uml: style fixes ...
30
31
  /*
   * This is a per-cpu array.  A processor only modifies its entry and it only
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
32
33
34
35
   * cares about its entry, so it's OK if another processor is modifying its
   * entry.
   */
  struct cpu_task cpu_tasks[NR_CPUS] = { [0 ... NR_CPUS - 1] = { -1, NULL } };
2dc5802a2   Karol Swietlicki   uml: remove dupli...
36
  static inline int external_pid(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
37
  {
77bf44003   Jeff Dike   uml: remove code ...
38
  	/* FIXME: Need to look up userspace_pid by cpu */
ba180fd43   Jeff Dike   uml: style fixes ...
39
  	return userspace_pid[0];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
40
41
42
43
44
  }
  
  int pid_to_processor_id(int pid)
  {
  	int i;
c5d4bb171   Jeff Dike   uml: style fixes ...
45
  	for (i = 0; i < ncpus; i++) {
ba180fd43   Jeff Dike   uml: style fixes ...
46
  		if (cpu_tasks[i].pid == pid)
6e21aec3f   Jeff Dike   uml: tidy process.c
47
  			return i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
48
  	}
6e21aec3f   Jeff Dike   uml: tidy process.c
49
  	return -1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
50
51
52
53
54
55
56
57
58
59
  }
  
  void free_stack(unsigned long stack, int order)
  {
  	free_pages(stack, order);
  }
  
  unsigned long alloc_stack(int order, int atomic)
  {
  	unsigned long page;
53f9fc93f   Al Viro   [PATCH] gfp_t: re...
60
  	gfp_t flags = GFP_KERNEL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
61

46db4a42d   Paolo 'Blaisorblade' Giarrusso   [PATCH] uml: Fix ...
62
63
  	if (atomic)
  		flags = GFP_ATOMIC;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
64
  	page = __get_free_pages(flags, order);
5c8aaceab   Jeff Dike   uml: stop special...
65

6e21aec3f   Jeff Dike   uml: tidy process.c
66
  	return page;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
67
  }
6e21aec3f   Jeff Dike   uml: tidy process.c
68
  static inline void set_current(struct task_struct *task)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
69
  {
ca9bc0bb2   Al Viro   [PATCH] uml: task...
70
  	cpu_tasks[task_thread_info(task)->cpu] = ((struct cpu_task)
2dc5802a2   Karol Swietlicki   uml: remove dupli...
71
  		{ external_pid(), task });
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
72
  }
291248fd6   Karol Swietlicki   uml: remove unuse...
73
  extern void arch_switch_to(struct task_struct *to);
77bf44003   Jeff Dike   uml: remove code ...
74

76b278edd   Richard Weinberger   um: Use asm-gener...
75
  void *__switch_to(struct task_struct *from, struct task_struct *to)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
76
  {
995473aec   Jeff Dike   [PATCH] uml: file...
77
78
  	to->thread.prev_sched = from;
  	set_current(to);
f6e34c6af   Jeff Dike   [PATCH] uml: _swi...
79

a1850e9c7   Richard Weinberger   um: Get rid of th...
80
81
  	switch_threads(&from->thread.switch_buf, &to->thread.switch_buf);
  	arch_switch_to(current);
f6e34c6af   Jeff Dike   [PATCH] uml: _swi...
82

6e21aec3f   Jeff Dike   uml: tidy process.c
83
  	return current->thread.prev_sched;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
84
85
86
87
  }
  
  void interrupt_end(void)
  {
ba180fd43   Jeff Dike   uml: style fixes ...
88
  	if (need_resched())
6e21aec3f   Jeff Dike   uml: tidy process.c
89
  		schedule();
d50349b0c   Al Viro   um: add TIF_NOTIF...
90
  	if (test_thread_flag(TIF_SIGPENDING))
6e21aec3f   Jeff Dike   uml: tidy process.c
91
  		do_signal();
a42c6ded8   Al Viro   move key_repace_s...
92
  	if (test_and_clear_thread_flag(TIF_NOTIFY_RESUME))
d50349b0c   Al Viro   um: add TIF_NOTIF...
93
  		tracehook_notify_resume(&current->thread.regs);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
94
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
95
96
  void exit_thread(void)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
97
  }
995473aec   Jeff Dike   [PATCH] uml: file...
98

c2220b2a1   Al Viro   um: kill HOST_TAS...
99
  int get_current_pid(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
100
  {
c2220b2a1   Al Viro   um: kill HOST_TAS...
101
  	return task_pid_nr(current);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
102
  }
ba180fd43   Jeff Dike   uml: style fixes ...
103
104
  /*
   * This is called magically, by its address being stuffed in a jmp_buf
77bf44003   Jeff Dike   uml: remove code ...
105
106
107
108
109
110
   * and being longjmp-d to.
   */
  void new_thread_handler(void)
  {
  	int (*fn)(void *), n;
  	void *arg;
ba180fd43   Jeff Dike   uml: style fixes ...
111
  	if (current->thread.prev_sched != NULL)
77bf44003   Jeff Dike   uml: remove code ...
112
113
114
115
116
  		schedule_tail(current->thread.prev_sched);
  	current->thread.prev_sched = NULL;
  
  	fn = current->thread.request.u.thread.proc;
  	arg = current->thread.request.u.thread.arg;
ba180fd43   Jeff Dike   uml: style fixes ...
117
  	/*
22e2430d6   Al Viro   x86, um: convert ...
118
  	 * callback returns only if the kernel thread execs a process
77bf44003   Jeff Dike   uml: remove code ...
119
  	 */
22e2430d6   Al Viro   x86, um: convert ...
120
121
  	n = fn(arg);
  	userspace(&current->thread.regs.regs);
77bf44003   Jeff Dike   uml: remove code ...
122
123
124
125
126
127
  }
  
  /* Called magically, see new_thread_handler above */
  void fork_handler(void)
  {
  	force_flush_all();
77bf44003   Jeff Dike   uml: remove code ...
128
129
  
  	schedule_tail(current->thread.prev_sched);
ba180fd43   Jeff Dike   uml: style fixes ...
130
131
  	/*
  	 * XXX: if interrupt_end() calls schedule, this call to
77bf44003   Jeff Dike   uml: remove code ...
132
  	 * arch_switch_to isn't needed. We could want to apply this to
ba180fd43   Jeff Dike   uml: style fixes ...
133
134
  	 * improve performance. -bb
  	 */
291248fd6   Karol Swietlicki   uml: remove unuse...
135
  	arch_switch_to(current);
77bf44003   Jeff Dike   uml: remove code ...
136
137
  
  	current->thread.prev_sched = NULL;
77bf44003   Jeff Dike   uml: remove code ...
138
139
  	userspace(&current->thread.regs.regs);
  }
6f2c55b84   Alexey Dobriyan   Simplify copy_thr...
140
  int copy_thread(unsigned long clone_flags, unsigned long sp,
afa86fc42   Al Viro   flagday: don't pa...
141
  		unsigned long arg, struct task_struct * p)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
142
  {
77bf44003   Jeff Dike   uml: remove code ...
143
  	void (*handler)(void);
d2ce4e92f   Al Viro   um: kill thread->...
144
  	int kthread = current->flags & PF_KTHREAD;
77bf44003   Jeff Dike   uml: remove code ...
145
  	int ret = 0;
aa6758d48   Paolo 'Blaisorblade' Giarrusso   [PATCH] uml: impl...
146

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
147
  	p->thread = (struct thread_struct) INIT_THREAD;
aa6758d48   Paolo 'Blaisorblade' Giarrusso   [PATCH] uml: impl...
148

d2ce4e92f   Al Viro   um: kill thread->...
149
  	if (!kthread) {
2b067fc9d   Al Viro   um: don't bother ...
150
  	  	memcpy(&p->thread.regs.regs, current_pt_regs(),
77bf44003   Jeff Dike   uml: remove code ...
151
  		       sizeof(p->thread.regs.regs));
a3170d2ec   Al Viro   um: switch UPT_SE...
152
  		PT_REGS_SET_SYSCALL_RETURN(&p->thread.regs, 0);
ba180fd43   Jeff Dike   uml: style fixes ...
153
  		if (sp != 0)
18badddaa   Jeff Dike   uml: rename pt_re...
154
  			REGS_SP(p->thread.regs.regs.gp) = sp;
aa6758d48   Paolo 'Blaisorblade' Giarrusso   [PATCH] uml: impl...
155

77bf44003   Jeff Dike   uml: remove code ...
156
  		handler = fork_handler;
aa6758d48   Paolo 'Blaisorblade' Giarrusso   [PATCH] uml: impl...
157

77bf44003   Jeff Dike   uml: remove code ...
158
  		arch_copy_thread(&current->thread.arch, &p->thread.arch);
d2ce4e92f   Al Viro   um: kill thread->...
159
  	} else {
fbfe9c847   Ingo van Lil   um: Save FPU regi...
160
  		get_safe_registers(p->thread.regs.regs.gp, p->thread.regs.regs.fp);
1f02ab4a2   Al Viro   um: switch to gen...
161
162
  		p->thread.request.u.thread.proc = (int (*)(void *))sp;
  		p->thread.request.u.thread.arg = (void *)arg;
77bf44003   Jeff Dike   uml: remove code ...
163
164
165
166
  		handler = new_thread_handler;
  	}
  
  	new_thread(task_stack_page(p), &p->thread.switch_buf, handler);
d2ce4e92f   Al Viro   um: kill thread->...
167
  	if (!kthread) {
77bf44003   Jeff Dike   uml: remove code ...
168
169
170
171
172
173
174
175
  		clear_flushed_tls(p);
  
  		/*
  		 * Set a new TLS for the child thread?
  		 */
  		if (clone_flags & CLONE_SETTLS)
  			ret = arch_copy_tls(p);
  	}
aa6758d48   Paolo 'Blaisorblade' Giarrusso   [PATCH] uml: impl...
176

aa6758d48   Paolo 'Blaisorblade' Giarrusso   [PATCH] uml: impl...
177
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
178
179
180
181
182
183
184
  }
  
  void initial_thread_cb(void (*proc)(void *), void *arg)
  {
  	int save_kmalloc_ok = kmalloc_ok;
  
  	kmalloc_ok = 0;
6aa802ce6   Jeff Dike   uml: throw out CH...
185
  	initial_thread_cb_skas(proc, arg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
186
187
  	kmalloc_ok = save_kmalloc_ok;
  }
995473aec   Jeff Dike   [PATCH] uml: file...
188

8198c1696   Richard Weinberger   um: Use generic i...
189
  void arch_cpu_idle(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
190
  {
b160fb630   Jeff Dike   uml: eliminate in...
191
  	unsigned long long nsecs;
a5a678c80   Jeff Dike   uml: current.h cl...
192
  	cpu_tasks[current_thread_info()->cpu].pid = os_getpid();
8198c1696   Richard Weinberger   um: Use generic i...
193
194
195
  	nsecs = disable_timer();
  	idle_sleep(nsecs);
  	local_irq_enable();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
196
  }
b63162939   Paolo 'Blaisorblade' Giarrusso   [PATCH] uml: avoi...
197
198
199
  int __cant_sleep(void) {
  	return in_atomic() || irqs_disabled() || in_interrupt();
  	/* Is in_interrupt() really needed? */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
200
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
201
202
203
204
205
  int user_context(unsigned long sp)
  {
  	unsigned long stack;
  
  	stack = sp & (PAGE_MASK << CONFIG_KERNEL_STACK_ORDER);
a5a678c80   Jeff Dike   uml: current.h cl...
206
  	return stack != (unsigned long) current_thread_info();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
207
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
208
209
210
211
212
213
214
215
216
217
  extern exitcall_t __uml_exitcall_begin, __uml_exitcall_end;
  
  void do_uml_exitcalls(void)
  {
  	exitcall_t *call;
  
  	call = &__uml_exitcall_end;
  	while (--call >= &__uml_exitcall_begin)
  		(*call)();
  }
c0a9290ec   WANG Cong   uml: const and ot...
218
  char *uml_strdup(const char *string)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
219
  {
dfe52244e   Robert Love   [PATCH] kstrdup: ...
220
  	return kstrdup(string, GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
221
  }
73395a000   Al Viro   um: distribute ex...
222
  EXPORT_SYMBOL(uml_strdup);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
223

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
224
225
  int copy_to_user_proc(void __user *to, void *from, int size)
  {
6e21aec3f   Jeff Dike   uml: tidy process.c
226
  	return copy_to_user(to, from, size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
227
228
229
230
  }
  
  int copy_from_user_proc(void *to, void __user *from, int size)
  {
6e21aec3f   Jeff Dike   uml: tidy process.c
231
  	return copy_from_user(to, from, size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
232
233
234
235
  }
  
  int clear_user_proc(void __user *buf, int size)
  {
6e21aec3f   Jeff Dike   uml: tidy process.c
236
  	return clear_user(buf, size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
237
238
239
240
  }
  
  int strlen_user_proc(char __user *str)
  {
6e21aec3f   Jeff Dike   uml: tidy process.c
241
  	return strlen_user(str);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
242
243
244
245
246
  }
  
  int smp_sigio_handler(void)
  {
  #ifdef CONFIG_SMP
a5a678c80   Jeff Dike   uml: current.h cl...
247
  	int cpu = current_thread_info()->cpu;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
248
  	IPI_handler(cpu);
ba180fd43   Jeff Dike   uml: style fixes ...
249
  	if (cpu != 0)
6e21aec3f   Jeff Dike   uml: tidy process.c
250
  		return 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
251
  #endif
6e21aec3f   Jeff Dike   uml: tidy process.c
252
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
253
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
254
255
  int cpu(void)
  {
a5a678c80   Jeff Dike   uml: current.h cl...
256
  	return current_thread_info()->cpu;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
  }
  
  static atomic_t using_sysemu = ATOMIC_INIT(0);
  int sysemu_supported;
  
  void set_using_sysemu(int value)
  {
  	if (value > sysemu_supported)
  		return;
  	atomic_set(&using_sysemu, value);
  }
  
  int get_using_sysemu(void)
  {
  	return atomic_read(&using_sysemu);
  }
6613c5e86   Alexey Dobriyan   uml: convert to s...
273
  static int sysemu_proc_show(struct seq_file *m, void *v)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
274
  {
6613c5e86   Alexey Dobriyan   uml: convert to s...
275
276
277
278
  	seq_printf(m, "%d
  ", get_using_sysemu());
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
279

6613c5e86   Alexey Dobriyan   uml: convert to s...
280
281
282
  static int sysemu_proc_open(struct inode *inode, struct file *file)
  {
  	return single_open(file, sysemu_proc_show, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
283
  }
6613c5e86   Alexey Dobriyan   uml: convert to s...
284
285
  static ssize_t sysemu_proc_write(struct file *file, const char __user *buf,
  				 size_t count, loff_t *pos)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
286
287
288
289
290
291
292
293
  {
  	char tmp[2];
  
  	if (copy_from_user(tmp, buf, 1))
  		return -EFAULT;
  
  	if (tmp[0] >= '0' && tmp[0] <= '2')
  		set_using_sysemu(tmp[0] - '0');
ba180fd43   Jeff Dike   uml: style fixes ...
294
295
  	/* We use the first char, but pretend to write everything */
  	return count;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
296
  }
6613c5e86   Alexey Dobriyan   uml: convert to s...
297
298
299
300
301
302
303
304
  static const struct file_operations sysemu_proc_fops = {
  	.owner		= THIS_MODULE,
  	.open		= sysemu_proc_open,
  	.read		= seq_read,
  	.llseek		= seq_lseek,
  	.release	= single_release,
  	.write		= sysemu_proc_write,
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
305
306
307
308
309
  int __init make_proc_sysemu(void)
  {
  	struct proc_dir_entry *ent;
  	if (!sysemu_supported)
  		return 0;
6613c5e86   Alexey Dobriyan   uml: convert to s...
310
  	ent = proc_create("sysemu", 0600, NULL, &sysemu_proc_fops);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
311
312
313
  
  	if (ent == NULL)
  	{
30f417c65   Christophe Lucas   [PATCH] uml: Clea...
314
315
  		printk(KERN_WARNING "Failed to register /proc/sysemu
  ");
6e21aec3f   Jeff Dike   uml: tidy process.c
316
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
317
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
318
319
320
321
322
323
324
325
  	return 0;
  }
  
  late_initcall(make_proc_sysemu);
  
  int singlestepping(void * t)
  {
  	struct task_struct *task = t ? t : current;
c5d4bb171   Jeff Dike   uml: style fixes ...
326
  	if (!(task->ptrace & PT_DTRACE))
ba180fd43   Jeff Dike   uml: style fixes ...
327
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
328
329
  
  	if (task->thread.singlestep_syscall)
ba180fd43   Jeff Dike   uml: style fixes ...
330
  		return 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
331
332
333
  
  	return 2;
  }
b8bd0220c   Bodo Stroesser   [PATCH] uml: S390...
334
335
336
  /*
   * Only x86 and x86_64 have an arch_align_stack().
   * All other arches have "#define arch_align_stack(x) (x)"
cf7bc58f6   David Howells   asm/system.h: um:...
337
   * in their asm/exec.h
b8bd0220c   Bodo Stroesser   [PATCH] uml: S390...
338
339
340
341
   * As this is included in UML from asm-um/system-generic.h,
   * we can use it to behave as the subarch does.
   */
  #ifndef arch_align_stack
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
342
343
  unsigned long arch_align_stack(unsigned long sp)
  {
8f80e9466   Jeff Dike   [PATCH] uml: Fix ...
344
  	if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
345
346
347
  		sp -= get_random_int() % 8192;
  	return sp & ~0xf;
  }
b8bd0220c   Bodo Stroesser   [PATCH] uml: S390...
348
  #endif
c11274655   Jeff Dike   uml: implement ge...
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
  
  unsigned long get_wchan(struct task_struct *p)
  {
  	unsigned long stack_page, sp, ip;
  	bool seen_sched = 0;
  
  	if ((p == NULL) || (p == current) || (p->state == TASK_RUNNING))
  		return 0;
  
  	stack_page = (unsigned long) task_stack_page(p);
  	/* Bail if the process has no kernel stack for some reason */
  	if (stack_page == 0)
  		return 0;
  
  	sp = p->thread.switch_buf->JB_SP;
  	/*
  	 * Bail if the stack pointer is below the bottom of the kernel
  	 * stack for some reason
  	 */
  	if (sp < stack_page)
  		return 0;
  
  	while (sp < stack_page + THREAD_SIZE) {
  		ip = *((unsigned long *) sp);
  		if (in_sched_functions(ip))
  			/* Ignore everything until we're above the scheduler */
  			seen_sched = 1;
  		else if (kernel_text_address(ip) && seen_sched)
  			return ip;
  
  		sp += sizeof(unsigned long);
  	}
  
  	return 0;
  }
8192ab42b   Jeff Dike   uml: header untan...
384
385
386
387
388
389
390
  
  int elf_core_copy_fpregs(struct task_struct *t, elf_fpregset_t *fpu)
  {
  	int cpu = current_thread_info()->cpu;
  
  	return save_fp_registers(userspace_pid[cpu], (unsigned long *) fpu);
  }