Mercurial > illumos > fmac
changeset 2036:6b118cfdcfda onnv_41
FWARC 2005/367 sun4v watchdog service API
FWARC 2006/093 sun4v watchdog API update
6354584 Add watchdog timer support in sun4v
author | wentaoy |
---|---|
date | Mon, 22 May 2006 18:36:17 -0700 |
parents | a29bc457bcb9 |
children | 132880d31aba |
files | usr/src/uts/common/os/clock.c usr/src/uts/sparc/sys/wdt.h usr/src/uts/sun4/os/cpu_states.c usr/src/uts/sun4u/os/mach_cpu_states.c usr/src/uts/sun4v/Makefile.files usr/src/uts/sun4v/io/hardclk.c usr/src/uts/sun4v/ml/hcall.s usr/src/uts/sun4v/os/mach_cpu_states.c usr/src/uts/sun4v/os/wdt.c usr/src/uts/sun4v/sys/hypervisor_api.h |
diffstat | 10 files changed, 450 insertions(+), 21 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/uts/common/os/clock.c Mon May 22 15:43:31 2006 -0700 +++ b/usr/src/uts/common/os/clock.c Mon May 22 18:36:17 2006 -0700 @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * 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. @@ -24,7 +23,7 @@ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -70,6 +69,10 @@ #include <sys/chip.h> #include <sys/sdt.h> +#ifdef __sparc +#include <sys/wdt.h> +#endif + /* * for NTP support */ @@ -1851,6 +1854,10 @@ lbolt += hz; lbolt64 += hz; +#ifdef __sparc + watchdog_pat(); +#endif + if (!deadman_panic_timers) return; /* allow all timers to be manually disabled */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/sparc/sys/wdt.h Mon May 22 18:36:17 2006 -0700 @@ -0,0 +1,46 @@ +/* + * 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 2006 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); + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_WDT_H */
--- a/usr/src/uts/sun4/os/cpu_states.c Mon May 22 15:43:31 2006 -0700 +++ b/usr/src/uts/sun4/os/cpu_states.c Mon May 22 18:36:17 2006 -0700 @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * 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. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -37,6 +36,7 @@ #include <sys/ivintr.h> #include <sys/kdi.h> #include <sys/callb.h> +#include <sys/wdt.h> #ifdef TRAPTRACE #include <sys/traptrace.h> @@ -63,10 +63,8 @@ /* * Platform tunable to disable the h/w watchdog timer. */ -int disable_watchdog_on_exit = 0; extern void clear_watchdog_on_exit(void); - /* * On sun4u platform, abort_sequence_enter() can be called at high PIL * and we can't afford to acquire any adaptive mutex or use any @@ -265,6 +263,8 @@ else prom_enter_mon(); + restore_watchdog_on_entry(); + curthread->t_pcb = old_pcb; splx(s); pm_cfb_rele();
--- a/usr/src/uts/sun4u/os/mach_cpu_states.c Mon May 22 15:43:31 2006 -0700 +++ b/usr/src/uts/sun4u/os/mach_cpu_states.c Mon May 22 18:36:17 2006 -0700 @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * 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. @@ -50,7 +49,7 @@ extern u_longlong_t gettick(); static void reboot_machine(char *); -extern int disable_watchdog_on_exit; +int disable_watchdog_on_exit = 0; /* * Machine dependent code to reboot. @@ -434,6 +433,14 @@ } } +/* + * This null routine is only used by sun4v watchdog timer support. + */ +void +restore_watchdog_on_entry(void) +{ +} + int kdi_watchdog_disable(void) { @@ -456,6 +463,46 @@ } } +/* + * 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/Makefile.files Mon May 22 15:43:31 2006 -0700 +++ b/usr/src/uts/sun4v/Makefile.files Mon May 22 18:36:17 2006 -0700 @@ -78,6 +78,7 @@ CORE_OBJS += promif_version.o CORE_OBJS += sfmmu_kdi.o CORE_OBJS += swtch.o +CORE_OBJS += wdt.o CORE_OBJS += xhat_sfmmu.o CORE_OBJS += mdesc_diff.o
--- a/usr/src/uts/sun4v/io/hardclk.c Mon May 22 15:43:31 2006 -0700 +++ b/usr/src/uts/sun4v/io/hardclk.c Mon May 22 18:36:17 2006 -0700 @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * 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. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -49,6 +48,7 @@ #include <sys/atomic.h> #include <sys/cpu_module.h> #include <sys/hypervisor_api.h> +#include <sys/wdt.h> uint_t sys_clock_mhz = 0; uint64_t sys_tick_freq = 0; @@ -61,6 +61,10 @@ void clkstart(void) { + /* + * Now is a good time to activate hardware watchdog. + */ + watchdog_init(); } /* @@ -146,6 +150,12 @@ int i; unsigned int spl_old; uint64_t ret; + + /* + * Pat the watchdog timer regularly. + */ + watchdog_pat(); + /* * Make sure we don't get preempted * while getting the tod value.
--- a/usr/src/uts/sun4v/ml/hcall.s Mon May 22 15:43:31 2006 -0700 +++ b/usr/src/uts/sun4v/ml/hcall.s Mon May 22 18:36:17 2006 -0700 @@ -321,6 +321,11 @@ uint64_t *supported_minor) { return (0); } +/*ARGSUSED*/ +uint64_t +hv_mach_set_watchdog(uint64_t timeout, uint64_t *time_remaining) +{ return (0); } + #else /* lint || __lint */ /* @@ -658,6 +663,20 @@ stx %o1, [%o2] SET_SIZE(hv_dump_buf_update) + /* + * arg0 - timeout value (%o0) + * + * ret0 - status (%o0) + * ret1 - time_remaining (%o1) + * hv_mach_set_watchdog(uint64_t timeout, uint64_t *time_remaining) + */ + ENTRY(hv_mach_set_watchdog) + mov %o1, %o2 + mov MACH_SET_WATCHDOG, %o5 + ta FAST_TRAP + retl + stx %o1, [%o2] + SET_SIZE(hv_mach_set_watchdog) /* * For memory scrub
--- a/usr/src/uts/sun4v/os/mach_cpu_states.c Mon May 22 15:43:31 2006 -0700 +++ b/usr/src/uts/sun4v/os/mach_cpu_states.c Mon May 22 18:36:17 2006 -0700 @@ -50,6 +50,7 @@ #include <sys/callb.h> #include <sys/mdesc.h> #include <sys/mach_descrip.h> +#include <sys/wdt.h> /* * hvdump_buf_va is a pointer to the currently-configured hvdump_buf. @@ -151,6 +152,8 @@ */ reset_leaves(); + watchdog_clear(); + if (fcn == AD_HALT) { halt((char *)NULL); } else if (fcn == AD_POWEROFF) { @@ -467,23 +470,32 @@ void clear_watchdog_on_exit(void) { + prom_printf("Debugging requested; hardware watchdog suspended.\n"); + (void) watchdog_suspend(); } +/* + * Restore the watchdog timer when returning from a debugger + * after a panic or L1-A and resume watchdog pat. + */ void -clear_watchdog_timer(void) +restore_watchdog_on_entry() { + watchdog_resume(); } int kdi_watchdog_disable(void) { - return (0); /* sun4v has no watchdog */ + watchdog_suspend(); + + return (0); } void kdi_watchdog_restore(void) { - /* nothing to do -- no watchdog to re-enable */ + watchdog_resume(); } void @@ -977,6 +989,25 @@ kdi->mkdi_get_stick = kdi_get_stick; } +static void +sun4v_system_claim(void) +{ + watchdog_suspend(); +} + +static void +sun4v_system_release(void) +{ + watchdog_resume(); +} + +void +plat_kdi_init(kdi_t *kdi) +{ + kdi->pkdi_system_claim = sun4v_system_claim; + kdi->pkdi_system_release = sun4v_system_release; +} + /* * Routine to return memory information associated * with a physical address and syndrome.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/sun4v/os/wdt.c Mon May 22 18:36:17 2006 -0700 @@ -0,0 +1,266 @@ +/* + * 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 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <sys/types.h> +#include <sys/hsvc.h> +#include <sys/wdt.h> +#include <sys/cmn_err.h> +#include <sys/kmem.h> +#include <sys/systm.h> +#include <sys/sysmacros.h> +#include <sys/hypervisor_api.h> +#include <sys/mach_descrip.h> +#include <sys/mdesc.h> + +#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_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); + +/* + * Flag used to pat/suspend/resume the watchdog timer. + */ +static int watchdog_activated = WDT_OFF; +static uint64_t watchdog_regular_timeout = WDT_REGULAR_TIMEOUT; +static uint64_t watchdog_long_timeout = 0; +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) +{ + int num_nodes; + int nplat; + md_t *mdp; + mde_cookie_t *listp = NULL; + int listsz; + uint64_t major; + uint64_t minor; + uint64_t watchdog_max_timeout; + + if (!watchdog_enabled) { + return; + } + + if (hsvc_version(HSVC_GROUP_CORE, &major, &minor) != 0 || + major != WDT_MIN_COREAPI_MAJOR || + minor < WDT_MIN_COREAPI_MINOR) { + cmn_err(CE_NOTE, "Disabling watchdog as watchdog services are " + "not available\n"); + watchdog_enabled = 0; + return; + } + + /* + * Get the watchdog-max-timeout and watchdog-resolution MD properties. + */ + if ((mdp = md_get_handle()) == NULL) { + cmn_err(CE_WARN, "Unable to initialize machine description, " + "watchdog is disabled."); + watchdog_enabled = 0; + return; + } + + num_nodes = md_node_count(mdp); + ASSERT(num_nodes > 0); + + listsz = num_nodes * sizeof (mde_cookie_t); + 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); + + 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_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; + } + + if (md_get_prop_val(mdp, listp[0], "watchdog-resolution", + &watchdog_resolution)) { + cmn_err(CE_WARN, "Cannot read watchdog-resolution, watchdog " + "is disabled."); + watchdog_enabled = 0; + kmem_free(listp, listsz); + (void) md_fini_handle(mdp); + return; + } + + if (watchdog_resolution == 0 || + watchdog_resolution > WDT_MAX_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(); + + config_watchdog(watchdog_regular_timeout, WDT_ON); +} + +/* + * Pat the watchdog timer periodically, for regular pat in tod_get when + * the kernel runs normally and long pat in deadman when panicking. + */ +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; + } + } +} + +/* + * We don't save/restore the remaining watchdog timeout time at present. + */ +void +watchdog_suspend() +{ + if (watchdog_enabled && watchdog_activated) { + config_watchdog(0, WDT_OFF); + } +} + +/* + * We don't save/restore the remaining watchdog timeout time at present. + */ +void +watchdog_resume() +{ + if (watchdog_enabled && !watchdog_activated) { + if (panicstr) { + config_watchdog(watchdog_long_timeout, WDT_ON); + } else { + config_watchdog(watchdog_regular_timeout, WDT_ON); + } + } +} + +void +watchdog_clear() +{ + if (watchdog_enabled && watchdog_activated) { + config_watchdog(0, WDT_OFF); + } +} + +/* + * 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) +{ + uint64_t time_remaining; + uint64_t ret; + + watchdog_activated = new_state; + 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); + watchdog_enabled = 0; + } +}
--- a/usr/src/uts/sun4v/sys/hypervisor_api.h Mon May 22 15:43:31 2006 -0700 +++ b/usr/src/uts/sun4v/sys/hypervisor_api.h Mon May 22 18:36:17 2006 -0700 @@ -90,6 +90,7 @@ #define HV_MACH_EXIT 0x00 #define HV_MACH_DESC 0x01 #define HV_MACH_SIR 0x02 +#define MACH_SET_WATCHDOG 0x05 #define HV_CPU_START 0x10 #define HV_CPU_STOP 0x11 @@ -352,6 +353,7 @@ extern uint64_t hv_ttrace_enable(uint64_t, uint64_t *); extern uint64_t hv_ttrace_freeze(uint64_t, uint64_t *); extern uint64_t hv_dump_buf_update(uint64_t, uint64_t, uint64_t *); +extern uint64_t hv_mach_set_watchdog(uint64_t, uint64_t *); extern int64_t hv_cnputchar(uint8_t); extern int64_t hv_cngetchar(uint8_t *);