Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F106177517
D12777.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
16 KB
Referenced Files
None
Subscribers
None
D12777.diff
View Options
Index: lib/libc/sys/reboot.2
===================================================================
--- lib/libc/sys/reboot.2
+++ lib/libc/sys/reboot.2
@@ -28,7 +28,7 @@
.\" @(#)reboot.2 8.1 (Berkeley) 6/4/93
.\" $FreeBSD$
.\"
-.Dd September 18, 2015
+.Dd October 24, 2017
.Dt REBOOT 2
.Os
.Sh NAME
@@ -84,6 +84,14 @@
.It Dv RB_HALT
The processor is simply halted; no reboot takes place.
This option should be used with caution.
+.It Dv RB_POWERCYCLE
+After halting, the shutdown code will do what it can to turn
+off the power and then turn the power back on.
+This requires hardware support, usually an auxiliary microprocessor
+that can sequence the power supply.
+At present only the
+.Xr ipmi 4
+driver implements this feature.
.It Dv RB_POWEROFF
After halting, the shutdown code will do what it can to turn
off the power.
Index: lib/libsysdecode/flags.c
===================================================================
--- lib/libsysdecode/flags.c
+++ lib/libsysdecode/flags.c
@@ -647,9 +647,9 @@
/*
* RB_AUTOBOOT is special in that its value is zero, but it is
* also an implied argument if a different operation is not
- * requested via RB_HALT, RB_POWEROFF, or RB_REROOT.
+ * requested via RB_HALT, RB_POWERCYCLE, RB_POWEROFF, or RB_REROOT.
*/
- if (howto != 0 && (howto & (RB_HALT | RB_POWEROFF | RB_REROOT)) == 0) {
+ if (howto != 0 && (howto & (RB_HALT | RB_POWEROFF | RB_REROOT | RB_POWERCYCLE)) == 0) {
fputs("RB_AUTOBOOT|", fp);
printed = true;
} else
Index: sbin/init/init.8
===================================================================
--- sbin/init/init.8
+++ sbin/init/init.8
@@ -286,6 +286,7 @@
.It Sy "Run-level Signal Action"
.It Cm 0 Ta Dv SIGUSR1 Ta "Halt"
.It Cm 0 Ta Dv SIGUSR2 Ta "Halt and turn the power off"
+.It Cm 0 Ta Dv SIGWINCH Ta "Halt and turn the power off and then back on"
.It Cm 1 Ta Dv SIGTERM Ta "Go to single-user mode"
.It Cm 6 Ta Dv SIGINT Ta "Reboot the machine"
.It Cm c Ta Dv SIGTSTP Ta "Block further logins"
Index: sbin/init/init.c
===================================================================
--- sbin/init/init.c
+++ sbin/init/init.c
@@ -305,12 +305,12 @@
handle(disaster, SIGABRT, SIGFPE, SIGILL, SIGSEGV, SIGBUS, SIGXCPU,
SIGXFSZ, 0);
handle(transition_handler, SIGHUP, SIGINT, SIGEMT, SIGTERM, SIGTSTP,
- SIGUSR1, SIGUSR2, 0);
+ SIGUSR1, SIGUSR2, SIGWINCH, 0);
handle(alrm_handler, SIGALRM, 0);
sigfillset(&mask);
delset(&mask, SIGABRT, SIGFPE, SIGILL, SIGSEGV, SIGBUS, SIGSYS,
SIGXCPU, SIGXFSZ, SIGHUP, SIGINT, SIGEMT, SIGTERM, SIGTSTP,
- SIGALRM, SIGUSR1, SIGUSR2, 0);
+ SIGALRM, SIGUSR1, SIGUSR2, SIGWINCH, 0);
sigprocmask(SIG_SETMASK, &mask, (sigset_t *) 0);
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
@@ -1557,8 +1557,9 @@
current_state == clean_ttys || current_state == catatonia)
requested_transition = clean_ttys;
break;
+ case SIGWINCH:
case SIGUSR2:
- howto = RB_POWEROFF;
+ howto = sig == SIGUSR2 ? RB_POWEROFF : RB_POWERCYCLE;
case SIGUSR1:
howto |= RB_HALT;
case SIGINT:
Index: sbin/reboot/reboot.8
===================================================================
--- sbin/reboot/reboot.8
+++ sbin/reboot/reboot.8
@@ -28,7 +28,7 @@
.\" @(#)reboot.8 8.1 (Berkeley) 6/9/93
.\" $FreeBSD$
.\"
-.Dd March 19, 2017
+.Dd October 23, 2017
.Dt REBOOT 8
.Os
.Sh NAME
@@ -42,7 +42,7 @@
.Op Fl lNnpq
.Op Fl k Ar kernel
.Nm
-.Op Fl dlNnpqr
+.Op Fl cdlNnpqr
.Op Fl k Ar kernel
.Nm fasthalt
.Op Fl lNnpq
@@ -66,6 +66,20 @@
.Pp
The options are as follows:
.Bl -tag -width indent
+.It Fl c
+The system will turn off the power and then turn it back on if it can.
+If the power down action fails, the system
+will halt or reboot normally, depending on whether
+.Nm halt
+or
+.Nm
+was called.
+At the present time, only the
+.Xr ipmi 4
+driver implements the power cycle functionality and only on hardware
+with a BMC that supports power cycling.
+Unlike power off, the amount of hardware that supports power cycling
+is small.
.It Fl d
The system is requested to create a crash dump.
This option is
@@ -162,6 +176,7 @@
.Sh SEE ALSO
.Xr kenv 1 ,
.Xr getutxent 3 ,
+.Xr ipmi 4 ,
.Xr boot 8 ,
.Xr dumpon 8 ,
.Xr nextboot 8 ,
Index: sbin/reboot/reboot.c
===================================================================
--- sbin/reboot/reboot.c
+++ sbin/reboot/reboot.c
@@ -77,8 +77,11 @@
} else
howto = 0;
lflag = nflag = qflag = Nflag = 0;
- while ((ch = getopt(argc, argv, "dk:lNnpqr")) != -1)
+ while ((ch = getopt(argc, argv, "cdk:lNnpqr")) != -1)
switch(ch) {
+ case 'c':
+ howto |= RB_POWERCYCLE;
+ break;
case 'd':
howto |= RB_DUMP;
break;
@@ -116,8 +119,10 @@
errx(1, "cannot dump (-d) when halting; must reboot instead");
if (Nflag && (howto & RB_NOSYNC) != 0)
errx(1, "-N cannot be used with -n");
+ if ((howto & RB_POWEROFF) && (howto & RB_POWERCYCLE))
+ errx(1, "-c and -p cannot be used together");
if ((howto & RB_REROOT) != 0 && howto != RB_REROOT)
- errx(1, "-r cannot be used with -d, -n, or -p");
+ errx(1, "-r cannot be used with -c, -d, -n, or -p");
if (geteuid()) {
errno = EPERM;
err(1, NULL);
@@ -151,6 +156,12 @@
} else if (howto & RB_REROOT) {
openlog("reroot", 0, LOG_AUTH | LOG_CONS);
syslog(LOG_CRIT, "rerooted by %s", user);
+ } else if (howto & RB_POWEROFF) {
+ openlog("reboot", 0, LOG_AUTH | LOG_CONS);
+ syslog(LOG_CRIT, "powered off by %s", user);
+ } else if (howto & RB_POWERCYCLE) {
+ openlog("reboot", 0, LOG_AUTH | LOG_CONS);
+ syslog(LOG_CRIT, "power cycled by %s", user);
} else {
openlog("reboot", 0, LOG_AUTH | LOG_CONS);
syslog(LOG_CRIT, "rebooted by %s", user);
Index: sbin/shutdown/shutdown.8
===================================================================
--- sbin/shutdown/shutdown.8
+++ sbin/shutdown/shutdown.8
@@ -28,7 +28,7 @@
.\" @(#)shutdown.8 8.2 (Berkeley) 4/27/95
.\" $FreeBSD$
.\"
-.Dd September 21, 2016
+.Dd October 23, 2017
.Dt SHUTDOWN 8
.Os
.Sh NAME
@@ -39,7 +39,7 @@
.Nm
.Op Fl
.Oo
-.Fl h | Fl p |
+.Fl c | Fl h | Fl p |
.Fl r | Fl k
.Oc
.Oo
@@ -59,12 +59,22 @@
.Pp
The following options are available:
.Bl -tag -width indent
+.It Fl c
+The system is power cycled (power turned off and then back on)
+at the specified time.
+If the hardware doesn't support power cycle, the system will be
+halted.
+At the present time, only systems with BMC supported by the
+.Xr ipmi 4
+driver that implement this functionality support this flag.
+The amount of time the system is off is dependent on the device
+that implements this feature.
.It Fl h
The system is halted at the specified
.Ar time .
.It Fl p
The system is halted and the power is turned off
-(hardware support required)
+(hardware support required, otherwise the system is halted)
at the specified
.Ar time .
.It Fl r
@@ -79,6 +89,7 @@
system multi-user with logins disabled (for all but super-user).
.It Fl o
If one of the
+.Fl c ,
.Fl h ,
.Fl p
or
Index: sbin/shutdown/shutdown.c
===================================================================
--- sbin/shutdown/shutdown.c
+++ sbin/shutdown/shutdown.c
@@ -89,7 +89,7 @@
#undef S
static time_t offset, shuttime;
-static int dohalt, dopower, doreboot, killflg, mbuflen, oflag;
+static int docycle, dohalt, dopower, doreboot, killflg, mbuflen, oflag;
static char mbuf[BUFSIZ];
static const char *nosync, *whom;
@@ -141,11 +141,14 @@
goto poweroff;
}
- while ((ch = getopt(argc, argv, "-hknopr")) != -1)
+ while ((ch = getopt(argc, argv, "-chknopr")) != -1)
switch (ch) {
case '-':
readstdin = 1;
break;
+ case 'c':
+ docycle = 1;
+ break;
case 'h':
dohalt = 1;
break;
@@ -174,11 +177,11 @@
if (argc < 1)
usage((char *)NULL);
- if (killflg + doreboot + dohalt + dopower > 1)
- usage("incompatible switches -h, -k, -p and -r");
+ if (killflg + doreboot + dohalt + dopower + docycle > 1)
+ usage("incompatible switches -c, -h, -k, -p and -r");
- if (oflag && !(dohalt || dopower || doreboot))
- usage("-o requires -h, -p or -r");
+ if (oflag && !(dohalt || dopower || doreboot || docycle))
+ usage("-o requires -c, -h, -p or -r");
if (nosync != NULL && !oflag)
usage("-n requires -o");
@@ -356,8 +359,8 @@
char *empty_environ[] = { NULL };
syslog(LOG_NOTICE, "%s by %s: %s",
- doreboot ? "reboot" : dohalt ? "halt" : dopower ? "power-down" :
- "shutdown", whom, mbuf);
+ doreboot ? "reboot" : dohalt ? "halt" : dopower ? "power-down" :
+ docycle ? "power-cycle" : "shutdown", whom, mbuf);
(void)printf("\r\nSystem shutdown time has arrived\007\007\r\n");
if (killflg) {
@@ -367,6 +370,8 @@
#ifdef DEBUG
if (doreboot)
(void)printf("reboot");
+ else if (docycle)
+ (void)printf("power-cycle");
else if (dohalt)
(void)printf("halt");
else if (dopower)
@@ -379,6 +384,7 @@
(void)kill(1, doreboot ? SIGINT : /* reboot */
dohalt ? SIGUSR1 : /* halt */
dopower ? SIGUSR2 : /* power-down */
+ docycle ? SIGWINCH : /* power-cycle */
SIGTERM); /* single-user */
} else {
if (doreboot) {
@@ -402,6 +408,13 @@
_PATH_HALT);
warn(_PATH_HALT);
}
+ else if (docycle) {
+ execle(_PATH_HALT, "halt", "-l", "-c", nosync,
+ (char *)NULL, empty_environ);
+ syslog(LOG_ERR, "shutdown: can't exec %s: %m.",
+ _PATH_HALT);
+ warn(_PATH_HALT);
+ }
(void)kill(1, SIGTERM); /* to single-user */
}
#endif
Index: share/man/man4/ipmi.4
===================================================================
--- share/man/man4/ipmi.4
+++ share/man/man4/ipmi.4
@@ -90,6 +90,17 @@
.Tn Linux
driver; however, not all features described in the
standard are supported.
+.Pp
+The
+.Nm
+driver implements the power cycling option to
+.Xr shutdown 8
+to implement power cycling of the system.
+The motherboard's BMC must support the chassis device and the optional
+power cycle subcomand of the chassis control command as described in section 28.3
+if the IPMI standard.
+The length of time the system is off will be at least one second, but
+may be longer if the power cycle interval has been set (see section 28.9).
.Sh IOCTLS
Sending and receiving messages through the
.Nm
@@ -179,6 +190,8 @@
.Sh SEE ALSO
.Xr ioctl 2 ,
.Xr watchdog 4 ,
+.Xr reboot 8 ,
+.Xr shutdown 8 ,
.Xr watchdog 8 ,
.Xr watchdogd 8 ,
.Xr watchdog 9
Index: sys/cam/ata/ata_da.c
===================================================================
--- sys/cam/ata/ata_da.c
+++ sys/cam/ata/ata_da.c
@@ -3513,7 +3513,7 @@
adaflush();
if (ada_spindown_shutdown != 0 &&
- (howto & (RB_HALT | RB_POWEROFF)) != 0)
+ (howto & (RB_HALT | RB_POWEROFF | RB_POWERCYCLE)) != 0)
adaspindown(ATA_STANDBY_IMMEDIATE, 0);
}
Index: sys/dev/ipmi/ipmi.c
===================================================================
--- sys/dev/ipmi/ipmi.c
+++ sys/dev/ipmi/ipmi.c
@@ -36,6 +36,7 @@
#include <sys/malloc.h>
#include <sys/module.h>
#include <sys/poll.h>
+#include <sys/reboot.h>
#include <sys/rman.h>
#include <sys/selinfo.h>
#include <sys/sysctl.h>
@@ -689,6 +690,45 @@
}
}
+static void
+ipmi_power_cycle(void *arg, int howto)
+{
+ struct ipmi_softc *sc = arg;
+ struct ipmi_request *req;
+
+ /*
+ * Ignore everything except power cycling requests
+ */
+ if ((howto & RB_POWERCYCLE) == 0)
+ return;
+
+ device_printf(sc->ipmi_dev, "Power cycling using IPMI\n");
+
+ /*
+ * Send a CHASSIS_CONTROL command to the CHASSIS device, subcommand 2
+ * as described in IPMI v2.0 spec section 28.3.
+ */
+ IPMI_ALLOC_DRIVER_REQUEST(req, IPMI_ADDR(IPMI_CHASSIS_REQUEST, 0),
+ IPMI_CHASSIS_CONTROL, 1, 0);
+ req->ir_request[0] = IPMI_CC_POWER_CYCLE;
+
+ ipmi_submit_driver_request(sc, req, MAX_TIMEOUT);
+
+ if (req->ir_error != 0 || req->ir_compcode != 0) {
+ device_printf(sc->ipmi_dev, "Power cycling via IPMI failed code %#x %#x\n",
+ req->ir_error, req->ir_compcode);
+ return;
+ }
+
+ /*
+ * BMCs are notoriously slow, give it up to 10s to effect the power
+ * down leg of the power cycle. If that fails, fallback to the next
+ * hanlder in the shutdown_final chain and/or the platform failsafe.
+ */
+ DELAY(10 * 1000 * 1000);
+ device_printf(sc->ipmi_dev, "Power cycling via IPMI timed out\n");
+}
+
static void
ipmi_startup(void *arg)
{
@@ -737,10 +777,12 @@
}
device_printf(dev, "IPMI device rev. %d, firmware rev. %d.%d%d, "
- "version %d.%d\n",
- req->ir_reply[1] & 0x0f,
- req->ir_reply[2] & 0x7f, req->ir_reply[3] >> 4, req->ir_reply[3] & 0x0f,
- req->ir_reply[4] & 0x0f, req->ir_reply[4] >> 4);
+ "version %d.%d, device support mask %#x\n",
+ req->ir_reply[1] & 0x0f,
+ req->ir_reply[2] & 0x7f, req->ir_reply[3] >> 4, req->ir_reply[3] & 0x0f,
+ req->ir_reply[4] & 0x0f, req->ir_reply[4] >> 4, req->ir_reply[5]);
+
+ sc->ipmi_dev_support = req->ir_reply[5];
IPMI_INIT_DRIVER_REQUEST(req, IPMI_ADDR(IPMI_APP_REQUEST, 0),
IPMI_CLEAR_FLAGS, 1, 0);
@@ -792,6 +834,17 @@
return;
}
sc->ipmi_cdev->si_drv1 = sc;
+
+ /*
+ * Power cycle the system off using IPMI. We use last - 1 since we don't
+ * handle all the other kinds of reboots. We'll let others handle them.
+ * We only try to do this if the BMC supports the Chassis device.
+ */
+ if (sc->ipmi_dev_support & IPMI_ADS_CHASSIS) {
+ device_printf(dev, "Establishing power cycle handler\n");
+ sc->ipmi_power_cycle_tag = EVENTHANDLER_REGISTER(shutdown_final,
+ ipmi_power_cycle, sc, SHUTDOWN_PRI_LAST - 1);
+ }
}
int
@@ -844,6 +897,10 @@
ipmi_set_watchdog(sc, 0);
}
+ /* Detach from shutdown handling for power cycle reboot */
+ if (sc->ipmi_power_cycle_tag)
+ EVENTHANDLER_DEREGISTER(shutdown_final, sc->ipmi_power_cycle_tag);
+
/* XXX: should use shutdown callout I think. */
/* If the backend uses a kthread, shut it down. */
IPMI_LOCK(sc);
Index: sys/dev/ipmi/ipmivars.h
===================================================================
--- sys/dev/ipmi/ipmivars.h
+++ sys/dev/ipmi/ipmivars.h
@@ -103,9 +103,11 @@
void *ipmi_irq;
int ipmi_detaching;
int ipmi_opened;
+ uint8_t ipmi_dev_support; /* IPMI_ADS_* */
struct cdev *ipmi_cdev;
TAILQ_HEAD(,ipmi_request) ipmi_pending_requests;
int ipmi_driver_requests_polled;
+ eventhandler_tag ipmi_power_cycle_tag;
eventhandler_tag ipmi_watchdog_tag;
int ipmi_watchdog_active;
struct intr_config_hook ipmi_ich;
Index: sys/kern/kern_shutdown.c
===================================================================
--- sys/kern/kern_shutdown.c
+++ sys/kern/kern_shutdown.c
@@ -263,6 +263,8 @@
PROC_LOCK(initproc);
if (howto & RB_POWEROFF)
kern_psignal(initproc, SIGUSR2);
+ else if (howto & RB_POWERCYCLE)
+ kern_psignal(initproc, SIGWINCH);
else if (howto & RB_HALT)
kern_psignal(initproc, SIGUSR1);
else
@@ -797,7 +799,7 @@
poweroff_wait(void *junk, int howto)
{
- if (!(howto & RB_POWEROFF) || poweroff_delay <= 0)
+ if ((howto & (RB_POWEROFF | RB_POWERCYCLE)) == 0 || poweroff_delay <= 0)
return;
DELAY(poweroff_delay * 1000);
}
Index: sys/sys/ipmi.h
===================================================================
--- sys/sys/ipmi.h
+++ sys/sys/ipmi.h
@@ -56,8 +56,25 @@
#define IPMI_ASYNC_EVENT_RECV_TYPE 2
#define IPMI_CMD_RECV_TYPE 3
+#define IPMI_CHASSIS_REQUEST 0x00
+# define IPMI_CHASSIS_CONTROL 0x02
+# define IPMI_CC_POWER_DOWN 0x0
+# define IPMI_CC_POWER_UP 0x1
+# define IPMI_CC_POWER_CYCLE 0x2
+# define IPMI_CC_HARD_RESET 0x3
+# define IPMI_CC_PULSE_DI 0x4
+# define IPMI_CC_SOFT_OVERTEMP 0x5
+
#define IPMI_APP_REQUEST 0x06
#define IPMI_GET_DEVICE_ID 0x01
+# define IPMI_ADS_CHASSIS 0x80
+# define IPMI_ADS_BRIDGE 0x40
+# define IPMI_ADS_EVENT_GEN 0x20
+# define IPMI_ADS_EVENT_RCV 0x10
+# define IPMI_ADS_FRU_INV 0x08
+# define IPMI_ADS_SEL 0x04
+# define IPMI_ADS_SDR 0x02
+# define IPMI_ADS_SENSOR 0x01
#define IPMI_CLEAR_FLAGS 0x30
#define IPMI_GET_MSG_FLAGS 0x31
# define IPMI_MSG_AVAILABLE 0x01
Index: sys/sys/reboot.h
===================================================================
--- sys/sys/reboot.h
+++ sys/sys/reboot.h
@@ -60,6 +60,7 @@
#define RB_RESERVED2 0x80000 /* reserved for internal use of boot blocks */
#define RB_PAUSE 0x100000 /* pause after each output line during probe */
#define RB_REROOT 0x200000 /* unmount the rootfs and mount it again */
+#define RB_POWERCYCLE 0x400000 /* Power cycle if possible */
#define RB_MULTIPLE 0x20000000 /* use multiple consoles */
#define RB_BOOTINFO 0x80000000 /* have `struct bootinfo *' arg */
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Dec 27, 4:21 PM (8 h, 55 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15615721
Default Alt Text
D12777.diff (16 KB)
Attached To
Mode
D12777: Implenent power cycle option to reboot
Attached
Detach File
Event Timeline
Log In to Comment