1 #include <linux/kernel.h>
2 #include <linux/mmzone.h>
3 #include <linux/spinlock.h>
5 #include <asm/atomic.h>
6 #include <asm/sn/types.h>
7 #include <asm/sn/addrs.h>
8 #include <asm/sn/nmi.h>
9 #include <asm/sn/arch.h>
10 #include <asm/sn/sn0/hub.h>
13 #define NODE_NUM_CPUS(n) CNODE_NUM_CPUS(n)
15 #define NODE_NUM_CPUS(n) CPUS_PER_NODE
18 #define CNODEID_NONE (cnodeid_t)-1
19 #define enter_panic_mode() spin_lock(&nmi_lock)
21 typedef unsigned long machreg_t
;
23 spinlock_t nmi_lock
= SPIN_LOCK_UNLOCKED
;
26 * Lets see what else we need to do here. Set up sp, gp?
30 void cont_nmi_dump(void);
35 void install_cpu_nmi_handler(int slice
)
39 nmi_addr
= (nmi_t
*)NMI_ADDR(get_nasid(), slice
);
40 if (nmi_addr
->call_addr
)
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;
50 * Copy the cpu registers which have been saved in the IP27prom format
51 * into the eframe format for the node under consideration.
55 nmi_cpu_eframe_save(nasid_t nasid
,
58 int i
, numberof_nmi_cpu_regs
;
59 machreg_t
*prom_format
;
61 /* Get the total number of registers being saved by the prom */
62 numberof_nmi_cpu_regs
= sizeof(struct reg_struct
) / sizeof(machreg_t
);
64 /* Get the pointer to the current cpu's register set. */
66 (machreg_t
*)(TO_UNCAC(TO_NODE(nasid
, IP27_NMI_KREGS_OFFSET
)) +
67 slice
* IP27_NMI_KREGS_CPU_SIZE
);
69 printk("NMI nasid %d: slice %d\n", nasid
, slice
);
70 for (i
= 0; i
< numberof_nmi_cpu_regs
; i
++)
71 printk("0x%lx ", prom_format
[i
]);
76 * Copy the cpu registers which have been saved in the IP27prom format
77 * into the eframe format for the node under consideration.
80 nmi_node_eframe_save(cnodeid_t cnode
)
85 /* Make sure that we have a valid node */
86 if (cnode
== CNODEID_NONE
)
89 nasid
= COMPACT_TO_NASID_NODEID(cnode
);
90 if (nasid
== INVALID_NASID
)
93 /* Save the registers into eframe for each cpu */
94 for(cpu
= 0; cpu
< NODE_NUM_CPUS(cnode
); cpu
++)
95 nmi_cpu_eframe_save(nasid
, cpu
);
99 * Save the nmi cpu registers for all cpus in the system.
102 nmi_eframes_save(void)
106 for(cnode
= 0 ; cnode
< numnodes
; cnode
++)
107 nmi_node_eframe_save(cnode
);
113 #ifndef REAL_NMI_SIGNAL
114 static atomic_t nmied_cpus
= ATOMIC_INIT(0);
116 atomic_inc(&nmied_cpus
);
119 * Use enter_panic_mode to allow only 1 cpu to proceed
123 #ifdef REAL_NMI_SIGNAL
125 * Wait up to 15 seconds for the other cpus to respond to the NMI.
126 * If a cpu has not responded after 10 sec, send it 1 additional NMI.
127 * This is for 2 reasons:
128 * - sometimes a MMSC fail to NMI all cpus.
129 * - on 512p SN0 system, the MMSC will only send NMIs to
130 * half the cpus. Unfortunately, we dont know which cpus may be
131 * NMIed - it depends on how the site chooses to configure.
133 * Note: it has been measure that it takes the MMSC up to 2.3 secs to
134 * send NMIs to all cpus on a 256p system.
136 for (i
=0; i
< 1500; i
++) {
137 for (node
=0; node
< numnodes
; node
++)
138 if (NODEPDA(node
)->dump_count
== 0)
140 if (node
== numnodes
)
143 for (node
=0; node
< numnodes
; node
++)
144 if (NODEPDA(node
)->dump_count
== 0) {
145 cpu
= CNODE_TO_CPU_BASE(node
);
146 for (n
=0; n
< CNODE_NUM_CPUS(node
); cpu
++, n
++) {
147 CPUMASK_SETB(nmied_cpus
, cpu
);
149 * cputonasid, cputoslice
152 SEND_NMI((cputonasid(cpu
)), (cputoslice(cpu
)));
160 while (atomic_read(&nmied_cpus
) != smp_num_cpus
);
164 * Save the nmi cpu registers for all cpu in the eframe format.
167 LOCAL_HUB_S(NI_PORT_RESET
, NPR_PORTRESET
| NPR_LOCALRESET
);