process.c 3.9 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
/*
 *  linux/arch/h8300/kernel/process.c
 *
 * Yoshinori Sato <ysato@users.sourceforge.jp>
 *
 *  Based on:
 *
 *  linux/arch/m68knommu/kernel/process.c
 *
 *  Copyright (C) 1998  D. Jeff Dionne <jeff@ryeham.ee.ryerson.ca>,
 *                      Kenneth Albanowski <kjahds@kjahds.com>,
 *                      The Silver Hammer Group, Ltd.
 *
 *  linux/arch/m68k/kernel/process.c
 *
 *  Copyright (C) 1995  Hamish Macdonald
 *
 *  68060 fixes by Jesper Skov
 */

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

#include <linux/errno.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/stddef.h>
#include <linux/unistd.h>
#include <linux/ptrace.h>
#include <linux/user.h>
#include <linux/interrupt.h>
#include <linux/reboot.h>
Y
Yoshinori Sato 已提交
37
#include <linux/fs.h>
38
#include <linux/slab.h>
39
#include <linux/rcupdate.h>
L
Linus Torvalds 已提交
40 41 42 43 44 45

#include <asm/uaccess.h>
#include <asm/traps.h>
#include <asm/setup.h>
#include <asm/pgtable.h>

A
Adrian Bunk 已提交
46 47 48
void (*pm_power_off)(void) = NULL;
EXPORT_SYMBOL(pm_power_off);

L
Linus Torvalds 已提交
49
asmlinkage void ret_from_fork(void);
A
Al Viro 已提交
50
asmlinkage void ret_from_kernel_thread(void);
L
Linus Torvalds 已提交
51 52 53 54 55

/*
 * The idle loop on an H8/300..
 */
#if !defined(CONFIG_H8300H_SIM) && !defined(CONFIG_H8S_SIM)
56
static void default_idle(void)
L
Linus Torvalds 已提交
57
{
58 59 60 61 62 63 64
	local_irq_disable();
	if (!need_resched()) {
		local_irq_enable();
		/* XXX: race here! What if need_resched() gets set now? */
		__asm__("sleep");
	} else
		local_irq_enable();
L
Linus Torvalds 已提交
65 66
}
#else
67
static void default_idle(void)
L
Linus Torvalds 已提交
68
{
69
	cpu_relax();
L
Linus Torvalds 已提交
70 71 72 73 74 75 76 77 78 79 80 81
}
#endif
void (*idle)(void) = default_idle;

/*
 * 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)
 */
void cpu_idle(void)
{
82
	while (1) {
83
		rcu_idle_enter();
84 85
		while (!need_resched())
			idle();
86
		rcu_idle_exit();
87
		schedule_preempt_disabled();
88
	}
L
Linus Torvalds 已提交
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
}

void machine_restart(char * __unused)
{
	local_irq_disable();
	__asm__("jmp @@0"); 
}

void machine_halt(void)
{
	local_irq_disable();
	__asm__("sleep");
	for (;;);
}

void machine_power_off(void)
{
	local_irq_disable();
	__asm__("sleep");
	for (;;);
}

void show_regs(struct pt_regs * regs)
{
	printk("\nPC: %08lx  Status: %02x",
	       regs->pc, regs->ccr);
	printk("\nORIG_ER0: %08lx ER0: %08lx ER1: %08lx",
	       regs->orig_er0, regs->er0, regs->er1);
	printk("\nER2: %08lx ER3: %08lx ER4: %08lx ER5: %08lx",
	       regs->er2, regs->er3, regs->er4, regs->er5);
	printk("\nER6' %08lx ",regs->er6);
	if (user_mode(regs))
		printk("USP: %08lx\n", rdusp());
	else
		printk("\n");
}

void flush_thread(void)
{
}

A
Alexey Dobriyan 已提交
130
int copy_thread(unsigned long clone_flags,
L
Linus Torvalds 已提交
131
                unsigned long usp, unsigned long topstk,
132
		 struct task_struct * p, struct pt_regs *unused)
L
Linus Torvalds 已提交
133 134 135
{
	struct pt_regs * childregs;

A
Al Viro 已提交
136
	childregs = (struct pt_regs *) (THREAD_SIZE + task_stack_page(p)) - 1;
L
Linus Torvalds 已提交
137

A
Al Viro 已提交
138 139 140 141 142 143 144
	if (unlikely(p->flags & PF_KTHREAD)) {
		memset(childregs, 0, sizeof(struct pt_regs));
		childregs->retpc = (unsigned long) ret_from_kernel_thread;
		childregs->er4 = topstk; /* arg */
		childregs->er5 = usp; /* fn */
		p->thread.ksp = (unsigned long)childregs;
	}
145
	*childregs = *current_pt_regs();
L
Linus Torvalds 已提交
146 147
	childregs->retpc = (unsigned long) ret_from_fork;
	childregs->er0 = 0;
148
	p->thread.usp = usp ?: rdusp();
L
Linus Torvalds 已提交
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
	p->thread.ksp = (unsigned long)childregs;

	return 0;
}

unsigned long thread_saved_pc(struct task_struct *tsk)
{
	return ((struct pt_regs *)tsk->thread.esp0)->pc;
}

unsigned long get_wchan(struct task_struct *p)
{
	unsigned long fp, pc;
	unsigned long stack_page;
	int count = 0;
	if (!p || p == current || p->state == TASK_RUNNING)
		return 0;

	stack_page = (unsigned long)p;
	fp = ((struct pt_regs *)p->thread.ksp)->er6;
	do {
		if (fp < stack_page+sizeof(struct thread_info) ||
		    fp >= 8184+stack_page)
			return 0;
		pc = ((unsigned long *)fp)[1];
		if (!in_sched_functions(pc))
			return pc;
		fp = *(unsigned long *) fp;
	} while (count++ < 16);
	return 0;
}