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
mips
sgi-ip27
ip27-nmi.c
Go to the documentation of this file.
1
#include <linux/kernel.h>
2
#include <
linux/mmzone.h
>
3
#include <
linux/nodemask.h
>
4
#include <
linux/spinlock.h
>
5
#include <
linux/smp.h
>
6
#include <
linux/atomic.h
>
7
#include <asm/sn/types.h>
8
#include <asm/sn/addrs.h>
9
#include <
asm/sn/nmi.h
>
10
#include <asm/sn/arch.h>
11
#include <
asm/sn/sn0/hub.h
>
12
13
#if 0
14
#define NODE_NUM_CPUS(n) CNODE_NUM_CPUS(n)
15
#else
16
#define NODE_NUM_CPUS(n) CPUS_PER_NODE
17
#endif
18
19
#define CNODEID_NONE (cnodeid_t)-1
20
21
typedef
unsigned
long
machreg_t
;
22
23
static
arch_spinlock_t
nmi_lock =
__ARCH_SPIN_LOCK_UNLOCKED
;
24
25
/*
26
* Lets see what else we need to do here. Set up sp, gp?
27
*/
28
void
nmi_dump
(
void
)
29
{
30
void
cont_nmi_dump
(
void
);
31
32
cont_nmi_dump
();
33
}
34
35
void
install_cpu_nmi_handler
(
int
slice
)
36
{
37
nmi_t
*nmi_addr;
38
39
nmi_addr = (
nmi_t
*)
NMI_ADDR
(
get_nasid
(), slice);
40
if
(nmi_addr->
call_addr
)
41
return
;
42
nmi_addr->
magic
=
NMI_MAGIC
;
43
nmi_addr->
call_addr
= (
void
*)
nmi_dump
;
44
nmi_addr->
call_addr_c
=
45
(
void
*)(~((
unsigned
long
)(nmi_addr->
call_addr
)));
46
nmi_addr->
call_parm
= 0;
47
}
48
49
/*
50
* Copy the cpu registers which have been saved in the IP27prom format
51
* into the eframe format for the node under consideration.
52
*/
53
54
void
nmi_cpu_eframe_save
(
nasid_t
nasid,
int
slice
)
55
{
56
struct
reg_struct
*
nr
;
57
int
i
;
58
59
/* Get the pointer to the current cpu's register set. */
60
nr = (
struct
reg_struct
*)
61
(TO_UNCAC(
TO_NODE
(nasid,
IP27_NMI_KREGS_OFFSET
)) +
62
slice *
IP27_NMI_KREGS_CPU_SIZE
);
63
64
printk
(
"NMI nasid %d: slice %d\n"
, nasid, slice);
65
66
/*
67
* Saved main processor registers
68
*/
69
for
(i = 0; i < 32; ) {
70
if
((i % 4) == 0)
71
printk
(
"$%2d :"
, i);
72
printk
(
" %016lx"
, nr->
gpr
[i]);
73
74
i++;
75
if
((i % 4) == 0)
76
printk
(
"\n"
);
77
}
78
79
printk
(
"Hi : (value lost)\n"
);
80
printk
(
"Lo : (value lost)\n"
);
81
82
/*
83
* Saved cp0 registers
84
*/
85
printk
(
"epc : %016lx %pS\n"
, nr->
epc
, (
void
*) nr->
epc
);
86
printk
(
"%s\n"
,
print_tainted
());
87
printk
(
"ErrEPC: %016lx %pS\n"
, nr->
error_epc
, (
void
*) nr->
error_epc
);
88
printk
(
"ra : %016lx %pS\n"
, nr->
gpr
[31], (
void
*) nr->
gpr
[31]);
89
printk
(
"Status: %08lx "
, nr->
sr
);
90
91
if
(nr->
sr
&
ST0_KX
)
92
printk
(
"KX "
);
93
if
(nr->
sr
&
ST0_SX
)
94
printk
(
"SX "
);
95
if
(nr->
sr
&
ST0_UX
)
96
printk
(
"UX "
);
97
98
switch
(nr->
sr
&
ST0_KSU
) {
99
case
KSU_USER
:
100
printk
(
"USER "
);
101
break
;
102
case
KSU_SUPERVISOR
:
103
printk
(
"SUPERVISOR "
);
104
break
;
105
case
KSU_KERNEL
:
106
printk
(
"KERNEL "
);
107
break
;
108
default
:
109
printk
(
"BAD_MODE "
);
110
break
;
111
}
112
113
if
(nr->
sr
&
ST0_ERL
)
114
printk
(
"ERL "
);
115
if
(nr->
sr
&
ST0_EXL
)
116
printk
(
"EXL "
);
117
if
(nr->
sr
&
ST0_IE
)
118
printk
(
"IE "
);
119
printk
(
"\n"
);
120
121
printk
(
"Cause : %08lx\n"
, nr->
cause
);
122
printk
(
"PrId : %08x\n"
,
read_c0_prid
());
123
printk
(
"BadVA : %016lx\n"
, nr->
badva
);
124
printk
(
"CErr : %016lx\n"
, nr->
cache_err
);
125
printk
(
"NMI_SR: %016lx\n"
, nr->
nmi_sr
);
126
127
printk
(
"\n"
);
128
}
129
130
void
nmi_dump_hub_irq
(
nasid_t
nasid,
int
slice
)
131
{
132
hubreg_t
mask0, mask1, pend0, pend1;
133
134
if
(slice == 0) {
/* Slice A */
135
mask0 =
REMOTE_HUB_L
(nasid,
PI_INT_MASK0_A
);
136
mask1 =
REMOTE_HUB_L
(nasid,
PI_INT_MASK1_A
);
137
}
else
{
/* Slice B */
138
mask0 =
REMOTE_HUB_L
(nasid,
PI_INT_MASK0_B
);
139
mask1 =
REMOTE_HUB_L
(nasid,
PI_INT_MASK1_B
);
140
}
141
142
pend0 =
REMOTE_HUB_L
(nasid,
PI_INT_PEND0
);
143
pend1 =
REMOTE_HUB_L
(nasid,
PI_INT_PEND1
);
144
145
printk
(
"PI_INT_MASK0: %16Lx PI_INT_MASK1: %16Lx\n"
, mask0, mask1);
146
printk
(
"PI_INT_PEND0: %16Lx PI_INT_PEND1: %16Lx\n"
, pend0, pend1);
147
printk
(
"\n\n"
);
148
}
149
150
/*
151
* Copy the cpu registers which have been saved in the IP27prom format
152
* into the eframe format for the node under consideration.
153
*/
154
void
nmi_node_eframe_save
(
cnodeid_t
cnode)
155
{
156
nasid_t
nasid;
157
int
slice
;
158
159
/* Make sure that we have a valid node */
160
if
(cnode ==
CNODEID_NONE
)
161
return
;
162
163
nasid =
COMPACT_TO_NASID_NODEID
(cnode);
164
if
(nasid ==
INVALID_NASID
)
165
return
;
166
167
/* Save the registers into eframe for each cpu */
168
for
(slice = 0; slice <
NODE_NUM_CPUS
(slice); slice++) {
169
nmi_cpu_eframe_save
(nasid, slice);
170
nmi_dump_hub_irq
(nasid, slice);
171
}
172
}
173
174
/*
175
* Save the nmi cpu registers for all cpus in the system.
176
*/
177
void
178
nmi_eframes_save
(
void
)
179
{
180
cnodeid_t
cnode;
181
182
for_each_online_node
(cnode)
183
nmi_node_eframe_save
(cnode);
184
}
185
186
void
187
cont_nmi_dump
(
void
)
188
{
189
#ifndef REAL_NMI_SIGNAL
190
static
atomic_t
nmied_cpus =
ATOMIC_INIT
(0);
191
192
atomic_inc
(&nmied_cpus);
193
#endif
194
/*
195
* Only allow 1 cpu to proceed
196
*/
197
arch_spin_lock
(&nmi_lock);
198
199
#ifdef REAL_NMI_SIGNAL
200
/*
201
* Wait up to 15 seconds for the other cpus to respond to the NMI.
202
* If a cpu has not responded after 10 sec, send it 1 additional NMI.
203
* This is for 2 reasons:
204
* - sometimes a MMSC fail to NMI all cpus.
205
* - on 512p SN0 system, the MMSC will only send NMIs to
206
* half the cpus. Unfortunately, we don't know which cpus may be
207
* NMIed - it depends on how the site chooses to configure.
208
*
209
* Note: it has been measure that it takes the MMSC up to 2.3 secs to
210
* send NMIs to all cpus on a 256p system.
211
*/
212
for
(
i
=0;
i
< 1500;
i
++) {
213
for_each_online_node
(
node
)
214
if
(
NODEPDA
(
node
)->dump_count == 0)
215
break
;
216
if
(
node
==
MAX_NUMNODES
)
217
break
;
218
if
(
i
== 1000) {
219
for_each_online_node
(
node
)
220
if
(
NODEPDA
(
node
)->dump_count == 0) {
221
cpu
= cpumask_first(
cpumask_of_node
(
node
));
222
for
(
n
=0;
n
< CNODE_NUM_CPUS(
node
);
cpu
++,
n
++) {
223
CPUMASK_SETB(nmied_cpus,
cpu
);
224
/*
225
* cputonasid, cputoslice
226
* needs kernel cpuid
227
*/
228
SEND_NMI
((
cputonasid
(
cpu
)), (
cputoslice
(
cpu
)));
229
}
230
}
231
232
}
233
udelay
(10000);
234
}
235
#else
236
while
(
atomic_read
(&nmied_cpus) !=
num_online_cpus
());
237
#endif
238
239
/*
240
* Save the nmi cpu registers for all cpu in the eframe format.
241
*/
242
nmi_eframes_save
();
243
LOCAL_HUB_S
(
NI_PORT_RESET
,
NPR_PORTRESET
|
NPR_LOCALRESET
);
244
}
Generated on Thu Jan 10 2013 13:12:14 for Linux Kernel by
1.8.2