1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
  23  *
  24  * Use is subject to license terms.
  25  */
  26 
  27 #include <sys/types.h>
  28 #include <sys/t_lock.h>
  29 #include <sys/uadmin.h>
  30 #include <sys/panic.h>
  31 #include <sys/reboot.h>
  32 #include <sys/autoconf.h>
  33 #include <sys/machsystm.h>
  34 #include <sys/promif.h>
  35 #include <sys/membar.h>
  36 #include <vm/hat_sfmmu.h>
  37 #include <sys/cpu_module.h>
  38 #include <sys/cpu_sgnblk_defs.h>
  39 #include <sys/intreg.h>
  40 #include <sys/consdev.h>
  41 #include <sys/kdi_impl.h>
  42 #include <sys/callb.h>
  43 #include <sys/dumphdr.h>
  44 
  45 #ifdef  TRAPTRACE
  46 #include <sys/traptrace.h>
  47 u_longlong_t panic_tick;
  48 #endif /* TRAPTRACE */
  49 
  50 extern u_longlong_t     gettick();
  51 static void reboot_machine(char *);
  52 int disable_watchdog_on_exit = 0;
  53 extern uint64_t         cpc_level15_inum;
  54 
  55 /*
  56  * Machine dependent code to reboot.
  57  * "mdep" is interpreted as a character pointer; if non-null, it is a pointer
  58  * to a string to be used as the argument string when rebooting.
  59  *
  60  * "invoke_cb" is a boolean. It is set to true when mdboot() can safely
  61  * invoke CB_CL_MDBOOT callbacks before shutting the system down, i.e. when
  62  * we are in a normal shutdown sequence (interrupts are not blocked, the
  63  * system is not panic'ing or being suspended).
  64  */
  65 /*ARGSUSED*/
  66 void
  67 mdboot(int cmd, int fcn, char *bootstr, boolean_t invoke_cb)
  68 {
  69         extern void pm_cfb_check_and_powerup(void);
  70 
  71         /*
  72          * Disable the hw watchdog timer.
  73          */
  74         if (disable_watchdog_on_exit && watchdog_activated) {
  75                 mutex_enter(&tod_lock);
  76                 (void) tod_ops.tod_clear_watchdog_timer();
  77                 mutex_exit(&tod_lock);
  78         }
  79 
  80         /*
  81          * XXX - rconsvp is set to NULL to ensure that output messages
  82          * are sent to the underlying "hardware" device using the
  83          * monitor's printf routine since we are in the process of
  84          * either rebooting or halting the machine.
  85          */
  86         rconsvp = NULL;
  87 
  88         /*
  89          * At a high interrupt level we can't:
  90          *      1) bring up the console
  91          * or
  92          *      2) wait for pending interrupts prior to redistribution
  93          *         to the current CPU
  94          *
  95          * so we do them now.
  96          */
  97         pm_cfb_check_and_powerup();
  98 
  99         /* make sure there are no more changes to the device tree */
 100         devtree_freeze();
 101 
 102         if (invoke_cb)
 103                 (void) callb_execute_class(CB_CL_MDBOOT, NULL);
 104 
 105         /*
 106          * Clear any unresolved UEs from memory.
 107          */
 108         page_retire_mdboot();
 109 
 110         /*
 111          * stop other cpus which also raise our priority. since there is only
 112          * one active cpu after this, and our priority will be too high
 113          * for us to be preempted, we're essentially single threaded
 114          * from here on out.
 115          */
 116         stop_other_cpus();
 117 
 118         /*
 119          * try and reset leaf devices.  reset_leaves() should only
 120          * be called when there are no other threads that could be
 121          * accessing devices
 122          */
 123         reset_leaves();
 124 
 125         if (fcn == AD_HALT) {
 126                 halt((char *)NULL);
 127         } else if (fcn == AD_POWEROFF) {
 128                 power_down(NULL);
 129         } else {
 130                 if (bootstr == NULL) {
 131                         switch (fcn) {
 132 
 133                         case AD_FASTREBOOT:
 134                         case AD_BOOT:
 135                                 bootstr = "";
 136                                 break;
 137 
 138                         case AD_IBOOT:
 139                                 bootstr = "-a";
 140                                 break;
 141 
 142                         case AD_SBOOT:
 143                                 bootstr = "-s";
 144                                 break;
 145 
 146                         case AD_SIBOOT:
 147                                 bootstr = "-sa";
 148                                 break;
 149                         default:
 150                                 cmn_err(CE_WARN,
 151                                     "mdboot: invalid function %d", fcn);
 152                                 bootstr = "";
 153                                 break;
 154                         }
 155                 }
 156                 if (fcn == AD_FASTREBOOT) {
 157                         pnode_t onode;
 158                         int dllen;
 159                         onode = prom_optionsnode();
 160                         if ((onode == OBP_NONODE) || (onode == OBP_BADNODE)) {
 161                                 cmn_err(CE_WARN, "Unable to set diag level for"
 162                                     " quick reboot");
 163                         } else {
 164                                 dllen = prom_getproplen(onode, "diag-level");
 165                                 if (dllen != -1) {
 166                                         char *newstr = kmem_alloc(strlen(
 167                                             bootstr) + dllen + 5, KM_NOSLEEP);
 168                                         if (newstr != NULL) {
 169                                                 int newstrlen;
 170                                                 (void) strcpy(newstr, bootstr);
 171                                                 (void) strcat(newstr, " -f ");
 172                                                 newstrlen = strlen(bootstr) + 4;
 173                                                 (void) prom_getprop(onode,
 174                                                     "diag-level",
 175                                                     (caddr_t)
 176                                                     &(newstr[newstrlen]));
 177                                                 newstr[newstrlen + dllen] =
 178                                                     '\0';
 179                                                 bootstr = newstr;
 180                                                 (void) prom_setprop(onode,
 181                                                     "diag-level",
 182                                                     "off", 4);
 183                                         }
 184                                 }
 185                         }
 186                 }
 187                 reboot_machine(bootstr);
 188         }
 189         /* MAYBE REACHED */
 190 }
 191 
 192 /* mdpreboot - may be called prior to mdboot while root fs still mounted */
 193 /*ARGSUSED*/
 194 void
 195 mdpreboot(int cmd, int fcn, char *bootstr)
 196 {
 197 }
 198 
 199 /*
 200  * Halt the machine and then reboot with the device
 201  * and arguments specified in bootstr.
 202  */
 203 static void
 204 reboot_machine(char *bootstr)
 205 {
 206         flush_windows();
 207         stop_other_cpus();              /* send stop signal to other CPUs */
 208         prom_printf("rebooting...\n");
 209         /*
 210          * For platforms that use CPU signatures, we
 211          * need to set the signature block to OS and
 212          * the state to exiting for all the processors.
 213          */
 214         CPU_SIGNATURE(OS_SIG, SIGST_EXIT, SIGSUBST_REBOOT, -1);
 215         prom_reboot(bootstr);
 216         /*NOTREACHED*/
 217 }
 218 
 219 /*
 220  * We use the x-trap mechanism and idle_stop_xcall() to stop the other CPUs.
 221  * Once in panic_idle() they raise spl, record their location, and spin.
 222  */
 223 static void
 224 panic_idle(void)
 225 {
 226         cpu_async_panic_callb(); /* check for async errors */
 227 
 228         (void) spl7();
 229 
 230         debug_flush_windows();
 231         (void) setjmp(&curthread->t_pcb);
 232 
 233         CPU->cpu_m.in_prom = 1;
 234         membar_stld();
 235 
 236         for (;;)
 237                 continue;
 238 }
 239 
 240 /*
 241  * Force the other CPUs to trap into panic_idle(), and then remove them
 242  * from the cpu_ready_set so they will no longer receive cross-calls.
 243  */
 244 /*ARGSUSED*/
 245 void
 246 panic_stopcpus(cpu_t *cp, kthread_t *t, int spl)
 247 {
 248         cpuset_t cps;
 249         int i;
 250 
 251         (void) splzs();
 252         CPUSET_ALL_BUT(cps, cp->cpu_id);
 253         xt_some(cps, (xcfunc_t *)idle_stop_xcall, (uint64_t)&panic_idle, NULL);
 254 
 255         for (i = 0; i < NCPU; i++) {
 256                 if (i != cp->cpu_id && CPU_XCALL_READY(i)) {
 257                         int ntries = 0x10000;
 258 
 259                         while (!cpu[i]->cpu_m.in_prom && ntries) {
 260                                 DELAY(50);
 261                                 ntries--;
 262                         }
 263 
 264                         if (!cpu[i]->cpu_m.in_prom)
 265                                 printf("panic: failed to stop cpu%d\n", i);
 266 
 267                         cpu[i]->cpu_flags &= ~CPU_READY;
 268                         cpu[i]->cpu_flags |= CPU_QUIESCED;
 269                         CPUSET_DEL(cpu_ready_set, cpu[i]->cpu_id);
 270                 }
 271         }
 272 }
 273 
 274 /*
 275  * Platform callback following each entry to panicsys().  If we've panicked at
 276  * level 14, we examine t_panic_trap to see if a fatal trap occurred.  If so,
 277  * we disable further %tick_cmpr interrupts.  If not, an explicit call to panic
 278  * was made and so we re-enqueue an interrupt request structure to allow
 279  * further level 14 interrupts to be processed once we lower PIL.  This allows
 280  * us to handle panics from the deadman() CY_HIGH_LEVEL cyclic.
 281  *
 282  * In case we panic at level 15, ensure that the cpc handler has been
 283  * reinstalled otherwise we could run the risk of hitting a missing interrupt
 284  * handler when this thread drops PIL and the cpc counter overflows.
 285  */
 286 void
 287 panic_enter_hw(int spl)
 288 {
 289         uint_t opstate;
 290 
 291         if (spl == ipltospl(PIL_14)) {
 292                 opstate = disable_vec_intr();
 293 
 294                 if (curthread->t_panic_trap != NULL) {
 295                         tickcmpr_disable();
 296                         intr_dequeue_req(PIL_14, cbe_level14_inum);
 297                 } else {
 298                         if (!tickcmpr_disabled())
 299                                 intr_enqueue_req(PIL_14, cbe_level14_inum);
 300                         /*
 301                          * Clear SOFTINT<14>, SOFTINT<0> (TICK_INT)
 302                          * and SOFTINT<16> (STICK_INT) to indicate
 303                          * that the current level 14 has been serviced.
 304                          */
 305                         wr_clr_softint((1 << PIL_14) |
 306                             TICK_INT_MASK | STICK_INT_MASK);
 307                 }
 308 
 309                 enable_vec_intr(opstate);
 310         } else if (spl == ipltospl(PIL_15)) {
 311                 opstate = disable_vec_intr();
 312                 intr_enqueue_req(PIL_15, cpc_level15_inum);
 313                 wr_clr_softint(1 << PIL_15);
 314                 enable_vec_intr(opstate);
 315         }
 316 }
 317 
 318 /*
 319  * Miscellaneous hardware-specific code to execute after panicstr is set
 320  * by the panic code: we also print and record PTL1 panic information here.
 321  */
 322 /*ARGSUSED*/
 323 void
 324 panic_quiesce_hw(panic_data_t *pdp)
 325 {
 326         extern uint_t getpstate(void);
 327         extern void setpstate(uint_t);
 328 
 329 #ifdef TRAPTRACE
 330         /*
 331          * Turn off TRAPTRACE and save the current %tick value in panic_tick.
 332          */
 333         if (!panic_tick)
 334                 panic_tick = gettick();
 335         TRAPTRACE_FREEZE;
 336 #endif
 337         /*
 338          * For Platforms that use CPU signatures, we
 339          * need to set the signature block to OS, the state to
 340          * exiting, and the substate to panic for all the processors.
 341          */
 342         CPU_SIGNATURE(OS_SIG, SIGST_EXIT, SIGSUBST_PANIC, -1);
 343 
 344         /*
 345          * De-activate ECC functions and disable the watchdog timer now that
 346          * we've made it through the critical part of the panic code.
 347          */
 348         if (watchdog_enable)
 349                 (void) tod_ops.tod_clear_watchdog_timer();
 350 
 351         /*
 352          * Disable further ECC errors from the CPU module and the bus nexus.
 353          */
 354         cpu_disable_errors();
 355         (void) bus_func_invoke(BF_TYPE_ERRDIS);
 356 
 357         /*
 358          * Redirect all interrupts to the current CPU.
 359          */
 360         intr_redist_all_cpus_shutdown();
 361 
 362         /*
 363          * This call exists solely to support dumps to network
 364          * devices after sync from OBP.
 365          *
 366          * If we came here via the sync callback, then on some
 367          * platforms, interrupts may have arrived while we were
 368          * stopped in OBP.  OBP will arrange for those interrupts to
 369          * be redelivered if you say "go", but not if you invoke a
 370          * client callback like 'sync'.  For some dump devices
 371          * (network swap devices), we need interrupts to be
 372          * delivered in order to dump, so we have to call the bus
 373          * nexus driver to reset the interrupt state machines.
 374          */
 375         (void) bus_func_invoke(BF_TYPE_RESINTR);
 376 
 377         setpstate(getpstate() | PSTATE_IE);
 378 }
 379 
 380 /*
 381  * Platforms that use CPU signatures need to set the signature block to OS and
 382  * the state to exiting for all CPUs. PANIC_CONT indicates that we're about to
 383  * write the crash dump, which tells the SSP/SMS to begin a timeout routine to
 384  * reboot the machine if the dump never completes.
 385  */
 386 /*ARGSUSED*/
 387 void
 388 panic_dump_hw(int spl)
 389 {
 390         CPU_SIGNATURE(OS_SIG, SIGST_EXIT, SIGSUBST_DUMP, -1);
 391 }
 392 
 393 /*
 394  * for ptl1_panic
 395  */
 396 void
 397 ptl1_init_cpu(struct cpu *cpu)
 398 {
 399         ptl1_state_t *pstate = &cpu->cpu_m.ptl1_state;
 400 
 401         /*CONSTCOND*/
 402         if (sizeof (struct cpu) + PTL1_SSIZE > CPU_ALLOC_SIZE) {
 403                 panic("ptl1_init_cpu: not enough space left for ptl1_panic "
 404                     "stack, sizeof (struct cpu) = %lu", sizeof (struct cpu));
 405         }
 406 
 407         pstate->ptl1_stktop = (uintptr_t)cpu + CPU_ALLOC_SIZE;
 408         cpu_pa[cpu->cpu_id] = va_to_pa(cpu);
 409 }
 410 
 411 void
 412 ptl1_panic_handler(ptl1_state_t *pstate)
 413 {
 414         static const char *ptl1_reasons[] = {
 415 #ifdef  PTL1_PANIC_DEBUG
 416                 "trap for debug purpose",       /* PTL1_BAD_DEBUG */
 417 #else
 418                 "unknown trap",                 /* PTL1_BAD_DEBUG */
 419 #endif
 420                 "register window trap",         /* PTL1_BAD_WTRAP */
 421                 "kernel MMU miss",              /* PTL1_BAD_KMISS */
 422                 "kernel protection fault",      /* PTL1_BAD_KPROT_FAULT */
 423                 "ISM MMU miss",                 /* PTL1_BAD_ISM */
 424                 "kernel MMU trap",              /* PTL1_BAD_MMUTRAP */
 425                 "kernel trap handler state",    /* PTL1_BAD_TRAP */
 426                 "floating point trap",          /* PTL1_BAD_FPTRAP */
 427 #ifdef  DEBUG
 428                 "pointer to intr_vec",          /* PTL1_BAD_INTR_VEC */
 429 #else
 430                 "unknown trap",                 /* PTL1_BAD_INTR_VEC */
 431 #endif
 432 #ifdef  TRAPTRACE
 433                 "TRACE_PTR state",              /* PTL1_BAD_TRACE_PTR */
 434 #else
 435                 "unknown trap",                 /* PTL1_BAD_TRACE_PTR */
 436 #endif
 437                 "stack overflow",               /* PTL1_BAD_STACK */
 438                 "DTrace flags",                 /* PTL1_BAD_DTRACE_FLAGS */
 439                 "attempt to steal locked ctx",  /* PTL1_BAD_CTX_STEAL */
 440                 "CPU ECC error loop",           /* PTL1_BAD_ECC */
 441                 "non-kernel context in sys/priv_trap() below or",
 442                                                 /* PTL1_BAD_CTX */
 443                 "error raising a TSB exception", /* PTL1_BAD_RAISE_TSBEXCP */
 444                 "missing shared TSB"    /* PTL1_NO_SCDTSB8K */
 445         };
 446 
 447         uint_t reason = pstate->ptl1_regs.ptl1_g1;
 448         uint_t tl = pstate->ptl1_regs.ptl1_trap_regs[0].ptl1_tl;
 449         struct panic_trap_info ti = { 0 };
 450 
 451         /*
 452          * Use trap_info for a place holder to call panic_savetrap() and
 453          * panic_showtrap() to save and print out ptl1_panic information.
 454          */
 455         if (curthread->t_panic_trap == NULL)
 456                 curthread->t_panic_trap = &ti;
 457 
 458         if (reason < sizeof (ptl1_reasons) / sizeof (ptl1_reasons[0]))
 459                 panic("bad %s at TL %u", ptl1_reasons[reason], tl);
 460         else
 461                 panic("ptl1_panic reason 0x%x at TL %u", reason, tl);
 462 }
 463 
 464 void
 465 clear_watchdog_on_exit()
 466 {
 467         /*
 468          * Only shut down an active hardware watchdog timer if the platform
 469          * has expressed an interest to.
 470          */
 471         if (disable_watchdog_on_exit && watchdog_activated) {
 472                 prom_printf("Debugging requested; hardware watchdog "
 473                     "disabled; reboot to re-enable.\n");
 474                 cmn_err(CE_WARN, "!Debugging requested; hardware watchdog "
 475                     "disabled; reboot to re-enable.");
 476                 mutex_enter(&tod_lock);
 477                 (void) tod_ops.tod_clear_watchdog_timer();
 478                 mutex_exit(&tod_lock);
 479         }
 480 }
 481 
 482 /*
 483  * This null routine is only used by sun4v watchdog timer support.
 484  */
 485 void
 486 restore_watchdog_on_entry(void)
 487 {
 488 }
 489 
 490 int
 491 kdi_watchdog_disable(void)
 492 {
 493         if (watchdog_activated) {
 494                 mutex_enter(&tod_lock);
 495                 (void) tod_ops.tod_clear_watchdog_timer();
 496                 mutex_exit(&tod_lock);
 497         }
 498 
 499         return (watchdog_activated);
 500 }
 501 
 502 void
 503 kdi_watchdog_restore(void)
 504 {
 505         if (watchdog_enable) {
 506                 mutex_enter(&tod_lock);
 507                 (void) tod_ops.tod_set_watchdog_timer(watchdog_timeout_seconds);
 508                 mutex_exit(&tod_lock);
 509         }
 510 }
 511 
 512 /*ARGSUSED*/
 513 void
 514 mach_dump_buffer_init(void)
 515 {
 516         /*
 517          * setup dump buffer to store extra crash information
 518          * not applicable to sun4u
 519          */
 520 }
 521 
 522 /*
 523  * xt_sync - wait for previous x-traps to finish
 524  */
 525 void
 526 xt_sync(cpuset_t cpuset)
 527 {
 528         kpreempt_disable();
 529         CPUSET_DEL(cpuset, CPU->cpu_id);
 530         CPUSET_AND(cpuset, cpu_ready_set);
 531         xt_some(cpuset, (xcfunc_t *)xt_sync_tl1, 0, 0);
 532         kpreempt_enable();
 533 }
 534 
 535 /*
 536  * mach_soft_state_init() - dummy routine for sun4v soft state
 537  */
 538 void
 539 mach_soft_state_init(void)
 540 {}