Mercurial > illumos > illumos-gate
changeset 3996:82246a4b06ef
6498483 Running SunVTS cpu tests on Sun-Fire-T200,Sun-Blade-T6300 causes shutdown due to watchdog timeout
author | ae112802 |
---|---|
date | Mon, 09 Apr 2007 11:39:46 -0700 |
parents | 63fc894a6109 |
children | acd5a5a557ce |
files | usr/src/uts/common/os/clock.c usr/src/uts/sparc/sys/wdt.h usr/src/uts/sun4/sys/wdt.h usr/src/uts/sun4u/os/mach_cpu_states.c usr/src/uts/sun4v/io/hardclk.c usr/src/uts/sun4v/os/wdt.c |
diffstat | 6 files changed, 149 insertions(+), 190 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/uts/common/os/clock.c Mon Apr 09 05:58:12 2007 -0700 +++ b/usr/src/uts/common/os/clock.c Mon Apr 09 11:39:46 2007 -0700 @@ -68,10 +68,6 @@ #include <sys/task.h> #include <sys/sdt.h> -#ifdef __sparc -#include <sys/wdt.h> -#endif - /* * for NTP support */ @@ -1822,10 +1818,6 @@ lbolt += hz; lbolt64 += hz; -#ifdef __sparc - watchdog_pat(); -#endif - if (!deadman_panic_timers) return; /* allow all timers to be manually disabled */
--- a/usr/src/uts/sparc/sys/wdt.h Mon Apr 09 05:58:12 2007 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _SYS_WDT_H -#define _SYS_WDT_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -extern void watchdog_init(void); -extern void watchdog_pat(void); -extern void watchdog_suspend(void); -extern void watchdog_resume(void); -extern void watchdog_clear(void); -extern void restore_watchdog_on_entry(void); - -extern int watchdog_enabled; -extern int watchdog_activated; - -#ifdef __cplusplus -} -#endif - -#endif /* _SYS_WDT_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/sun4/sys/wdt.h Mon Apr 09 11:39:46 2007 -0700 @@ -0,0 +1,49 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _SYS_WDT_H +#define _SYS_WDT_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifdef __cplusplus +extern "C" { +#endif + +extern void watchdog_init(void); +extern void watchdog_pat(void); +extern void watchdog_suspend(void); +extern void watchdog_resume(void); +extern void watchdog_clear(void); +extern void restore_watchdog_on_entry(void); + +extern int watchdog_enabled; +extern int watchdog_activated; + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_WDT_H */
--- a/usr/src/uts/sun4u/os/mach_cpu_states.c Mon Apr 09 05:58:12 2007 -0700 +++ b/usr/src/uts/sun4u/os/mach_cpu_states.c Mon Apr 09 11:39:46 2007 -0700 @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -462,46 +462,6 @@ } } -/* - * This null routine is only used by sun4v watchdog timer support. - */ -void -watchdog_init(void) -{ -} - -/* - * This null routine is only used by sun4v watchdog timer support. - */ -void -watchdog_pat(void) -{ -} - -/* - * This null routine is only used by sun4v watchdog timer support. - */ -void -watchdog_suspend(void) -{ -} - -/* - * This null routine is only used by sun4v watchdog timer support. - */ -void -watchdog_resume(void) -{ -} - -/* - * This null routine is only used by sun4v watchdog timer support. - */ -void -watchdog_clear(void) -{ -} - /*ARGSUSED*/ void mach_dump_buffer_init(void)
--- a/usr/src/uts/sun4v/io/hardclk.c Mon Apr 09 05:58:12 2007 -0700 +++ b/usr/src/uts/sun4v/io/hardclk.c Mon Apr 09 11:39:46 2007 -0700 @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -152,11 +152,6 @@ uint64_t ret; /* - * Pat the watchdog timer regularly. - */ - watchdog_pat(); - - /* * Make sure we don't get preempted * while getting the tod value. * getting preempted could mean we always
--- a/usr/src/uts/sun4v/os/wdt.c Mon Apr 09 05:58:12 2007 -0700 +++ b/usr/src/uts/sun4v/os/wdt.c Mon Apr 09 11:39:46 2007 -0700 @@ -29,6 +29,7 @@ #include <sys/hsvc.h> #include <sys/wdt.h> #include <sys/cmn_err.h> +#include <sys/cyclic.h> #include <sys/kmem.h> #include <sys/systm.h> #include <sys/sysmacros.h> @@ -38,36 +39,41 @@ #define WDT_ON 1 #define WDT_OFF 0 -#define WDT_DEFAULT_RESOLUTION 10 /* 10 milliseconds */ + /* * MILLISEC defines the number of milliseconds in a second. */ -#define WDT_MAX_RESOLUTION (1 * MILLISEC) /* 1 second */ -#define WDT_REGULAR_TIMEOUT (10 * MILLISEC) /* 10 seconds */ -#define WDT_LONG_TIMEOUT (60 * MILLISEC) /* 60 seconds */ +#define WDT_DEFAULT_RESOLUTION (1 * MILLISEC) /* Default resolution = 1s */ +#define WDT_MIN_TIMEOUT (1 * MILLISEC) /* Minimum timeout = 1s */ +#define WDT_REGULAR_TIMEOUT (10 * MILLISEC) /* Default timeout = 10s */ +#define WDT_LONG_TIMEOUT (60 * MILLISEC) /* Long timeout = 60s */ + #define WDT_MIN_COREAPI_MAJOR 1 #define WDT_MIN_COREAPI_MINOR 1 -/* - * The ratio to calculate the watchdog timer pat interval. - */ -#define WDT_PAT_INTERVAL(x) ((x) / 2) -int watchdog_enabled = 1; - -static void set_watchdog_pat_intervals(void); static void config_watchdog(uint64_t, int); +static void watchdog_cyclic_init(hrtime_t); /* * Flag used to pat/suspend/resume the watchdog timer. */ int watchdog_activated = WDT_OFF; -static uint64_t watchdog_regular_timeout = WDT_REGULAR_TIMEOUT; -static uint64_t watchdog_long_timeout = 0; + +/* + * Tuneable to control watchdog functionality. Watchdog can be + * disabled via /etc/system. + */ +int watchdog_enabled = 1; + +/* + * The following tuneable can be set via /etc/system to control + * watchdog pat frequency, which is set to approximately 44% of + * the timeout value. + */ +static uint64_t watchdog_timeout = WDT_REGULAR_TIMEOUT; + +static uint64_t watchdog_long_timeout = WDT_LONG_TIMEOUT; static uint64_t watchdog_resolution = WDT_DEFAULT_RESOLUTION; -static int64_t watchdog_last_pat = 0; /* The time of last pat. */ -static int64_t last_pat_interval = 0; /* The pat interval of last pat. */ -static int64_t watchdog_long_pat_interval = 0; -static int64_t watchdog_regular_pat_interval = 0; void watchdog_init(void) @@ -80,6 +86,7 @@ uint64_t major; uint64_t minor; uint64_t watchdog_max_timeout; + hrtime_t cyclic_interval; if (!watchdog_enabled) { return; @@ -89,7 +96,7 @@ major != WDT_MIN_COREAPI_MAJOR || minor < WDT_MIN_COREAPI_MINOR) { cmn_err(CE_NOTE, "Disabling watchdog as watchdog services are " - "not available\n"); + "not available\n"); watchdog_enabled = 0; return; } @@ -99,7 +106,7 @@ */ if ((mdp = md_get_handle()) == NULL) { cmn_err(CE_WARN, "Unable to initialize machine description, " - "watchdog is disabled."); + "watchdog is disabled."); watchdog_enabled = 0; return; } @@ -111,33 +118,38 @@ listp = kmem_zalloc(listsz, KM_SLEEP); nplat = md_scan_dag(mdp, md_root_node(mdp), - md_find_name(mdp, "platform"), md_find_name(mdp, "fwd"), listp); + md_find_name(mdp, "platform"), md_find_name(mdp, "fwd"), listp); ASSERT(nplat == 1); if (md_get_prop_val(mdp, listp[0], "watchdog-max-timeout", - &watchdog_max_timeout)) { - cmn_err(CE_WARN, "Cannot read watchdog-max-timeout, watchdog " - "is disabled."); + &watchdog_max_timeout) || watchdog_max_timeout < WDT_MIN_TIMEOUT) { + cmn_err(CE_WARN, "Invalid watchdog-max-timeout, watchdog " + "is disabled."); watchdog_enabled = 0; kmem_free(listp, listsz); (void) md_fini_handle(mdp); return; } - if (watchdog_max_timeout < WDT_REGULAR_TIMEOUT) { - cmn_err(CE_WARN, "Invalid watchdog-max-timeout value, watchdog " - "is disabled."); - watchdog_enabled = 0; - kmem_free(listp, listsz); - (void) md_fini_handle(mdp); - return; - } + /* + * Make sure that watchdog timeout value is within limits. + */ + if (watchdog_timeout < WDT_MIN_TIMEOUT) + watchdog_timeout = WDT_MIN_TIMEOUT; + else if (watchdog_timeout > WDT_LONG_TIMEOUT) + watchdog_timeout = WDT_LONG_TIMEOUT; + + if (watchdog_timeout > watchdog_max_timeout) + watchdog_timeout = watchdog_max_timeout; + + if (watchdog_long_timeout > watchdog_max_timeout) + watchdog_long_timeout = watchdog_max_timeout; if (md_get_prop_val(mdp, listp[0], "watchdog-resolution", - &watchdog_resolution)) { + &watchdog_resolution)) { cmn_err(CE_WARN, "Cannot read watchdog-resolution, watchdog " - "is disabled."); + "is disabled."); watchdog_enabled = 0; kmem_free(listp, listsz); (void) md_fini_handle(mdp); @@ -145,61 +157,51 @@ } if (watchdog_resolution == 0 || - watchdog_resolution > WDT_MAX_RESOLUTION) { + watchdog_resolution > WDT_DEFAULT_RESOLUTION) watchdog_resolution = WDT_DEFAULT_RESOLUTION; - } + kmem_free(listp, listsz); (void) md_fini_handle(mdp); - watchdog_long_timeout = MIN(WDT_LONG_TIMEOUT, watchdog_max_timeout); - /* * round the timeout to the nearest smaller value. */ watchdog_long_timeout -= - watchdog_long_timeout % watchdog_resolution; - watchdog_regular_timeout -= - watchdog_regular_timeout % watchdog_resolution; - set_watchdog_pat_intervals(); + watchdog_long_timeout % watchdog_resolution; + watchdog_timeout -= + watchdog_timeout % watchdog_resolution; + + config_watchdog(watchdog_timeout, WDT_ON); - config_watchdog(watchdog_regular_timeout, WDT_ON); + /* + * Cyclic need to be fired twice the frequency of regular + * watchdog timeout. Pedantic here and setting cyclic + * frequency to approximately 44% of watchdog_timeout. + */ + cyclic_interval = (watchdog_timeout >> 1) - (watchdog_timeout >> 4); + /* + * Note that regular timeout interval is in millisecond, + * therefore to get cyclic interval in nanosecond need to + * multiply by MICROSEC. + */ + cyclic_interval *= MICROSEC; + + watchdog_cyclic_init(cyclic_interval); } /* - * Pat the watchdog timer periodically, for regular pat in tod_get when - * the kernel runs normally and long pat in deadman when panicking. + * Pat the watchdog timer periodically using the hypervisor API. + * Regular pat occurs when the system runs normally. + * Long pat is when system panics. */ void watchdog_pat() { - int64_t pat_interval; - int64_t current_lbolt64; - uint64_t timeout; - if (watchdog_enabled && watchdog_activated) { - if (panicstr) { - /* - * long timeout is only used while panicking. - */ - timeout = watchdog_long_timeout; - pat_interval = watchdog_long_pat_interval; - } else { - timeout = watchdog_regular_timeout; - pat_interval = watchdog_regular_pat_interval; - } - - current_lbolt64 = lbolt64; - - if ((current_lbolt64 - watchdog_last_pat) - >= last_pat_interval) { - /* - * Pat the watchdog via hv api: - */ - config_watchdog(timeout, WDT_ON); - - last_pat_interval = pat_interval; - watchdog_last_pat = current_lbolt64; - } + if (panicstr) + config_watchdog(watchdog_long_timeout, WDT_ON); + else + config_watchdog(watchdog_timeout, WDT_ON); } } @@ -224,7 +226,7 @@ if (panicstr) { config_watchdog(watchdog_long_timeout, WDT_ON); } else { - config_watchdog(watchdog_regular_timeout, WDT_ON); + config_watchdog(watchdog_timeout, WDT_ON); } } } @@ -237,19 +239,6 @@ } } -/* - * Set the pat intervals for both regular (when Solaris is running), - * and long timeout (i.e., when panicking) cases. - */ -static void -set_watchdog_pat_intervals(void) -{ - watchdog_regular_pat_interval = - MSEC_TO_TICK(WDT_PAT_INTERVAL(watchdog_regular_timeout)); - watchdog_long_pat_interval = - MSEC_TO_TICK(WDT_PAT_INTERVAL(watchdog_long_timeout)); -} - static void config_watchdog(uint64_t timeout, int new_state) { @@ -260,7 +249,30 @@ ret = hv_mach_set_watchdog(timeout, &time_remaining); if (ret != H_EOK) { cmn_err(CE_WARN, "Failed to operate on the watchdog. " - "Error = 0x%lx", ret); + "Error = 0x%lx", ret); watchdog_enabled = 0; } } + +/* + * Once the watchdog cyclic is initialized, it won't be removed. + * The only way to not add the watchdog cyclic is to disable the watchdog + * by setting the watchdog_enabled to 0 in /etc/system file. + */ +static void +watchdog_cyclic_init(hrtime_t wdt_cyclic_interval) +{ + cyc_handler_t hdlr; + cyc_time_t when; + + hdlr.cyh_func = (cyc_func_t)watchdog_pat; + hdlr.cyh_level = CY_HIGH_LEVEL; + hdlr.cyh_arg = NULL; + + when.cyt_when = 0; + when.cyt_interval = wdt_cyclic_interval; + + mutex_enter(&cpu_lock); + (void) cyclic_add(&hdlr, &when); + mutex_exit(&cpu_lock); +}