diff options
author | bz <bz@FreeBSD.org> | 2010-05-24 16:41:05 +0000 |
---|---|---|
committer | bz <bz@FreeBSD.org> | 2010-05-24 16:41:05 +0000 |
commit | 6776200983bceda223944d82e99b820658ecd62b (patch) | |
tree | bdd087309119f3eab516764a7a8a1643c4691a2b /sys/ddb/db_command.c | |
parent | 36eb388782ebccd910604f919e2bd8f13cc05362 (diff) | |
download | FreeBSD-src-6776200983bceda223944d82e99b820658ecd62b.zip FreeBSD-src-6776200983bceda223944d82e99b820658ecd62b.tar.gz |
MFp4 @178364:
Implement an optional delay to the ddb reset/reboot command.
This allows textdumps to be run automatically with unattended reboots
after a resonable timeout, while still permitting an administrator to
break into debugger if attached to the console at the time of the
event for further debugging. Cap the maximum delay at 1 week to avoid
highly accidental results, and default to 15s in case of problems
parsing the timeout value.
Move hex2dec helper function from db_thread.c to db_command.c to make
it generally available and prefix it with a "db_" to avoid namespace
collisions.
Reviewed by: rwatson
MFC after: 4 weeks
Diffstat (limited to 'sys/ddb/db_command.c')
-rw-r--r-- | sys/ddb/db_command.c | 64 |
1 files changed, 59 insertions, 5 deletions
diff --git a/sys/ddb/db_command.c b/sys/ddb/db_command.c index 73de0c5..7c7f54e 100644 --- a/sys/ddb/db_command.c +++ b/sys/ddb/db_command.c @@ -661,13 +661,42 @@ out: #undef DB_ERROR } +/* + * Reboot. In case there is an additional argument, take it as delay in + * seconds. Default to 15s if we cannot parse it and make sure we will + * never wait longer than 1 week. Some code is similar to + * kern_shutdown.c:shutdown_panic(). + */ +#ifndef DB_RESET_MAXDELAY +#define DB_RESET_MAXDELAY (3600 * 24 * 7) +#endif + static void -db_reset(dummy1, dummy2, dummy3, dummy4) - db_expr_t dummy1; - boolean_t dummy2; - db_expr_t dummy3; - char * dummy4; +db_reset(db_expr_t addr, boolean_t have_addr, db_expr_t count __unused, + char *modif __unused) { + int delay, loop; + + if (have_addr) { + delay = (int)db_hex2dec(addr); + + /* If we parse to fail, use 15s. */ + if (delay == -1) + delay = 15; + + /* Cap at one week. */ + if ((uintmax_t)delay > (uintmax_t)DB_RESET_MAXDELAY) + delay = DB_RESET_MAXDELAY; + + db_printf("Automatic reboot in %d seconds - " + "press a key on the console to abort\n", delay); + for (loop = delay * 10; loop > 0; --loop) { + DELAY(1000 * 100); /* 1/10th second */ + /* Did user type a key? */ + if (cncheckc() != -1) + return; + } + } cpu_reset(); } @@ -771,3 +800,28 @@ db_stack_trace_all(db_expr_t dummy, boolean_t dummy2, db_expr_t dummy3, kdb_jmpbuf(prev_jb); } } + +/* + * Take the parsed expression value from the command line that was parsed + * as a hexadecimal value and convert it as if the expression was parsed + * as a decimal value. Returns -1 if the expression was not a valid + * decimal value. + */ +db_expr_t +db_hex2dec(db_expr_t expr) +{ + uintptr_t x, y; + db_expr_t val; + + y = 1; + val = 0; + x = expr; + while (x != 0) { + if (x % 16 > 9) + return (-1); + val += (x % 16) * (y); + x >>= 4; + y *= 10; + } + return (val); +} |