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
7cdfcde3
Commit
7cdfcde3
authored
Apr 14, 2003
by
David Mosberger
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ia64: Update platform INIT handler to print a backtrace.
parent
f5cbfeb0
Changes
5
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
171 additions
and
50 deletions
+171
-50
arch/ia64/kernel/mca.c
arch/ia64/kernel/mca.c
+103
-11
arch/ia64/kernel/mca_asm.S
arch/ia64/kernel/mca_asm.S
+4
-2
arch/ia64/kernel/process.c
arch/ia64/kernel/process.c
+1
-1
arch/ia64/kernel/unwind.c
arch/ia64/kernel/unwind.c
+54
-34
include/asm-ia64/unwind.h
include/asm-ia64/unwind.h
+9
-2
No files found.
arch/ia64/kernel/mca.c
View file @
7cdfcde3
...
...
@@ -239,17 +239,91 @@ show_min_state (pal_min_state_area_t *minstate)
minstate
->
pmsa_bank1_gr
[
14
],
minstate
->
pmsa_bank1_gr
[
15
]);
}
/*
* This routine will be used to deal with platform specific handling
* of the init, i.e. drop into the kernel debugger on server machine,
* or if the processor is part of some parallel machine without a
* console, then we would call the appropriate debug hooks here.
static
void
fetch_min_state
(
pal_min_state_area_t
*
ms
,
struct
pt_regs
*
pt
,
struct
switch_stack
*
sw
)
{
u64
*
dst_banked
,
*
src_banked
,
bit
,
shift
,
nat_bits
;
int
i
;
/*
* First, update the pt-regs and switch-stack structures with the contents stored
* in the min-state area:
*/
unsigned
long
tr_val
[
32
],
tr_idx
;
if
(((
struct
ia64_psr
*
)
&
ms
->
pmsa_ipsr
)
->
ic
==
0
)
{
pt
->
cr_ipsr
=
ms
->
pmsa_xpsr
;
pt
->
cr_iip
=
ms
->
pmsa_xip
;
pt
->
cr_ifs
=
ms
->
pmsa_xfs
;
}
else
{
pt
->
cr_ipsr
=
ms
->
pmsa_ipsr
;
pt
->
cr_iip
=
ms
->
pmsa_iip
;
pt
->
cr_ifs
=
ms
->
pmsa_ifs
;
}
pt
->
ar_rsc
=
ms
->
pmsa_rsc
;
pt
->
pr
=
ms
->
pmsa_pr
;
pt
->
r1
=
ms
->
pmsa_gr
[
0
];
pt
->
r2
=
ms
->
pmsa_gr
[
1
];
pt
->
r3
=
ms
->
pmsa_gr
[
2
];
sw
->
r4
=
ms
->
pmsa_gr
[
3
];
sw
->
r5
=
ms
->
pmsa_gr
[
4
];
sw
->
r6
=
ms
->
pmsa_gr
[
5
];
sw
->
r7
=
ms
->
pmsa_gr
[
6
];
pt
->
r8
=
ms
->
pmsa_gr
[
7
];
pt
->
r9
=
ms
->
pmsa_gr
[
8
];
pt
->
r10
=
ms
->
pmsa_gr
[
9
];
pt
->
r11
=
ms
->
pmsa_gr
[
10
];
pt
->
r12
=
ms
->
pmsa_gr
[
11
];
pt
->
r13
=
ms
->
pmsa_gr
[
12
];
pt
->
r14
=
ms
->
pmsa_gr
[
13
];
pt
->
r15
=
ms
->
pmsa_gr
[
14
];
dst_banked
=
&
pt
->
r16
;
/* r16-r31 are contiguous in struct pt_regs */
src_banked
=
ms
->
pmsa_bank1_gr
;
for
(
i
=
0
;
i
<
16
;
++
i
)
*
dst_banked
=
*
src_banked
;
pt
->
b0
=
ms
->
pmsa_br0
;
sw
->
b1
=
ms
->
pmsa_br1
;
/* construct the NaT bits for the pt-regs structure: */
# define PUT_NAT_BIT(dst, addr) \
do { \
bit = nat_bits & 1; nat_bits >>= 1; \
shift = ((unsigned long) addr >> 3) & 0x3f; \
dst = ((dst) & ~(1UL << shift)) | (bit << shift); \
} while (0)
/* Rotate the saved NaT bits such that bit 0 corresponds to pmsa_gr[0]: */
shift
=
((
unsigned
long
)
&
ms
->
pmsa_gr
[
0
]
>>
3
)
&
0x3f
;
nat_bits
=
(
ms
->
pmsa_nat_bits
>>
shift
)
|
(
ms
->
pmsa_nat_bits
<<
(
64
-
shift
));
PUT_NAT_BIT
(
sw
->
caller_unat
,
&
pt
->
r1
);
PUT_NAT_BIT
(
sw
->
caller_unat
,
&
pt
->
r2
);
PUT_NAT_BIT
(
sw
->
caller_unat
,
&
pt
->
r3
);
PUT_NAT_BIT
(
sw
->
ar_unat
,
&
sw
->
r4
);
PUT_NAT_BIT
(
sw
->
ar_unat
,
&
sw
->
r5
);
PUT_NAT_BIT
(
sw
->
ar_unat
,
&
sw
->
r6
);
PUT_NAT_BIT
(
sw
->
ar_unat
,
&
sw
->
r7
);
PUT_NAT_BIT
(
sw
->
caller_unat
,
&
pt
->
r8
);
PUT_NAT_BIT
(
sw
->
caller_unat
,
&
pt
->
r9
);
PUT_NAT_BIT
(
sw
->
caller_unat
,
&
pt
->
r10
);
PUT_NAT_BIT
(
sw
->
caller_unat
,
&
pt
->
r11
);
PUT_NAT_BIT
(
sw
->
caller_unat
,
&
pt
->
r12
);
PUT_NAT_BIT
(
sw
->
caller_unat
,
&
pt
->
r13
);
PUT_NAT_BIT
(
sw
->
caller_unat
,
&
pt
->
r14
);
PUT_NAT_BIT
(
sw
->
caller_unat
,
&
pt
->
r15
);
nat_bits
>>=
16
;
/* skip over bank0 NaT bits */
PUT_NAT_BIT
(
sw
->
caller_unat
,
&
pt
->
r16
);
PUT_NAT_BIT
(
sw
->
caller_unat
,
&
pt
->
r17
);
PUT_NAT_BIT
(
sw
->
caller_unat
,
&
pt
->
r18
);
PUT_NAT_BIT
(
sw
->
caller_unat
,
&
pt
->
r19
);
PUT_NAT_BIT
(
sw
->
caller_unat
,
&
pt
->
r20
);
PUT_NAT_BIT
(
sw
->
caller_unat
,
&
pt
->
r21
);
PUT_NAT_BIT
(
sw
->
caller_unat
,
&
pt
->
r22
);
PUT_NAT_BIT
(
sw
->
caller_unat
,
&
pt
->
r23
);
PUT_NAT_BIT
(
sw
->
caller_unat
,
&
pt
->
r24
);
PUT_NAT_BIT
(
sw
->
caller_unat
,
&
pt
->
r25
);
PUT_NAT_BIT
(
sw
->
caller_unat
,
&
pt
->
r26
);
PUT_NAT_BIT
(
sw
->
caller_unat
,
&
pt
->
r27
);
PUT_NAT_BIT
(
sw
->
caller_unat
,
&
pt
->
r28
);
PUT_NAT_BIT
(
sw
->
caller_unat
,
&
pt
->
r29
);
PUT_NAT_BIT
(
sw
->
caller_unat
,
&
pt
->
r30
);
PUT_NAT_BIT
(
sw
->
caller_unat
,
&
pt
->
r31
);
}
void
init_handler_platform
(
sal_log_processor_info_t
*
proc_ptr
,
struct
pt_regs
*
regs
)
init_handler_platform
(
sal_log_processor_info_t
*
proc_ptr
,
struct
pt_regs
*
pt
,
struct
switch_stack
*
sw
)
{
unsigned
long
ip
,
sp
,
bsp
;
struct
unw_frame_info
info
;
char
buf
[
80
];
/* if a kernel debugger is available call it here else just dump the registers */
/*
...
...
@@ -262,6 +336,23 @@ init_handler_platform (sal_log_processor_info_t *proc_ptr, struct pt_regs *regs)
udelay
(
5
*
1000000
);
show_min_state
(
&
SAL_LPI_PSI_INFO
(
proc_ptr
)
->
min_state_area
);
fetch_min_state
(
&
SAL_LPI_PSI_INFO
(
proc_ptr
)
->
min_state_area
,
pt
,
sw
);
printk
(
"
\n
Call Trace:
\n
"
);
unw_init_from_interruption
(
&
info
,
current
,
pt
,
sw
);
do
{
unw_get_ip
(
&
info
,
&
ip
);
if
(
ip
==
0
)
break
;
unw_get_sp
(
&
info
,
&
sp
);
unw_get_bsp
(
&
info
,
&
bsp
);
snprintf
(
buf
,
sizeof
(
buf
),
" [<%016lx>] %%s
\n\t\t
sp=%016lx bsp=%016lx
\n
"
,
ip
,
sp
,
bsp
);
print_symbol
(
buf
,
ip
);
}
while
(
unw_unwind
(
&
info
)
>=
0
);
printk
(
"
\n
INIT dump complete. Please reboot now.
\n
"
);
while
(
1
);
/* hang city if no debugger */
}
...
...
@@ -1133,7 +1224,7 @@ device_initcall(ia64_mca_late_init);
*
*/
void
ia64_init_handler
(
struct
pt_regs
*
regs
)
ia64_init_handler
(
struct
pt_regs
*
pt
,
struct
switch_stack
*
sw
)
{
sal_log_processor_info_t
*
proc_ptr
;
ia64_err_rec_t
*
plog_ptr
;
...
...
@@ -1160,7 +1251,7 @@ ia64_init_handler (struct pt_regs *regs)
/* Clear the INIT SAL logs now that they have been saved in the OS buffer */
ia64_sal_clear_state_info
(
SAL_INFO_TYPE_INIT
);
init_handler_platform
(
proc_ptr
,
regs
);
/* call platform specific routines */
init_handler_platform
(
proc_ptr
,
pt
,
sw
);
/* call platform specific routines */
}
/*
...
...
@@ -2210,7 +2301,8 @@ ia64_log_print(int sal_info_type, prfunc_t prfunc)
switch
(
sal_info_type
)
{
case
SAL_INFO_TYPE_MCA
:
prfunc
(
"+BEGIN HARDWARE ERROR STATE AT MCA
\n
"
);
platform_err
=
ia64_log_platform_info_print
(
IA64_LOG_CURR_BUFFER
(
sal_info_type
),
prfunc
);
platform_err
=
ia64_log_platform_info_print
(
IA64_LOG_CURR_BUFFER
(
sal_info_type
),
prfunc
);
prfunc
(
"+END HARDWARE ERROR STATE AT MCA
\n
"
);
break
;
case
SAL_INFO_TYPE_INIT
:
...
...
arch/ia64/kernel/mca_asm.S
View file @
7cdfcde3
...
...
@@ -796,10 +796,12 @@ IVirtual_Switch:
//
//
Let
's call the C handler to get the rest of the state info
//
alloc
r14
=
ar
.
pfs
,
0
,
0
,
1
,
0
//
now
it
's safe (must be first in insn group!)
;;
//
alloc
r14
=
ar
.
pfs
,
0
,
0
,
2
,
0
//
now
it
's safe (must be first in insn group!)
;;
adds
out0
=
16
,
sp
//
out0
=
pointer
to
pt_regs
;;
DO_SAVE_SWITCH_STACK
adds
out1
=
16
,
sp
//
out0
=
pointer
to
switch_stack
br.call.sptk.many
rp
=
ia64_init_handler
.
ret1
:
...
...
arch/ia64/kernel/process.c
View file @
7cdfcde3
...
...
@@ -57,7 +57,7 @@ do_show_stack (struct unw_frame_info *info, void *arg)
unw_get_sp
(
info
,
&
sp
);
unw_get_bsp
(
info
,
&
bsp
);
snprintf
(
buf
,
sizeof
(
buf
),
" [<%016lx>] %%s
sp=0x%016lx bsp=0x
%016lx
\n
"
,
snprintf
(
buf
,
sizeof
(
buf
),
" [<%016lx>] %%s
\n\t\t
sp=%016lx bsp=
%016lx
\n
"
,
ip
,
sp
,
bsp
);
print_symbol
(
buf
,
ip
);
}
while
(
unw_unwind
(
info
)
>=
0
);
...
...
arch/ia64/kernel/unwind.c
View file @
7cdfcde3
...
...
@@ -1888,22 +1888,21 @@ unw_unwind_to_user (struct unw_frame_info *info)
return
-
1
;
}
void
unw_init_frame_info
(
struct
unw_frame_info
*
info
,
struct
task_struct
*
t
,
struct
switch_stack
*
sw
)
static
void
init_frame_info
(
struct
unw_frame_info
*
info
,
struct
task_struct
*
t
,
struct
switch_stack
*
sw
,
unsigned
long
stktop
)
{
unsigned
long
rbslimit
,
rbstop
,
stklimit
,
stktop
,
sol
;
unsigned
long
rbslimit
,
rbstop
,
stklimit
;
STAT
(
unsigned
long
start
,
flags
;)
STAT
(
local_irq_save
(
flags
);
++
unw
.
stat
.
api
.
inits
;
start
=
ia64_get_itc
());
/*
* Subtle stuff here: we _could_ unwind through the
* switch_stack frame but we don't want to do that because it
* would be slow as each preserved register would have to be
* processed. Instead, what we do here is zero out the frame
* info and start the unwind process at the function that
* created the switch_stack frame. When a preserved value in
* switch_stack needs to be accessed, run_script() will
* Subtle stuff here: we _could_ unwind through the switch_stack frame but we
* don't want to do that because it would be slow as each preserved register would
* have to be processed. Instead, what we do here is zero out the frame info and
* start the unwind process at the function that created the switch_stack frame.
* When a preserved value in switch_stack needs to be accessed, run_script() will
* initialize the appropriate pointer on demand.
*/
memset
(
info
,
0
,
sizeof
(
*
info
));
...
...
@@ -1914,7 +1913,6 @@ unw_init_frame_info (struct unw_frame_info *info, struct task_struct *t, struct
rbstop
=
rbslimit
;
stklimit
=
(
unsigned
long
)
t
+
IA64_STK_OFFSET
;
stktop
=
(
unsigned
long
)
sw
-
16
;
if
(
stktop
<=
rbstop
)
stktop
=
rbstop
;
...
...
@@ -1924,34 +1922,56 @@ unw_init_frame_info (struct unw_frame_info *info, struct task_struct *t, struct
info
->
memstk
.
top
=
stktop
;
info
->
task
=
t
;
info
->
sw
=
sw
;
info
->
sp
=
info
->
psp
=
(
unsigned
long
)
(
sw
+
1
)
-
16
;
info
->
pt
=
0
;
info
->
sp
=
info
->
psp
=
stktop
;
info
->
pr
=
sw
->
pr
;
UNW_DPRINT
(
3
,
"unwind.%s:
\n
"
" task 0x%lx
\n
"
" rbs = [0x%lx-0x%lx)
\n
"
" stk = [0x%lx-0x%lx)
\n
"
" pr 0x%lx
\n
"
" sw 0x%lx
\n
"
" sp 0x%lx
\n
"
,
__FUNCTION__
,
(
unsigned
long
)
task
,
rbslimit
,
rbstop
,
stktop
,
stklimit
,
info
->
pr
,
(
unsigned
long
)
info
->
sw
,
info
->
sp
);
STAT
(
unw
.
stat
.
api
.
init_time
+=
ia64_get_itc
()
-
start
;
local_irq_restore
(
flags
));
}
void
unw_init_from_interruption
(
struct
unw_frame_info
*
info
,
struct
task_struct
*
t
,
struct
pt_regs
*
pt
,
struct
switch_stack
*
sw
)
{
unsigned
long
sof
;
init_frame_info
(
info
,
t
,
sw
,
pt
->
r12
);
info
->
cfm_loc
=
&
pt
->
cr_ifs
;
sof
=
*
info
->
cfm_loc
&
0x7f
;
info
->
bsp
=
(
unsigned
long
)
ia64_rse_skip_regs
((
unsigned
long
*
)
info
->
regstk
.
top
,
-
sof
);
info
->
ip
=
pt
->
cr_iip
+
ia64_psr
(
pt
)
->
ri
;
info
->
pt
=
(
unsigned
long
)
pt
;
UNW_DPRINT
(
3
,
"unwind.%s:
\n
"
" bsp 0x%lx
\n
"
" sof 0x%lx
\n
"
" ip 0x%lx
\n
"
,
info
->
bsp
,
sof
,
info
->
ip
);
find_save_locs
(
info
);
}
void
unw_init_frame_info
(
struct
unw_frame_info
*
info
,
struct
task_struct
*
t
,
struct
switch_stack
*
sw
)
{
unsigned
long
sol
;
init_frame_info
(
info
,
t
,
sw
,
(
unsigned
long
)
(
sw
+
1
)
-
16
);
info
->
cfm_loc
=
&
sw
->
ar_pfs
;
sol
=
(
*
info
->
cfm_loc
>>
7
)
&
0x7f
;
info
->
bsp
=
(
unsigned
long
)
ia64_rse_skip_regs
((
unsigned
long
*
)
info
->
regstk
.
top
,
-
sol
);
info
->
ip
=
sw
->
b0
;
info
->
pr
=
sw
->
pr
;
UNW_DPRINT
(
3
,
"unwind.%s
\n
"
" rbslimit 0x%lx
\n
"
" rbstop 0x%lx
\n
"
" stklimit 0x%lx
\n
"
" stktop 0x%lx
\n
"
" task 0x%lx
\n
"
" sw 0x%lx
\n
"
,
__FUNCTION__
,
rbslimit
,
rbstop
,
stklimit
,
stktop
,
(
unsigned
long
)(
info
->
task
),
(
unsigned
long
)(
info
->
sw
));
UNW_DPRINT
(
3
,
" sp/psp 0x%lx
\n
"
" sol 0x%lx
\n
"
UNW_DPRINT
(
3
,
"unwind.%s:
\n
"
" bsp 0x%lx
\n
"
" ip 0x%lx
\n
"
" pr 0x%lx
\n
"
,
info
->
sp
,
sol
,
info
->
bsp
,
info
->
ip
,
info
->
pr
);
" sol 0x%lx
\n
"
" ip 0x%lx
\n
"
,
info
->
bsp
,
sol
,
info
->
ip
);
find_save_locs
(
info
);
STAT
(
unw
.
stat
.
api
.
init_time
+=
ia64_get_itc
()
-
start
;
local_irq_restore
(
flags
));
}
void
...
...
include/asm-ia64/unwind.h
View file @
7cdfcde3
...
...
@@ -2,8 +2,8 @@
#define _ASM_IA64_UNWIND_H
/*
* Copyright (C) 1999-2000 Hewlett-Packard Co
*
Copyright (C) 1999-2000
David Mosberger-Tang <davidm@hpl.hp.com>
* Copyright (C) 1999-2000
, 2003
Hewlett-Packard Co
*
David Mosberger-Tang <davidm@hpl.hp.com>
*
* A simple API for unwinding kernel stacks. This is used for
* debugging and error reporting purposes. The kernel doesn't need
...
...
@@ -107,6 +107,13 @@ extern void unw_remove_unwind_table (void *handle);
*/
extern
void
unw_init_from_blocked_task
(
struct
unw_frame_info
*
info
,
struct
task_struct
*
t
);
/*
* Prepare to unwind from interruption. The pt-regs and switch-stack structures must have
* be "adjacent" (no state modifications between pt-regs and switch-stack).
*/
extern
void
unw_init_from_interruption
(
struct
unw_frame_info
*
info
,
struct
task_struct
*
t
,
struct
pt_regs
*
pt
,
struct
switch_stack
*
sw
);
extern
void
unw_init_frame_info
(
struct
unw_frame_info
*
info
,
struct
task_struct
*
t
,
struct
switch_stack
*
sw
);
...
...
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