cpu_states.c revision b0fc0e77220f1fa4c933fd58a4e1dedcd650b0f1
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys/*
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * CDDL HEADER START
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys *
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * The contents of this file are subject to the terms of the
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * Common Development and Distribution License (the "License").
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * You may not use this file except in compliance with the License.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys *
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * or http://www.opensolaris.org/os/licensing.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * See the License for the specific language governing permissions
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * and limitations under the License.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys *
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * When distributing Covered Code, include this CDDL HEADER in each
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * If applicable, add the following below this CDDL HEADER, with the
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * fields enclosed by brackets "[]" replaced with your own identifying
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * information: Portions Copyright [yyyy] [name of copyright owner]
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys *
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * CDDL HEADER END
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys */
2c9a247fb01631b3eb3b85a1127e72f0b60ae108Wyllys Ingersoll/*
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * Use is subject to license terms.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#pragma ident "%Z%%M% %I% %E% SMI"
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#include <sys/reboot.h>
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#include <sys/systm.h>
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#include <sys/archsystm.h>
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#include <sys/machsystm.h>
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#include <sys/promif.h>
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#include <sys/promimpl.h>
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#include <sys/prom_plat.h>
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#include <sys/cpu_sgnblk_defs.h>
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#include <sys/ivintr.h>
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#include <sys/kdi.h>
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#include <sys/callb.h>
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#include <sys/wdt.h>
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#ifdef TRAPTRACE
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#include <sys/traptrace.h>
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#endif /* TRAPTRACE */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#ifdef C2_AUDIT
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysextern void audit_enterprom();
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysextern void audit_exitprom();
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#endif /* C2_AUDIT */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
d00756ccb34596a328f8a15d1965da5412d366d0wyllys/*
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * Platforms that use CPU signatures need to set cpu_sgn_func
e65e5c2d2f32a99e8c5f740cabae9075dab03ce7Wyllys Ingersoll * to point to a platform specific function. This needs to
e65e5c2d2f32a99e8c5f740cabae9075dab03ce7Wyllys Ingersoll * be done in set_platform_defaults() within the platmod.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysvoid (*cpu_sgn_func)(ushort_t, uchar_t, uchar_t, int) = NULL;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys/*
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * abort_seq_handler required by sysctrl.
6b35cb3cf158584a9408d44b9b6796564e8e1882Richard PALO */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysvoid debug_enter(char *);
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllysvoid (*abort_seq_handler)(char *) = debug_enter;
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys/*
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys * Platform tunable to disable the h/w watchdog timer.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysextern void clear_watchdog_on_exit(void);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys/*
e65e5c2d2f32a99e8c5f740cabae9075dab03ce7Wyllys Ingersoll * On sun4u platform, abort_sequence_enter() can be called at high PIL
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * and we can't afford to acquire any adaptive mutex or use any
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * condition variables as we are not allowed to sleep while running
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * on interrupt stack. We work around this problem by posting a level
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * 10 soft interrupt and then invoking the "abort_seq_handler" within
e65e5c2d2f32a99e8c5f740cabae9075dab03ce7Wyllys Ingersoll * that soft interrupt context.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys *
e65e5c2d2f32a99e8c5f740cabae9075dab03ce7Wyllys Ingersoll * This has the side effect of not allowing us to drop into debugger
e65e5c2d2f32a99e8c5f740cabae9075dab03ce7Wyllys Ingersoll * when the kernel is stuck at high PIL (PIL > 10). It's better to
e65e5c2d2f32a99e8c5f740cabae9075dab03ce7Wyllys Ingersoll * be able to break into a hung system even if it means crashing the
e65e5c2d2f32a99e8c5f740cabae9075dab03ce7Wyllys Ingersoll * system. If a user presses L1-A more than once within a 15 seconds
e65e5c2d2f32a99e8c5f740cabae9075dab03ce7Wyllys Ingersoll * window, and the previous L1-A soft interrupt is still pending, then
e65e5c2d2f32a99e8c5f740cabae9075dab03ce7Wyllys Ingersoll * we directly invoke the abort_sequence_enter.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys *
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * Since the "msg" argument passed to abort_sequence_enter can refer
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys * to a message anywhere in memory, including stack, it's copied into
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * abort_seq_msgbuf buffer for processing by the soft interrupt.
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys#define ABORT_SEQ_MSGBUFSZ 256
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#define FORCE_ABORT_SEQ_INTERVAL ((hrtime_t)15 * NANOSEC)
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllysstatic kmutex_t abort_seq_lock;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysstatic uint64_t abort_seq_inum; /* abort seq softintr # */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysstatic hrtime_t abort_seq_tstamp; /* hrtime of last abort seq */
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllysstatic size_t abort_seq_msglen; /* abort seq message length */
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllysstatic char abort_seq_msgbuf[ABORT_SEQ_MSGBUFSZ];
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys/*ARGSUSED0*/
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysstatic uint_t
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllysabort_seq_softintr(caddr_t arg)
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys{
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys char *msg;
d00756ccb34596a328f8a15d1965da5412d366d0wyllys char msgbuf[ABORT_SEQ_MSGBUFSZ];
d00756ccb34596a328f8a15d1965da5412d366d0wyllys
d00756ccb34596a328f8a15d1965da5412d366d0wyllys mutex_enter(&abort_seq_lock);
d00756ccb34596a328f8a15d1965da5412d366d0wyllys if (abort_enable != 0 && abort_seq_tstamp != 0LL) {
d00756ccb34596a328f8a15d1965da5412d366d0wyllys if (abort_seq_msglen > 0) {
d00756ccb34596a328f8a15d1965da5412d366d0wyllys bcopy(abort_seq_msgbuf, msgbuf, abort_seq_msglen);
d00756ccb34596a328f8a15d1965da5412d366d0wyllys msg = msgbuf;
d00756ccb34596a328f8a15d1965da5412d366d0wyllys } else
d00756ccb34596a328f8a15d1965da5412d366d0wyllys msg = NULL;
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys abort_seq_tstamp = 0LL;
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys mutex_exit(&abort_seq_lock);
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys#ifdef C2_AUDIT
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (audit_active)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys audit_enterprom(1);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#endif /* C2_AUDIT */
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys (*abort_seq_handler)(msg);
a44b45c8fa54b3a79a2de076aa2d8c48cd75dee4Huie-Ying Lee#ifdef C2_AUDIT
a44b45c8fa54b3a79a2de076aa2d8c48cd75dee4Huie-Ying Lee if (audit_active)
a44b45c8fa54b3a79a2de076aa2d8c48cd75dee4Huie-Ying Lee audit_exitprom(1);
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys#endif /* C2_AUDIT */
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys } else {
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys mutex_exit(&abort_seq_lock);
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys#ifdef C2_AUDIT
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys if (audit_active)
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys audit_enterprom(0);
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys#endif /* C2_AUDIT */
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys }
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys return (1);
a44b45c8fa54b3a79a2de076aa2d8c48cd75dee4Huie-Ying Lee}
a44b45c8fa54b3a79a2de076aa2d8c48cd75dee4Huie-Ying Lee
a44b45c8fa54b3a79a2de076aa2d8c48cd75dee4Huie-Ying Leevoid
a44b45c8fa54b3a79a2de076aa2d8c48cd75dee4Huie-Ying Leeabort_sequence_init(void)
a44b45c8fa54b3a79a2de076aa2d8c48cd75dee4Huie-Ying Lee{
a44b45c8fa54b3a79a2de076aa2d8c48cd75dee4Huie-Ying Lee mutex_init(&abort_seq_lock, NULL, MUTEX_SPIN, (void *)PIL_12);
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys abort_seq_tstamp = 0LL;
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys if (abort_seq_inum == 0)
a44b45c8fa54b3a79a2de076aa2d8c48cd75dee4Huie-Ying Lee abort_seq_inum = add_softintr(LOCK_LEVEL,
a44b45c8fa54b3a79a2de076aa2d8c48cd75dee4Huie-Ying Lee (softintrfunc)abort_seq_softintr, NULL, SOFTINT_ST);
a44b45c8fa54b3a79a2de076aa2d8c48cd75dee4Huie-Ying Lee}
a44b45c8fa54b3a79a2de076aa2d8c48cd75dee4Huie-Ying Lee
a44b45c8fa54b3a79a2de076aa2d8c48cd75dee4Huie-Ying Lee/*
a44b45c8fa54b3a79a2de076aa2d8c48cd75dee4Huie-Ying Lee * Machine dependent abort sequence handling
a44b45c8fa54b3a79a2de076aa2d8c48cd75dee4Huie-Ying Lee */
a44b45c8fa54b3a79a2de076aa2d8c48cd75dee4Huie-Ying Leevoid
a44b45c8fa54b3a79a2de076aa2d8c48cd75dee4Huie-Ying Leeabort_sequence_enter(char *msg)
a44b45c8fa54b3a79a2de076aa2d8c48cd75dee4Huie-Ying Lee{
a44b45c8fa54b3a79a2de076aa2d8c48cd75dee4Huie-Ying Lee int s, on_intr;
a44b45c8fa54b3a79a2de076aa2d8c48cd75dee4Huie-Ying Lee size_t msglen;
a44b45c8fa54b3a79a2de076aa2d8c48cd75dee4Huie-Ying Lee hrtime_t tstamp;
a44b45c8fa54b3a79a2de076aa2d8c48cd75dee4Huie-Ying Lee
a44b45c8fa54b3a79a2de076aa2d8c48cd75dee4Huie-Ying Lee if (abort_enable != 0) {
a44b45c8fa54b3a79a2de076aa2d8c48cd75dee4Huie-Ying Lee s = splhi();
a44b45c8fa54b3a79a2de076aa2d8c48cd75dee4Huie-Ying Lee on_intr = CPU_ON_INTR(CPU) || (spltoipl(s) > LOCK_LEVEL);
a44b45c8fa54b3a79a2de076aa2d8c48cd75dee4Huie-Ying Lee splx(s);
a44b45c8fa54b3a79a2de076aa2d8c48cd75dee4Huie-Ying Lee
a44b45c8fa54b3a79a2de076aa2d8c48cd75dee4Huie-Ying Lee tstamp = gethrtime();
a44b45c8fa54b3a79a2de076aa2d8c48cd75dee4Huie-Ying Lee mutex_enter(&abort_seq_lock);
a44b45c8fa54b3a79a2de076aa2d8c48cd75dee4Huie-Ying Lee
a44b45c8fa54b3a79a2de076aa2d8c48cd75dee4Huie-Ying Lee /*
a44b45c8fa54b3a79a2de076aa2d8c48cd75dee4Huie-Ying Lee * If we are on an interrupt stack and/or running at
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * PIL > LOCK_LEVEL, then we post a softint and invoke
a44b45c8fa54b3a79a2de076aa2d8c48cd75dee4Huie-Ying Lee * abort_seq_handler from there as we can't afford to
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * acquire any adaptive mutex here. However, if we
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * already have a pending softint, which was posted
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * within FORCE_ABORT_SEQ_INTERVAL duration, then we
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * bypass softint approach as our softint may be blocked
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * and the user really wants to drop into the debugger.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (on_intr && abort_seq_inum != 0 &&
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys (abort_seq_tstamp == 0LL || tstamp >
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys (abort_seq_tstamp + FORCE_ABORT_SEQ_INTERVAL))) {
e65e5c2d2f32a99e8c5f740cabae9075dab03ce7Wyllys Ingersoll abort_seq_tstamp = tstamp;
e65e5c2d2f32a99e8c5f740cabae9075dab03ce7Wyllys Ingersoll if (msg != NULL) {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys msglen = strlen(msg);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (msglen >= ABORT_SEQ_MSGBUFSZ)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys msglen = ABORT_SEQ_MSGBUFSZ - 1;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys bcopy(msg, abort_seq_msgbuf, msglen);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys abort_seq_msgbuf[msglen] = '\0';
6b35cb3cf158584a9408d44b9b6796564e8e1882Richard PALO abort_seq_msglen = msglen + 1;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys } else
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys abort_seq_msglen = 0;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys mutex_exit(&abort_seq_lock);
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys setsoftint(abort_seq_inum);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys } else {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys /*
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * Ignore any pending abort sequence softint
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * as we are invoking the abort_seq_handler
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * here.
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys */
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys abort_seq_tstamp = 0LL;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys mutex_exit(&abort_seq_lock);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#ifdef C2_AUDIT
448b8615fe9e8af757530284920a235430ead7e8wyllys if (!on_intr && audit_active)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys audit_enterprom(1);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#endif /* C2_AUDIT */
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys (*abort_seq_handler)(msg);
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys#ifdef C2_AUDIT
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (!on_intr && audit_active)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys audit_exitprom(1);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#endif /* C2_AUDIT */
448b8615fe9e8af757530284920a235430ead7e8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys } else {
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys#ifdef C2_AUDIT
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (audit_active)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys audit_enterprom(0);
e65e5c2d2f32a99e8c5f740cabae9075dab03ce7Wyllys Ingersoll#endif /* C2_AUDIT */
e65e5c2d2f32a99e8c5f740cabae9075dab03ce7Wyllys Ingersoll }
e65e5c2d2f32a99e8c5f740cabae9075dab03ce7Wyllys Ingersoll}
e65e5c2d2f32a99e8c5f740cabae9075dab03ce7Wyllys Ingersoll
e65e5c2d2f32a99e8c5f740cabae9075dab03ce7Wyllys Ingersoll/*
e65e5c2d2f32a99e8c5f740cabae9075dab03ce7Wyllys Ingersoll * Enter debugger. Called when the user types L1-A or break or whenever
e65e5c2d2f32a99e8c5f740cabae9075dab03ce7Wyllys Ingersoll * code wants to enter the debugger and possibly resume later.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * If the debugger isn't present, enter the PROM monitor.
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys *
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys * If console is a framebuffer which is powered off, it will be powered up
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * before jumping to the debugger. If we are called above lock level, a
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys * softint is triggered to reenter this code and allow the fb to be powered
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * up as in the less than lock level case. If this code is entered at greater
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys * than lock level and the fb is not already powered up, the msg argument
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys * will not be displayed.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys */
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllysvoid
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysdebug_enter(char *msg)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys{
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys label_t old_pcb;
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys int s;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys extern void pm_cfb_powerup(void);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys extern void pm_cfb_rele(void);
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys extern void pm_cfb_trigger(void);
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys extern int pm_cfb_check_and_hold(void);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
d00756ccb34596a328f8a15d1965da5412d366d0wyllys /*
d00756ccb34596a328f8a15d1965da5412d366d0wyllys * For platforms that use CPU signatures, update the signature
d00756ccb34596a328f8a15d1965da5412d366d0wyllys * to indicate that we are entering the debugger if we are in
d00756ccb34596a328f8a15d1965da5412d366d0wyllys * the middle of a panic flow.
d00756ccb34596a328f8a15d1965da5412d366d0wyllys */
d00756ccb34596a328f8a15d1965da5412d366d0wyllys if (panicstr)
d00756ccb34596a328f8a15d1965da5412d366d0wyllys CPU_SIGNATURE(OS_SIG, SIGST_EXIT, SIGSUBST_DEBUG, -1);
d00756ccb34596a328f8a15d1965da5412d366d0wyllys
d00756ccb34596a328f8a15d1965da5412d366d0wyllys if (!panicstr)
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys (void) callb_execute_class(CB_CL_ENTER_DEBUGGER, 0);
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys if (pm_cfb_check_and_hold())
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (getpil() > LOCK_LEVEL) {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys pm_cfb_trigger();
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys return;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys } else
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys pm_cfb_powerup();
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (msg)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys prom_printf("%s\n", msg);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys clear_watchdog_on_exit();
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys if ((s = getpil()) < ipltospl(12))
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys s = splzs();
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys old_pcb = curthread->t_pcb;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys (void) setjmp(&curthread->t_pcb);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (boothowto & RB_DEBUG)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys kdi_dvec_enter();
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys else
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys prom_enter_mon();
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys restore_watchdog_on_entry();
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
e65e5c2d2f32a99e8c5f740cabae9075dab03ce7Wyllys Ingersoll curthread->t_pcb = old_pcb;
e65e5c2d2f32a99e8c5f740cabae9075dab03ce7Wyllys Ingersoll splx(s);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys pm_cfb_rele();
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (!panicstr)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys (void) callb_execute_class(CB_CL_ENTER_DEBUGGER, 1);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
6b35cb3cf158584a9408d44b9b6796564e8e1882Richard PALO if (panicstr)
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys CPU_SIGNATURE(OS_SIG, SIGST_EXIT, SIGSUBST_PANIC_CONT, -1);
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys}
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys/*
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * Halt the machine and return to the monitor
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysvoid
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllyshalt(char *s)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys{
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys flush_windows();
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys stop_other_cpus(); /* send stop signal to other CPUs */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (s)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys prom_printf("(%s) ", s);
448b8615fe9e8af757530284920a235430ead7e8wyllys
448b8615fe9e8af757530284920a235430ead7e8wyllys /*
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * For Platforms that use CPU signatures, we
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * need to set the signature block to OS and
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys * the state to exiting for all the processors.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys CPU_SIGNATURE(OS_SIG, SIGST_EXIT, SIGSUBST_HALT, -1);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys prom_exit_to_mon();
e65e5c2d2f32a99e8c5f740cabae9075dab03ce7Wyllys Ingersoll /*NOTREACHED*/
e65e5c2d2f32a99e8c5f740cabae9075dab03ce7Wyllys Ingersoll}
e65e5c2d2f32a99e8c5f740cabae9075dab03ce7Wyllys Ingersoll
e65e5c2d2f32a99e8c5f740cabae9075dab03ce7Wyllys Ingersoll/*
e65e5c2d2f32a99e8c5f740cabae9075dab03ce7Wyllys Ingersoll * Halt the machine and power off the system.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys */
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllysvoid
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllyspower_down(const char *s)
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys{
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys flush_windows();
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys stop_other_cpus(); /* send stop signal to other CPUs */
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (s != NULL)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys prom_printf("(%s) ", s);
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys /*
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * For platforms that use CPU signatures, we need to set up the
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * signature blocks to indicate that we have an environmental
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys * interrupt request to power down, and then exit to the prom monitor.
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys CPU_SIGNATURE(OS_SIG, SIGST_EXIT, SIGSUBST_ENVIRON, -1);
d00756ccb34596a328f8a15d1965da5412d366d0wyllys prom_power_off();
d00756ccb34596a328f8a15d1965da5412d366d0wyllys /*
d00756ccb34596a328f8a15d1965da5412d366d0wyllys * If here is reached, for some reason prom's power-off command failed.
d00756ccb34596a328f8a15d1965da5412d366d0wyllys * Prom should have already printed out error messages. Exit to
d00756ccb34596a328f8a15d1965da5412d366d0wyllys * firmware.
d00756ccb34596a328f8a15d1965da5412d366d0wyllys */
d00756ccb34596a328f8a15d1965da5412d366d0wyllys prom_exit_to_mon();
d00756ccb34596a328f8a15d1965da5412d366d0wyllys /*NOTREACHED*/
d00756ccb34596a328f8a15d1965da5412d366d0wyllys}
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllysvoid
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllysdo_shutdown(void)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys{
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys proc_t *initpp;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys /*
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys * If we're still booting and init(1) isn't set up yet, simply halt.
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys mutex_enter(&pidlock);
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys initpp = prfind(P_INITPID);
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys mutex_exit(&pidlock);
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys if (initpp == NULL) {
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys extern void halt(char *);
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys prom_power_off();
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys halt("Power off the System"); /* just in case */
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys }
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys /*
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys * else, graceful shutdown with inittab and all getting involved
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys */
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys psignal(initpp, SIGPWR);
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys}
30a5e8fa1253cb33980ee4514743cf683f584b4ewyllys