Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
arch
h8300
kernel
process.c
Go to the documentation of this file.
1
/*
2
* linux/arch/h8300/kernel/process.c
3
*
4
* Yoshinori Sato <
[email protected]
>
5
*
6
* Based on:
7
*
8
* linux/arch/m68knommu/kernel/process.c
9
*
10
* Copyright (C) 1998 D. Jeff Dionne <
[email protected]
>,
11
* Kenneth Albanowski <
[email protected]
>,
12
* The Silver Hammer Group, Ltd.
13
*
14
* linux/arch/m68k/kernel/process.c
15
*
16
* Copyright (C) 1995 Hamish Macdonald
17
*
18
* 68060 fixes by Jesper Skov
19
*/
20
21
/*
22
* This file handles the architecture-dependent parts of process handling..
23
*/
24
25
#include <linux/errno.h>
26
#include <linux/module.h>
27
#include <linux/sched.h>
28
#include <linux/kernel.h>
29
#include <
linux/mm.h
>
30
#include <
linux/smp.h
>
31
#include <linux/stddef.h>
32
#include <
linux/unistd.h
>
33
#include <linux/ptrace.h>
34
#include <
linux/user.h
>
35
#include <
linux/interrupt.h
>
36
#include <linux/reboot.h>
37
#include <linux/fs.h>
38
#include <linux/slab.h>
39
#include <
linux/rcupdate.h
>
40
41
#include <asm/uaccess.h>
42
#include <asm/traps.h>
43
#include <asm/setup.h>
44
#include <asm/pgtable.h>
45
46
void
(*
pm_power_off
)(
void
) =
NULL
;
47
EXPORT_SYMBOL
(
pm_power_off
);
48
49
asmlinkage
void
ret_from_fork
(
void
);
50
51
/*
52
* The idle loop on an H8/300..
53
*/
54
#if !defined(CONFIG_H8300H_SIM) && !defined(CONFIG_H8S_SIM)
55
static
void
default_idle
(
void
)
56
{
57
local_irq_disable
();
58
if
(!need_resched()) {
59
local_irq_enable
();
60
/* XXX: race here! What if need_resched() gets set now? */
61
__asm__
(
"sleep"
);
62
}
else
63
local_irq_enable
();
64
}
65
#else
66
static
void
default_idle
(
void
)
67
{
68
cpu_relax
();
69
}
70
#endif
71
void
(*
idle
)(
void
) = default_idle;
72
73
/*
74
* The idle thread. There's no useful work to be
75
* done, so just try to conserve power and have a
76
* low exit latency (ie sit in a loop waiting for
77
* somebody to say that they'd like to reschedule)
78
*/
79
void
cpu_idle
(
void
)
80
{
81
while
(1) {
82
rcu_idle_enter
();
83
while
(!need_resched())
84
idle
();
85
rcu_idle_exit
();
86
schedule_preempt_disabled
();
87
}
88
}
89
90
void
machine_restart
(
char
*
__unused
)
91
{
92
local_irq_disable
();
93
__asm__
(
"jmp @@0"
);
94
}
95
96
void
machine_halt
(
void
)
97
{
98
local_irq_disable
();
99
__asm__
(
"sleep"
);
100
for
(;;);
101
}
102
103
void
machine_power_off
(
void
)
104
{
105
local_irq_disable
();
106
__asm__
(
"sleep"
);
107
for
(;;);
108
}
109
110
void
show_regs
(
struct
pt_regs
*
regs
)
111
{
112
printk
(
"\nPC: %08lx Status: %02x"
,
113
regs->
pc
, regs->
ccr
);
114
printk
(
"\nORIG_ER0: %08lx ER0: %08lx ER1: %08lx"
,
115
regs->
orig_er0
, regs->
er0
, regs->
er1
);
116
printk
(
"\nER2: %08lx ER3: %08lx ER4: %08lx ER5: %08lx"
,
117
regs->
er2
, regs->
er3
, regs->
er4
, regs->
er5
);
118
printk
(
"\nER6' %08lx "
,regs->
er6
);
119
if
(
user_mode
(regs))
120
printk
(
"USP: %08lx\n"
, rdusp());
121
else
122
printk
(
"\n"
);
123
}
124
125
/*
126
* Create a kernel thread
127
*/
128
int
kernel_thread
(
int
(*
fn
)(
void
*),
void
*
arg
,
unsigned
long
flags
)
129
{
130
long
retval
;
131
long
clone_arg;
132
mm_segment_t
fs
;
133
134
fs =
get_fs
();
135
set_fs
(
KERNEL_DS
);
136
clone_arg = flags |
CLONE_VM
;
137
__asm__
(
"mov.l sp,er3\n\t"
138
"sub.l er2,er2\n\t"
139
"mov.l %2,er1\n\t"
140
"mov.l %1,er0\n\t"
141
"trapa #0\n\t"
142
"cmp.l sp,er3\n\t"
143
"beq 1f\n\t"
144
"mov.l %4,er0\n\t"
145
"mov.l %3,er1\n\t"
146
"jsr @er1\n\t"
147
"mov.l %5,er0\n\t"
148
"trapa #0\n"
149
"1:\n\t"
150
"mov.l er0,%0"
151
:
"=r"
(retval)
152
:
"i"
(
__NR_clone
),
"g"
(clone_arg),
"g"
(
fn
),
"g"
(arg),
"i"
(
__NR_exit
)
153
:
"er0"
,
"er1"
,
"er2"
,
"er3"
);
154
set_fs
(fs);
155
return
retval
;
156
}
157
158
void
flush_thread
(
void
)
159
{
160
}
161
162
/*
163
* "h8300_fork()".. By the time we get here, the
164
* non-volatile registers have also been saved on the
165
* stack. We do some ugly pointer stuff here.. (see
166
* also copy_thread)
167
*/
168
169
asmlinkage
int
h8300_fork
(
struct
pt_regs
*
regs
)
170
{
171
return
-
EINVAL
;
172
}
173
174
asmlinkage
int
h8300_vfork
(
struct
pt_regs
*
regs
)
175
{
176
return
do_fork
(
CLONE_VFORK
|
CLONE_VM
|
SIGCHLD
, rdusp(), regs, 0,
NULL
,
NULL
);
177
}
178
179
asmlinkage
int
h8300_clone
(
struct
pt_regs
*
regs
)
180
{
181
unsigned
long
clone_flags;
182
unsigned
long
newsp;
183
184
/* syscall2 puts clone_flags in er1 and usp in er2 */
185
clone_flags = regs->
er1
;
186
newsp = regs->
er2
;
187
if
(!newsp)
188
newsp = rdusp();
189
return
do_fork
(clone_flags, newsp, regs, 0,
NULL
,
NULL
);
190
191
}
192
193
int
copy_thread
(
unsigned
long
clone_flags,
194
unsigned
long
usp
,
unsigned
long
topstk,
195
struct
task_struct
*
p
,
struct
pt_regs
*
regs
)
196
{
197
struct
pt_regs
* childregs;
198
199
childregs = (
struct
pt_regs
*) (
THREAD_SIZE
+
task_stack_page
(p)) - 1;
200
201
*childregs = *
regs
;
202
childregs->
retpc
= (
unsigned
long
)
ret_from_fork
;
203
childregs->
er0
= 0;
204
205
p->
thread
.usp =
usp
;
206
p->
thread
.ksp = (
unsigned
long
)childregs;
207
208
return
0;
209
}
210
211
/*
212
* sys_execve() executes a new program.
213
*/
214
asmlinkage
int
sys_execve
(
const
char
*
name
,
215
const
char
*
const
*argv,
216
const
char
*
const
*envp,
217
int
dummy
, ...)
218
{
219
int
error
;
220
struct
filename
*
filename
;
221
struct
pt_regs
*
regs
= (
struct
pt_regs
*) ((
unsigned
char
*)&dummy-4);
222
223
filename =
getname
(name);
224
error = PTR_ERR(filename);
225
if
(IS_ERR(filename))
226
return
error
;
227
error =
do_execve
(filename->
name
, argv, envp, regs);
228
putname
(filename);
229
return
error
;
230
}
231
232
unsigned
long
thread_saved_pc
(
struct
task_struct
*tsk)
233
{
234
return
((
struct
pt_regs
*)tsk->
thread
.esp0)->pc;
235
}
236
237
unsigned
long
get_wchan
(
struct
task_struct
*
p
)
238
{
239
unsigned
long
fp
,
pc
;
240
unsigned
long
stack_page;
241
int
count
= 0;
242
if
(!p || p ==
current
|| p->
state
==
TASK_RUNNING
)
243
return
0;
244
245
stack_page = (
unsigned
long
)p;
246
fp = ((
struct
pt_regs
*)p->
thread
.ksp)->er6;
247
do
{
248
if
(fp < stack_page+
sizeof
(
struct
thread_info
) ||
249
fp >= 8184+stack_page)
250
return
0;
251
pc = ((
unsigned
long
*)fp)[1];
252
if
(!
in_sched_functions
(pc))
253
return
pc;
254
fp = *(
unsigned
long
*) fp;
255
}
while
(count++ < 16);
256
return
0;
257
}
Generated on Thu Jan 10 2013 12:52:22 for Linux Kernel by
1.8.2