vserver 1.9.5.x5
[linux-2.6.git] / arch / x86_64 / kernel / process.c
1 /*
2  *  linux/arch/x86-64/kernel/process.c
3  *
4  *  Copyright (C) 1995  Linus Torvalds
5  *
6  *  Pentium III FXSR, SSE support
7  *      Gareth Hughes <gareth@valinux.com>, May 2000
8  * 
9  *  X86-64 port
10  *      Andi Kleen.
11  * 
12  *  $Id: process.c,v 1.38 2002/01/15 10:08:03 ak Exp $
13  */
14
15 /*
16  * This file handles the architecture-dependent parts of process handling..
17  */
18
19 #include <stdarg.h>
20
21 #include <linux/errno.h>
22 #include <linux/sched.h>
23 #include <linux/kernel.h>
24 #include <linux/mm.h>
25 #include <linux/elfcore.h>
26 #include <linux/smp.h>
27 #include <linux/slab.h>
28 #include <linux/user.h>
29 #include <linux/module.h>
30 #include <linux/a.out.h>
31 #include <linux/interrupt.h>
32 #include <linux/delay.h>
33 #include <linux/irq.h>
34 #include <linux/ptrace.h>
35 #include <linux/utsname.h>
36
37 #include <asm/uaccess.h>
38 #include <asm/pgtable.h>
39 #include <asm/system.h>
40 #include <asm/io.h>
41 #include <asm/processor.h>
42 #include <asm/i387.h>
43 #include <asm/mmu_context.h>
44 #include <asm/pda.h>
45 #include <asm/prctl.h>
46 #include <asm/kdebug.h>
47 #include <asm/desc.h>
48 #include <asm/proto.h>
49 #include <asm/ia32.h>
50
51 asmlinkage extern void ret_from_fork(void);
52
53 unsigned long kernel_thread_flags = CLONE_VM | CLONE_UNTRACED;
54
55 atomic_t hlt_counter = ATOMIC_INIT(0);
56
57 unsigned long boot_option_idle_override = 0;
58 EXPORT_SYMBOL(boot_option_idle_override);
59
60 /*
61  * Powermanagement idle function, if any..
62  */
63 void (*pm_idle)(void);
64 static cpumask_t cpu_idle_map;
65
66 void disable_hlt(void)
67 {
68         atomic_inc(&hlt_counter);
69 }
70
71 EXPORT_SYMBOL(disable_hlt);
72
73 void enable_hlt(void)
74 {
75         atomic_dec(&hlt_counter);
76 }
77
78 EXPORT_SYMBOL(enable_hlt);
79
80 /*
81  * We use this if we don't have any better
82  * idle routine..
83  */
84 void default_idle(void)
85 {
86         if (!atomic_read(&hlt_counter)) {
87                 local_irq_disable();
88                 if (!need_resched())
89                         safe_halt();
90                 else
91                         local_irq_enable();
92         }
93 }
94
95 /*
96  * On SMP it's slightly faster (but much more power-consuming!)
97  * to poll the ->need_resched flag instead of waiting for the
98  * cross-CPU IPI to arrive. Use this option with caution.
99  */
100 static void poll_idle (void)
101 {
102         int oldval;
103
104         local_irq_enable();
105
106         /*
107          * Deal with another CPU just having chosen a thread to
108          * run here:
109          */
110         oldval = test_and_clear_thread_flag(TIF_NEED_RESCHED);
111
112         if (!oldval) {
113                 set_thread_flag(TIF_POLLING_NRFLAG); 
114                 asm volatile(
115                         "2:"
116                         "testl %0,%1;"
117                         "rep; nop;"
118                         "je 2b;"
119                         : :
120                         "i" (_TIF_NEED_RESCHED), 
121                         "m" (current_thread_info()->flags));
122         } else {
123                 set_need_resched();
124         }
125 }
126
127
128 void cpu_idle_wait(void)
129 {
130         int cpu;
131         cpumask_t map;
132
133         for_each_online_cpu(cpu)
134                 cpu_set(cpu, cpu_idle_map);
135
136         wmb();
137         do {
138                 ssleep(1);
139                 cpus_and(map, cpu_idle_map, cpu_online_map);
140         } while (!cpus_empty(map));
141 }
142 EXPORT_SYMBOL_GPL(cpu_idle_wait);
143
144 /*
145  * The idle thread. There's no useful work to be
146  * done, so just try to conserve power and have a
147  * low exit latency (ie sit in a loop waiting for
148  * somebody to say that they'd like to reschedule)
149  */
150 void cpu_idle (void)
151 {
152         int cpu = smp_processor_id();
153
154         /* endless idle loop with no priority at all */
155         while (1) {
156                 while (!need_resched()) {
157                         void (*idle)(void);
158
159                         if (cpu_isset(cpu, cpu_idle_map))
160                                 cpu_clear(cpu, cpu_idle_map);
161                         rmb();
162                         idle = pm_idle;
163                         if (!idle)
164                                 idle = default_idle;
165                         idle();
166                 }
167                 schedule();
168         }
169 }
170
171 /*
172  * This uses new MONITOR/MWAIT instructions on P4 processors with PNI,
173  * which can obviate IPI to trigger checking of need_resched.
174  * We execute MONITOR against need_resched and enter optimized wait state
175  * through MWAIT. Whenever someone changes need_resched, we would be woken
176  * up from MWAIT (without an IPI).
177  */
178 static void mwait_idle(void)
179 {
180         local_irq_enable();
181
182         if (!need_resched()) {
183                 set_thread_flag(TIF_POLLING_NRFLAG);
184                 do {
185                         __monitor((void *)&current_thread_info()->flags, 0, 0);
186                         if (need_resched())
187                                 break;
188                         __mwait(0, 0);
189                 } while (!need_resched());
190                 clear_thread_flag(TIF_POLLING_NRFLAG);
191         }
192 }
193
194 void __init select_idle_routine(const struct cpuinfo_x86 *c)
195 {
196         static int printed;
197         if (cpu_has(c, X86_FEATURE_MWAIT)) {
198                 /*
199                  * Skip, if setup has overridden idle.
200                  * One CPU supports mwait => All CPUs supports mwait
201                  */
202                 if (!pm_idle) {
203                         if (!printed) {
204                                 printk("using mwait in idle threads.\n");
205                                 printed = 1;
206                         }
207                         pm_idle = mwait_idle;
208                 }
209         }
210 }
211
212 static int __init idle_setup (char *str)
213 {
214         if (!strncmp(str, "poll", 4)) {
215                 printk("using polling idle threads.\n");
216                 pm_idle = poll_idle;
217         }
218
219         boot_option_idle_override = 1;
220         return 1;
221 }
222
223 __setup("idle=", idle_setup);
224
225 /* Prints also some state that isn't saved in the pt_regs */ 
226 void __show_regs(struct pt_regs * regs)
227 {
228         unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L, fs, gs, shadowgs;
229         unsigned int fsindex,gsindex;
230         unsigned int ds,cs,es; 
231
232         printk("\n");
233         print_modules();
234         printk("Pid: %d, comm: %.20s %s %s\n", 
235                current->pid, current->comm, print_tainted(), system_utsname.release);
236         printk("RIP: %04lx:[<%016lx>] ", regs->cs & 0xffff, regs->rip);
237         printk_address(regs->rip); 
238         printk("\nRSP: %04lx:%016lx  EFLAGS: %08lx\n", regs->ss, regs->rsp, regs->eflags);
239         printk("RAX: %016lx RBX: %016lx RCX: %016lx\n",
240                regs->rax, regs->rbx, regs->rcx);
241         printk("RDX: %016lx RSI: %016lx RDI: %016lx\n",
242                regs->rdx, regs->rsi, regs->rdi); 
243         printk("RBP: %016lx R08: %016lx R09: %016lx\n",
244                regs->rbp, regs->r8, regs->r9); 
245         printk("R10: %016lx R11: %016lx R12: %016lx\n",
246                regs->r10, regs->r11, regs->r12); 
247         printk("R13: %016lx R14: %016lx R15: %016lx\n",
248                regs->r13, regs->r14, regs->r15); 
249
250         asm("movl %%ds,%0" : "=r" (ds)); 
251         asm("movl %%cs,%0" : "=r" (cs)); 
252         asm("movl %%es,%0" : "=r" (es)); 
253         asm("movl %%fs,%0" : "=r" (fsindex));
254         asm("movl %%gs,%0" : "=r" (gsindex));
255
256         rdmsrl(MSR_FS_BASE, fs);
257         rdmsrl(MSR_GS_BASE, gs); 
258         rdmsrl(MSR_KERNEL_GS_BASE, shadowgs); 
259
260         asm("movq %%cr0, %0": "=r" (cr0));
261         asm("movq %%cr2, %0": "=r" (cr2));
262         asm("movq %%cr3, %0": "=r" (cr3));
263         asm("movq %%cr4, %0": "=r" (cr4));
264
265         printk("FS:  %016lx(%04x) GS:%016lx(%04x) knlGS:%016lx\n", 
266                fs,fsindex,gs,gsindex,shadowgs); 
267         printk("CS:  %04x DS: %04x ES: %04x CR0: %016lx\n", cs, ds, es, cr0); 
268         printk("CR2: %016lx CR3: %016lx CR4: %016lx\n", cr2, cr3, cr4);
269 }
270
271 void show_regs(struct pt_regs *regs)
272 {
273         __show_regs(regs);
274         show_trace(&regs->rsp);
275 }
276
277 /*
278  * Free current thread data structures etc..
279  */
280 void exit_thread(void)
281 {
282         struct task_struct *me = current;
283         struct thread_struct *t = &me->thread;
284         if (me->thread.io_bitmap_ptr) { 
285                 struct tss_struct *tss = &per_cpu(init_tss, get_cpu());
286
287                 kfree(t->io_bitmap_ptr);
288                 t->io_bitmap_ptr = NULL;
289                 /*
290                  * Careful, clear this in the TSS too:
291                  */
292                 memset(tss->io_bitmap, 0xff, t->io_bitmap_max);
293                 t->io_bitmap_max = 0;
294                 put_cpu();
295         }
296 }
297
298 void flush_thread(void)
299 {
300         struct task_struct *tsk = current;
301         struct thread_info *t = current_thread_info();
302
303         if (t->flags & _TIF_ABI_PENDING)
304                 t->flags ^= (_TIF_ABI_PENDING | _TIF_IA32);
305
306         tsk->thread.debugreg0 = 0;
307         tsk->thread.debugreg1 = 0;
308         tsk->thread.debugreg2 = 0;
309         tsk->thread.debugreg3 = 0;
310         tsk->thread.debugreg6 = 0;
311         tsk->thread.debugreg7 = 0;
312         memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array));        
313         /*
314          * Forget coprocessor state..
315          */
316         clear_fpu(tsk);
317         clear_used_math();
318 }
319
320 void release_thread(struct task_struct *dead_task)
321 {
322         if (dead_task->mm) {
323                 if (dead_task->mm->context.size) {
324                         printk("WARNING: dead process %8s still has LDT? <%p/%d>\n",
325                                         dead_task->comm,
326                                         dead_task->mm->context.ldt,
327                                         dead_task->mm->context.size);
328                         BUG();
329                 }
330         }
331 }
332
333 static inline void set_32bit_tls(struct task_struct *t, int tls, u32 addr)
334 {
335         struct user_desc ud = { 
336                 .base_addr = addr,
337                 .limit = 0xfffff,
338                 .seg_32bit = 1,
339                 .limit_in_pages = 1,
340                 .useable = 1,
341         };
342         struct n_desc_struct *desc = (void *)t->thread.tls_array;
343         desc += tls;
344         desc->a = LDT_entry_a(&ud); 
345         desc->b = LDT_entry_b(&ud); 
346 }
347
348 static inline u32 read_32bit_tls(struct task_struct *t, int tls)
349 {
350         struct desc_struct *desc = (void *)t->thread.tls_array;
351         desc += tls;
352         return desc->base0 | 
353                 (((u32)desc->base1) << 16) | 
354                 (((u32)desc->base2) << 24);
355 }
356
357 /*
358  * This gets called before we allocate a new thread and copy
359  * the current task into it.
360  */
361 void prepare_to_copy(struct task_struct *tsk)
362 {
363         unlazy_fpu(tsk);
364 }
365
366 int copy_thread(int nr, unsigned long clone_flags, unsigned long rsp, 
367                 unsigned long unused,
368         struct task_struct * p, struct pt_regs * regs)
369 {
370         int err;
371         struct pt_regs * childregs;
372         struct task_struct *me = current;
373
374         childregs = ((struct pt_regs *) (THREAD_SIZE + (unsigned long) p->thread_info)) - 1;
375
376         *childregs = *regs;
377
378         childregs->rax = 0;
379         childregs->rsp = rsp;
380         if (rsp == ~0UL) {
381                 childregs->rsp = (unsigned long)childregs;
382         }
383
384         p->thread.rsp = (unsigned long) childregs;
385         p->thread.rsp0 = (unsigned long) (childregs+1);
386         p->thread.userrsp = me->thread.userrsp; 
387
388         set_ti_thread_flag(p->thread_info, TIF_FORK);
389
390         p->thread.fs = me->thread.fs;
391         p->thread.gs = me->thread.gs;
392
393         asm("movl %%gs,%0" : "=m" (p->thread.gsindex));
394         asm("movl %%fs,%0" : "=m" (p->thread.fsindex));
395         asm("movl %%es,%0" : "=m" (p->thread.es));
396         asm("movl %%ds,%0" : "=m" (p->thread.ds));
397
398         if (unlikely(me->thread.io_bitmap_ptr != NULL)) { 
399                 p->thread.io_bitmap_ptr = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL);
400                 if (!p->thread.io_bitmap_ptr) {
401                         p->thread.io_bitmap_max = 0;
402                         return -ENOMEM;
403                 }
404                 memcpy(p->thread.io_bitmap_ptr, me->thread.io_bitmap_ptr, IO_BITMAP_BYTES);
405         } 
406
407         /*
408          * Set a new TLS for the child thread?
409          */
410         if (clone_flags & CLONE_SETTLS) {
411 #ifdef CONFIG_IA32_EMULATION
412                 if (test_thread_flag(TIF_IA32))
413                         err = ia32_child_tls(p, childregs); 
414                 else                    
415 #endif   
416                         err = do_arch_prctl(p, ARCH_SET_FS, childregs->r8); 
417                 if (err) 
418                         goto out;
419         }
420         err = 0;
421 out:
422         if (err && p->thread.io_bitmap_ptr) {
423                 kfree(p->thread.io_bitmap_ptr);
424                 p->thread.io_bitmap_max = 0;
425         }
426         return err;
427 }
428
429 /*
430  * This special macro can be used to load a debugging register
431  */
432 #define loaddebug(thread,r) set_debug(thread->debugreg ## r, r)
433
434 /*
435  *      switch_to(x,y) should switch tasks from x to y.
436  *
437  * This could still be optimized: 
438  * - fold all the options into a flag word and test it with a single test.
439  * - could test fs/gs bitsliced
440  */
441 struct task_struct *__switch_to(struct task_struct *prev_p, struct task_struct *next_p)
442 {
443         struct thread_struct *prev = &prev_p->thread,
444                                  *next = &next_p->thread;
445         int cpu = smp_processor_id();  
446         struct tss_struct *tss = &per_cpu(init_tss, cpu);
447
448         unlazy_fpu(prev_p);
449
450         /*
451          * Reload esp0, LDT and the page table pointer:
452          */
453         tss->rsp0 = next->rsp0;
454
455         /* 
456          * Switch DS and ES.
457          * This won't pick up thread selector changes, but I guess that is ok.
458          */
459         asm volatile("movl %%es,%0" : "=m" (prev->es)); 
460         if (unlikely(next->es | prev->es))
461                 loadsegment(es, next->es); 
462         
463         asm volatile ("movl %%ds,%0" : "=m" (prev->ds)); 
464         if (unlikely(next->ds | prev->ds))
465                 loadsegment(ds, next->ds);
466
467         load_TLS(next, cpu);
468
469         /* 
470          * Switch FS and GS.
471          */
472         { 
473                 unsigned fsindex;
474                 asm volatile("movl %%fs,%0" : "=g" (fsindex)); 
475                 /* segment register != 0 always requires a reload. 
476                    also reload when it has changed. 
477                    when prev process used 64bit base always reload
478                    to avoid an information leak. */
479                 if (unlikely(fsindex | next->fsindex | prev->fs)) {
480                         loadsegment(fs, next->fsindex);
481                         /* check if the user used a selector != 0
482                          * if yes clear 64bit base, since overloaded base
483                          * is always mapped to the Null selector
484                          */
485                         if (fsindex)
486                         prev->fs = 0;                           
487                 }
488                 /* when next process has a 64bit base use it */
489                 if (next->fs) 
490                         wrmsrl(MSR_FS_BASE, next->fs); 
491                 prev->fsindex = fsindex;
492         }
493         { 
494                 unsigned gsindex;
495                 asm volatile("movl %%gs,%0" : "=g" (gsindex)); 
496                 if (unlikely(gsindex | next->gsindex | prev->gs)) {
497                         load_gs_index(next->gsindex);
498                         if (gsindex)
499                         prev->gs = 0;                           
500                 }
501                 if (next->gs)
502                         wrmsrl(MSR_KERNEL_GS_BASE, next->gs); 
503                 prev->gsindex = gsindex;
504         }
505
506         /* 
507          * Switch the PDA context.
508          */
509         prev->userrsp = read_pda(oldrsp); 
510         write_pda(oldrsp, next->userrsp); 
511         write_pda(pcurrent, next_p); 
512         write_pda(kernelstack, (unsigned long)next_p->thread_info + THREAD_SIZE - PDA_STACKOFFSET);
513
514         /*
515          * Now maybe reload the debug registers
516          */
517         if (unlikely(next->debugreg7)) {
518                 loaddebug(next, 0);
519                 loaddebug(next, 1);
520                 loaddebug(next, 2);
521                 loaddebug(next, 3);
522                 /* no 4 and 5 */
523                 loaddebug(next, 6);
524                 loaddebug(next, 7);
525         }
526
527
528         /* 
529          * Handle the IO bitmap 
530          */ 
531         if (unlikely(prev->io_bitmap_ptr || next->io_bitmap_ptr)) {
532                 if (next->io_bitmap_ptr)
533                         /*
534                          * Copy the relevant range of the IO bitmap.
535                          * Normally this is 128 bytes or less:
536                          */
537                         memcpy(tss->io_bitmap, next->io_bitmap_ptr,
538                                 max(prev->io_bitmap_max, next->io_bitmap_max));
539                 else {
540                         /*
541                          * Clear any possible leftover bits:
542                          */
543                         memset(tss->io_bitmap, 0xff, prev->io_bitmap_max);
544                 }
545         }
546
547         return prev_p;
548 }
549
550 /*
551  * sys_execve() executes a new program.
552  */
553 asmlinkage 
554 long sys_execve(char __user *name, char __user * __user *argv,
555                 char __user * __user *envp, struct pt_regs regs)
556 {
557         long error;
558         char * filename;
559
560         filename = getname(name);
561         error = PTR_ERR(filename);
562         if (IS_ERR(filename)) 
563                 return error;
564         error = do_execve(filename, argv, envp, &regs); 
565         if (error == 0) {
566                 task_lock(current);
567                 current->ptrace &= ~PT_DTRACE;
568                 task_unlock(current);
569         }
570         putname(filename);
571         return error;
572 }
573
574 void set_personality_64bit(void)
575 {
576         /* inherit personality from parent */
577
578         /* Make sure to be in 64bit mode */
579         clear_thread_flag(TIF_IA32); 
580
581         /* TBD: overwrites user setup. Should have two bits.
582            But 64bit processes have always behaved this way,
583            so it's not too bad. The main problem is just that
584            32bit childs are affected again. */
585         current->personality &= ~READ_IMPLIES_EXEC;
586 }
587
588 asmlinkage long sys_fork(struct pt_regs *regs)
589 {
590         return do_fork(SIGCHLD, regs->rsp, regs, 0, NULL, NULL);
591 }
592
593 asmlinkage long sys_clone(unsigned long clone_flags, unsigned long newsp, void __user *parent_tid, void __user *child_tid, struct pt_regs *regs)
594 {
595         if (!newsp)
596                 newsp = regs->rsp;
597         return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid);
598 }
599
600 /*
601  * This is trivial, and on the face of it looks like it
602  * could equally well be done in user mode.
603  *
604  * Not so, for quite unobvious reasons - register pressure.
605  * In user mode vfork() cannot have a stack frame, and if
606  * done by calling the "clone()" system call directly, you
607  * do not have enough call-clobbered registers to hold all
608  * the information you need.
609  */
610 asmlinkage long sys_vfork(struct pt_regs *regs)
611 {
612         return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->rsp, regs, 0,
613                     NULL, NULL);
614 }
615
616 unsigned long get_wchan(struct task_struct *p)
617 {
618         unsigned long stack;
619         u64 fp,rip;
620         int count = 0;
621
622         if (!p || p == current || p->state==TASK_RUNNING)
623                 return 0; 
624         stack = (unsigned long)p->thread_info; 
625         if (p->thread.rsp < stack || p->thread.rsp > stack+THREAD_SIZE)
626                 return 0;
627         fp = *(u64 *)(p->thread.rsp);
628         do { 
629                 if (fp < (unsigned long)stack || fp > (unsigned long)stack+THREAD_SIZE)
630                         return 0; 
631                 rip = *(u64 *)(fp+8); 
632                 if (!in_sched_functions(rip))
633                         return rip; 
634                 fp = *(u64 *)fp; 
635         } while (count++ < 16); 
636         return 0;
637 }
638
639 long do_arch_prctl(struct task_struct *task, int code, unsigned long addr)
640
641         int ret = 0; 
642         int doit = task == current;
643         int cpu;
644
645         switch (code) { 
646         case ARCH_SET_GS:
647                 if (addr >= TASK_SIZE) 
648                         return -EPERM; 
649                 cpu = get_cpu();
650                 /* handle small bases via the GDT because that's faster to 
651                    switch. */
652                 if (addr <= 0xffffffff) {  
653                         set_32bit_tls(task, GS_TLS, addr); 
654                         if (doit) { 
655                                 load_TLS(&task->thread, cpu);
656                                 load_gs_index(GS_TLS_SEL); 
657                         }
658                         task->thread.gsindex = GS_TLS_SEL; 
659                         task->thread.gs = 0;
660                 } else { 
661                         task->thread.gsindex = 0;
662                         task->thread.gs = addr;
663                         if (doit) {
664                 load_gs_index(0);
665                 ret = checking_wrmsrl(MSR_KERNEL_GS_BASE, addr); 
666                         } 
667                 }
668                 put_cpu();
669                 break;
670         case ARCH_SET_FS:
671                 /* Not strictly needed for fs, but do it for symmetry
672                    with gs */
673                 if (addr >= TASK_SIZE)
674                         return -EPERM; 
675                 cpu = get_cpu();
676                 /* handle small bases via the GDT because that's faster to 
677                    switch. */
678                 if (addr <= 0xffffffff) { 
679                         set_32bit_tls(task, FS_TLS, addr);
680                         if (doit) { 
681                                 load_TLS(&task->thread, cpu); 
682                                 asm volatile("movl %0,%%fs" :: "r" (FS_TLS_SEL));
683                         }
684                         task->thread.fsindex = FS_TLS_SEL;
685                         task->thread.fs = 0;
686                 } else { 
687                         task->thread.fsindex = 0;
688                         task->thread.fs = addr;
689                         if (doit) {
690                                 /* set the selector to 0 to not confuse
691                                    __switch_to */
692                 asm volatile("movl %0,%%fs" :: "r" (0));
693                 ret = checking_wrmsrl(MSR_FS_BASE, addr); 
694                         }
695                 }
696                 put_cpu();
697                 break;
698         case ARCH_GET_FS: { 
699                 unsigned long base; 
700                 if (task->thread.fsindex == FS_TLS_SEL)
701                         base = read_32bit_tls(task, FS_TLS);
702                 else if (doit) {
703                         rdmsrl(MSR_FS_BASE, base);
704                 } else
705                         base = task->thread.fs;
706                 ret = put_user(base, (unsigned long __user *)addr); 
707                 break; 
708         }
709         case ARCH_GET_GS: { 
710                 unsigned long base;
711                 if (task->thread.gsindex == GS_TLS_SEL)
712                         base = read_32bit_tls(task, GS_TLS);
713                 else if (doit) {
714                         rdmsrl(MSR_KERNEL_GS_BASE, base);
715                 } else
716                         base = task->thread.gs;
717                 ret = put_user(base, (unsigned long __user *)addr); 
718                 break;
719         }
720
721         default:
722                 ret = -EINVAL;
723                 break;
724         } 
725
726         return ret;     
727
728
729 long sys_arch_prctl(int code, unsigned long addr)
730 {
731         return do_arch_prctl(current, code, addr);
732
733
734 /* 
735  * Capture the user space registers if the task is not running (in user space)
736  */
737 int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs)
738 {
739         struct pt_regs *pp, ptregs;
740
741         pp = (struct pt_regs *)(tsk->thread.rsp0);
742         --pp; 
743
744         ptregs = *pp; 
745         ptregs.cs &= 0xffff;
746         ptregs.ss &= 0xffff;
747
748         elf_core_copy_regs(regs, &ptregs);
749  
750         return 1;
751 }