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
openrisc
kernel
process.c
Go to the documentation of this file.
1
/*
2
* OpenRISC process.c
3
*
4
* Linux architectural port borrowing liberally from similar works of
5
* others. All original copyrights apply as per the original source
6
* declaration.
7
*
8
* Modifications for the OpenRISC architecture:
9
* Copyright (C) 2003 Matjaz Breskvar <
[email protected]
>
10
* Copyright (C) 2010-2011 Jonas Bonn <
[email protected]
>
11
*
12
* This program is free software; you can redistribute it and/or
13
* modify it under the terms of the GNU General Public License
14
* as published by the Free Software Foundation; either version
15
* 2 of the License, or (at your option) any later version.
16
*
17
* This file handles the architecture-dependent parts of process handling...
18
*/
19
20
#define __KERNEL_SYSCALLS__
21
#include <stdarg.h>
22
23
#include <linux/errno.h>
24
#include <linux/sched.h>
25
#include <linux/kernel.h>
26
#include <linux/module.h>
27
#include <
linux/mm.h
>
28
#include <linux/stddef.h>
29
#include <
linux/unistd.h
>
30
#include <linux/ptrace.h>
31
#include <linux/slab.h>
32
#include <linux/elfcore.h>
33
#include <
linux/interrupt.h
>
34
#include <
linux/delay.h
>
35
#include <
linux/init_task.h
>
36
#include <
linux/mqueue.h
>
37
#include <linux/fs.h>
38
39
#include <asm/uaccess.h>
40
#include <asm/pgtable.h>
41
#include <asm/io.h>
42
#include <asm/processor.h>
43
#include <
asm/spr_defs.h
>
44
45
#include <
linux/smp.h
>
46
47
/*
48
* Pointer to Current thread info structure.
49
*
50
* Used at user space -> kernel transitions.
51
*/
52
struct
thread_info
*
current_thread_info_set
[
NR_CPUS
] = { &
init_thread_info
, };
53
54
void
machine_restart
(
void
)
55
{
56
printk
(
KERN_INFO
"*** MACHINE RESTART ***\n"
);
57
__asm__
(
"l.nop 1"
);
58
}
59
60
/*
61
* Similar to machine_power_off, but don't shut off power. Add code
62
* here to freeze the system for e.g. post-mortem debug purpose when
63
* possible. This halt has nothing to do with the idle halt.
64
*/
65
void
machine_halt
(
void
)
66
{
67
printk
(
KERN_INFO
"*** MACHINE HALT ***\n"
);
68
__asm__
(
"l.nop 1"
);
69
}
70
71
/* If or when software power-off is implemented, add code here. */
72
void
machine_power_off
(
void
)
73
{
74
printk
(
KERN_INFO
"*** MACHINE POWER OFF ***\n"
);
75
__asm__
(
"l.nop 1"
);
76
}
77
78
void
(*
pm_power_off
) (
void
) =
machine_power_off
;
79
80
/*
81
* When a process does an "exec", machine state like FPU and debug
82
* registers need to be reset. This is a hook function for that.
83
* Currently we don't have any such state to reset, so this is empty.
84
*/
85
void
flush_thread
(
void
)
86
{
87
}
88
89
void
show_regs
(
struct
pt_regs
*
regs
)
90
{
91
extern
void
show_registers
(
struct
pt_regs
*regs);
92
93
/* __PHX__ cleanup this mess */
94
show_registers
(regs);
95
}
96
97
unsigned
long
thread_saved_pc
(
struct
task_struct
*
t
)
98
{
99
return
(
unsigned
long
)
user_regs
(t->
stack
)->pc;
100
}
101
102
void
release_thread
(
struct
task_struct
*dead_task)
103
{
104
}
105
106
/*
107
* Copy the thread-specific (arch specific) info from the current
108
* process to the new one p
109
*/
110
extern
asmlinkage
void
ret_from_fork
(
void
);
111
112
int
113
copy_thread
(
unsigned
long
clone_flags,
unsigned
long
usp,
114
unsigned
long
unused
,
struct
task_struct
*
p
,
struct
pt_regs
*
regs
)
115
{
116
struct
pt_regs
*childregs;
117
struct
pt_regs
*kregs;
118
unsigned
long
sp
= (
unsigned
long
)
task_stack_page
(p) +
THREAD_SIZE
;
119
struct
thread_info
*ti;
120
unsigned
long
top_of_kernel_stack;
121
122
top_of_kernel_stack =
sp
;
123
124
p->
set_child_tid
= p->
clear_child_tid
=
NULL
;
125
126
/* Copy registers */
127
/* redzone */
128
sp -=
STACK_FRAME_OVERHEAD
;
129
sp -=
sizeof
(
struct
pt_regs
);
130
childregs = (
struct
pt_regs
*)sp;
131
132
/* Copy parent registers */
133
*childregs = *
regs
;
134
135
if
((childregs->
sr
&
SPR_SR_SM
) == 1) {
136
/* for kernel thread, set `current_thread_info'
137
* and stackptr in new task
138
*/
139
childregs->
sp
= (
unsigned
long
)
task_stack_page
(p) +
THREAD_SIZE
;
140
childregs->
gpr
[10] = (
unsigned
long
)
task_thread_info
(p);
141
}
else
{
142
childregs->
sp
=
usp
;
143
}
144
145
childregs->
gpr
[11] = 0;
/* Result from fork() */
146
147
/*
148
* The way this works is that at some point in the future
149
* some task will call _switch to switch to the new task.
150
* That will pop off the stack frame created below and start
151
* the new task running at ret_from_fork. The new task will
152
* do some house keeping and then return from the fork or clone
153
* system call, using the stack frame created above.
154
*/
155
/* redzone */
156
sp -=
STACK_FRAME_OVERHEAD
;
157
sp -=
sizeof
(
struct
pt_regs
);
158
kregs = (
struct
pt_regs
*)sp;
159
160
ti =
task_thread_info
(p);
161
ti->ksp =
sp
;
162
163
/* kregs->sp must store the location of the 'pre-switch' kernel stack
164
* pointer... for a newly forked process, this is simply the top of
165
* the kernel stack.
166
*/
167
kregs->
sp
= top_of_kernel_stack;
168
kregs->
gpr
[3] = (
unsigned
long
)
current
;
/* arg to schedule_tail */
169
kregs->
gpr
[10] = (
unsigned
long
)
task_thread_info
(p);
170
kregs->
gpr
[9] = (
unsigned
long
)
ret_from_fork
;
171
172
return
0;
173
}
174
175
/*
176
* Set up a thread for executing a new program
177
*/
178
void
start_thread
(
struct
pt_regs
*
regs
,
unsigned
long
pc
,
unsigned
long
sp
)
179
{
180
unsigned
long
sr
= regs->
sr
& ~
SPR_SR_SM
;
181
182
set_fs
(
USER_DS
);
183
memset
(regs->
gpr
, 0,
sizeof
(regs->
gpr
));
184
185
regs->
pc
=
pc
;
186
regs->
sr
=
sr
;
187
regs->
sp
=
sp
;
188
189
/* printk("start thread, ksp = %lx\n", current_thread_info()->ksp);*/
190
}
191
192
/* Fill in the fpu structure for a core dump. */
193
int
dump_fpu
(
struct
pt_regs
*
regs
,
elf_fpregset_t
*
fpu
)
194
{
195
/* TODO */
196
return
0;
197
}
198
199
extern
struct
thread_info
*
_switch
(
struct
thread_info
*old_ti,
200
struct
thread_info
*new_ti);
201
202
struct
task_struct
*
__switch_to
(
struct
task_struct
*old,
203
struct
task_struct
*
new
)
204
{
205
struct
task_struct
*
last
;
206
struct
thread_info
*new_ti, *old_ti;
207
unsigned
long
flags
;
208
209
local_irq_save
(flags);
210
211
/* current_set is an array of saved current pointers
212
* (one for each cpu). we need them at user->kernel transition,
213
* while we save them at kernel->user transition
214
*/
215
new_ti =
new
->stack;
216
old_ti = old->
stack
;
217
218
current_thread_info_set[
smp_processor_id
()] = new_ti;
219
last = (
_switch
(old_ti, new_ti))->
task
;
220
221
local_irq_restore
(flags);
222
223
return
last;
224
}
225
226
/*
227
* Write out registers in core dump format, as defined by the
228
* struct user_regs_struct
229
*/
230
void
dump_elf_thread
(
elf_greg_t
*
dest
,
struct
pt_regs
*
regs
)
231
{
232
dest[0] = 0;
/* r0 */
233
memcpy
(dest+1, regs->
gpr
+1, 31*
sizeof
(
unsigned
long
));
234
dest[32] = regs->
pc
;
235
dest[33] = regs->
sr
;
236
dest[34] = 0;
237
dest[35] = 0;
238
}
239
240
extern
void
_kernel_thread_helper
(
void
);
241
242
void
__noreturn
kernel_thread_helper
(
int
(*
fn
) (
void
*),
void
*
arg
)
243
{
244
do_exit
(
fn
(arg));
245
}
246
247
/*
248
* Create a kernel thread.
249
*/
250
int
kernel_thread
(
int
(*
fn
) (
void
*),
void
*
arg
,
unsigned
long
flags
)
251
{
252
struct
pt_regs
regs;
253
254
memset
(®s, 0,
sizeof
(regs));
255
256
regs.
gpr
[20] = (
unsigned
long
)
fn
;
257
regs.
gpr
[22] = (
unsigned
long
)arg;
258
regs.
sr
=
mfspr
(
SPR_SR
);
259
regs.
pc
= (
unsigned
long
)
_kernel_thread_helper
;
260
261
return
do_fork
(flags |
CLONE_VM
|
CLONE_UNTRACED
,
262
0, ®s, 0,
NULL
,
NULL
);
263
}
264
265
/*
266
* sys_execve() executes a new program.
267
*/
268
asmlinkage
long
_sys_execve
(
const
char
__user *
name
,
269
const
char
__user *
const
__user *argv,
270
const
char
__user *
const
__user *envp,
271
struct
pt_regs
*
regs
)
272
{
273
int
error
;
274
struct
filename
*
filename
;
275
276
filename =
getname
(name);
277
error = PTR_ERR(filename);
278
279
if
(IS_ERR(filename))
280
goto
out
;
281
282
error =
do_execve
(filename->
name
, argv, envp, regs);
283
putname
(filename);
284
285
out
:
286
return
error
;
287
}
288
289
unsigned
long
get_wchan
(
struct
task_struct
*
p
)
290
{
291
/* TODO */
292
293
return
0;
294
}
295
296
int
kernel_execve
(
const
char
*
filename
,
char
*
const
argv[],
char
*
const
envp[])
297
{
298
register
long
__res
asm
(
"r11"
) =
__NR_execve
;
299
register
long
__a
asm
(
"r3"
) = (
long
)(
filename
);
300
register
long
__b
asm
(
"r4"
) = (
long
)(argv);
301
register
long
__c
asm
(
"r5"
) = (
long
)(envp);
302
__asm__
volatile
(
"l.sys 1"
303
:
"=r"
(__res),
"=r"
(__a),
"=r"
(__b),
"=r"
(__c)
304
:
"0"
(__res),
"1"
(__a),
"2"
(__b),
"3"
(__c)
305
:
"r6"
,
"r7"
,
"r8"
,
"r12"
,
"r13"
,
"r15"
,
306
"r17"
,
"r19"
,
"r21"
,
"r23"
,
"r25"
,
"r27"
,
307
"r29"
,
"r31"
);
308
__asm__
volatile
(
"l.nop"
);
309
return
__res;
310
}
Generated on Thu Jan 10 2013 12:52:24 for Linux Kernel by
1.8.2