linux/arch/mips/sgi-ip27/ip27-nmi.c
<<
>>
Prefs
   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
  22typedef unsigned long machreg_t;
  23
  24static 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 */
  29void nmi_dump(void)
  30{
  31        void cont_nmi_dump(void);
  32
  33        cont_nmi_dump();
  34}
  35
  36void 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
  55void 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        printk("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                        printk("$%2d   :", i);
  73                printk(" %016lx", nr->gpr[i]);
  74
  75                i++;
  76                if ((i % 4) == 0)
  77                        printk("\n");
  78        }
  79
  80        printk("Hi    : (value lost)\n");
  81        printk("Lo    : (value lost)\n");
  82
  83        /*
  84         * Saved cp0 registers
  85         */
  86        printk("epc   : %016lx %pS\n", nr->epc, (void *) nr->epc);
  87        printk("%s\n", print_tainted());
  88        printk("ErrEPC: %016lx %pS\n", nr->error_epc, (void *) nr->error_epc);
  89        printk("ra    : %016lx %pS\n", nr->gpr[31], (void *) nr->gpr[31]);
  90        printk("Status: %08lx         ", nr->sr);
  91
  92        if (nr->sr & ST0_KX)
  93                printk("KX ");
  94        if (nr->sr & ST0_SX)
  95                printk("SX      ");
  96        if (nr->sr & ST0_UX)
  97                printk("UX ");
  98
  99        switch (nr->sr & ST0_KSU) {
 100        case KSU_USER:
 101                printk("USER ");
 102                break;
 103        case KSU_SUPERVISOR:
 104                printk("SUPERVISOR ");
 105                break;
 106        case KSU_KERNEL:
 107                printk("KERNEL ");
 108                break;
 109        default:
 110                printk("BAD_MODE ");
 111                break;
 112        }
 113
 114        if (nr->sr & ST0_ERL)
 115                printk("ERL ");
 116        if (nr->sr & ST0_EXL)
 117                printk("EXL ");
 118        if (nr->sr & ST0_IE)
 119                printk("IE ");
 120        printk("\n");
 121
 122        printk("Cause : %08lx\n", nr->cause);
 123        printk("PrId  : %08x\n", read_c0_prid());
 124        printk("BadVA : %016lx\n", nr->badva);
 125        printk("CErr  : %016lx\n", nr->cache_err);
 126        printk("NMI_SR: %016lx\n", nr->nmi_sr);
 127
 128        printk("\n");
 129}
 130
 131void nmi_dump_hub_irq(nasid_t nasid, int slice)
 132{
 133        hubreg_t 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        printk("PI_INT_MASK0: %16Lx PI_INT_MASK1: %16Lx\n", mask0, mask1);
 147        printk("PI_INT_PEND0: %16Lx PI_INT_PEND1: %16Lx\n", pend0, pend1);
 148        printk("\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 */
 155void 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 */
 178void
 179nmi_eframes_save(void)
 180{
 181        cnodeid_t       cnode;
 182
 183        for_each_online_node(cnode)
 184                nmi_node_eframe_save(cnode);
 185}
 186
 187void
 188cont_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