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
cris
arch-v10
kernel
process.c
Go to the documentation of this file.
1
/*
2
* linux/arch/cris/kernel/process.c
3
*
4
* Copyright (C) 1995 Linus Torvalds
5
* Copyright (C) 2000-2002 Axis Communications AB
6
*
7
* Authors: Bjorn Wesen (
[email protected]
)
8
* Mikael Starvik (
[email protected]
)
9
*
10
* This file handles the architecture-dependent parts of process handling..
11
*/
12
13
#include <linux/sched.h>
14
#include <linux/slab.h>
15
#include <
linux/err.h
>
16
#include <linux/fs.h>
17
#include <
arch/svinto.h
>
18
#include <
linux/init.h
>
19
#include <arch/system.h>
20
21
#ifdef CONFIG_ETRAX_GPIO
22
void
etrax_gpio_wake_up_check
(
void
);
/* drivers/gpio.c */
23
#endif
24
25
/*
26
* We use this if we don't have any better
27
* idle routine..
28
*/
29
void
default_idle
(
void
)
30
{
31
#ifdef CONFIG_ETRAX_GPIO
32
etrax_gpio_wake_up_check
();
33
#endif
34
}
35
36
/*
37
* Free current thread data structures etc..
38
*/
39
40
void
exit_thread
(
void
)
41
{
42
/* Nothing needs to be done. */
43
}
44
45
/* if the watchdog is enabled, we can simply disable interrupts and go
46
* into an eternal loop, and the watchdog will reset the CPU after 0.1s
47
* if on the other hand the watchdog wasn't enabled, we just enable it and wait
48
*/
49
50
void
hard_reset_now
(
void
)
51
{
52
/*
53
* Don't declare this variable elsewhere. We don't want any other
54
* code to know about it than the watchdog handler in entry.S and
55
* this code, implementing hard reset through the watchdog.
56
*/
57
#if defined(CONFIG_ETRAX_WATCHDOG) && !defined(CONFIG_SVINTO_SIM)
58
extern
int
cause_of_death;
59
#endif
60
61
printk
(
"*** HARD RESET ***\n"
);
62
local_irq_disable
();
63
64
#if defined(CONFIG_ETRAX_WATCHDOG) && !defined(CONFIG_SVINTO_SIM)
65
cause_of_death = 0xbedead;
66
#else
67
/* Since we dont plan to keep on resetting the watchdog,
68
the key can be arbitrary hence three */
69
*R_WATCHDOG =
IO_FIELD
(R_WATCHDOG,
key
, 3) |
70
IO_STATE
(R_WATCHDOG,
enable
,
start
);
71
#endif
72
73
while
(1)
/* waiting for RETRIBUTION! */
;
74
}
75
76
/*
77
* Return saved PC of a blocked thread.
78
*/
79
unsigned
long
thread_saved_pc
(
struct
task_struct
*
t
)
80
{
81
return
task_pt_regs
(t)->irp;
82
}
83
84
static
void
kernel_thread_helper
(
void
*
dummy
,
int
(*
fn
)(
void
*),
void
*
arg
)
85
{
86
fn
(arg);
87
do_exit
(-1);
/* Should never be called, return bad exit value */
88
}
89
90
/*
91
* Create a kernel thread
92
*/
93
int
kernel_thread
(
int
(*
fn
)(
void
*),
void
*
arg
,
unsigned
long
flags
)
94
{
95
struct
pt_regs
regs;
96
97
memset
(®s, 0,
sizeof
(regs));
98
99
/* Don't use r10 since that is set to 0 in copy_thread */
100
regs.
r11
= (
unsigned
long
)
fn
;
101
regs.
r12
= (
unsigned
long
)arg;
102
regs.
irp
= (
unsigned
long
)
kernel_thread_helper
;
103
regs.
dccr
= 1 <<
I_DCCR_BITNR
;
104
105
/* Ok, create the new process.. */
106
return
do_fork
(flags |
CLONE_VM
|
CLONE_UNTRACED
, 0, ®s, 0,
NULL
,
NULL
);
107
}
108
109
/* setup the child's kernel stack with a pt_regs and switch_stack on it.
110
* it will be un-nested during _resume and _ret_from_sys_call when the
111
* new thread is scheduled.
112
*
113
* also setup the thread switching structure which is used to keep
114
* thread-specific data during _resumes.
115
*
116
*/
117
asmlinkage
void
ret_from_fork
(
void
);
118
119
int
copy_thread
(
unsigned
long
clone_flags,
unsigned
long
usp
,
120
unsigned
long
unused
,
121
struct
task_struct
*
p
,
struct
pt_regs
*
regs
)
122
{
123
struct
pt_regs
* childregs;
124
struct
switch_stack
*swstack;
125
126
/* put the pt_regs structure at the end of the new kernel stack page and fix it up
127
* remember that the task_struct doubles as the kernel stack for the task
128
*/
129
130
childregs =
task_pt_regs
(p);
131
132
*childregs = *
regs
;
/* struct copy of pt_regs */
133
134
p->
set_child_tid
= p->
clear_child_tid
=
NULL
;
135
136
childregs->
r10
= 0;
/* child returns 0 after a fork/clone */
137
138
/* put the switch stack right below the pt_regs */
139
140
swstack = ((
struct
switch_stack
*)childregs) - 1;
141
142
swstack->
r9
= 0;
/* parameter to ret_from_sys_call, 0 == dont restart the syscall */
143
144
/* we want to return into ret_from_sys_call after the _resume */
145
146
swstack->
return_ip
= (
unsigned
long
)
ret_from_fork
;
/* Will call ret_from_sys_call */
147
148
/* fix the user-mode stackpointer */
149
150
p->
thread
.usp = usp;
151
152
/* and the kernel-mode one */
153
154
p->
thread
.ksp = (
unsigned
long
) swstack;
155
156
#ifdef DEBUG
157
printk
(
"copy_thread: new regs at 0x%p, as shown below:\n"
, childregs);
158
show_registers
(childregs);
159
#endif
160
161
return
0;
162
}
163
164
/*
165
* Be aware of the "magic" 7th argument in the four system-calls below.
166
* They need the latest stackframe, which is put as the 7th argument by
167
* entry.S. The previous arguments are dummies or actually used, but need
168
* to be defined to reach the 7th argument.
169
*
170
* N.B.: Another method to get the stackframe is to use current_regs(). But
171
* it returns the latest stack-frame stacked when going from _user mode_ and
172
* some of these (at least sys_clone) are called from kernel-mode sometimes
173
* (for example during kernel_thread, above) and thus cannot use it. Thus,
174
* to be sure not to get any surprises, we use the method for the other calls
175
* as well.
176
*/
177
178
asmlinkage
int
sys_fork
(
long
r10
,
long
r11
,
long
r12
,
long
r13
,
long
mof,
long
srp,
179
struct
pt_regs
*
regs
)
180
{
181
return
do_fork
(
SIGCHLD
, rdusp(), regs, 0,
NULL
,
NULL
);
182
}
183
184
/* if newusp is 0, we just grab the old usp */
185
/* FIXME: Is parent_tid/child_tid really third/fourth argument? Update lib? */
186
asmlinkage
int
sys_clone
(
unsigned
long
newusp,
unsigned
long
flags
,
187
int
* parent_tid,
int
* child_tid,
long
mof,
long
srp,
188
struct
pt_regs
*
regs
)
189
{
190
if
(!newusp)
191
newusp = rdusp();
192
return
do_fork
(flags, newusp, regs, 0, parent_tid, child_tid);
193
}
194
195
/* vfork is a system call in i386 because of register-pressure - maybe
196
* we can remove it and handle it in libc but we put it here until then.
197
*/
198
199
asmlinkage
int
sys_vfork
(
long
r10
,
long
r11
,
long
r12
,
long
r13
,
long
mof,
long
srp,
200
struct
pt_regs
*
regs
)
201
{
202
return
do_fork
(
CLONE_VFORK
|
CLONE_VM
|
SIGCHLD
, rdusp(), regs, 0,
NULL
,
NULL
);
203
}
204
205
/*
206
* sys_execve() executes a new program.
207
*/
208
asmlinkage
int
sys_execve
(
const
char
*
fname
,
209
const
char
*
const
*argv,
210
const
char
*
const
*envp,
211
long
r13
,
long
mof,
long
srp,
212
struct
pt_regs
*
regs
)
213
{
214
int
error
;
215
struct
filename
*
filename
;
216
217
filename =
getname
(fname);
218
error = PTR_ERR(filename);
219
220
if
(IS_ERR(filename))
221
goto
out
;
222
error =
do_execve
(filename->
name
, argv, envp, regs);
223
putname
(filename);
224
out
:
225
return
error
;
226
}
227
228
unsigned
long
get_wchan
(
struct
task_struct
*
p
)
229
{
230
#if 0
231
/* YURGH. TODO. */
232
233
unsigned
long
ebp,
esp
, eip;
234
unsigned
long
stack_page;
235
int
count
= 0;
236
if
(!p || p ==
current
|| p->
state
==
TASK_RUNNING
)
237
return
0;
238
stack_page = (
unsigned
long
)p;
239
esp = p->
thread
.esp;
240
if
(!stack_page ||
esp < stack_page || esp >
8188+stack_page)
241
return
0;
242
/* include/asm-i386/system.h:switch_to() pushes ebp last. */
243
ebp = *(
unsigned
long
*) esp;
244
do
{
245
if
(ebp < stack_page || ebp > 8184+stack_page)
246
return
0;
247
eip = *(
unsigned
long
*) (ebp+4);
248
if
(!
in_sched_functions
(eip))
249
return
eip;
250
ebp = *(
unsigned
long
*) ebp;
251
}
while
(count++ < 16);
252
#endif
253
return
0;
254
}
255
#undef last_sched
256
#undef first_sched
257
258
void
show_regs
(
struct
pt_regs
*
regs
)
259
{
260
unsigned
long
usp = rdusp();
261
printk
(
"IRP: %08lx SRP: %08lx DCCR: %08lx USP: %08lx MOF: %08lx\n"
,
262
regs->
irp
, regs->
srp
, regs->
dccr
, usp, regs->
mof
);
263
printk
(
" r0: %08lx r1: %08lx r2: %08lx r3: %08lx\n"
,
264
regs->
r0
, regs->
r1
, regs->
r2
, regs->
r3
);
265
printk
(
" r4: %08lx r5: %08lx r6: %08lx r7: %08lx\n"
,
266
regs->
r4
, regs->
r5
, regs->
r6
, regs->
r7
);
267
printk
(
" r8: %08lx r9: %08lx r10: %08lx r11: %08lx\n"
,
268
regs->
r8
, regs->
r9
, regs->
r10
, regs->
r11
);
269
printk
(
"r12: %08lx r13: %08lx oR10: %08lx\n"
,
270
regs->
r12
, regs->
r13
, regs->
orig_r10
);
271
}
272
Generated on Thu Jan 10 2013 12:52:21 for Linux Kernel by
1.8.2