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