process.c 9.2 KB
Newer Older
J
Jeff Dike 已提交
1
/*
J
Jeff Dike 已提交
2
 * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
L
Linus Torvalds 已提交
3 4 5 6
 * Copyright 2003 PathScale, Inc.
 * Licensed under the GPL
 */

J
Jeff Dike 已提交
7 8 9
#include "linux/stddef.h"
#include "linux/err.h"
#include "linux/hardirq.h"
L
Linus Torvalds 已提交
10
#include "linux/mm.h"
J
Jeff Dike 已提交
11
#include "linux/personality.h"
L
Linus Torvalds 已提交
12 13 14
#include "linux/proc_fs.h"
#include "linux/ptrace.h"
#include "linux/random.h"
J
Jeff Dike 已提交
15
#include "linux/sched.h"
J
Jeff Dike 已提交
16
#include "linux/tick.h"
J
Jeff Dike 已提交
17
#include "linux/threads.h"
L
Linus Torvalds 已提交
18 19
#include "asm/pgtable.h"
#include "asm/uaccess.h"
J
Jeff Dike 已提交
20
#include "as-layout.h"
J
Jeff Dike 已提交
21
#include "kern_util.h"
L
Linus Torvalds 已提交
22
#include "os.h"
23
#include "skas.h"
J
Jeff Dike 已提交
24
#include "tlb.h"
L
Linus Torvalds 已提交
25

J
Jeff Dike 已提交
26 27
/*
 * This is a per-cpu array.  A processor only modifies its entry and it only
L
Linus Torvalds 已提交
28 29 30 31 32
 * cares about its entry, so it's OK if another processor is modifying its
 * entry.
 */
struct cpu_task cpu_tasks[NR_CPUS] = { [0 ... NR_CPUS - 1] = { -1, NULL } };

J
Jeff Dike 已提交
33
static inline int external_pid(struct task_struct *task)
L
Linus Torvalds 已提交
34
{
35
	/* FIXME: Need to look up userspace_pid by cpu */
J
Jeff Dike 已提交
36
	return userspace_pid[0];
L
Linus Torvalds 已提交
37 38 39 40 41 42
}

int pid_to_processor_id(int pid)
{
	int i;

J
Jeff Dike 已提交
43 44
	for(i = 0; i < ncpus; i++) {
		if (cpu_tasks[i].pid == pid)
J
Jeff Dike 已提交
45
			return i;
L
Linus Torvalds 已提交
46
	}
J
Jeff Dike 已提交
47
	return -1;
L
Linus Torvalds 已提交
48 49 50 51 52 53 54 55 56 57
}

void free_stack(unsigned long stack, int order)
{
	free_pages(stack, order);
}

unsigned long alloc_stack(int order, int atomic)
{
	unsigned long page;
A
Al Viro 已提交
58
	gfp_t flags = GFP_KERNEL;
L
Linus Torvalds 已提交
59

60 61
	if (atomic)
		flags = GFP_ATOMIC;
L
Linus Torvalds 已提交
62
	page = __get_free_pages(flags, order);
63

J
Jeff Dike 已提交
64
	return page;
L
Linus Torvalds 已提交
65 66 67 68 69 70 71 72
}

int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
{
	int pid;

	current->thread.request.u.thread.proc = fn;
	current->thread.request.u.thread.arg = arg;
J
Jeff Dike 已提交
73 74
	pid = do_fork(CLONE_VM | CLONE_UNTRACED | flags, 0,
		      &current->thread.regs, 0, NULL, NULL);
J
Jeff Dike 已提交
75
	return pid;
L
Linus Torvalds 已提交
76 77
}

J
Jeff Dike 已提交
78
static inline void set_current(struct task_struct *task)
L
Linus Torvalds 已提交
79
{
A
Al Viro 已提交
80
	cpu_tasks[task_thread_info(task)->cpu] = ((struct cpu_task)
L
Linus Torvalds 已提交
81 82 83
		{ external_pid(task), task });
}

84
extern void arch_switch_to(struct task_struct *to);
85

L
Linus Torvalds 已提交
86 87
void *_switch_to(void *prev, void *next, void *last)
{
J
Jeff Dike 已提交
88
	struct task_struct *from = prev;
89
	struct task_struct *to = next;
90

J
Jeff Dike 已提交
91 92
	to->thread.prev_sched = from;
	set_current(to);
93

94
	do {
J
Jeff Dike 已提交
95
		current->thread.saved_task = NULL;
96

97
		switch_threads(&from->thread.switch_buf, &to->thread.switch_buf);
98

99
		arch_switch_to(current);
100

J
Jeff Dike 已提交
101
		if (current->thread.saved_task)
102
			show_regs(&(current->thread.regs));
103 104 105
		next = current->thread.saved_task;
		prev = current;
	} while (current->thread.saved_task);
106

J
Jeff Dike 已提交
107
	return current->thread.prev_sched;
108

L
Linus Torvalds 已提交
109 110 111 112
}

void interrupt_end(void)
{
J
Jeff Dike 已提交
113
	if (need_resched())
J
Jeff Dike 已提交
114
		schedule();
J
Jeff Dike 已提交
115
	if (test_tsk_thread_flag(current, TIF_SIGPENDING))
J
Jeff Dike 已提交
116
		do_signal();
L
Linus Torvalds 已提交
117 118 119 120 121
}

void exit_thread(void)
{
}
J
Jeff Dike 已提交
122

L
Linus Torvalds 已提交
123 124
void *get_current(void)
{
J
Jeff Dike 已提交
125
	return current;
L
Linus Torvalds 已提交
126 127
}

128 129
extern void schedule_tail(struct task_struct *prev);

J
Jeff Dike 已提交
130 131
/*
 * This is called magically, by its address being stuffed in a jmp_buf
132 133 134 135 136 137 138
 * and being longjmp-d to.
 */
void new_thread_handler(void)
{
	int (*fn)(void *), n;
	void *arg;

J
Jeff Dike 已提交
139
	if (current->thread.prev_sched != NULL)
140 141 142 143 144 145
		schedule_tail(current->thread.prev_sched);
	current->thread.prev_sched = NULL;

	fn = current->thread.request.u.thread.proc;
	arg = current->thread.request.u.thread.arg;

J
Jeff Dike 已提交
146 147
	/*
	 * The return value is 1 if the kernel thread execs a process,
148 149 150
	 * 0 if it just exits
	 */
	n = run_kernel_thread(fn, arg, &current->thread.exec_buf);
J
Jeff Dike 已提交
151
	if (n == 1) {
152 153 154 155 156 157 158 159 160 161 162 163 164 165
		/* Handle any immediate reschedules or signals */
		interrupt_end();
		userspace(&current->thread.regs.regs);
	}
	else do_exit(0);
}

/* Called magically, see new_thread_handler above */
void fork_handler(void)
{
	force_flush_all();

	schedule_tail(current->thread.prev_sched);

J
Jeff Dike 已提交
166 167
	/*
	 * XXX: if interrupt_end() calls schedule, this call to
168
	 * arch_switch_to isn't needed. We could want to apply this to
J
Jeff Dike 已提交
169 170
	 * improve performance. -bb
	 */
171
	arch_switch_to(current);
172 173 174 175 176 177 178 179 180

	current->thread.prev_sched = NULL;

	/* Handle any immediate reschedules or signals */
	interrupt_end();

	userspace(&current->thread.regs.regs);
}

L
Linus Torvalds 已提交
181
int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
J
Jeff Dike 已提交
182
		unsigned long stack_top, struct task_struct * p,
L
Linus Torvalds 已提交
183 184
		struct pt_regs *regs)
{
185 186
	void (*handler)(void);
	int ret = 0;
187

L
Linus Torvalds 已提交
188
	p->thread = (struct thread_struct) INIT_THREAD;
189

J
Jeff Dike 已提交
190
	if (current->thread.forking) {
191 192
	  	memcpy(&p->thread.regs.regs, &regs->regs,
		       sizeof(p->thread.regs.regs));
193
		REGS_SET_SYSCALL_RETURN(p->thread.regs.regs.gp, 0);
J
Jeff Dike 已提交
194
		if (sp != 0)
195
			REGS_SP(p->thread.regs.regs.gp) = sp;
196

197
		handler = fork_handler;
198

199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217
		arch_copy_thread(&current->thread.arch, &p->thread.arch);
	}
	else {
		init_thread_registers(&p->thread.regs.regs);
		p->thread.request.u.thread = current->thread.request.u.thread;
		handler = new_thread_handler;
	}

	new_thread(task_stack_page(p), &p->thread.switch_buf, handler);

	if (current->thread.forking) {
		clear_flushed_tls(p);

		/*
		 * Set a new TLS for the child thread?
		 */
		if (clone_flags & CLONE_SETTLS)
			ret = arch_copy_tls(p);
	}
218 219

	return ret;
L
Linus Torvalds 已提交
220 221 222 223 224 225 226
}

void initial_thread_cb(void (*proc)(void *), void *arg)
{
	int save_kmalloc_ok = kmalloc_ok;

	kmalloc_ok = 0;
J
Jeff Dike 已提交
227
	initial_thread_cb_skas(proc, arg);
L
Linus Torvalds 已提交
228 229
	kmalloc_ok = save_kmalloc_ok;
}
J
Jeff Dike 已提交
230

L
Linus Torvalds 已提交
231 232
void default_idle(void)
{
233 234
	unsigned long long nsecs;

J
Jeff Dike 已提交
235
	while(1) {
L
Linus Torvalds 已提交
236 237 238 239 240 241
		/* endless idle loop with no priority at all */

		/*
		 * although we are an idle CPU, we do not want to
		 * get into the scheduler unnecessarily.
		 */
J
Jeff Dike 已提交
242
		if (need_resched())
L
Linus Torvalds 已提交
243
			schedule();
J
Jeff Dike 已提交
244

J
Jeff Dike 已提交
245
		tick_nohz_stop_sched_tick();
246 247
		nsecs = disable_timer();
		idle_sleep(nsecs);
J
Jeff Dike 已提交
248
		tick_nohz_restart_sched_tick();
L
Linus Torvalds 已提交
249 250 251 252 253
	}
}

void cpu_idle(void)
{
J
Jeff Dike 已提交
254
	cpu_tasks[current_thread_info()->cpu].pid = os_getpid();
255
	default_idle();
L
Linus Torvalds 已提交
256 257 258 259 260 261
}

void dump_thread(struct pt_regs *regs, struct user *u)
{
}

262 263 264
int __cant_sleep(void) {
	return in_atomic() || irqs_disabled() || in_interrupt();
	/* Is in_interrupt() really needed? */
L
Linus Torvalds 已提交
265 266 267 268 269 270 271
}

int user_context(unsigned long sp)
{
	unsigned long stack;

	stack = sp & (PAGE_MASK << CONFIG_KERNEL_STACK_ORDER);
J
Jeff Dike 已提交
272
	return stack != (unsigned long) current_thread_info();
L
Linus Torvalds 已提交
273 274 275 276 277 278 279 280 281 282 283 284 285
}

extern exitcall_t __uml_exitcall_begin, __uml_exitcall_end;

void do_uml_exitcalls(void)
{
	exitcall_t *call;

	call = &__uml_exitcall_end;
	while (--call >= &__uml_exitcall_begin)
		(*call)();
}

W
WANG Cong 已提交
286
char *uml_strdup(const char *string)
L
Linus Torvalds 已提交
287
{
288
	return kstrdup(string, GFP_KERNEL);
L
Linus Torvalds 已提交
289 290 291 292
}

int copy_to_user_proc(void __user *to, void *from, int size)
{
J
Jeff Dike 已提交
293
	return copy_to_user(to, from, size);
L
Linus Torvalds 已提交
294 295 296 297
}

int copy_from_user_proc(void *to, void __user *from, int size)
{
J
Jeff Dike 已提交
298
	return copy_from_user(to, from, size);
L
Linus Torvalds 已提交
299 300 301 302
}

int clear_user_proc(void __user *buf, int size)
{
J
Jeff Dike 已提交
303
	return clear_user(buf, size);
L
Linus Torvalds 已提交
304 305 306 307
}

int strlen_user_proc(char __user *str)
{
J
Jeff Dike 已提交
308
	return strlen_user(str);
L
Linus Torvalds 已提交
309 310 311 312 313
}

int smp_sigio_handler(void)
{
#ifdef CONFIG_SMP
J
Jeff Dike 已提交
314
	int cpu = current_thread_info()->cpu;
L
Linus Torvalds 已提交
315
	IPI_handler(cpu);
J
Jeff Dike 已提交
316
	if (cpu != 0)
J
Jeff Dike 已提交
317
		return 1;
L
Linus Torvalds 已提交
318
#endif
J
Jeff Dike 已提交
319
	return 0;
L
Linus Torvalds 已提交
320 321 322 323
}

int cpu(void)
{
J
Jeff Dike 已提交
324
	return current_thread_info()->cpu;
L
Linus Torvalds 已提交
325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343
}

static atomic_t using_sysemu = ATOMIC_INIT(0);
int sysemu_supported;

void set_using_sysemu(int value)
{
	if (value > sysemu_supported)
		return;
	atomic_set(&using_sysemu, value);
}

int get_using_sysemu(void)
{
	return atomic_read(&using_sysemu);
}

static int proc_read_sysemu(char *buf, char **start, off_t offset, int size,int *eof, void *data)
{
J
Jeff Dike 已提交
344 345
	if (snprintf(buf, size, "%d\n", get_using_sysemu()) < size)
		/* No overflow */
L
Linus Torvalds 已提交
346 347 348 349 350
		*eof = 1;

	return strlen(buf);
}

A
Al Viro 已提交
351
static int proc_write_sysemu(struct file *file,const char __user *buf, unsigned long count,void *data)
L
Linus Torvalds 已提交
352 353 354 355 356 357 358 359
{
	char tmp[2];

	if (copy_from_user(tmp, buf, 1))
		return -EFAULT;

	if (tmp[0] >= '0' && tmp[0] <= '2')
		set_using_sysemu(tmp[0] - '0');
J
Jeff Dike 已提交
360 361
	/* We use the first char, but pretend to write everything */
	return count;
L
Linus Torvalds 已提交
362 363 364 365 366 367 368 369 370 371 372 373
}

int __init make_proc_sysemu(void)
{
	struct proc_dir_entry *ent;
	if (!sysemu_supported)
		return 0;

	ent = create_proc_entry("sysemu", 0600, &proc_root);

	if (ent == NULL)
	{
374
		printk(KERN_WARNING "Failed to register /proc/sysemu\n");
J
Jeff Dike 已提交
375
		return 0;
L
Linus Torvalds 已提交
376 377 378 379 380 381 382 383 384 385 386 387 388 389 390
	}

	ent->read_proc  = proc_read_sysemu;
	ent->write_proc = proc_write_sysemu;

	return 0;
}

late_initcall(make_proc_sysemu);

int singlestepping(void * t)
{
	struct task_struct *task = t ? t : current;

	if ( ! (task->ptrace & PT_DTRACE) )
J
Jeff Dike 已提交
391
		return 0;
L
Linus Torvalds 已提交
392 393

	if (task->thread.singlestep_syscall)
J
Jeff Dike 已提交
394
		return 1;
L
Linus Torvalds 已提交
395 396 397 398

	return 2;
}

399 400 401 402 403 404 405 406
/*
 * Only x86 and x86_64 have an arch_align_stack().
 * All other arches have "#define arch_align_stack(x) (x)"
 * in their asm/system.h
 * As this is included in UML from asm-um/system-generic.h,
 * we can use it to behave as the subarch does.
 */
#ifndef arch_align_stack
L
Linus Torvalds 已提交
407 408
unsigned long arch_align_stack(unsigned long sp)
{
J
Jeff Dike 已提交
409
	if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
L
Linus Torvalds 已提交
410 411 412
		sp -= get_random_int() % 8192;
	return sp & ~0xf;
}
413
#endif
J
Jeff Dike 已提交
414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448

unsigned long get_wchan(struct task_struct *p)
{
	unsigned long stack_page, sp, ip;
	bool seen_sched = 0;

	if ((p == NULL) || (p == current) || (p->state == TASK_RUNNING))
		return 0;

	stack_page = (unsigned long) task_stack_page(p);
	/* Bail if the process has no kernel stack for some reason */
	if (stack_page == 0)
		return 0;

	sp = p->thread.switch_buf->JB_SP;
	/*
	 * Bail if the stack pointer is below the bottom of the kernel
	 * stack for some reason
	 */
	if (sp < stack_page)
		return 0;

	while (sp < stack_page + THREAD_SIZE) {
		ip = *((unsigned long *) sp);
		if (in_sched_functions(ip))
			/* Ignore everything until we're above the scheduler */
			seen_sched = 1;
		else if (kernel_text_address(ip) && seen_sched)
			return ip;

		sp += sizeof(unsigned long);
	}

	return 0;
}
J
Jeff Dike 已提交
449 450 451 452 453 454 455 456

int elf_core_copy_fpregs(struct task_struct *t, elf_fpregset_t *fpu)
{
	int cpu = current_thread_info()->cpu;

	return save_fp_registers(userspace_pid[cpu], (unsigned long *) fpu);
}