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
frv
kernel
process.c
Go to the documentation of this file.
1
/* process.c: FRV specific parts of process handling
2
*
3
* Copyright (C) 2003-5 Red Hat, Inc. All Rights Reserved.
4
* Written by David Howells (
[email protected]
)
5
* - Derived from arch/m68k/kernel/process.c
6
*
7
* This program is free software; you can redistribute it and/or
8
* modify it under the terms of the GNU General Public License
9
* as published by the Free Software Foundation; either version
10
* 2 of the License, or (at your option) any later version.
11
*/
12
13
#include <linux/module.h>
14
#include <linux/errno.h>
15
#include <linux/sched.h>
16
#include <linux/kernel.h>
17
#include <
linux/mm.h
>
18
#include <
linux/smp.h
>
19
#include <linux/stddef.h>
20
#include <
linux/unistd.h
>
21
#include <linux/ptrace.h>
22
#include <linux/slab.h>
23
#include <
linux/user.h
>
24
#include <linux/elf.h>
25
#include <linux/reboot.h>
26
#include <
linux/interrupt.h
>
27
#include <
linux/pagemap.h
>
28
#include <
linux/rcupdate.h
>
29
30
#include <asm/asm-offsets.h>
31
#include <asm/uaccess.h>
32
#include <asm/setup.h>
33
#include <asm/pgtable.h>
34
#include <asm/tlb.h>
35
#include <asm/gdb-stub.h>
36
#include <
asm/mb-regs.h
>
37
38
#include "
local.h
"
39
40
asmlinkage
void
ret_from_fork
(
void
);
41
asmlinkage
void
ret_from_kernel_thread
(
void
);
42
43
#include <asm/pgalloc.h>
44
45
void
(*
pm_power_off
)(
void
);
46
EXPORT_SYMBOL
(
pm_power_off
);
47
48
static
void
core_sleep_idle(
void
)
49
{
50
#ifdef LED_DEBUG_SLEEP
51
/* Show that we're sleeping... */
52
__set_LEDS
(0x55aa);
53
#endif
54
frv_cpu_core_sleep
();
55
#ifdef LED_DEBUG_SLEEP
56
/* ... and that we woke up */
57
__set_LEDS
(0);
58
#endif
59
mb
();
60
}
61
62
void
(*
idle
)(
void
) = core_sleep_idle;
63
64
/*
65
* The idle thread. There's no useful work to be
66
* done, so just try to conserve power and have a
67
* low exit latency (ie sit in a loop waiting for
68
* somebody to say that they'd like to reschedule)
69
*/
70
void
cpu_idle
(
void
)
71
{
72
/* endless idle loop with no priority at all */
73
while
(1) {
74
rcu_idle_enter
();
75
while
(!need_resched()) {
76
check_pgt_cache
();
77
78
if
(!
frv_dma_inprogress
&&
idle
)
79
idle
();
80
}
81
rcu_idle_exit
();
82
83
schedule_preempt_disabled
();
84
}
85
}
86
87
void
machine_restart
(
char
*
__unused
)
88
{
89
unsigned
long
reset_addr;
90
#ifdef CONFIG_GDBSTUB
91
gdbstub_exit
(0);
92
#endif
93
94
if
(
PSR_IMPLE
(
__get_PSR
()) ==
PSR_IMPLE_FR551
)
95
reset_addr = 0xfefff500;
96
else
97
reset_addr = 0xfeff0500;
98
99
/* Software reset. */
100
asm
volatile
(
" dcef @(gr0,gr0),1 ! membar !"
101
" sti %1,@(%0,0) !"
102
" nop ! nop ! nop ! nop ! nop ! "
103
" nop ! nop ! nop ! nop ! nop ! "
104
" nop ! nop ! nop ! nop ! nop ! "
105
" nop ! nop ! nop ! nop ! nop ! "
106
: :
"r"
(reset_addr),
"r"
(1) );
107
108
for
(;;)
109
;
110
}
111
112
void
machine_halt
(
void
)
113
{
114
#ifdef CONFIG_GDBSTUB
115
gdbstub_exit
(0);
116
#endif
117
118
for
(;;);
119
}
120
121
void
machine_power_off
(
void
)
122
{
123
#ifdef CONFIG_GDBSTUB
124
gdbstub_exit
(0);
125
#endif
126
127
for
(;;);
128
}
129
130
void
flush_thread
(
void
)
131
{
132
/* nothing */
133
}
134
135
inline
unsigned
long
user_stack
(
const
struct
pt_regs
*
regs
)
136
{
137
while
(regs->
next_frame
)
138
regs = regs->
next_frame
;
139
return
user_mode
(regs) ? regs->
sp
: 0;
140
}
141
142
asmlinkage
int
sys_fork
(
void
)
143
{
144
#ifndef CONFIG_MMU
145
/* fork almost works, enough to trick you into looking elsewhere:-( */
146
return
-
EINVAL
;
147
#else
148
return
do_fork
(
SIGCHLD
,
user_stack
(__frame), __frame, 0,
NULL
,
NULL
);
149
#endif
150
}
151
152
asmlinkage
int
sys_vfork
(
void
)
153
{
154
return
do_fork
(
CLONE_VFORK
|
CLONE_VM
|
SIGCHLD
,
user_stack
(__frame), __frame, 0,
155
NULL
,
NULL
);
156
}
157
158
/*****************************************************************************/
159
/*
160
* clone a process
161
* - tlsptr is retrieved by copy_thread()
162
*/
163
asmlinkage
int
sys_clone
(
unsigned
long
clone_flags,
unsigned
long
newsp,
164
int
__user *parent_tidptr,
int
__user *child_tidptr,
165
int
__user *tlsptr)
166
{
167
if
(!newsp)
168
newsp =
user_stack
(__frame);
169
return
do_fork
(clone_flags, newsp, __frame, 0, parent_tidptr, child_tidptr);
170
}
/* end sys_clone() */
171
172
/*
173
* set up the kernel stack and exception frames for a new process
174
*/
175
int
copy_thread
(
unsigned
long
clone_flags,
176
unsigned
long
usp,
unsigned
long
arg
,
177
struct
task_struct
*
p
,
struct
pt_regs
*
regs
)
178
{
179
struct
pt_regs
*childregs;
180
181
childregs = (
struct
pt_regs
*)
182
(
task_stack_page
(p) +
THREAD_SIZE
- FRV_FRAME0_SIZE);
183
184
/* set up the userspace frame (the only place that the USP is stored) */
185
*childregs = *
__kernel_frame0_ptr
;
186
187
p->
set_child_tid
= p->
clear_child_tid
=
NULL
;
188
189
p->
thread
.frame = childregs;
190
p->
thread
.curr =
p
;
191
p->
thread
.sp = (
unsigned
long
) childregs;
192
p->
thread
.fp = 0;
193
p->
thread
.lr = 0;
194
p->
thread
.frame0 = childregs;
195
196
if
(
unlikely
(!regs)) {
197
childregs->
gr9
=
usp
;
/* function */
198
childregs->
gr8
=
arg
;
199
p->
thread
.pc = (
unsigned
long
)
ret_from_kernel_thread
;
200
save_user_regs
(p->
thread
.user);
201
return
0;
202
}
203
204
/* set up the userspace frame (the only place that the USP is stored) */
205
*childregs = *
regs
;
206
207
childregs->
sp
=
usp
;
208
childregs->
next_frame
=
NULL
;
209
210
p->
thread
.pc = (
unsigned
long
)
ret_from_fork
;
211
212
/* the new TLS pointer is passed in as arg #5 to sys_clone() */
213
if
(clone_flags &
CLONE_SETTLS
)
214
childregs->
gr29
= childregs->
gr12
;
215
216
save_user_regs
(p->
thread
.user);
217
218
return
0;
219
}
/* end copy_thread() */
220
221
unsigned
long
get_wchan
(
struct
task_struct
*
p
)
222
{
223
struct
pt_regs
*regs0;
224
unsigned
long
fp
,
pc
;
225
unsigned
long
stack_limit;
226
int
count
= 0;
227
if
(!p || p ==
current
|| p->
state
==
TASK_RUNNING
)
228
return
0;
229
230
stack_limit = (
unsigned
long
) (p + 1);
231
fp = p->
thread
.fp;
232
regs0 = p->
thread
.frame0;
233
234
do
{
235
if
(fp < stack_limit || fp >= (
unsigned
long
) regs0 || fp & 3)
236
return
0;
237
238
pc = ((
unsigned
long
*) fp)[2];
239
240
/* FIXME: This depends on the order of these functions. */
241
if
(!
in_sched_functions
(pc))
242
return
pc;
243
244
fp = *(
unsigned
long
*) fp;
245
}
while
(count++ < 16);
246
247
return
0;
248
}
249
250
unsigned
long
thread_saved_pc
(
struct
task_struct
*tsk)
251
{
252
/* Check whether the thread is blocked in resume() */
253
if
(
in_sched_functions
(tsk->
thread
.pc))
254
return
((
unsigned
long
*)tsk->
thread
.fp)[2];
255
else
256
return
tsk->
thread
.pc;
257
}
258
259
int
elf_check_arch
(
const
struct
elf32_hdr
*
hdr
)
260
{
261
unsigned
long
hsr0 =
__get_HSR
(0);
262
unsigned
long
psr
=
__get_PSR
();
263
264
if
(hdr->
e_machine
!=
EM_FRV
)
265
return
0;
266
267
switch
(hdr->
e_flags
&
EF_FRV_GPR_MASK
) {
268
case
EF_FRV_GPR64
:
269
if
((hsr0 &
HSR0_GRN
) ==
HSR0_GRN_32
)
270
return
0;
271
case
EF_FRV_GPR32
:
272
case
0:
273
break
;
274
default
:
275
return
0;
276
}
277
278
switch
(hdr->
e_flags
&
EF_FRV_FPR_MASK
) {
279
case
EF_FRV_FPR64
:
280
if
((hsr0 &
HSR0_FRN
) ==
HSR0_FRN_32
)
281
return
0;
282
case
EF_FRV_FPR32
:
283
case
EF_FRV_FPR_NONE
:
284
case
0:
285
break
;
286
default
:
287
return
0;
288
}
289
290
if
((hdr->
e_flags
&
EF_FRV_MULADD
) ==
EF_FRV_MULADD
)
291
if
(
PSR_IMPLE
(psr) !=
PSR_IMPLE_FR405
&&
292
PSR_IMPLE
(psr) !=
PSR_IMPLE_FR451
)
293
return
0;
294
295
switch
(hdr->
e_flags
&
EF_FRV_CPU_MASK
) {
296
case
EF_FRV_CPU_GENERIC
:
297
break
;
298
case
EF_FRV_CPU_FR300
:
299
case
EF_FRV_CPU_SIMPLE
:
300
case
EF_FRV_CPU_TOMCAT
:
301
default
:
302
return
0;
303
case
EF_FRV_CPU_FR400
:
304
if
(
PSR_IMPLE
(psr) !=
PSR_IMPLE_FR401
&&
305
PSR_IMPLE
(psr) !=
PSR_IMPLE_FR405
&&
306
PSR_IMPLE
(psr) !=
PSR_IMPLE_FR451
&&
307
PSR_IMPLE
(psr) !=
PSR_IMPLE_FR551
)
308
return
0;
309
break
;
310
case
EF_FRV_CPU_FR450
:
311
if
(
PSR_IMPLE
(psr) !=
PSR_IMPLE_FR451
)
312
return
0;
313
break
;
314
case
EF_FRV_CPU_FR500
:
315
if
(
PSR_IMPLE
(psr) !=
PSR_IMPLE_FR501
)
316
return
0;
317
break
;
318
case
EF_FRV_CPU_FR550
:
319
if
(
PSR_IMPLE
(psr) !=
PSR_IMPLE_FR551
)
320
return
0;
321
break
;
322
}
323
324
return
1;
325
}
326
327
int
dump_fpu
(
struct
pt_regs
*
regs
,
elf_fpregset_t
*fpregs)
328
{
329
memcpy
(fpregs,
330
&
current
->thread.user->f,
331
sizeof
(
current
->thread.user->f));
332
return
1;
333
}
Generated on Thu Jan 10 2013 12:52:22 for Linux Kernel by
1.8.2