Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
linux-davinci
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
linux
linux-davinci
Commits
06d67d54
Commit
06d67d54
authored
Oct 10, 2005
by
Paul Mackerras
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
powerpc: make process.c suitable for both 32-bit and 64-bit
Signed-off-by:
Paul Mackerras
<
paulus@samba.org
>
parent
daec962e
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
347 additions
and
131 deletions
+347
-131
arch/powerpc/kernel/init_task.c
arch/powerpc/kernel/init_task.c
+36
-0
arch/powerpc/kernel/process.c
arch/powerpc/kernel/process.c
+309
-127
include/asm-powerpc/elf.h
include/asm-powerpc/elf.h
+2
-4
No files found.
arch/powerpc/kernel/init_task.c
0 → 100644
View file @
06d67d54
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/init_task.h>
#include <linux/fs.h>
#include <linux/mqueue.h>
#include <asm/uaccess.h>
static
struct
fs_struct
init_fs
=
INIT_FS
;
static
struct
files_struct
init_files
=
INIT_FILES
;
static
struct
signal_struct
init_signals
=
INIT_SIGNALS
(
init_signals
);
static
struct
sighand_struct
init_sighand
=
INIT_SIGHAND
(
init_sighand
);
struct
mm_struct
init_mm
=
INIT_MM
(
init_mm
);
EXPORT_SYMBOL
(
init_mm
);
/*
* Initial thread structure.
*
* We need to make sure that this is 16384-byte aligned due to the
* way process stacks are handled. This is done by having a special
* "init_task" linker map entry..
*/
union
thread_union
init_thread_union
__attribute__
((
__section__
(
".data.init_task"
)))
=
{
INIT_THREAD_INFO
(
init_task
)
};
/*
* Initial task structure.
*
* All other task structs will be allocated on slabs in fork.c
*/
struct
task_struct
init_task
=
INIT_TASK
(
init_task
);
EXPORT_SYMBOL
(
init_task
);
arch/powerpc/kernel/process.c
View file @
06d67d54
...
...
@@ -36,6 +36,8 @@
#include <linux/kallsyms.h>
#include <linux/mqueue.h>
#include <linux/hardirq.h>
#include <linux/utsname.h>
#include <linux/kprobes.h>
#include <asm/pgtable.h>
#include <asm/uaccess.h>
...
...
@@ -44,6 +46,11 @@
#include <asm/processor.h>
#include <asm/mmu.h>
#include <asm/prom.h>
#ifdef CONFIG_PPC64
#include <asm/firmware.h>
#include <asm/plpar_wrappers.h>
#include <asm/time.h>
#endif
extern
unsigned
long
_get_SP
(
void
);
...
...
@@ -53,26 +60,6 @@ struct task_struct *last_task_used_altivec = NULL;
struct
task_struct
*
last_task_used_spe
=
NULL
;
#endif
static
struct
fs_struct
init_fs
=
INIT_FS
;
static
struct
files_struct
init_files
=
INIT_FILES
;
static
struct
signal_struct
init_signals
=
INIT_SIGNALS
(
init_signals
);
static
struct
sighand_struct
init_sighand
=
INIT_SIGHAND
(
init_sighand
);
struct
mm_struct
init_mm
=
INIT_MM
(
init_mm
);
EXPORT_SYMBOL
(
init_mm
);
/* this is 8kB-aligned so we can get to the thread_info struct
at the base of it from the stack pointer with 1 integer instruction. */
union
thread_union
init_thread_union
__attribute__
((
__section__
(
".data.init_task"
)))
=
{
INIT_THREAD_INFO
(
init_task
)
};
/* initial task structure */
struct
task_struct
init_task
=
INIT_TASK
(
init_task
);
EXPORT_SYMBOL
(
init_task
);
/* only used to get secondary processor up */
struct
task_struct
*
current_set
[
NR_CPUS
]
=
{
&
init_task
,
};
/*
* Make sure the floating-point register state in the
* the thread_struct is up to date for task tsk.
...
...
@@ -237,7 +224,10 @@ int set_dabr(unsigned long dabr)
return
ret
;
}
#ifdef CONFIG_PPC64
DEFINE_PER_CPU
(
struct
cpu_usage
,
cpu_usage_array
);
static
DEFINE_PER_CPU
(
unsigned
long
,
current_dabr
);
#endif
struct
task_struct
*
__switch_to
(
struct
task_struct
*
prev
,
struct
task_struct
*
new
)
...
...
@@ -308,10 +298,27 @@ struct task_struct *__switch_to(struct task_struct *prev,
set_dabr
(
new
->
thread
.
dabr
);
__get_cpu_var
(
current_dabr
)
=
new
->
thread
.
dabr
;
}
flush_tlb_pending
();
#endif
new_thread
=
&
new
->
thread
;
old_thread
=
&
current
->
thread
;
#ifdef CONFIG_PPC64
/*
* Collect processor utilization data per process
*/
if
(
firmware_has_feature
(
FW_FEATURE_SPLPAR
))
{
struct
cpu_usage
*
cu
=
&
__get_cpu_var
(
cpu_usage_array
);
long
unsigned
start_tb
,
current_tb
;
start_tb
=
old_thread
->
start_tb
;
cu
->
current_tb
=
current_tb
=
mfspr
(
SPRN_PURR
);
old_thread
->
accum_tb
+=
(
current_tb
-
start_tb
);
new_thread
->
start_tb
=
current_tb
;
}
#endif
local_irq_save
(
flags
);
last
=
_switch
(
old_thread
,
new_thread
);
...
...
@@ -320,37 +327,106 @@ struct task_struct *__switch_to(struct task_struct *prev,
return
last
;
}
static
int
instructions_to_print
=
16
;
#ifdef CONFIG_PPC64
#define BAD_PC(pc) ((REGION_ID(pc) != KERNEL_REGION_ID) && \
(REGION_ID(pc) != VMALLOC_REGION_ID))
#else
#define BAD_PC(pc) ((pc) < KERNELBASE)
#endif
static
void
show_instructions
(
struct
pt_regs
*
regs
)
{
int
i
;
unsigned
long
pc
=
regs
->
nip
-
(
instructions_to_print
*
3
/
4
*
sizeof
(
int
));
printk
(
"Instruction dump:"
);
for
(
i
=
0
;
i
<
instructions_to_print
;
i
++
)
{
int
instr
;
if
(
!
(
i
%
8
))
printk
(
"
\n
"
);
if
(
BAD_PC
(
pc
)
||
__get_user
(
instr
,
(
unsigned
int
*
)
pc
))
{
printk
(
"XXXXXXXX "
);
}
else
{
if
(
regs
->
nip
==
pc
)
printk
(
"<%08x> "
,
instr
);
else
printk
(
"%08x "
,
instr
);
}
pc
+=
sizeof
(
int
);
}
printk
(
"
\n
"
);
}
static
struct
regbit
{
unsigned
long
bit
;
const
char
*
name
;
}
msr_bits
[]
=
{
{
MSR_EE
,
"EE"
},
{
MSR_PR
,
"PR"
},
{
MSR_FP
,
"FP"
},
{
MSR_ME
,
"ME"
},
{
MSR_IR
,
"IR"
},
{
MSR_DR
,
"DR"
},
{
0
,
NULL
}
};
static
void
printbits
(
unsigned
long
val
,
struct
regbit
*
bits
)
{
const
char
*
sep
=
""
;
printk
(
"<"
);
for
(;
bits
->
bit
;
++
bits
)
if
(
val
&
bits
->
bit
)
{
printk
(
"%s%s"
,
sep
,
bits
->
name
);
sep
=
","
;
}
printk
(
">"
);
}
#ifdef CONFIG_PPC64
#define REG "%016lX"
#define REGS_PER_LINE 4
#define LAST_VOLATILE 13
#else
#define REG "%08lX"
#define REGS_PER_LINE 8
#define LAST_VOLATILE 12
#endif
void
show_regs
(
struct
pt_regs
*
regs
)
{
int
i
,
trap
;
printk
(
"NIP: %08lX LR: %08lX SP: %08lX REGS: %p TRAP: %04lx %s
\n
"
,
regs
->
nip
,
regs
->
link
,
regs
->
gpr
[
1
],
regs
,
regs
->
trap
,
print_tainted
());
printk
(
"MSR: %08lx EE: %01x PR: %01x FP: %01x ME: %01x IR/DR: %01x%01x
\n
"
,
regs
->
msr
,
regs
->
msr
&
MSR_EE
?
1
:
0
,
regs
->
msr
&
MSR_PR
?
1
:
0
,
regs
->
msr
&
MSR_FP
?
1
:
0
,
regs
->
msr
&
MSR_ME
?
1
:
0
,
regs
->
msr
&
MSR_IR
?
1
:
0
,
regs
->
msr
&
MSR_DR
?
1
:
0
);
printk
(
"NIP: "
REG
" LR: "
REG
" CTR: "
REG
"
\n
"
,
regs
->
nip
,
regs
->
link
,
regs
->
ctr
);
printk
(
"REGS: %p TRAP: %04lx %s (%s)
\n
"
,
regs
,
regs
->
trap
,
print_tainted
(),
system_utsname
.
release
);
printk
(
"MSR: "
REG
" "
,
regs
->
msr
);
printbits
(
regs
->
msr
,
msr_bits
);
printk
(
" CR: %08lX XER: %08lX
\n
"
,
regs
->
ccr
,
regs
->
xer
);
trap
=
TRAP
(
regs
);
if
(
trap
==
0x300
||
trap
==
0x600
)
printk
(
"DAR:
%08lX, DSISR: %08lX
\n
"
,
regs
->
dar
,
regs
->
dsisr
);
printk
(
"TASK = %p[%d] '%s' THREAD: %p
\n
"
,
printk
(
"DAR:
"
REG
", DSISR: "
REG
"
\n
"
,
regs
->
dar
,
regs
->
dsisr
);
printk
(
"TASK = %p[%d] '%s' THREAD: %p"
,
current
,
current
->
pid
,
current
->
comm
,
current
->
thread_info
);
printk
(
"Last syscall: %ld "
,
current
->
thread
.
last_syscall
);
#ifdef CONFIG_SMP
printk
(
" CPU: %d"
,
smp_processor_id
());
#endif
/* CONFIG_SMP */
for
(
i
=
0
;
i
<
32
;
i
++
)
{
long
r
;
if
((
i
%
8
)
==
0
)
if
((
i
%
REGS_PER_LINE
)
==
0
)
printk
(
"
\n
"
KERN_INFO
"GPR%02d: "
,
i
);
if
(
__get_user
(
r
,
&
regs
->
gpr
[
i
]))
break
;
printk
(
"%08lX "
,
r
);
if
(
i
==
12
&&
!
FULL_REGS
(
regs
))
printk
(
REG
" "
,
regs
->
gpr
[
i
]);
if
(
i
==
LAST_VOLATILE
&&
!
FULL_REGS
(
regs
))
break
;
}
printk
(
"
\n
"
);
...
...
@@ -359,16 +435,20 @@ void show_regs(struct pt_regs * regs)
* Lookup NIP late so we have the best change of getting the
* above info out without failing
*/
printk
(
"NIP [
%08lx
] "
,
regs
->
nip
);
printk
(
"NIP [
"
REG
"
] "
,
regs
->
nip
);
print_symbol
(
"%s
\n
"
,
regs
->
nip
);
printk
(
"LR [
%08lx
] "
,
regs
->
link
);
printk
(
"LR [
"
REG
"
] "
,
regs
->
link
);
print_symbol
(
"%s
\n
"
,
regs
->
link
);
#endif
show_stack
(
current
,
(
unsigned
long
*
)
regs
->
gpr
[
1
]);
if
(
!
user_mode
(
regs
))
show_instructions
(
regs
);
}
void
exit_thread
(
void
)
{
kprobe_flush_task
(
current
);
#ifndef CONFIG_SMP
if
(
last_task_used_math
==
current
)
last_task_used_math
=
NULL
;
...
...
@@ -385,6 +465,14 @@ void exit_thread(void)
void
flush_thread
(
void
)
{
#ifdef CONFIG_PPC64
struct
thread_info
*
t
=
current_thread_info
();
if
(
t
->
flags
&
_TIF_ABI_PENDING
)
t
->
flags
^=
(
_TIF_ABI_PENDING
|
_TIF_32BIT
);
#endif
kprobe_flush_task
(
current
);
#ifndef CONFIG_SMP
if
(
last_task_used_math
==
current
)
last_task_used_math
=
NULL
;
...
...
@@ -425,15 +513,13 @@ void prepare_to_copy(struct task_struct *tsk)
/*
* Copy a thread..
*/
int
copy_thread
(
int
nr
,
unsigned
long
clone_flags
,
unsigned
long
usp
,
unsigned
long
unused
,
struct
task_struct
*
p
,
struct
pt_regs
*
regs
)
int
copy_thread
(
int
nr
,
unsigned
long
clone_flags
,
unsigned
long
usp
,
unsigned
long
unused
,
struct
task_struct
*
p
,
struct
pt_regs
*
regs
)
{
struct
pt_regs
*
childregs
,
*
kregs
;
extern
void
ret_from_fork
(
void
);
unsigned
long
sp
=
(
unsigned
long
)
p
->
thread_info
+
THREAD_SIZE
;
unsigned
long
childframe
;
CHECK_FULL_REGS
(
regs
);
/* Copy registers */
...
...
@@ -443,17 +529,26 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
if
((
childregs
->
msr
&
MSR_PR
)
==
0
)
{
/* for kernel thread, set `current' and stackptr in new task */
childregs
->
gpr
[
1
]
=
sp
+
sizeof
(
struct
pt_regs
);
#ifdef CONFIG_PPC32
childregs
->
gpr
[
2
]
=
(
unsigned
long
)
p
;
#else
clear_ti_thread_flag
(
p
->
thread_info
,
TIF_32BIT
);
#endif
p
->
thread
.
regs
=
NULL
;
/* no user register state */
}
else
{
childregs
->
gpr
[
1
]
=
usp
;
p
->
thread
.
regs
=
childregs
;
if
(
clone_flags
&
CLONE_SETTLS
)
if
(
clone_flags
&
CLONE_SETTLS
)
{
#ifdef CONFIG_PPC64
if
(
!
test_thread_flag
(
TIF_32BIT
))
childregs
->
gpr
[
13
]
=
childregs
->
gpr
[
6
];
else
#endif
childregs
->
gpr
[
2
]
=
childregs
->
gpr
[
6
];
}
}
childregs
->
gpr
[
3
]
=
0
;
/* Result from fork() */
sp
-=
STACK_FRAME_OVERHEAD
;
childframe
=
sp
;
/*
* The way this works is that at some point in the future
...
...
@@ -467,9 +562,30 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
kregs
=
(
struct
pt_regs
*
)
sp
;
sp
-=
STACK_FRAME_OVERHEAD
;
p
->
thread
.
ksp
=
sp
;
kregs
->
nip
=
(
unsigned
long
)
ret_from_fork
;
#ifdef CONFIG_PPC64
if
(
cpu_has_feature
(
CPU_FTR_SLB
))
{
unsigned
long
sp_vsid
=
get_kernel_vsid
(
sp
);
sp_vsid
<<=
SLB_VSID_SHIFT
;
sp_vsid
|=
SLB_VSID_KERNEL
;
if
(
cpu_has_feature
(
CPU_FTR_16M_PAGE
))
sp_vsid
|=
SLB_VSID_L
;
p
->
thread
.
ksp_vsid
=
sp_vsid
;
}
/*
* The PPC64 ABI makes use of a TOC to contain function
* pointers. The function (ret_from_except) is actually a pointer
* to the TOC entry. The first entry is a pointer to the actual
* function.
*/
kregs
->
nip
=
*
((
unsigned
long
*
)
ret_from_fork
);
#else
kregs
->
nip
=
(
unsigned
long
)
ret_from_fork
;
p
->
thread
.
last_syscall
=
-
1
;
#endif
return
0
;
}
...
...
@@ -477,18 +593,61 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
/*
* Set up a thread for executing a new program
*/
void
start_thread
(
struct
pt_regs
*
regs
,
unsigned
long
nip
,
unsigned
long
sp
)
void
start_thread
(
struct
pt_regs
*
regs
,
unsigned
long
start
,
unsigned
long
sp
)
{
set_fs
(
USER_DS
);
/*
* If we exec out of a kernel thread then thread.regs will not be
* set. Do it now.
*/
if
(
!
current
->
thread
.
regs
)
{
unsigned
long
childregs
=
(
unsigned
long
)
current
->
thread_info
+
THREAD_SIZE
;
childregs
-=
sizeof
(
struct
pt_regs
);
current
->
thread
.
regs
=
(
struct
pt_regs
*
)
childregs
;
}
memset
(
regs
->
gpr
,
0
,
sizeof
(
regs
->
gpr
));
regs
->
ctr
=
0
;
regs
->
link
=
0
;
regs
->
xer
=
0
;
regs
->
ccr
=
0
;
regs
->
mq
=
0
;
regs
->
nip
=
nip
;
regs
->
gpr
[
1
]
=
sp
;
#ifdef CONFIG_PPC32
regs
->
mq
=
0
;
regs
->
nip
=
start
;
regs
->
msr
=
MSR_USER
;
#else
if
(
test_thread_flag
(
TIF_32BIT
))
{
unsigned
long
entry
,
toc
,
load_addr
=
regs
->
gpr
[
2
];
/* start is a relocated pointer to the function descriptor for
* the elf _start routine. The first entry in the function
* descriptor is the entry address of _start and the second
* entry is the TOC value we need to use.
*/
__get_user
(
entry
,
(
unsigned
long
__user
*
)
start
);
__get_user
(
toc
,
(
unsigned
long
__user
*
)
start
+
1
);
/* Check whether the e_entry function descriptor entries
* need to be relocated before we can use them.
*/
if
(
load_addr
!=
0
)
{
entry
+=
load_addr
;
toc
+=
load_addr
;
}
regs
->
nip
=
entry
;
regs
->
gpr
[
2
]
=
toc
;
regs
->
msr
=
MSR_USER64
;
}
else
{
regs
->
nip
=
start
;
regs
->
gpr
[
2
]
=
0
;
regs
->
msr
=
MSR_USER32
;
}
#endif
#ifndef CONFIG_SMP
if
(
last_task_used_math
==
current
)
last_task_used_math
=
NULL
;
...
...
@@ -506,6 +665,7 @@ void start_thread(struct pt_regs *regs, unsigned long nip, unsigned long sp)
#ifdef CONFIG_ALTIVEC
memset
(
current
->
thread
.
vr
,
0
,
sizeof
(
current
->
thread
.
vr
));
memset
(
&
current
->
thread
.
vscr
,
0
,
sizeof
(
current
->
thread
.
vscr
));
current
->
thread
.
vscr
.
u
[
3
]
=
0x00010000
;
/* Java mode disabled */
current
->
thread
.
vrsave
=
0
;
current
->
thread
.
used_vr
=
0
;
#endif
/* CONFIG_ALTIVEC */
...
...
@@ -532,10 +692,12 @@ int set_fpexc_mode(struct task_struct *tsk, unsigned int val)
#ifdef CONFIG_SPE
tsk
->
thread
.
fpexc_mode
=
val
&
(
PR_FP_EXC_SW_ENABLE
|
PR_FP_ALL_EXCEPT
);
return
0
;
#else
return
-
EINVAL
;
#endif
}
else
{
}
/* on a CONFIG_SPE this does not hurt us. The bits that
* __pack_fe01 use do not overlap with bits used for
* PR_FP_EXC_SW_ENABLE. Additionally, the MSR[FE0,FE1] bits
...
...
@@ -547,7 +709,6 @@ int set_fpexc_mode(struct task_struct *tsk, unsigned int val)
if
(
regs
!=
NULL
&&
(
regs
->
msr
&
MSR_FP
)
!=
0
)
regs
->
msr
=
(
regs
->
msr
&
~
(
MSR_FE0
|
MSR_FE1
))
|
tsk
->
thread
.
fpexc_mode
;
}
return
0
;
}
...
...
@@ -566,6 +727,8 @@ int get_fpexc_mode(struct task_struct *tsk, unsigned long adr)
return
put_user
(
val
,
(
unsigned
int
__user
*
)
adr
);
}
#define TRUNC_PTR(x) ((typeof(x))(((unsigned long)(x)) & 0xffffffff))
int
sys_clone
(
unsigned
long
clone_flags
,
unsigned
long
usp
,
int
__user
*
parent_tidp
,
void
__user
*
child_threadptr
,
int
__user
*
child_tidp
,
int
p6
,
...
...
@@ -574,6 +737,12 @@ int sys_clone(unsigned long clone_flags, unsigned long usp,
CHECK_FULL_REGS
(
regs
);
if
(
usp
==
0
)
usp
=
regs
->
gpr
[
1
];
/* stack pointer for child */
#ifdef CONFIG_PPC64
if
(
test_thread_flag
(
TIF_32BIT
))
{
parent_tidp
=
TRUNC_PTR
(
parent_tidp
);
child_tidp
=
TRUNC_PTR
(
child_tidp
);
}
#endif
return
do_fork
(
clone_flags
,
usp
,
regs
,
0
,
parent_tidp
,
child_tidp
);
}
...
...
@@ -599,7 +768,7 @@ int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
struct
pt_regs
*
regs
)
{
int
error
;
char
*
filename
;
char
*
filename
;
filename
=
getname
((
char
__user
*
)
a0
);
error
=
PTR_ERR
(
filename
);
...
...
@@ -644,20 +813,53 @@ static int validate_sp(unsigned long sp, struct task_struct *p,
return
0
;
}
void
dump_stack
(
void
)
#ifdef CONFIG_PPC64
#define MIN_STACK_FRAME 112
/* same as STACK_FRAME_OVERHEAD, in fact */
#define FRAME_LR_SAVE 2
#define INT_FRAME_SIZE (sizeof(struct pt_regs) + STACK_FRAME_OVERHEAD + 288)
#define REGS_MARKER 0x7265677368657265ul
#define FRAME_MARKER 12
#else
#define MIN_STACK_FRAME 16
#define FRAME_LR_SAVE 1
#define INT_FRAME_SIZE (sizeof(struct pt_regs) + STACK_FRAME_OVERHEAD)
#define REGS_MARKER 0x72656773ul
#define FRAME_MARKER 2
#endif
unsigned
long
get_wchan
(
struct
task_struct
*
p
)
{
show_stack
(
current
,
NULL
);
unsigned
long
ip
,
sp
;
int
count
=
0
;
if
(
!
p
||
p
==
current
||
p
->
state
==
TASK_RUNNING
)
return
0
;
sp
=
p
->
thread
.
ksp
;
if
(
!
validate_sp
(
sp
,
p
,
MIN_STACK_FRAME
))
return
0
;
do
{
sp
=
*
(
unsigned
long
*
)
sp
;
if
(
!
validate_sp
(
sp
,
p
,
MIN_STACK_FRAME
))
return
0
;
if
(
count
>
0
)
{
ip
=
((
unsigned
long
*
)
sp
)[
FRAME_LR_SAVE
];
if
(
!
in_sched_functions
(
ip
))
return
ip
;
}
}
while
(
count
++
<
16
);
return
0
;
}
EXPORT_SYMBOL
(
get_wchan
);
EXPORT_SYMBOL
(
dump_stack
)
;
static
int
kstack_depth_to_print
=
64
;
void
show_stack
(
struct
task_struct
*
tsk
,
unsigned
long
*
stack
)
{
unsigned
long
sp
,
stack_top
,
prev_sp
,
ret
;
unsigned
long
sp
,
ip
,
lr
,
newsp
;
int
count
=
0
;
unsigned
long
next_exc
=
0
;
struct
pt_regs
*
regs
;
extern
char
ret_from_except
,
ret_from_except_full
,
ret_from_syscall
;
int
firstframe
=
1
;
sp
=
(
unsigned
long
)
stack
;
if
(
tsk
==
NULL
)
...
...
@@ -669,65 +871,45 @@ void show_stack(struct task_struct *tsk, unsigned long *stack)
sp
=
tsk
->
thread
.
ksp
;
}
prev_sp
=
(
unsigned
long
)
(
tsk
->
thread_info
+
1
);
stack_top
=
(
unsigned
long
)
tsk
->
thread_info
+
THREAD_SIZE
;
while
(
count
<
16
&&
sp
>
prev_sp
&&
sp
<
stack_top
&&
(
sp
&
3
)
==
0
)
{
if
(
count
==
0
)
{
printk
(
"Call trace:"
);
#ifdef CONFIG_KALLSYMS
printk
(
"
\n
"
);
#endif
}
else
{
if
(
next_exc
)
{
ret
=
next_exc
;
next_exc
=
0
;
}
else
ret
=
*
(
unsigned
long
*
)(
sp
+
4
);
printk
(
" [%08lx] "
,
ret
);
#ifdef CONFIG_KALLSYMS
print_symbol
(
"%s"
,
ret
);
lr
=
0
;
printk
(
"Call Trace:
\n
"
);
do
{
if
(
!
validate_sp
(
sp
,
tsk
,
MIN_STACK_FRAME
))
return
;
stack
=
(
unsigned
long
*
)
sp
;
newsp
=
stack
[
0
];
ip
=
stack
[
FRAME_LR_SAVE
];
if
(
!
firstframe
||
ip
!=
lr
)
{
printk
(
"["
REG
"] ["
REG
"] "
,
sp
,
ip
);
print_symbol
(
"%s"
,
ip
);
if
(
firstframe
)
printk
(
" (unreliable)"
);
printk
(
"
\n
"
);
#endif
if
(
ret
==
(
unsigned
long
)
&
ret_from_except
||
ret
==
(
unsigned
long
)
&
ret_from_except_full
||
ret
==
(
unsigned
long
)
&
ret_from_syscall
)
{
/* sp + 16 points to an exception frame */
regs
=
(
struct
pt_regs
*
)
(
sp
+
16
);
if
(
sp
+
16
+
sizeof
(
*
regs
)
<=
stack_top
)
next_exc
=
regs
->
nip
;
}
}
++
count
;
sp
=
*
(
unsigned
long
*
)
sp
;
firstframe
=
0
;
/*
* See if this is an exception frame.
* We look for the "regshere" marker in the current frame.
*/
if
(
validate_sp
(
sp
,
tsk
,
INT_FRAME_SIZE
)
&&
stack
[
FRAME_MARKER
]
==
REGS_MARKER
)
{
struct
pt_regs
*
regs
=
(
struct
pt_regs
*
)
(
sp
+
STACK_FRAME_OVERHEAD
);
printk
(
"--- Exception: %lx"
,
regs
->
trap
);
print_symbol
(
" at %s
\n
"
,
regs
->
nip
);
lr
=
regs
->
link
;
print_symbol
(
" LR = %s
\n
"
,
lr
);
firstframe
=
1
;
}
#ifndef CONFIG_KALLSYMS
if
(
count
>
0
)
printk
(
"
\n
"
);
#endif
sp
=
newsp
;
}
while
(
count
++
<
kstack_depth_to_print
);
}
unsigned
long
get_wchan
(
struct
task_struct
*
p
)
void
dump_stack
(
void
)
{
unsigned
long
ip
,
sp
;
int
count
=
0
;
if
(
!
p
||
p
==
current
||
p
->
state
==
TASK_RUNNING
)
return
0
;
sp
=
p
->
thread
.
ksp
;
if
(
!
validate_sp
(
sp
,
p
,
16
))
return
0
;
do
{
sp
=
*
(
unsigned
long
*
)
sp
;
if
(
!
validate_sp
(
sp
,
p
,
16
))
return
0
;
if
(
count
>
0
)
{
ip
=
*
(
unsigned
long
*
)(
sp
+
4
);
if
(
!
in_sched_functions
(
ip
))
return
ip
;
}
}
while
(
count
++
<
16
);
return
0
;
show_stack
(
current
,
NULL
);
}
EXPORT_SYMBOL
(
get_wchan
);
EXPORT_SYMBOL
(
dump_stack
);
include/asm-powerpc/elf.h
View file @
06d67d54
...
...
@@ -215,8 +215,6 @@ extern int dump_task_fpu(struct task_struct *, elf_fpregset_t *);
# define ELF_HWCAP (cur_cpu_spec->cpu_user_features)
#ifdef __powerpc64__
# define ELF_PLAT_INIT(_r, load_addr) do { \
memset(_r->gpr, 0, sizeof(_r->gpr)); \
_r->ctr = _r->link = _r->xer = _r->ccr = 0; \
_r->gpr[2] = load_addr; \
} while (0)
#endif
/* __powerpc64__ */
...
...
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