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
hexagon
kernel
process.c
Go to the documentation of this file.
1
/*
2
* Process creation support for Hexagon
3
*
4
* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
5
*
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License version 2 and
8
* only version 2 as published by the Free Software Foundation.
9
*
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
14
*
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18
* 02110-1301, USA.
19
*/
20
21
#include <linux/sched.h>
22
#include <linux/types.h>
23
#include <linux/module.h>
24
#include <
linux/tick.h
>
25
#include <
linux/uaccess.h
>
26
#include <linux/slab.h>
27
28
/*
29
* Kernel thread creation. The desired kernel function is "wrapped"
30
* in the kernel_thread_helper function, which does cleanup
31
* afterwards.
32
*/
33
static
void
__noreturn
kernel_thread_helper
(
void
*
arg
,
int
(*
fn
)(
void
*))
34
{
35
do_exit
(
fn
(arg));
36
}
37
38
int
kernel_thread
(
int
(*
fn
)(
void
*),
void
*arg,
unsigned
long
flags
)
39
{
40
struct
pt_regs
regs;
41
42
memset
(®s, 0,
sizeof
(regs));
43
/*
44
* Yes, we're exploting illicit knowledge of the ABI here.
45
*/
46
regs.
r00
= (
unsigned
long
) arg;
47
regs.
r01
= (
unsigned
long
)
fn
;
48
pt_set_elr
(®s, (
unsigned
long
)
kernel_thread_helper
);
49
pt_set_kmode
(®s);
50
51
return
do_fork
(flags|
CLONE_VM
|
CLONE_UNTRACED
, 0, ®s, 0,
NULL
,
NULL
);
52
}
53
EXPORT_SYMBOL
(
kernel_thread
);
54
55
/*
56
* Program thread launch. Often defined as a macro in processor.h,
57
* but we're shooting for a small footprint and it's not an inner-loop
58
* performance-critical operation.
59
*
60
* The Hexagon ABI specifies that R28 is zero'ed before program launch,
61
* so that gets automatically done here. If we ever stop doing that here,
62
* we'll probably want to define the ELF_PLAT_INIT macro.
63
*/
64
void
start_thread
(
struct
pt_regs
*
regs
,
unsigned
long
pc
,
unsigned
long
sp
)
65
{
66
/* Set to run with user-mode data segmentation */
67
set_fs
(
USER_DS
);
68
/* We want to zero all data-containing registers. Is this overkill? */
69
memset
(regs, 0,
sizeof
(*regs));
70
/* We might want to also zero all Processor registers here */
71
pt_set_usermode
(regs);
72
pt_set_elr
(regs, pc);
73
pt_set_rte_sp
(regs, sp);
74
}
75
76
/*
77
* Spin, or better still, do a hardware or VM wait instruction
78
* If hardware or VM offer wait termination even though interrupts
79
* are disabled.
80
*/
81
static
void
default_idle
(
void
)
82
{
83
__vmwait
();
84
}
85
86
void
(*
idle_sleep
)(
void
) = default_idle;
87
88
void
cpu_idle
(
void
)
89
{
90
while
(1) {
91
tick_nohz_idle_enter();
92
local_irq_disable
();
93
while
(!need_resched()) {
94
idle_sleep
();
95
/* interrupts wake us up, but aren't serviced */
96
local_irq_enable
();
/* service interrupt */
97
local_irq_disable
();
98
}
99
local_irq_enable
();
100
tick_nohz_idle_exit();
101
schedule
();
102
}
103
}
104
105
/*
106
* Return saved PC of a blocked thread
107
*/
108
unsigned
long
thread_saved_pc
(
struct
task_struct
*tsk)
109
{
110
return
0;
111
}
112
113
/*
114
* Copy architecture-specific thread state
115
*/
116
int
copy_thread
(
unsigned
long
clone_flags,
unsigned
long
usp
,
117
unsigned
long
unused
,
struct
task_struct
*
p
,
118
struct
pt_regs
*
regs
)
119
{
120
struct
thread_info
*ti =
task_thread_info
(p);
121
struct
hexagon_switch_stack
*
ss
;
122
struct
pt_regs
*childregs;
123
asmlinkage
void
ret_from_fork
(
void
);
124
125
childregs = (
struct
pt_regs
*) (((
unsigned
long
) ti +
THREAD_SIZE
) -
126
sizeof
(*childregs));
127
128
memcpy
(childregs, regs,
sizeof
(*childregs));
129
ti->regs = childregs;
130
131
/*
132
* Establish kernel stack pointer and initial PC for new thread
133
*/
134
ss = (
struct
hexagon_switch_stack
*) ((
unsigned
long
) childregs -
135
sizeof
(*ss));
136
ss->
lr
= (
unsigned
long
)ret_from_fork;
137
p->
thread
.switch_sp =
ss
;
138
139
/* If User mode thread, set pt_reg stack pointer as per parameter */
140
if
(
user_mode
(childregs)) {
141
pt_set_rte_sp
(childregs, usp);
142
143
/* Child sees zero return value */
144
childregs->
r00
= 0;
145
146
/*
147
* The clone syscall has the C signature:
148
* int [r0] clone(int flags [r0],
149
* void *child_frame [r1],
150
* void *parent_tid [r2],
151
* void *child_tid [r3],
152
* void *thread_control_block [r4]);
153
* ugp is used to provide TLS support.
154
*/
155
if
(clone_flags &
CLONE_SETTLS
)
156
childregs->
ugp
= childregs->
r04
;
157
158
/*
159
* Parent sees new pid -- not necessary, not even possible at
160
* this point in the fork process
161
* Might also want to set things like ti->addr_limit
162
*/
163
}
else
{
164
/*
165
* If kernel thread, resume stack is kernel stack base.
166
* Note that this is pointer arithmetic on pt_regs *
167
*/
168
pt_set_rte_sp
(childregs, (
unsigned
long
)(childregs + 1));
169
/*
170
* We need the current thread_info fast path pointer
171
* set up in pt_regs. The register to be used is
172
* parametric for assembler code, but the mechanism
173
* doesn't drop neatly into C. Needs to be fixed.
174
*/
175
childregs->THREADINFO_REG = (
unsigned
long
) ti;
176
}
177
178
/*
179
* thread_info pointer is pulled out of task_struct "stack"
180
* field on switch_to.
181
*/
182
p->
stack
= (
void
*)ti;
183
184
return
0;
185
}
186
187
/*
188
* Release any architecture-specific resources locked by thread
189
*/
190
void
release_thread
(
struct
task_struct
*dead_task)
191
{
192
}
193
194
/*
195
* Free any architecture-specific thread data structures, etc.
196
*/
197
void
exit_thread
(
void
)
198
{
199
}
200
201
/*
202
* Some archs flush debug and FPU info here
203
*/
204
void
flush_thread
(
void
)
205
{
206
}
207
208
/*
209
* The "wait channel" terminology is archaic, but what we want
210
* is an identification of the point at which the scheduler
211
* was invoked by a blocked thread.
212
*/
213
unsigned
long
get_wchan
(
struct
task_struct
*
p
)
214
{
215
unsigned
long
fp
,
pc
;
216
unsigned
long
stack_page;
217
int
count
= 0;
218
if
(!p || p ==
current
|| p->
state
==
TASK_RUNNING
)
219
return
0;
220
221
stack_page = (
unsigned
long
)
task_stack_page
(p);
222
fp = ((
struct
hexagon_switch_stack
*)p->
thread
.switch_sp)->fp;
223
do
{
224
if
(fp < (stack_page +
sizeof
(
struct
thread_info
)) ||
225
fp >= (
THREAD_SIZE
- 8 + stack_page))
226
return
0;
227
pc = ((
unsigned
long
*)fp)[1];
228
if
(!
in_sched_functions
(pc))
229
return
pc;
230
fp = *(
unsigned
long
*) fp;
231
}
while
(count++ < 16);
232
233
return
0;
234
}
235
236
/*
237
* Required placeholder.
238
*/
239
int
dump_fpu
(
struct
pt_regs
*
regs
,
elf_fpregset_t
*
fpu
)
240
{
241
return
0;
242
}
Generated on Thu Jan 10 2013 12:52:22 for Linux Kernel by
1.8.2