hw-breakpoints: Rewrite the hw-breakpoints layer on top of perf events
[deliverable/linux.git] / arch / x86 / kernel / process_64.c
CommitLineData
1da177e4 1/*
1da177e4
LT
2 * Copyright (C) 1995 Linus Torvalds
3 *
4 * Pentium III FXSR, SSE support
5 * Gareth Hughes <gareth@valinux.com>, May 2000
6612538c 6 *
1da177e4
LT
7 * X86-64 port
8 * Andi Kleen.
76e4f660
AR
9 *
10 * CPU hotplug support - ashok.raj@intel.com
1da177e4
LT
11 */
12
13/*
14 * This file handles the architecture-dependent parts of process handling..
15 */
16
42059429 17#include <linux/stackprotector.h>
76e4f660 18#include <linux/cpu.h>
1da177e4
LT
19#include <linux/errno.h>
20#include <linux/sched.h>
6612538c 21#include <linux/fs.h>
1da177e4
LT
22#include <linux/kernel.h>
23#include <linux/mm.h>
24#include <linux/elfcore.h>
25#include <linux/smp.h>
26#include <linux/slab.h>
27#include <linux/user.h>
1da177e4 28#include <linux/interrupt.h>
6612538c 29#include <linux/utsname.h>
1da177e4 30#include <linux/delay.h>
6612538c 31#include <linux/module.h>
1da177e4 32#include <linux/ptrace.h>
95833c83 33#include <linux/notifier.h>
c6fd91f0 34#include <linux/kprobes.h>
1eeb66a1 35#include <linux/kdebug.h>
02290683 36#include <linux/tick.h>
529e25f6 37#include <linux/prctl.h>
7de08b4e
GP
38#include <linux/uaccess.h>
39#include <linux/io.h>
8b96f011 40#include <linux/ftrace.h>
48ec4d95 41#include <linux/dmi.h>
1da177e4 42
1da177e4
LT
43#include <asm/pgtable.h>
44#include <asm/system.h>
1da177e4
LT
45#include <asm/processor.h>
46#include <asm/i387.h>
47#include <asm/mmu_context.h>
1da177e4 48#include <asm/prctl.h>
1da177e4
LT
49#include <asm/desc.h>
50#include <asm/proto.h>
51#include <asm/ia32.h>
95833c83 52#include <asm/idle.h>
bbc1f698 53#include <asm/syscalls.h>
bf53de90 54#include <asm/ds.h>
66cb5917 55#include <asm/debugreg.h>
1da177e4
LT
56
57asmlinkage extern void ret_from_fork(void);
58
3d1e42a7 59DEFINE_PER_CPU(unsigned long, old_rsp);
c2558e0e 60static DEFINE_PER_CPU(unsigned char, is_idle);
3d1e42a7 61
1da177e4
LT
62unsigned long kernel_thread_flags = CLONE_VM | CLONE_UNTRACED;
63
e041c683 64static ATOMIC_NOTIFIER_HEAD(idle_notifier);
95833c83
AK
65
66void idle_notifier_register(struct notifier_block *n)
67{
e041c683 68 atomic_notifier_chain_register(&idle_notifier, n);
95833c83 69}
c7d87d79
VP
70EXPORT_SYMBOL_GPL(idle_notifier_register);
71
72void idle_notifier_unregister(struct notifier_block *n)
73{
74 atomic_notifier_chain_unregister(&idle_notifier, n);
75}
76EXPORT_SYMBOL_GPL(idle_notifier_unregister);
95833c83 77
95833c83
AK
78void enter_idle(void)
79{
c2558e0e 80 percpu_write(is_idle, 1);
e041c683 81 atomic_notifier_call_chain(&idle_notifier, IDLE_START, NULL);
95833c83
AK
82}
83
84static void __exit_idle(void)
85{
c2558e0e 86 if (x86_test_and_clear_bit_percpu(0, is_idle) == 0)
a15da49d 87 return;
e041c683 88 atomic_notifier_call_chain(&idle_notifier, IDLE_END, NULL);
95833c83
AK
89}
90
91/* Called from interrupts to signify idle end */
92void exit_idle(void)
93{
a15da49d
AK
94 /* idle loop has pid 0 */
95 if (current->pid)
95833c83
AK
96 return;
97 __exit_idle();
98}
99
913da64b 100#ifndef CONFIG_SMP
76e4f660
AR
101static inline void play_dead(void)
102{
103 BUG();
104}
913da64b 105#endif
76e4f660 106
1da177e4
LT
107/*
108 * The idle thread. There's no useful work to be
109 * done, so just try to conserve power and have a
110 * low exit latency (ie sit in a loop waiting for
111 * somebody to say that they'd like to reschedule)
112 */
b10db7f0 113void cpu_idle(void)
1da177e4 114{
495ab9c0 115 current_thread_info()->status |= TS_POLLING;
ce22bd92 116
ce22bd92 117 /*
5c79d2a5
TH
118 * If we're the non-boot CPU, nothing set the stack canary up
119 * for us. CPU0 already has it initialized but no harm in
120 * doing it again. This is a good place for updating it, as
121 * we wont ever return from this function (so the invalid
122 * canaries already on the stack wont ever trigger).
ce22bd92 123 */
18aa8bb1
IM
124 boot_init_stack_canary();
125
1da177e4
LT
126 /* endless idle loop with no priority at all */
127 while (1) {
b8f8c3cf 128 tick_nohz_stop_sched_tick(1);
1da177e4 129 while (!need_resched()) {
1da177e4 130
1da177e4 131 rmb();
6ddd2a27 132
76e4f660
AR
133 if (cpu_is_offline(smp_processor_id()))
134 play_dead();
d331e739
VP
135 /*
136 * Idle routines should keep interrupts disabled
137 * from here on, until they go to idle.
138 * Otherwise, idle callbacks can misfire.
139 */
140 local_irq_disable();
95833c83 141 enter_idle();
81d68a96
SR
142 /* Don't trace irqs off for idle */
143 stop_critical_timings();
6ddd2a27 144 pm_idle();
81d68a96 145 start_critical_timings();
a15da49d
AK
146 /* In many cases the interrupt that ended idle
147 has already called exit_idle. But some idle
148 loops can be woken up without interrupt. */
95833c83 149 __exit_idle();
1da177e4
LT
150 }
151
02290683 152 tick_nohz_restart_sched_tick();
5bfb5d69 153 preempt_enable_no_resched();
1da177e4 154 schedule();
5bfb5d69 155 preempt_disable();
1da177e4
LT
156 }
157}
158
6612538c 159/* Prints also some state that isn't saved in the pt_regs */
e2ce07c8 160void __show_regs(struct pt_regs *regs, int all)
1da177e4
LT
161{
162 unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L, fs, gs, shadowgs;
bb1995d5 163 unsigned long d0, d1, d2, d3, d6, d7;
6612538c
HS
164 unsigned int fsindex, gsindex;
165 unsigned int ds, cs, es;
48ec4d95 166 const char *board;
1da177e4
LT
167
168 printk("\n");
169 print_modules();
48ec4d95
KM
170 board = dmi_get_system_info(DMI_PRODUCT_NAME);
171 if (!board)
172 board = "";
173 printk(KERN_INFO "Pid: %d, comm: %.20s %s %s %.*s %s\n",
9acf23c4 174 current->pid, current->comm, print_tainted(),
96b644bd
SH
175 init_utsname()->release,
176 (int)strcspn(init_utsname()->version, " "),
48ec4d95 177 init_utsname()->version, board);
8092c654 178 printk(KERN_INFO "RIP: %04lx:[<%016lx>] ", regs->cs & 0xffff, regs->ip);
aafbd7eb 179 printk_address(regs->ip, 1);
8092c654
GP
180 printk(KERN_INFO "RSP: %04lx:%016lx EFLAGS: %08lx\n", regs->ss,
181 regs->sp, regs->flags);
182 printk(KERN_INFO "RAX: %016lx RBX: %016lx RCX: %016lx\n",
65ea5b03 183 regs->ax, regs->bx, regs->cx);
8092c654 184 printk(KERN_INFO "RDX: %016lx RSI: %016lx RDI: %016lx\n",
65ea5b03 185 regs->dx, regs->si, regs->di);
8092c654 186 printk(KERN_INFO "RBP: %016lx R08: %016lx R09: %016lx\n",
65ea5b03 187 regs->bp, regs->r8, regs->r9);
8092c654 188 printk(KERN_INFO "R10: %016lx R11: %016lx R12: %016lx\n",
7de08b4e 189 regs->r10, regs->r11, regs->r12);
8092c654 190 printk(KERN_INFO "R13: %016lx R14: %016lx R15: %016lx\n",
7de08b4e 191 regs->r13, regs->r14, regs->r15);
1da177e4 192
7de08b4e
GP
193 asm("movl %%ds,%0" : "=r" (ds));
194 asm("movl %%cs,%0" : "=r" (cs));
195 asm("movl %%es,%0" : "=r" (es));
1da177e4
LT
196 asm("movl %%fs,%0" : "=r" (fsindex));
197 asm("movl %%gs,%0" : "=r" (gsindex));
198
199 rdmsrl(MSR_FS_BASE, fs);
7de08b4e
GP
200 rdmsrl(MSR_GS_BASE, gs);
201 rdmsrl(MSR_KERNEL_GS_BASE, shadowgs);
1da177e4 202
e2ce07c8
PE
203 if (!all)
204 return;
1da177e4 205
f51c9452
GOC
206 cr0 = read_cr0();
207 cr2 = read_cr2();
208 cr3 = read_cr3();
209 cr4 = read_cr4();
1da177e4 210
8092c654 211 printk(KERN_INFO "FS: %016lx(%04x) GS:%016lx(%04x) knlGS:%016lx\n",
7de08b4e 212 fs, fsindex, gs, gsindex, shadowgs);
8092c654
GP
213 printk(KERN_INFO "CS: %04x DS: %04x ES: %04x CR0: %016lx\n", cs, ds,
214 es, cr0);
215 printk(KERN_INFO "CR2: %016lx CR3: %016lx CR4: %016lx\n", cr2, cr3,
216 cr4);
bb1995d5
AS
217
218 get_debugreg(d0, 0);
219 get_debugreg(d1, 1);
220 get_debugreg(d2, 2);
8092c654 221 printk(KERN_INFO "DR0: %016lx DR1: %016lx DR2: %016lx\n", d0, d1, d2);
bb1995d5
AS
222 get_debugreg(d3, 3);
223 get_debugreg(d6, 6);
224 get_debugreg(d7, 7);
8092c654 225 printk(KERN_INFO "DR3: %016lx DR6: %016lx DR7: %016lx\n", d3, d6, d7);
1da177e4
LT
226}
227
228void show_regs(struct pt_regs *regs)
229{
8092c654 230 printk(KERN_INFO "CPU %d:", smp_processor_id());
e2ce07c8 231 __show_regs(regs, 1);
bc850d6b 232 show_trace(NULL, regs, (void *)(regs + 1), regs->bp);
1da177e4
LT
233}
234
1da177e4
LT
235void release_thread(struct task_struct *dead_task)
236{
237 if (dead_task->mm) {
238 if (dead_task->mm->context.size) {
239 printk("WARNING: dead process %8s still has LDT? <%p/%d>\n",
240 dead_task->comm,
241 dead_task->mm->context.ldt,
242 dead_task->mm->context.size);
243 BUG();
244 }
245 }
246}
247
248static inline void set_32bit_tls(struct task_struct *t, int tls, u32 addr)
249{
6612538c 250 struct user_desc ud = {
1da177e4
LT
251 .base_addr = addr,
252 .limit = 0xfffff,
253 .seg_32bit = 1,
254 .limit_in_pages = 1,
255 .useable = 1,
256 };
ade1af77 257 struct desc_struct *desc = t->thread.tls_array;
1da177e4 258 desc += tls;
80fbb69a 259 fill_ldt(desc, &ud);
1da177e4
LT
260}
261
262static inline u32 read_32bit_tls(struct task_struct *t, int tls)
263{
91394eb0 264 return get_desc_base(&t->thread.tls_array[tls]);
1da177e4
LT
265}
266
267/*
268 * This gets called before we allocate a new thread and copy
269 * the current task into it.
270 */
271void prepare_to_copy(struct task_struct *tsk)
272{
273 unlazy_fpu(tsk);
274}
275
6f2c55b8 276int copy_thread(unsigned long clone_flags, unsigned long sp,
1da177e4 277 unsigned long unused,
7de08b4e 278 struct task_struct *p, struct pt_regs *regs)
1da177e4
LT
279{
280 int err;
7de08b4e 281 struct pt_regs *childregs;
1da177e4
LT
282 struct task_struct *me = current;
283
a88cde13 284 childregs = ((struct pt_regs *)
57eafdc2 285 (THREAD_SIZE + task_stack_page(p))) - 1;
1da177e4
LT
286 *childregs = *regs;
287
65ea5b03
PA
288 childregs->ax = 0;
289 childregs->sp = sp;
290 if (sp == ~0UL)
291 childregs->sp = (unsigned long)childregs;
1da177e4 292
faca6227
PA
293 p->thread.sp = (unsigned long) childregs;
294 p->thread.sp0 = (unsigned long) (childregs+1);
295 p->thread.usersp = me->thread.usersp;
1da177e4 296
e4f17c43 297 set_tsk_thread_flag(p, TIF_FORK);
1da177e4
LT
298
299 p->thread.fs = me->thread.fs;
300 p->thread.gs = me->thread.gs;
66cb5917 301 p->thread.io_bitmap_ptr = NULL;
1da177e4 302
ada85708
JF
303 savesegment(gs, p->thread.gsindex);
304 savesegment(fs, p->thread.fsindex);
305 savesegment(es, p->thread.es);
306 savesegment(ds, p->thread.ds);
1da177e4 307
66cb5917 308 err = -ENOMEM;
24f1e32c 309 memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps));
66cb5917 310
d3a4f48d 311 if (unlikely(test_tsk_thread_flag(me, TIF_IO_BITMAP))) {
1da177e4
LT
312 p->thread.io_bitmap_ptr = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL);
313 if (!p->thread.io_bitmap_ptr) {
314 p->thread.io_bitmap_max = 0;
315 return -ENOMEM;
316 }
a88cde13
AK
317 memcpy(p->thread.io_bitmap_ptr, me->thread.io_bitmap_ptr,
318 IO_BITMAP_BYTES);
d3a4f48d 319 set_tsk_thread_flag(p, TIF_IO_BITMAP);
6612538c 320 }
1da177e4
LT
321
322 /*
323 * Set a new TLS for the child thread?
324 */
325 if (clone_flags & CLONE_SETTLS) {
326#ifdef CONFIG_IA32_EMULATION
327 if (test_thread_flag(TIF_IA32))
efd1ca52 328 err = do_set_thread_area(p, -1,
65ea5b03 329 (struct user_desc __user *)childregs->si, 0);
7de08b4e
GP
330 else
331#endif
332 err = do_arch_prctl(p, ARCH_SET_FS, childregs->r8);
333 if (err)
1da177e4
LT
334 goto out;
335 }
bf53de90 336
2311f0de
MM
337 clear_tsk_thread_flag(p, TIF_DS_AREA_MSR);
338 p->thread.ds_ctx = NULL;
bf53de90
MM
339
340 clear_tsk_thread_flag(p, TIF_DEBUGCTLMSR);
341 p->thread.debugctlmsr = 0;
342
1da177e4
LT
343 err = 0;
344out:
345 if (err && p->thread.io_bitmap_ptr) {
346 kfree(p->thread.io_bitmap_ptr);
347 p->thread.io_bitmap_max = 0;
348 }
66cb5917 349
1da177e4
LT
350 return err;
351}
352
513ad84b
IM
353void
354start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp)
355{
ada85708
JF
356 loadsegment(fs, 0);
357 loadsegment(es, 0);
358 loadsegment(ds, 0);
513ad84b
IM
359 load_gs_index(0);
360 regs->ip = new_ip;
361 regs->sp = new_sp;
3d1e42a7 362 percpu_write(old_rsp, new_sp);
513ad84b
IM
363 regs->cs = __USER_CS;
364 regs->ss = __USER_DS;
365 regs->flags = 0x200;
366 set_fs(USER_DS);
aa283f49
SS
367 /*
368 * Free the old FP and other extended state
369 */
370 free_thread_xstate(current);
513ad84b
IM
371}
372EXPORT_SYMBOL_GPL(start_thread);
373
1da177e4
LT
374/*
375 * switch_to(x,y) should switch tasks from x to y.
376 *
6612538c 377 * This could still be optimized:
1da177e4
LT
378 * - fold all the options into a flag word and test it with a single test.
379 * - could test fs/gs bitsliced
099f318b
AK
380 *
381 * Kprobes not supported here. Set the probe on schedule instead.
8b96f011 382 * Function graph tracer not supported too.
1da177e4 383 */
8b96f011 384__notrace_funcgraph struct task_struct *
a88cde13 385__switch_to(struct task_struct *prev_p, struct task_struct *next_p)
1da177e4 386{
87b935a0
JF
387 struct thread_struct *prev = &prev_p->thread;
388 struct thread_struct *next = &next_p->thread;
6612538c 389 int cpu = smp_processor_id();
1da177e4 390 struct tss_struct *tss = &per_cpu(init_tss, cpu);
478de5a9 391 unsigned fsindex, gsindex;
17950c5b
JF
392 bool preload_fpu;
393
394 /*
395 * If the task has used fpu the last 5 timeslices, just do a full
396 * restore of the math state immediately to avoid the trap; the
397 * chances of needing FPU soon are obviously high now
398 */
399 preload_fpu = tsk_used_math(next_p) && next_p->fpu_counter > 5;
1da177e4 400
e07e23e1 401 /* we're going to use this soon, after a few expensive things */
17950c5b 402 if (preload_fpu)
61c4628b 403 prefetch(next->xstate);
e07e23e1 404
1da177e4
LT
405 /*
406 * Reload esp0, LDT and the page table pointer:
407 */
7818a1e0 408 load_sp0(tss, next);
1da177e4 409
7de08b4e 410 /*
1da177e4
LT
411 * Switch DS and ES.
412 * This won't pick up thread selector changes, but I guess that is ok.
413 */
ada85708 414 savesegment(es, prev->es);
1da177e4 415 if (unlikely(next->es | prev->es))
7de08b4e 416 loadsegment(es, next->es);
ada85708
JF
417
418 savesegment(ds, prev->ds);
1da177e4
LT
419 if (unlikely(next->ds | prev->ds))
420 loadsegment(ds, next->ds);
421
478de5a9
JF
422
423 /* We must save %fs and %gs before load_TLS() because
424 * %fs and %gs may be cleared by load_TLS().
425 *
426 * (e.g. xen_load_tls())
427 */
428 savesegment(fs, fsindex);
429 savesegment(gs, gsindex);
430
1da177e4
LT
431 load_TLS(next, cpu);
432
16d9dbf0
JF
433 /* Must be after DS reload */
434 unlazy_fpu(prev_p);
435
17950c5b
JF
436 /* Make sure cpu is ready for new context */
437 if (preload_fpu)
438 clts();
439
3fe0a63e
JF
440 /*
441 * Leave lazy mode, flushing any hypercalls made here.
442 * This must be done before restoring TLS segments so
443 * the GDT and LDT are properly updated, and must be
444 * done before math_state_restore, so the TS bit is up
445 * to date.
446 */
224101ed 447 arch_end_context_switch(next_p);
3fe0a63e 448
7de08b4e 449 /*
1da177e4 450 * Switch FS and GS.
87b935a0
JF
451 *
452 * Segment register != 0 always requires a reload. Also
453 * reload when it has changed. When prev process used 64bit
454 * base always reload to avoid an information leak.
1da177e4 455 */
87b935a0
JF
456 if (unlikely(fsindex | next->fsindex | prev->fs)) {
457 loadsegment(fs, next->fsindex);
7de08b4e 458 /*
87b935a0
JF
459 * Check if the user used a selector != 0; if yes
460 * clear 64bit base, since overloaded base is always
461 * mapped to the Null selector
462 */
463 if (fsindex)
7de08b4e 464 prev->fs = 0;
1da177e4 465 }
87b935a0
JF
466 /* when next process has a 64bit base use it */
467 if (next->fs)
468 wrmsrl(MSR_FS_BASE, next->fs);
469 prev->fsindex = fsindex;
470
471 if (unlikely(gsindex | next->gsindex | prev->gs)) {
472 load_gs_index(next->gsindex);
473 if (gsindex)
7de08b4e 474 prev->gs = 0;
1da177e4 475 }
87b935a0
JF
476 if (next->gs)
477 wrmsrl(MSR_KERNEL_GS_BASE, next->gs);
478 prev->gsindex = gsindex;
1da177e4 479
7de08b4e 480 /*
45948d77 481 * Switch the PDA and FPU contexts.
1da177e4 482 */
3d1e42a7
BG
483 prev->usersp = percpu_read(old_rsp);
484 percpu_write(old_rsp, next->usersp);
c6f5e0ac 485 percpu_write(current_task, next_p);
18bd057b 486
9af45651 487 percpu_write(kernel_stack,
87b935a0 488 (unsigned long)task_stack_page(next_p) +
9af45651 489 THREAD_SIZE - KERNEL_STACK_OFFSET);
1da177e4
LT
490
491 /*
d3a4f48d 492 * Now maybe reload the debug registers and handle I/O bitmaps
1da177e4 493 */
eee3af4a
MM
494 if (unlikely(task_thread_info(next_p)->flags & _TIF_WORK_CTXSW_NEXT ||
495 task_thread_info(prev_p)->flags & _TIF_WORK_CTXSW_PREV))
d3a4f48d 496 __switch_to_xtra(prev_p, next_p, tss);
1da177e4 497
17950c5b
JF
498 /*
499 * Preload the FPU context, now that we've determined that the
500 * task is likely to be using it.
e07e23e1 501 */
17950c5b
JF
502 if (preload_fpu)
503 __math_state_restore();
66cb5917 504
1da177e4
LT
505 return prev_p;
506}
507
508/*
509 * sys_execve() executes a new program.
510 */
6612538c 511asmlinkage
1da177e4 512long sys_execve(char __user *name, char __user * __user *argv,
5d119b2c 513 char __user * __user *envp, struct pt_regs *regs)
1da177e4
LT
514{
515 long error;
7de08b4e 516 char *filename;
1da177e4
LT
517
518 filename = getname(name);
519 error = PTR_ERR(filename);
5d119b2c 520 if (IS_ERR(filename))
1da177e4 521 return error;
5d119b2c 522 error = do_execve(filename, argv, envp, regs);
1da177e4
LT
523 putname(filename);
524 return error;
525}
526
527void set_personality_64bit(void)
528{
529 /* inherit personality from parent */
530
531 /* Make sure to be in 64bit mode */
6612538c 532 clear_thread_flag(TIF_IA32);
1da177e4
LT
533
534 /* TBD: overwrites user setup. Should have two bits.
535 But 64bit processes have always behaved this way,
536 so it's not too bad. The main problem is just that
6612538c 537 32bit childs are affected again. */
1da177e4
LT
538 current->personality &= ~READ_IMPLIES_EXEC;
539}
540
a88cde13
AK
541asmlinkage long
542sys_clone(unsigned long clone_flags, unsigned long newsp,
543 void __user *parent_tid, void __user *child_tid, struct pt_regs *regs)
1da177e4
LT
544{
545 if (!newsp)
65ea5b03 546 newsp = regs->sp;
1da177e4
LT
547 return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid);
548}
549
1da177e4
LT
550unsigned long get_wchan(struct task_struct *p)
551{
552 unsigned long stack;
7de08b4e 553 u64 fp, ip;
1da177e4
LT
554 int count = 0;
555
7de08b4e
GP
556 if (!p || p == current || p->state == TASK_RUNNING)
557 return 0;
57eafdc2 558 stack = (unsigned long)task_stack_page(p);
e1e23bb0 559 if (p->thread.sp < stack || p->thread.sp >= stack+THREAD_SIZE)
1da177e4 560 return 0;
faca6227 561 fp = *(u64 *)(p->thread.sp);
7de08b4e 562 do {
a88cde13 563 if (fp < (unsigned long)stack ||
e1e23bb0 564 fp >= (unsigned long)stack+THREAD_SIZE)
7de08b4e 565 return 0;
65ea5b03
PA
566 ip = *(u64 *)(fp+8);
567 if (!in_sched_functions(ip))
568 return ip;
7de08b4e
GP
569 fp = *(u64 *)fp;
570 } while (count++ < 16);
1da177e4
LT
571 return 0;
572}
573
574long do_arch_prctl(struct task_struct *task, int code, unsigned long addr)
7de08b4e
GP
575{
576 int ret = 0;
1da177e4
LT
577 int doit = task == current;
578 int cpu;
579
7de08b4e 580 switch (code) {
1da177e4 581 case ARCH_SET_GS:
84929801 582 if (addr >= TASK_SIZE_OF(task))
7de08b4e 583 return -EPERM;
1da177e4 584 cpu = get_cpu();
7de08b4e 585 /* handle small bases via the GDT because that's faster to
1da177e4 586 switch. */
7de08b4e
GP
587 if (addr <= 0xffffffff) {
588 set_32bit_tls(task, GS_TLS, addr);
589 if (doit) {
1da177e4 590 load_TLS(&task->thread, cpu);
7de08b4e 591 load_gs_index(GS_TLS_SEL);
1da177e4 592 }
7de08b4e 593 task->thread.gsindex = GS_TLS_SEL;
1da177e4 594 task->thread.gs = 0;
7de08b4e 595 } else {
1da177e4
LT
596 task->thread.gsindex = 0;
597 task->thread.gs = addr;
598 if (doit) {
a88cde13
AK
599 load_gs_index(0);
600 ret = checking_wrmsrl(MSR_KERNEL_GS_BASE, addr);
7de08b4e 601 }
1da177e4
LT
602 }
603 put_cpu();
604 break;
605 case ARCH_SET_FS:
606 /* Not strictly needed for fs, but do it for symmetry
607 with gs */
84929801 608 if (addr >= TASK_SIZE_OF(task))
6612538c 609 return -EPERM;
1da177e4 610 cpu = get_cpu();
6612538c 611 /* handle small bases via the GDT because that's faster to
1da177e4 612 switch. */
6612538c 613 if (addr <= 0xffffffff) {
1da177e4 614 set_32bit_tls(task, FS_TLS, addr);
6612538c
HS
615 if (doit) {
616 load_TLS(&task->thread, cpu);
ada85708 617 loadsegment(fs, FS_TLS_SEL);
1da177e4
LT
618 }
619 task->thread.fsindex = FS_TLS_SEL;
620 task->thread.fs = 0;
6612538c 621 } else {
1da177e4
LT
622 task->thread.fsindex = 0;
623 task->thread.fs = addr;
624 if (doit) {
625 /* set the selector to 0 to not confuse
626 __switch_to */
ada85708 627 loadsegment(fs, 0);
a88cde13 628 ret = checking_wrmsrl(MSR_FS_BASE, addr);
1da177e4
LT
629 }
630 }
631 put_cpu();
632 break;
6612538c
HS
633 case ARCH_GET_FS: {
634 unsigned long base;
1da177e4
LT
635 if (task->thread.fsindex == FS_TLS_SEL)
636 base = read_32bit_tls(task, FS_TLS);
a88cde13 637 else if (doit)
1da177e4 638 rdmsrl(MSR_FS_BASE, base);
a88cde13 639 else
1da177e4 640 base = task->thread.fs;
6612538c
HS
641 ret = put_user(base, (unsigned long __user *)addr);
642 break;
1da177e4 643 }
6612538c 644 case ARCH_GET_GS: {
1da177e4 645 unsigned long base;
97c2803c 646 unsigned gsindex;
1da177e4
LT
647 if (task->thread.gsindex == GS_TLS_SEL)
648 base = read_32bit_tls(task, GS_TLS);
97c2803c 649 else if (doit) {
ada85708 650 savesegment(gs, gsindex);
97c2803c
JB
651 if (gsindex)
652 rdmsrl(MSR_KERNEL_GS_BASE, base);
653 else
654 base = task->thread.gs;
7de08b4e 655 } else
1da177e4 656 base = task->thread.gs;
6612538c 657 ret = put_user(base, (unsigned long __user *)addr);
1da177e4
LT
658 break;
659 }
660
661 default:
662 ret = -EINVAL;
663 break;
6612538c 664 }
1da177e4 665
6612538c
HS
666 return ret;
667}
1da177e4
LT
668
669long sys_arch_prctl(int code, unsigned long addr)
670{
671 return do_arch_prctl(current, code, addr);
1da177e4
LT
672}
673
This page took 0.825415 seconds and 5 git commands to generate.