Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
Kernel
提交
cbf23cf1
K
Kernel
项目概览
openeuler
/
Kernel
1 年多 前同步成功
通知
8
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
Kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
cbf23cf1
编写于
10月 19, 2012
作者:
J
Jonas Bonn
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
openrisc: use generic kernel_thread/kernel_execve
Signed-off-by:
N
Jonas Bonn
<
jonas@southpole.se
>
上级
287ad220
变更
3
显示空白变更内容
内联
并排
Showing
3 changed file
with
68 addition
and
102 deletion
+68
-102
arch/openrisc/Kconfig
arch/openrisc/Kconfig
+2
-0
arch/openrisc/kernel/entry.S
arch/openrisc/kernel/entry.S
+10
-20
arch/openrisc/kernel/process.c
arch/openrisc/kernel/process.c
+56
-82
未找到文件。
arch/openrisc/Kconfig
浏览文件 @
cbf23cf1
...
...
@@ -22,6 +22,8 @@ config OPENRISC
select GENERIC_STRNCPY_FROM_USER
select GENERIC_STRNLEN_USER
select MODULES_USE_ELF_RELA
select GENERIC_KERNEL_THREAD
select GENERIC_KERNEL_EXECVE
config MMU
def_bool y
...
...
arch/openrisc/kernel/entry.S
浏览文件 @
cbf23cf1
...
...
@@ -894,6 +894,16 @@ ENTRY(ret_from_fork)
l.jal
schedule_tail
l.nop
/
*
Check
if
we
are
a
kernel
thread
*/
l.sfeqi
r20
,
0
l.bf
1
f
l.nop
/
*
...
we
are
a
kernel
thread
so
invoke
the
requested
callback
*/
l.jalr
r20
l.or
r3
,
r22
,
r0
1
:
/
*
_syscall_returns
expect
r11
to
contain
return
value
*/
l.lwz
r11
,
PT_GPR11
(
r1
)
...
...
@@ -915,26 +925,6 @@ ENTRY(ret_from_fork)
l.j
_syscall_return
l.nop
/*
Since
syscalls
don
't save call-clobbered registers, the args to
*
kernel_thread_helper
will
need
to
be
passed
through
callee
-
saved
*
registers
and
copied
to
the
parameter
registers
when
the
thread
*
begins
running
.
*
*
See
arch
/
openrisc
/
kernel
/
process
.
c
:
*
The
args
are
passed
as
follows
:
*
arg1
(
r3
)
:
passed
in
r20
*
arg2
(
r4
)
:
passed
in
r22
*/
ENTRY
(
_kernel_thread_helper
)
l.or
r3
,
r20
,
r0
l.or
r4
,
r22
,
r0
l.movhi
r31
,
hi
(
kernel_thread_helper
)
l.ori
r31
,
r31
,
lo
(
kernel_thread_helper
)
l.jr
r31
l.nop
/*
========================================================
[
switch
]
===
*/
/*
...
...
arch/openrisc/kernel/process.c
浏览文件 @
cbf23cf1
...
...
@@ -109,65 +109,82 @@ void release_thread(struct task_struct *dead_task)
*/
extern
asmlinkage
void
ret_from_fork
(
void
);
/*
* copy_thread
* @clone_flags: flags
* @usp: user stack pointer or fn for kernel thread
* @arg: arg to fn for kernel thread; always NULL for userspace thread
* @p: the newly created task
* @regs: CPU context to copy for userspace thread; always NULL for kthread
*
* At the top of a newly initialized kernel stack are two stacked pt_reg
* structures. The first (topmost) is the userspace context of the thread.
* The second is the kernelspace context of the thread.
*
* A kernel thread will not be returning to userspace, so the topmost pt_regs
* struct can be uninitialized; it _does_ need to exist, though, because
* a kernel thread can become a userspace thread by doing a kernel_execve, in
* which case the topmost context will be initialized and used for 'returning'
* to userspace.
*
* The second pt_reg struct needs to be initialized to 'return' to
* ret_from_fork. A kernel thread will need to set r20 to the address of
* a function to call into (with arg in r22); userspace threads need to set
* r20 to NULL in which case ret_from_fork will just continue a return to
* userspace.
*
* A kernel thread 'fn' may return; this is effectively what happens when
* kernel_execve is called. In that case, the userspace pt_regs must have
* been initialized (which kernel_execve takes care of, see start_thread
* below); ret_from_fork will then continue its execution causing the
* 'kernel thread' to return to userspace as a userspace thread.
*/
int
copy_thread
(
unsigned
long
clone_flags
,
unsigned
long
usp
,
unsigned
long
unused
,
struct
task_struct
*
p
,
struct
pt_regs
*
regs
)
unsigned
long
arg
,
struct
task_struct
*
p
,
struct
pt_regs
*
regs
)
{
struct
pt_regs
*
child
regs
;
struct
pt_regs
*
user
regs
;
struct
pt_regs
*
kregs
;
unsigned
long
sp
=
(
unsigned
long
)
task_stack_page
(
p
)
+
THREAD_SIZE
;
struct
thread_info
*
ti
;
unsigned
long
top_of_kernel_stack
;
top_of_kernel_stack
=
sp
;
p
->
set_child_tid
=
p
->
clear_child_tid
=
NULL
;
/* Copy registers */
/* redzone */
sp
-=
STACK_FRAME_OVERHEAD
;
/* Locate userspace context on stack... */
sp
-=
STACK_FRAME_OVERHEAD
;
/* redzone */
sp
-=
sizeof
(
struct
pt_regs
);
childregs
=
(
struct
pt_regs
*
)
sp
;
userregs
=
(
struct
pt_regs
*
)
sp
;
/* Copy parent registers */
*
childregs
=
*
regs
;
/* ...and kernel context */
sp
-=
STACK_FRAME_OVERHEAD
;
/* redzone */
sp
-=
sizeof
(
struct
pt_regs
);
kregs
=
(
struct
pt_regs
*
)
sp
;
if
((
childregs
->
sr
&
SPR_SR_SM
)
==
1
)
{
/* for kernel thread, set `current_thread_info'
* and stackptr in new task
*/
childregs
->
sp
=
(
unsigned
long
)
task_stack_page
(
p
)
+
THREAD_SIZE
;
childregs
->
gpr
[
10
]
=
(
unsigned
long
)
task_thread_info
(
p
);
if
(
unlikely
(
p
->
flags
&
PF_KTHREAD
))
{
memset
(
kregs
,
0
,
sizeof
(
struct
pt_regs
));
kregs
->
gpr
[
20
]
=
usp
;
/* fn, kernel thread */
kregs
->
gpr
[
22
]
=
arg
;
}
else
{
childregs
->
sp
=
usp
;
}
*
userregs
=
*
regs
;
childregs
->
gpr
[
11
]
=
0
;
/* Result from fork() */
userregs
->
sp
=
usp
;
userregs
->
gpr
[
11
]
=
0
;
/* Result from fork() */
/*
* The way this works is that at some point in the future
* some task will call _switch to switch to the new task.
* That will pop off the stack frame created below and start
* the new task running at ret_from_fork. The new task will
* do some house keeping and then return from the fork or clone
* system call, using the stack frame created above.
*/
/* redzone */
sp
-=
STACK_FRAME_OVERHEAD
;
sp
-=
sizeof
(
struct
pt_regs
);
kregs
=
(
struct
pt_regs
*
)
sp
;
ti
=
task_thread_info
(
p
);
ti
->
ksp
=
sp
;
kregs
->
gpr
[
20
]
=
0
;
/* Userspace thread */
}
/*
kregs->sp must store the location of the 'pre-switch' kernel stack
*
pointer... for a newly forked process, this is simply the top of
*
the kernel stack
.
/*
*
_switch wants the kernel stack page in pt_regs->sp so that it
*
can restore it to thread_info->ksp... see _switch for details
.
*/
kregs
->
sp
=
top_of_kernel_stack
;
kregs
->
gpr
[
10
]
=
(
unsigned
long
)
task_thread_info
(
p
);
kregs
->
gpr
[
9
]
=
(
unsigned
long
)
ret_from_fork
;
task_thread_info
(
p
)
->
ksp
=
(
unsigned
long
)
kregs
;
return
0
;
}
...
...
@@ -176,16 +193,14 @@ copy_thread(unsigned long clone_flags, unsigned long usp,
*/
void
start_thread
(
struct
pt_regs
*
regs
,
unsigned
long
pc
,
unsigned
long
sp
)
{
unsigned
long
sr
=
regs
->
sr
&
~
SPR_SR_SM
;
unsigned
long
sr
=
mfspr
(
SPR_SR
)
&
~
SPR_SR_SM
;
set_fs
(
USER_DS
);
memset
(
regs
->
gpr
,
0
,
sizeof
(
regs
->
gpr
));
memset
(
regs
,
0
,
sizeof
(
struct
pt_regs
));
regs
->
pc
=
pc
;
regs
->
sr
=
sr
;
regs
->
sp
=
sp
;
/* printk("start thread, ksp = %lx\n", current_thread_info()->ksp);*/
}
/* Fill in the fpu structure for a core dump. */
...
...
@@ -236,31 +251,6 @@ void dump_elf_thread(elf_greg_t *dest, struct pt_regs* regs)
dest
[
35
]
=
0
;
}
extern
void
_kernel_thread_helper
(
void
);
void
__noreturn
kernel_thread_helper
(
int
(
*
fn
)
(
void
*
),
void
*
arg
)
{
do_exit
(
fn
(
arg
));
}
/*
* Create a kernel thread.
*/
int
kernel_thread
(
int
(
*
fn
)
(
void
*
),
void
*
arg
,
unsigned
long
flags
)
{
struct
pt_regs
regs
;
memset
(
&
regs
,
0
,
sizeof
(
regs
));
regs
.
gpr
[
20
]
=
(
unsigned
long
)
fn
;
regs
.
gpr
[
22
]
=
(
unsigned
long
)
arg
;
regs
.
sr
=
mfspr
(
SPR_SR
);
regs
.
pc
=
(
unsigned
long
)
_kernel_thread_helper
;
return
do_fork
(
flags
|
CLONE_VM
|
CLONE_UNTRACED
,
0
,
&
regs
,
0
,
NULL
,
NULL
);
}
/*
* sys_execve() executes a new program.
*/
...
...
@@ -291,19 +281,3 @@ unsigned long get_wchan(struct task_struct *p)
return
0
;
}
int
kernel_execve
(
const
char
*
filename
,
char
*
const
argv
[],
char
*
const
envp
[])
{
register
long
__res
asm
(
"r11"
)
=
__NR_execve
;
register
long
__a
asm
(
"r3"
)
=
(
long
)(
filename
);
register
long
__b
asm
(
"r4"
)
=
(
long
)(
argv
);
register
long
__c
asm
(
"r5"
)
=
(
long
)(
envp
);
__asm__
volatile
(
"l.sys 1"
:
"=r"
(
__res
),
"=r"
(
__a
),
"=r"
(
__b
),
"=r"
(
__c
)
:
"0"
(
__res
),
"1"
(
__a
),
"2"
(
__b
),
"3"
(
__c
)
:
"r6"
,
"r7"
,
"r8"
,
"r12"
,
"r13"
,
"r15"
,
"r17"
,
"r19"
,
"r21"
,
"r23"
,
"r25"
,
"r27"
,
"r29"
,
"r31"
);
__asm__
volatile
(
"l.nop"
);
return
__res
;
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录