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