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