Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
94b28de4
Commit
94b28de4
authored
Nov 16, 2012
by
Al Viro
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'arch-ia64' into no-rebases
parents
c09c5ad4
71b4ecc3
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
84 additions
and
145 deletions
+84
-145
arch/ia64/Kconfig
arch/ia64/Kconfig
+2
-0
arch/ia64/include/asm/processor.h
arch/ia64/include/asm/processor.h
+0
-16
arch/ia64/include/asm/unistd.h
arch/ia64/include/asm/unistd.h
+1
-0
arch/ia64/kernel/entry.S
arch/ia64/kernel/entry.S
+23
-16
arch/ia64/kernel/head.S
arch/ia64/kernel/head.S
+0
-13
arch/ia64/kernel/process.c
arch/ia64/kernel/process.c
+58
-100
No files found.
arch/ia64/Kconfig
View file @
94b28de4
...
...
@@ -42,6 +42,8 @@ config IA64
select GENERIC_TIME_VSYSCALL_OLD
select HAVE_MOD_ARCH_SPECIFIC
select MODULES_USE_ELF_RELA
select GENERIC_KERNEL_THREAD
select GENERIC_KERNEL_EXECVE
default y
help
The Itanium Processor Family is Intel's 64-bit successor to
...
...
arch/ia64/include/asm/processor.h
View file @
94b28de4
...
...
@@ -340,22 +340,6 @@ struct task_struct;
*/
#define release_thread(dead_task)
/*
* This is the mechanism for creating a new kernel thread.
*
* NOTE 1: Only a kernel-only process (ie the swapper or direct
* descendants who haven't done an "execve()") should use this: it
* will work within a system call from a "real" process, but the
* process memory space will not be free'd until both the parent and
* the child have exited.
*
* NOTE 2: This MUST NOT be an inlined function. Otherwise, we get
* into trouble in init/main.c when the child thread returns to
* do_basic_setup() and the timing is such that free_initmem() has
* been called already.
*/
extern
pid_t
kernel_thread
(
int
(
*
fn
)(
void
*
),
void
*
arg
,
unsigned
long
flags
);
/* Get wait channel for task P. */
extern
unsigned
long
get_wchan
(
struct
task_struct
*
p
);
...
...
arch/ia64/include/asm/unistd.h
View file @
94b28de4
...
...
@@ -29,6 +29,7 @@
#define __ARCH_WANT_SYS_RT_SIGACTION
#define __ARCH_WANT_SYS_RT_SIGSUSPEND
#define __ARCH_WANT_SYS_EXECVE
#if !defined(__ASSEMBLY__) && !defined(ASSEMBLER)
...
...
arch/ia64/kernel/entry.S
View file @
94b28de4
...
...
@@ -61,14 +61,13 @@ ENTRY(ia64_execve)
*
Allocate
8
input
registers
since
ptrace
()
may
clobber
them
*/
.
prologue
ASM_UNW_PRLG_RP
|
ASM_UNW_PRLG_PFS
,
ASM_UNW_PRLG_GRSAVE
(
8
)
alloc
loc1
=
ar
.
pfs
,
8
,
2
,
4
,
0
alloc
loc1
=
ar
.
pfs
,
8
,
2
,
3
,
0
mov
loc0
=
rp
.
body
mov
out0
=
in0
//
filename
;; // stop bit between alloc and call
mov
out1
=
in1
//
argv
mov
out2
=
in2
//
envp
add
out3
=
16
,
sp
//
regs
br.call.sptk.many
rp
=
sys_execve
.
ret0
:
cmp4.ge
p6
,
p7
=
r8
,
r0
...
...
@@ -76,7 +75,6 @@ ENTRY(ia64_execve)
sxt4
r8
=
r8
//
return
64
-
bit
result
;;
stf.spill
[
sp
]=
f0
(
p6
)
cmp.ne
pKStk
,
pUStk
=
r0
,
r0
//
a
successful
execve
()
lands
us
in
user
-
mode
...
mov
rp
=
loc0
(
p6
)
mov
ar
.
pfs
=
r0
//
clear
ar
.
pfs
on
success
(
p7
)
br.ret.sptk.many
rp
...
...
@@ -484,19 +482,6 @@ GLOBAL_ENTRY(prefetch_stack)
br.ret.sptk.many
rp
END
(
prefetch_stack
)
GLOBAL_ENTRY
(
kernel_execve
)
rum
psr
.
ac
mov
r15
=
__NR_execve
//
put
syscall
number
in
place
break
__BREAK_SYSCALL
br.ret.sptk.many
rp
END
(
kernel_execve
)
GLOBAL_ENTRY
(
clone
)
mov
r15
=
__NR_clone
//
put
syscall
number
in
place
break
__BREAK_SYSCALL
br.ret.sptk.many
rp
END
(
clone
)
/
*
*
Invoke
a
system
call
,
but
do
some
tracing
before
and
after
the
call
.
*
We
MUST
preserve
the
current
register
frame
throughout
this
routine
...
...
@@ -600,6 +585,27 @@ GLOBAL_ENTRY(ia64_strace_leave_kernel)
.
ret4
:
br.cond.sptk
ia64_leave_kernel
END
(
ia64_strace_leave_kernel
)
ENTRY
(
call_payload
)
.
prologue
ASM_UNW_PRLG_RP
|
ASM_UNW_PRLG_PFS
,
ASM_UNW_PRLG_GRSAVE
(
0
)
/
*
call
the
kernel_thread
payload
; fn is in r4, arg - in r5 */
alloc
loc1
=
ar
.
pfs
,
0
,
3
,
1
,
0
mov
loc0
=
rp
mov
loc2
=
gp
mov
out0
=
r5
//
arg
ld8
r14
=
[
r4
],
8
//
fn
.
address
;;
mov
b6
=
r14
ld8
gp
=
[
r4
]
//
fn
.
gp
;;
br.call.sptk.many
rp
=
b6
//
fn
(
arg
)
.
ret12
:
mov
gp
=
loc2
mov
rp
=
loc0
mov
ar
.
pfs
=
loc1
/
*
...
and
if
it
has
returned
,
we
are
going
to
userland
*/
cmp.ne
pKStk
,
pUStk
=
r0
,
r0
br.ret.sptk.many
rp
END
(
call_payload
)
GLOBAL_ENTRY
(
ia64_ret_from_clone
)
PT_REGS_UNWIND_INFO
(0)
{
/
*
...
...
@@ -616,6 +622,7 @@ GLOBAL_ENTRY(ia64_ret_from_clone)
br.call.sptk.many
rp
=
ia64_invoke_schedule_tail
}
.
ret8
:
(
pKStk
)
br.call.sptk.many
rp
=
call_payload
adds
r2
=
TI_FLAGS
+
IA64_TASK_SIZE
,
r13
;;
ld4
r2
=[
r2
]
...
...
arch/ia64/kernel/head.S
View file @
94b28de4
...
...
@@ -1093,19 +1093,6 @@ GLOBAL_ENTRY(cycle_to_cputime)
END
(
cycle_to_cputime
)
#endif /* CONFIG_VIRT_CPU_ACCOUNTING */
GLOBAL_ENTRY
(
start_kernel_thread
)
.
prologue
.
save
rp
,
r0
//
this
is
the
end
of
the
call
-
chain
.
body
alloc
r2
=
ar
.
pfs
,
0
,
0
,
2
,
0
mov
out0
=
r9
mov
out1
=
r11
;;
br.call.sptk.many
rp
=
kernel_thread_helper
;;
mov
out0
=
r8
br.call.sptk.many
rp
=
sys_exit
;;
1
:
br.sptk.few
1
b
//
not
reached
END
(
start_kernel_thread
)
#ifdef CONFIG_IA64_BRL_EMU
/*
...
...
arch/ia64/kernel/process.c
View file @
94b28de4
...
...
@@ -401,64 +401,15 @@ copy_thread(unsigned long clone_flags,
struct
pt_regs
*
child_ptregs
;
int
retval
=
0
;
#ifdef CONFIG_SMP
/*
* For SMP idle threads, fork_by_hand() calls do_fork with
* NULL regs.
*/
if
(
!
regs
)
return
0
;
#endif
stack
=
((
struct
switch_stack
*
)
regs
)
-
1
;
child_ptregs
=
(
struct
pt_regs
*
)
((
unsigned
long
)
p
+
IA64_STK_OFFSET
)
-
1
;
child_stack
=
(
struct
switch_stack
*
)
child_ptregs
-
1
;
/* copy parent's switch_stack & pt_regs to child: */
memcpy
(
child_stack
,
stack
,
sizeof
(
*
child_ptregs
)
+
sizeof
(
*
child_stack
));
rbs
=
(
unsigned
long
)
current
+
IA64_RBS_OFFSET
;
child_rbs
=
(
unsigned
long
)
p
+
IA64_RBS_OFFSET
;
rbs_size
=
stack
->
ar_bspstore
-
rbs
;
/* copy the parent's register backing store to the child: */
memcpy
((
void
*
)
child_rbs
,
(
void
*
)
rbs
,
rbs_size
);
if
(
likely
(
user_mode
(
child_ptregs
)))
{
if
(
clone_flags
&
CLONE_SETTLS
)
child_ptregs
->
r13
=
regs
->
r16
;
/* see sys_clone2() in entry.S */
if
(
user_stack_base
)
{
child_ptregs
->
r12
=
user_stack_base
+
user_stack_size
-
16
;
child_ptregs
->
ar_bspstore
=
user_stack_base
;
child_ptregs
->
ar_rnat
=
0
;
child_ptregs
->
loadrs
=
0
;
}
}
else
{
/*
* Note: we simply preserve the relative position of
* the stack pointer here. There is no need to
* allocate a scratch area here, since that will have
* been taken care of by the caller of sys_clone()
* already.
*/
child_ptregs
->
r12
=
(
unsigned
long
)
child_ptregs
-
16
;
/* kernel sp */
child_ptregs
->
r13
=
(
unsigned
long
)
p
;
/* set `current' pointer */
}
child_stack
->
ar_bspstore
=
child_rbs
+
rbs_size
;
child_stack
->
b0
=
(
unsigned
long
)
&
ia64_ret_from_clone
;
/* copy parts of thread_struct: */
p
->
thread
.
ksp
=
(
unsigned
long
)
child_stack
-
16
;
/* stop some PSR bits from being inherited.
* the psr.up/psr.pp bits must be cleared on fork but inherited on execve()
* therefore we must specify them explicitly here and not include them in
* IA64_PSR_BITS_TO_CLEAR.
*/
child_ptregs
->
cr_ipsr
=
((
child_ptregs
->
cr_ipsr
|
IA64_PSR_BITS_TO_SET
)
&
~
(
IA64_PSR_BITS_TO_CLEAR
|
IA64_PSR_PP
|
IA64_PSR_UP
));
/*
* NOTE: The calling convention considers all floating point
* registers in the high partition (fph) to be scratch. Since
...
...
@@ -480,8 +431,66 @@ copy_thread(unsigned long clone_flags,
# define THREAD_FLAGS_TO_SET 0
p
->
thread
.
flags
=
((
current
->
thread
.
flags
&
~
THREAD_FLAGS_TO_CLEAR
)
|
THREAD_FLAGS_TO_SET
);
ia64_drop_fpu
(
p
);
/* don't pick up stale state from a CPU's fph */
if
(
unlikely
(
p
->
flags
&
PF_KTHREAD
))
{
if
(
unlikely
(
!
user_stack_base
))
{
/* fork_idle() called us */
return
0
;
}
memset
(
child_stack
,
0
,
sizeof
(
*
child_ptregs
)
+
sizeof
(
*
child_stack
));
child_stack
->
r4
=
user_stack_base
;
/* payload */
child_stack
->
r5
=
user_stack_size
;
/* argument */
/*
* Preserve PSR bits, except for bits 32-34 and 37-45,
* which we can't read.
*/
child_ptregs
->
cr_ipsr
=
ia64_getreg
(
_IA64_REG_PSR
)
|
IA64_PSR_BN
;
/* mark as valid, empty frame */
child_ptregs
->
cr_ifs
=
1UL
<<
63
;
child_stack
->
ar_fpsr
=
child_ptregs
->
ar_fpsr
=
ia64_getreg
(
_IA64_REG_AR_FPSR
);
child_stack
->
pr
=
(
1
<<
PRED_KERNEL_STACK
);
child_stack
->
ar_bspstore
=
child_rbs
;
child_stack
->
b0
=
(
unsigned
long
)
&
ia64_ret_from_clone
;
/* stop some PSR bits from being inherited.
* the psr.up/psr.pp bits must be cleared on fork but inherited on execve()
* therefore we must specify them explicitly here and not include them in
* IA64_PSR_BITS_TO_CLEAR.
*/
child_ptregs
->
cr_ipsr
=
((
child_ptregs
->
cr_ipsr
|
IA64_PSR_BITS_TO_SET
)
&
~
(
IA64_PSR_BITS_TO_CLEAR
|
IA64_PSR_PP
|
IA64_PSR_UP
));
return
0
;
}
stack
=
((
struct
switch_stack
*
)
regs
)
-
1
;
/* copy parent's switch_stack & pt_regs to child: */
memcpy
(
child_stack
,
stack
,
sizeof
(
*
child_ptregs
)
+
sizeof
(
*
child_stack
));
/* copy the parent's register backing store to the child: */
rbs_size
=
stack
->
ar_bspstore
-
rbs
;
memcpy
((
void
*
)
child_rbs
,
(
void
*
)
rbs
,
rbs_size
);
if
(
clone_flags
&
CLONE_SETTLS
)
child_ptregs
->
r13
=
regs
->
r16
;
/* see sys_clone2() in entry.S */
if
(
user_stack_base
)
{
child_ptregs
->
r12
=
user_stack_base
+
user_stack_size
-
16
;
child_ptregs
->
ar_bspstore
=
user_stack_base
;
child_ptregs
->
ar_rnat
=
0
;
child_ptregs
->
loadrs
=
0
;
}
child_stack
->
ar_bspstore
=
child_rbs
+
rbs_size
;
child_stack
->
b0
=
(
unsigned
long
)
&
ia64_ret_from_clone
;
/* stop some PSR bits from being inherited.
* the psr.up/psr.pp bits must be cleared on fork but inherited on execve()
* therefore we must specify them explicitly here and not include them in
* IA64_PSR_BITS_TO_CLEAR.
*/
child_ptregs
->
cr_ipsr
=
((
child_ptregs
->
cr_ipsr
|
IA64_PSR_BITS_TO_SET
)
&
~
(
IA64_PSR_BITS_TO_CLEAR
|
IA64_PSR_PP
|
IA64_PSR_UP
));
#ifdef CONFIG_PERFMON
if
(
current
->
thread
.
pfm_context
)
pfm_inherit
(
p
,
child_ptregs
);
...
...
@@ -608,57 +617,6 @@ dump_fpu (struct pt_regs *pt, elf_fpregset_t dst)
return
1
;
/* f0-f31 are always valid so we always return 1 */
}
long
sys_execve
(
const
char
__user
*
filename
,
const
char
__user
*
const
__user
*
argv
,
const
char
__user
*
const
__user
*
envp
,
struct
pt_regs
*
regs
)
{
struct
filename
*
fname
;
int
error
;
fname
=
getname
(
filename
);
error
=
PTR_ERR
(
fname
);
if
(
IS_ERR
(
fname
))
goto
out
;
error
=
do_execve
(
fname
->
name
,
argv
,
envp
,
regs
);
putname
(
fname
);
out:
return
error
;
}
pid_t
kernel_thread
(
int
(
*
fn
)(
void
*
),
void
*
arg
,
unsigned
long
flags
)
{
extern
void
start_kernel_thread
(
void
);
unsigned
long
*
helper_fptr
=
(
unsigned
long
*
)
&
start_kernel_thread
;
struct
{
struct
switch_stack
sw
;
struct
pt_regs
pt
;
}
regs
;
memset
(
&
regs
,
0
,
sizeof
(
regs
));
regs
.
pt
.
cr_iip
=
helper_fptr
[
0
];
/* set entry point (IP) */
regs
.
pt
.
r1
=
helper_fptr
[
1
];
/* set GP */
regs
.
pt
.
r9
=
(
unsigned
long
)
fn
;
/* 1st argument */
regs
.
pt
.
r11
=
(
unsigned
long
)
arg
;
/* 2nd argument */
/* Preserve PSR bits, except for bits 32-34 and 37-45, which we can't read. */
regs
.
pt
.
cr_ipsr
=
ia64_getreg
(
_IA64_REG_PSR
)
|
IA64_PSR_BN
;
regs
.
pt
.
cr_ifs
=
1UL
<<
63
;
/* mark as valid, empty frame */
regs
.
sw
.
ar_fpsr
=
regs
.
pt
.
ar_fpsr
=
ia64_getreg
(
_IA64_REG_AR_FPSR
);
regs
.
sw
.
ar_bspstore
=
(
unsigned
long
)
current
+
IA64_RBS_OFFSET
;
regs
.
sw
.
pr
=
(
1
<<
PRED_KERNEL_STACK
);
return
do_fork
(
flags
|
CLONE_VM
|
CLONE_UNTRACED
,
0
,
&
regs
.
pt
,
0
,
NULL
,
NULL
);
}
EXPORT_SYMBOL
(
kernel_thread
);
/* This gets called from kernel_thread() via ia64_invoke_thread_helper(). */
int
kernel_thread_helper
(
int
(
*
fn
)(
void
*
),
void
*
arg
)
{
return
(
*
fn
)(
arg
);
}
/*
* Flush thread state. This is called when a thread does an execve().
*/
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment