~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/mips/sgi-ip27/ip27-nmi.c

Version: ~ [ linux-5.4-rc3 ] ~ [ linux-5.3.6 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.79 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.149 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.196 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.196 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.75 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp