ia64/linux-2.6.18-xen.hg

annotate arch/mips/sgi-ip27/ip27-nmi.c @ 912:dd42cdb0ab89

[IA64] Build blktap2 driver by default in x86 builds.

add CONFIG_XEN_BLKDEV_TAP2=y to buildconfigs/linux-defconfig_xen_ia64.

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