process_32.c 17.1 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
1 2 3 4 5 6 7 8 9 10 11 12 13
/*
 *  Copyright (C) 1995  Linus Torvalds
 *
 *  Pentium III FXSR, SSE support
 *	Gareth Hughes <gareth@valinux.com>, May 2000
 */

/*
 * This file handles the architecture-dependent parts of process handling..
 */

#include <stdarg.h>

Zwane Mwaikambo's avatar
Zwane Mwaikambo committed
14
#include <linux/cpu.h>
Linus Torvalds's avatar
Linus Torvalds committed
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/elfcore.h>
#include <linux/smp.h>
#include <linux/stddef.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/user.h>
#include <linux/interrupt.h>
#include <linux/utsname.h>
#include <linux/delay.h>
#include <linux/reboot.h>
#include <linux/init.h>
#include <linux/mc146818rtc.h>
#include <linux/module.h>
#include <linux/kallsyms.h>
#include <linux/ptrace.h>
#include <linux/random.h>
36
#include <linux/personality.h>
37
#include <linux/tick.h>
38
#include <linux/percpu.h>
39
#include <linux/prctl.h>
Linus Torvalds's avatar
Linus Torvalds committed
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54

#include <asm/uaccess.h>
#include <asm/pgtable.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/ldt.h>
#include <asm/processor.h>
#include <asm/i387.h>
#include <asm/desc.h>
#ifdef CONFIG_MATH_EMULATION
#include <asm/math_emu.h>
#endif

#include <linux/err.h>

Zwane Mwaikambo's avatar
Zwane Mwaikambo committed
55 56
#include <asm/tlbflush.h>
#include <asm/cpu.h>
57
#include <asm/kdebug.h>
Zwane Mwaikambo's avatar
Zwane Mwaikambo committed
58

Linus Torvalds's avatar
Linus Torvalds committed
59 60
asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");

61 62 63 64 65 66
DEFINE_PER_CPU(struct task_struct *, current_task) = &init_task;
EXPORT_PER_CPU_SYMBOL(current_task);

DEFINE_PER_CPU(int, cpu_number);
EXPORT_PER_CPU_SYMBOL(cpu_number);

Linus Torvalds's avatar
Linus Torvalds committed
67 68 69 70 71
/*
 * Return saved PC of a blocked thread.
 */
unsigned long thread_saved_pc(struct task_struct *tsk)
{
72
	return ((unsigned long *)tsk->thread.sp)[3];
Linus Torvalds's avatar
Linus Torvalds committed
73 74 75 76 77 78 79 80
}

/*
 * The idle thread. There's no useful work to be
 * done, so just try to conserve power and have a
 * low exit latency (ie sit in a loop waiting for
 * somebody to say that they'd like to reschedule)
 */
Zwane Mwaikambo's avatar
Zwane Mwaikambo committed
81
void cpu_idle(void)
Linus Torvalds's avatar
Linus Torvalds committed
82
{
83
	int cpu = smp_processor_id();
Zwane Mwaikambo's avatar
Zwane Mwaikambo committed
84

85
	current_thread_info()->status |= TS_POLLING;
86

Linus Torvalds's avatar
Linus Torvalds committed
87 88
	/* endless idle loop with no priority at all */
	while (1) {
89
		tick_nohz_stop_sched_tick(1);
Linus Torvalds's avatar
Linus Torvalds committed
90 91
		while (!need_resched()) {

Christoph Lameter's avatar
Christoph Lameter committed
92
			check_pgt_cache();
Linus Torvalds's avatar
Linus Torvalds committed
93 94
			rmb();

95 96 97
			if (rcu_pending(cpu))
				rcu_check_callbacks(cpu, 0);

Zwane Mwaikambo's avatar
Zwane Mwaikambo committed
98 99 100
			if (cpu_is_offline(cpu))
				play_dead();

101
			local_irq_disable();
Linus Torvalds's avatar
Linus Torvalds committed
102
			__get_cpu_var(irq_stat).idle_timestamp = jiffies;
103 104
			/* Don't trace irqs off for idle */
			stop_critical_timings();
105
			pm_idle();
106
			start_critical_timings();
Linus Torvalds's avatar
Linus Torvalds committed
107
		}
108
		tick_nohz_restart_sched_tick();
109
		preempt_enable_no_resched();
Linus Torvalds's avatar
Linus Torvalds committed
110
		schedule();
111
		preempt_disable();
Linus Torvalds's avatar
Linus Torvalds committed
112 113 114
	}
}

115
void __show_registers(struct pt_regs *regs, int all)
Linus Torvalds's avatar
Linus Torvalds committed
116 117
{
	unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L;
118
	unsigned long d0, d1, d2, d3, d6, d7;
119
	unsigned long sp;
120 121 122
	unsigned short ss, gs;

	if (user_mode_vm(regs)) {
123 124
		sp = regs->sp;
		ss = regs->ss & 0xffff;
125 126
		savesegment(gs, gs);
	} else {
127
		sp = (unsigned long) (&regs->sp);
128 129 130
		savesegment(ss, ss);
		savesegment(gs, gs);
	}
Linus Torvalds's avatar
Linus Torvalds committed
131 132

	printk("\n");
133 134
	printk("Pid: %d, comm: %s %s (%s %.*s)\n",
			task_pid_nr(current), current->comm,
135 136 137 138 139
			print_tainted(), init_utsname()->release,
			(int)strcspn(init_utsname()->version, " "),
			init_utsname()->version);

	printk("EIP: %04x:[<%08lx>] EFLAGS: %08lx CPU: %d\n",
140
			(u16)regs->cs, regs->ip, regs->flags,
141
			smp_processor_id());
142
	print_symbol("EIP is at %s\n", regs->ip);
Linus Torvalds's avatar
Linus Torvalds committed
143 144

	printk("EAX: %08lx EBX: %08lx ECX: %08lx EDX: %08lx\n",
145
		regs->ax, regs->bx, regs->cx, regs->dx);
146
	printk("ESI: %08lx EDI: %08lx EBP: %08lx ESP: %08lx\n",
147
		regs->si, regs->di, regs->bp, sp);
148
	printk(" DS: %04x ES: %04x FS: %04x GS: %04x SS: %04x\n",
149
	       (u16)regs->ds, (u16)regs->es, (u16)regs->fs, gs, ss);
150 151 152

	if (!all)
		return;
Linus Torvalds's avatar
Linus Torvalds committed
153

154 155 156
	cr0 = read_cr0();
	cr2 = read_cr2();
	cr3 = read_cr3();
157
	cr4 = read_cr4_safe();
158 159
	printk("CR0: %08lx CR2: %08lx CR3: %08lx CR4: %08lx\n",
			cr0, cr2, cr3, cr4);
160 161 162 163 164 165 166

	get_debugreg(d0, 0);
	get_debugreg(d1, 1);
	get_debugreg(d2, 2);
	get_debugreg(d3, 3);
	printk("DR0: %08lx DR1: %08lx DR2: %08lx DR3: %08lx\n",
			d0, d1, d2, d3);
167

168 169
	get_debugreg(d6, 6);
	get_debugreg(d7, 7);
170 171 172
	printk("DR6: %08lx DR7: %08lx\n",
			d6, d7);
}
173

174 175 176
void show_regs(struct pt_regs *regs)
{
	__show_registers(regs, 1);
177
	show_trace(NULL, regs, &regs->sp, regs->bp);
Linus Torvalds's avatar
Linus Torvalds committed
178 179 180
}

/*
181 182
 * This gets run with %bx containing the
 * function to call, and %dx containing
Linus Torvalds's avatar
Linus Torvalds committed
183 184 185 186 187 188 189 190 191 192 193 194 195
 * the "args".
 */
extern void kernel_thread_helper(void);

/*
 * Create a kernel thread
 */
int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
{
	struct pt_regs regs;

	memset(&regs, 0, sizeof(regs));

196 197
	regs.bx = (unsigned long) fn;
	regs.dx = (unsigned long) arg;
Linus Torvalds's avatar
Linus Torvalds committed
198

199 200 201 202 203 204 205
	regs.ds = __USER_DS;
	regs.es = __USER_DS;
	regs.fs = __KERNEL_PERCPU;
	regs.orig_ax = -1;
	regs.ip = (unsigned long) kernel_thread_helper;
	regs.cs = __KERNEL_CS | get_kernel_rpl();
	regs.flags = X86_EFLAGS_IF | X86_EFLAGS_SF | X86_EFLAGS_PF | 0x2;
Linus Torvalds's avatar
Linus Torvalds committed
206 207

	/* Ok, create the new process.. */
208
	return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
Linus Torvalds's avatar
Linus Torvalds committed
209
}
210
EXPORT_SYMBOL(kernel_thread);
Linus Torvalds's avatar
Linus Torvalds committed
211 212 213 214 215 216 217

/*
 * Free current thread data structures etc..
 */
void exit_thread(void)
{
	/* The process may have allocated an io port bitmap... nuke it. */
218 219 220
	if (unlikely(test_thread_flag(TIF_IO_BITMAP))) {
		struct task_struct *tsk = current;
		struct thread_struct *t = &tsk->thread;
Linus Torvalds's avatar
Linus Torvalds committed
221 222 223 224 225
		int cpu = get_cpu();
		struct tss_struct *tss = &per_cpu(init_tss, cpu);

		kfree(t->io_bitmap_ptr);
		t->io_bitmap_ptr = NULL;
226
		clear_thread_flag(TIF_IO_BITMAP);
Linus Torvalds's avatar
Linus Torvalds committed
227 228 229 230 231 232 233
		/*
		 * Careful, clear this in the TSS too:
		 */
		memset(tss->io_bitmap, 0xff, tss->io_bitmap_max);
		t->io_bitmap_max = 0;
		tss->io_bitmap_owner = NULL;
		tss->io_bitmap_max = 0;
234
		tss->x86_tss.io_bitmap_base = INVALID_IO_BITMAP_OFFSET;
Linus Torvalds's avatar
Linus Torvalds committed
235 236 237 238 239 240 241 242
		put_cpu();
	}
}

void flush_thread(void)
{
	struct task_struct *tsk = current;

243 244 245 246 247 248
	tsk->thread.debugreg0 = 0;
	tsk->thread.debugreg1 = 0;
	tsk->thread.debugreg2 = 0;
	tsk->thread.debugreg3 = 0;
	tsk->thread.debugreg6 = 0;
	tsk->thread.debugreg7 = 0;
Linus Torvalds's avatar
Linus Torvalds committed
249
	memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array));	
250
	clear_tsk_thread_flag(tsk, TIF_DEBUG);
Linus Torvalds's avatar
Linus Torvalds committed
251 252 253
	/*
	 * Forget coprocessor state..
	 */
254
	tsk->fpu_counter = 0;
Linus Torvalds's avatar
Linus Torvalds committed
255 256 257 258 259 260
	clear_fpu(tsk);
	clear_used_math();
}

void release_thread(struct task_struct *dead_task)
{
261
	BUG_ON(dead_task->mm);
Linus Torvalds's avatar
Linus Torvalds committed
262 263 264 265 266 267 268 269 270 271 272 273
	release_vm86_irqs(dead_task);
}

/*
 * This gets called before we allocate a new thread and copy
 * the current task into it.
 */
void prepare_to_copy(struct task_struct *tsk)
{
	unlazy_fpu(tsk);
}

274
int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
Linus Torvalds's avatar
Linus Torvalds committed
275 276 277 278 279 280 281
	unsigned long unused,
	struct task_struct * p, struct pt_regs * regs)
{
	struct pt_regs * childregs;
	struct task_struct *tsk;
	int err;

282
	childregs = task_pt_regs(p);
283
	*childregs = *regs;
284 285
	childregs->ax = 0;
	childregs->sp = sp;
286

287 288
	p->thread.sp = (unsigned long) childregs;
	p->thread.sp0 = (unsigned long) (childregs+1);
Linus Torvalds's avatar
Linus Torvalds committed
289

290
	p->thread.ip = (unsigned long) ret_from_fork;
Linus Torvalds's avatar
Linus Torvalds committed
291

292
	savesegment(gs, p->thread.gs);
Linus Torvalds's avatar
Linus Torvalds committed
293 294

	tsk = current;
295
	if (unlikely(test_tsk_thread_flag(tsk, TIF_IO_BITMAP))) {
296 297
		p->thread.io_bitmap_ptr = kmemdup(tsk->thread.io_bitmap_ptr,
						IO_BITMAP_BYTES, GFP_KERNEL);
Linus Torvalds's avatar
Linus Torvalds committed
298 299 300 301
		if (!p->thread.io_bitmap_ptr) {
			p->thread.io_bitmap_max = 0;
			return -ENOMEM;
		}
302
		set_tsk_thread_flag(p, TIF_IO_BITMAP);
Linus Torvalds's avatar
Linus Torvalds committed
303 304
	}

Roland McGrath's avatar
Roland McGrath committed
305 306
	err = 0;

Linus Torvalds's avatar
Linus Torvalds committed
307 308 309
	/*
	 * Set a new TLS for the child thread?
	 */
Roland McGrath's avatar
Roland McGrath committed
310 311
	if (clone_flags & CLONE_SETTLS)
		err = do_set_thread_area(p, -1,
312
			(struct user_desc __user *)childregs->si, 0);
Linus Torvalds's avatar
Linus Torvalds committed
313 314 315 316 317 318 319 320

	if (err && p->thread.io_bitmap_ptr) {
		kfree(p->thread.io_bitmap_ptr);
		p->thread.io_bitmap_max = 0;
	}
	return err;
}

Ingo Molnar's avatar
Ingo Molnar committed
321 322 323 324 325 326 327 328 329 330 331 332
void
start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp)
{
	__asm__("movl %0, %%gs" :: "r"(0));
	regs->fs		= 0;
	set_fs(USER_DS);
	regs->ds		= __USER_DS;
	regs->es		= __USER_DS;
	regs->ss		= __USER_DS;
	regs->cs		= __USER_CS;
	regs->ip		= new_ip;
	regs->sp		= new_sp;
333 334 335 336
	/*
	 * Free the old FP and other extended state
	 */
	free_thread_xstate(current);
Ingo Molnar's avatar
Ingo Molnar committed
337 338 339
}
EXPORT_SYMBOL_GPL(start_thread);

340
static void hard_disable_TSC(void)
341 342 343
{
	write_cr4(read_cr4() | X86_CR4_TSD);
}
344

345 346 347 348 349 350 351 352 353 354 355
void disable_TSC(void)
{
	preempt_disable();
	if (!test_and_set_thread_flag(TIF_NOTSC))
		/*
		 * Must flip the CPU state synchronously with
		 * TIF_NOTSC in the current running context.
		 */
		hard_disable_TSC();
	preempt_enable();
}
356

357
static void hard_enable_TSC(void)
358 359 360
{
	write_cr4(read_cr4() & ~X86_CR4_TSD);
}
361

Ingo Molnar's avatar
Ingo Molnar committed
362
static void enable_TSC(void)
363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396
{
	preempt_disable();
	if (test_and_clear_thread_flag(TIF_NOTSC))
		/*
		 * Must flip the CPU state synchronously with
		 * TIF_NOTSC in the current running context.
		 */
		hard_enable_TSC();
	preempt_enable();
}

int get_tsc_mode(unsigned long adr)
{
	unsigned int val;

	if (test_thread_flag(TIF_NOTSC))
		val = PR_TSC_SIGSEGV;
	else
		val = PR_TSC_ENABLE;

	return put_user(val, (unsigned int __user *)adr);
}

int set_tsc_mode(unsigned int val)
{
	if (val == PR_TSC_SIGSEGV)
		disable_TSC();
	else if (val == PR_TSC_ENABLE)
		enable_TSC();
	else
		return -EINVAL;

	return 0;
}
397 398 399 400

static noinline void
__switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p,
		 struct tss_struct *tss)
Linus Torvalds's avatar
Linus Torvalds committed
401
{
402
	struct thread_struct *prev, *next;
403
	unsigned long debugctl;
404

405
	prev = &prev_p->thread;
406 407
	next = &next_p->thread;

408 409 410 411 412
	debugctl = prev->debugctlmsr;
	if (next->ds_area_msr != prev->ds_area_msr) {
		/* we clear debugctl to make sure DS
		 * is not in use when we change it */
		debugctl = 0;
413
		update_debugctlmsr(0);
414 415 416 417
		wrmsr(MSR_IA32_DS_AREA, next->ds_area_msr, 0);
	}

	if (next->debugctlmsr != debugctl)
418
		update_debugctlmsr(next->debugctlmsr);
419

420
	if (test_tsk_thread_flag(next_p, TIF_DEBUG)) {
421 422 423 424
		set_debugreg(next->debugreg0, 0);
		set_debugreg(next->debugreg1, 1);
		set_debugreg(next->debugreg2, 2);
		set_debugreg(next->debugreg3, 3);
425
		/* no 4 and 5 */
426 427
		set_debugreg(next->debugreg6, 6);
		set_debugreg(next->debugreg7, 7);
428 429
	}

430 431 432 433 434 435 436 437 438
	if (test_tsk_thread_flag(prev_p, TIF_NOTSC) ^
	    test_tsk_thread_flag(next_p, TIF_NOTSC)) {
		/* prev and next are different */
		if (test_tsk_thread_flag(next_p, TIF_NOTSC))
			hard_disable_TSC();
		else
			hard_enable_TSC();
	}

439
#ifdef X86_BTS
440 441 442 443 444
	if (test_tsk_thread_flag(prev_p, TIF_BTS_TRACE_TS))
		ptrace_bts_take_timestamp(prev_p, BTS_TASK_DEPARTS);

	if (test_tsk_thread_flag(next_p, TIF_BTS_TRACE_TS))
		ptrace_bts_take_timestamp(next_p, BTS_TASK_ARRIVES);
445
#endif
446 447


448
	if (!test_tsk_thread_flag(next_p, TIF_IO_BITMAP)) {
Linus Torvalds's avatar
Linus Torvalds committed
449 450 451 452
		/*
		 * Disable the bitmap via an invalid offset. We still cache
		 * the previous bitmap owner and the IO bitmap contents:
		 */
453
		tss->x86_tss.io_bitmap_base = INVALID_IO_BITMAP_OFFSET;
Linus Torvalds's avatar
Linus Torvalds committed
454 455
		return;
	}
456

Linus Torvalds's avatar
Linus Torvalds committed
457 458 459 460 461 462
	if (likely(next == tss->io_bitmap_owner)) {
		/*
		 * Previous owner of the bitmap (hence the bitmap content)
		 * matches the next task, we dont have to do anything but
		 * to set a valid offset in the TSS:
		 */
463
		tss->x86_tss.io_bitmap_base = IO_BITMAP_OFFSET;
Linus Torvalds's avatar
Linus Torvalds committed
464 465 466 467 468 469 470 471 472 473 474
		return;
	}
	/*
	 * Lazy TSS's I/O bitmap copy. We set an invalid offset here
	 * and we let the task to get a GPF in case an I/O instruction
	 * is performed.  The handler of the GPF will verify that the
	 * faulting task has a valid I/O bitmap and, it true, does the
	 * real copy and restart the instruction.  This will save us
	 * redundant copies when the currently switched task does not
	 * perform any I/O during its timeslice.
	 */
475
	tss->x86_tss.io_bitmap_base = INVALID_IO_BITMAP_OFFSET_LAZY;
Linus Torvalds's avatar
Linus Torvalds committed
476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500
}

/*
 *	switch_to(x,yn) should switch tasks from x to y.
 *
 * We fsave/fwait so that an exception goes off at the right time
 * (as a call from the fsave or fwait in effect) rather than to
 * the wrong process. Lazy FP saving no longer makes any sense
 * with modern CPU's, and this simplifies a lot of things (SMP
 * and UP become the same).
 *
 * NOTE! We used to use the x86 hardware context switching. The
 * reason for not using it any more becomes apparent when you
 * try to recover gracefully from saved state that is no longer
 * valid (stale segment register values in particular). With the
 * hardware task-switch, there is no way to fix up bad state in
 * a reasonable manner.
 *
 * The fact that Intel documents the hardware task-switching to
 * be slow is a fairly red herring - this code is not noticeably
 * faster. However, there _is_ some room for improvement here,
 * so the performance issues may eventually be a valid point.
 * More important, however, is the fact that this allows us much
 * more flexibility.
 *
501
 * The return value (in %ax) will be the "prev" task after
Linus Torvalds's avatar
Linus Torvalds committed
502 503 504
 * the task-switch, and shows up in ret_from_fork in entry.S,
 * for example.
 */
505
struct task_struct * __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
Linus Torvalds's avatar
Linus Torvalds committed
506 507 508 509 510 511 512 513 514 515
{
	struct thread_struct *prev = &prev_p->thread,
				 *next = &next_p->thread;
	int cpu = smp_processor_id();
	struct tss_struct *tss = &per_cpu(init_tss, cpu);

	/* never put a printk in __switch_to... printk() calls wake_up*() indirectly */

	__unlazy_fpu(prev_p);

516 517 518

	/* we're going to use this soon, after a few expensive things */
	if (next_p->fpu_counter > 5)
519
		prefetch(next->xstate);
520

Linus Torvalds's avatar
Linus Torvalds committed
521
	/*
522
	 * Reload esp0.
Linus Torvalds's avatar
Linus Torvalds committed
523
	 */
524
	load_sp0(tss, next);
Linus Torvalds's avatar
Linus Torvalds committed
525 526

	/*
527
	 * Save away %gs. No need to save %fs, as it was saved on the
528 529 530 531 532 533 534
	 * stack on entry.  No need to save %es and %ds, as those are
	 * always kernel segments while inside the kernel.  Doing this
	 * before setting the new TLS descriptors avoids the situation
	 * where we temporarily have non-reloadable segments in %fs
	 * and %gs.  This could be an issue if the NMI handler ever
	 * used %fs or %gs (it does not today), or if the kernel is
	 * running inside of a hypervisor layer.
Linus Torvalds's avatar
Linus Torvalds committed
535
	 */
536
	savesegment(gs, prev->gs);
Linus Torvalds's avatar
Linus Torvalds committed
537 538

	/*
539
	 * Load the per-thread Thread-Local Storage descriptor.
Linus Torvalds's avatar
Linus Torvalds committed
540
	 */
541
	load_TLS(next, cpu);
Linus Torvalds's avatar
Linus Torvalds committed
542

543 544 545 546 547 548 549 550 551
	/*
	 * Restore IOPL if needed.  In normal use, the flags restore
	 * in the switch assembly will handle this.  But if the kernel
	 * is running virtualized at a non-zero CPL, the popf will
	 * not restore flags, so it must be done in a separate step.
	 */
	if (get_kernel_rpl() && unlikely(prev->iopl != next->iopl))
		set_iopl_mask(next->iopl);

Linus Torvalds's avatar
Linus Torvalds committed
552
	/*
553
	 * Now maybe handle debug registers and/or IO bitmaps
Linus Torvalds's avatar
Linus Torvalds committed
554
	 */
555 556 557
	if (unlikely(task_thread_info(prev_p)->flags & _TIF_WORK_CTXSW_PREV ||
		     task_thread_info(next_p)->flags & _TIF_WORK_CTXSW_NEXT))
		__switch_to_xtra(prev_p, next_p, tss);
558

559 560 561 562 563 564 565 566 567
	/*
	 * Leave lazy mode, flushing any hypercalls made here.
	 * This must be done before restoring TLS segments so
	 * the GDT and LDT are properly updated, and must be
	 * done before math_state_restore, so the TS bit is up
	 * to date.
	 */
	arch_leave_lazy_cpu_mode();

568 569 570
	/* If the task has used fpu the last 5 timeslices, just do a full
	 * restore of the math state immediately to avoid the trap; the
	 * chances of needing FPU soon are obviously high now
571 572 573
	 *
	 * tsk_used_math() checks prevent calling math_state_restore(),
	 * which can sleep in the case of !tsk_used_math()
574
	 */
575
	if (tsk_used_math(next_p) && next_p->fpu_counter > 5)
576 577
		math_state_restore();

578 579 580 581 582 583
	/*
	 * Restore %gs if needed (which is common)
	 */
	if (prev->gs | next->gs)
		loadsegment(gs, next->gs);

584
	x86_write_percpu(current_task, next_p);
585

Linus Torvalds's avatar
Linus Torvalds committed
586 587 588 589 590
	return prev_p;
}

asmlinkage int sys_fork(struct pt_regs regs)
{
591
	return do_fork(SIGCHLD, regs.sp, &regs, 0, NULL, NULL);
Linus Torvalds's avatar
Linus Torvalds committed
592 593 594 595 596 597 598 599
}

asmlinkage int sys_clone(struct pt_regs regs)
{
	unsigned long clone_flags;
	unsigned long newsp;
	int __user *parent_tidptr, *child_tidptr;

600 601 602 603
	clone_flags = regs.bx;
	newsp = regs.cx;
	parent_tidptr = (int __user *)regs.dx;
	child_tidptr = (int __user *)regs.di;
Linus Torvalds's avatar
Linus Torvalds committed
604
	if (!newsp)
605
		newsp = regs.sp;
Linus Torvalds's avatar
Linus Torvalds committed
606 607 608 609 610 611 612 613 614 615 616 617 618 619 620
	return do_fork(clone_flags, newsp, &regs, 0, parent_tidptr, child_tidptr);
}

/*
 * This is trivial, and on the face of it looks like it
 * could equally well be done in user mode.
 *
 * Not so, for quite unobvious reasons - register pressure.
 * In user mode vfork() cannot have a stack frame, and if
 * done by calling the "clone()" system call directly, you
 * do not have enough call-clobbered registers to hold all
 * the information you need.
 */
asmlinkage int sys_vfork(struct pt_regs regs)
{
621
	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.sp, &regs, 0, NULL, NULL);
Linus Torvalds's avatar
Linus Torvalds committed
622 623 624 625 626 627 628 629 630 631
}

/*
 * sys_execve() executes a new program.
 */
asmlinkage int sys_execve(struct pt_regs regs)
{
	int error;
	char * filename;

632
	filename = getname((char __user *) regs.bx);
Linus Torvalds's avatar
Linus Torvalds committed
633 634 635 636
	error = PTR_ERR(filename);
	if (IS_ERR(filename))
		goto out;
	error = do_execve(filename,
637 638
			(char __user * __user *) regs.cx,
			(char __user * __user *) regs.dx,
Linus Torvalds's avatar
Linus Torvalds committed
639 640 641 642 643 644 645 646 647 648 649 650 651 652 653
			&regs);
	if (error == 0) {
		/* Make sure we don't return using sysenter.. */
		set_thread_flag(TIF_IRET);
	}
	putname(filename);
out:
	return error;
}

#define top_esp                (THREAD_SIZE - sizeof(unsigned long))
#define top_ebp                (THREAD_SIZE - 2*sizeof(unsigned long))

unsigned long get_wchan(struct task_struct *p)
{
654
	unsigned long bp, sp, ip;
Linus Torvalds's avatar
Linus Torvalds committed
655 656 657 658
	unsigned long stack_page;
	int count = 0;
	if (!p || p == current || p->state == TASK_RUNNING)
		return 0;
Al Viro's avatar
Al Viro committed
659
	stack_page = (unsigned long)task_stack_page(p);
660
	sp = p->thread.sp;
661
	if (!stack_page || sp < stack_page || sp > top_esp+stack_page)
Linus Torvalds's avatar
Linus Torvalds committed
662
		return 0;
663 664
	/* include/asm-i386/system.h:switch_to() pushes bp last. */
	bp = *(unsigned long *) sp;
Linus Torvalds's avatar
Linus Torvalds committed
665
	do {
666
		if (bp < stack_page || bp > top_ebp+stack_page)
Linus Torvalds's avatar
Linus Torvalds committed
667
			return 0;
668 669 670 671
		ip = *(unsigned long *) (bp+4);
		if (!in_sched_functions(ip))
			return ip;
		bp = *(unsigned long *) bp;
Linus Torvalds's avatar
Linus Torvalds committed
672 673 674 675 676 677
	} while (count++ < 16);
	return 0;
}

unsigned long arch_align_stack(unsigned long sp)
{
678
	if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
Linus Torvalds's avatar
Linus Torvalds committed
679 680 681
		sp -= get_random_int() % 8192;
	return sp & ~0xf;
}
Jiri Kosina's avatar
Jiri Kosina committed
682 683 684 685 686 687

unsigned long arch_randomize_brk(struct mm_struct *mm)
{
	unsigned long range_end = mm->brk + 0x02000000;
	return randomize_range(mm->brk, range_end, 0) ? : mm->brk;
}