Page MenuHomeFreeBSD

D12777.diff
No OneTemporary

D12777.diff

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

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)

Event Timeline