summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorMike Belopuhov <mikeb@cvs.openbsd.org>2016-02-02 17:52:47 +0000
committerMike Belopuhov <mikeb@cvs.openbsd.org>2016-02-02 17:52:47 +0000
commit2723176e82ce1395f04b2d4328817b28eb499af3 (patch)
tree32eba048c41c33034617b72a725eaeb8f7dccf5d /sys/dev
parent848453065448cd57923a6f38a376e35ad6ee353b (diff)
A few reliability improvements in the power management interface
Nathanael Rensen <nathanael at list ! polymorpheus ! com> came up with a few improvements to the event watcher and power management interface, namely: o Make sure to put our watcher on a list before issuing an XS_WATCH command since Xen will raise the event right after it's been set up. o The first time xen_control is called the "control/shutdown" node may not exist, so skip printing the error message in this case. o Acknowledge requests by writing back an empty string. o log(9) reboot and halt requests like vmt(4) does. Huge thanks!
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/pv/xen.c41
-rw-r--r--sys/dev/pv/xenstore.c17
-rw-r--r--sys/dev/pv/xenvar.h4
3 files changed, 43 insertions, 19 deletions
diff --git a/sys/dev/pv/xen.c b/sys/dev/pv/xen.c
index 8aa7565cba8..5770d897ceb 100644
--- a/sys/dev/pv/xen.c
+++ b/sys/dev/pv/xen.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: xen.c,v 1.48 2016/01/29 19:12:26 mikeb Exp $ */
+/* $OpenBSD: xen.c,v 1.49 2016/02/02 17:52:46 mikeb Exp $ */
/*
* Copyright (c) 2015 Mike Belopuhov
@@ -25,6 +25,7 @@
#include <sys/kernel.h>
#include <sys/device.h>
#include <sys/task.h>
+#include <sys/syslog.h>
#include <machine/bus.h>
#include <machine/cpu.h>
@@ -34,6 +35,8 @@
#include <machine/i82489var.h>
+#include <dev/rndvar.h>
+
#include <dev/pv/pvvar.h>
#include <dev/pv/pvreg.h>
#include <dev/pv/xenreg.h>
@@ -193,34 +196,48 @@ xen_control(void *arg)
struct xen_softc *sc = arg;
struct xs_transaction xst;
char action[128];
+ int error;
memset(&xst, 0, sizeof(xst));
xst.xst_id = 0;
xst.xst_sc = sc->sc_xs;
- if (xs_getprop(sc, "control", "shutdown", action, sizeof(action))) {
- printf("%s: failed to process control event\n",
- sc->sc_dev.dv_xname);
+ error = xs_getprop(sc, "control", "shutdown", action, sizeof(action));
+ if (error) {
+ if (error != ENOENT)
+ printf("%s: failed to process control event\n",
+ sc->sc_dev.dv_xname);
return;
}
if (strlen(action) == 0)
return;
+ /* Acknowledge the event */
+ xs_setprop(sc, "control", "shutdown", "", 0);
+
if (strcmp(action, "halt") == 0 || strcmp(action, "poweroff") == 0) {
extern int allowpowerdown;
- if (allowpowerdown == 1) {
- allowpowerdown = 0;
- prsignal(initprocess, SIGUSR2);
- }
+ if (allowpowerdown == 0)
+ return;
+
+ suspend_randomness();
+
+ log(LOG_KERN | LOG_NOTICE, "Shutting down in response to "
+ "request from Xen host\n");
+ prsignal(initprocess, SIGUSR2);
} else if (strcmp(action, "reboot") == 0) {
extern int allowpowerdown;
- if (allowpowerdown == 1) {
- allowpowerdown = 0;
- prsignal(initprocess, SIGINT);
- }
+ if (allowpowerdown == 0)
+ return;
+
+ suspend_randomness();
+
+ log(LOG_KERN | LOG_NOTICE, "Rebooting in response to request "
+ "from Xen host\n");
+ prsignal(initprocess, SIGINT);
} else if (strcmp(action, "crash") == 0) {
panic("xen told us to do this");
} else if (strcmp(action, "suspend") == 0) {
diff --git a/sys/dev/pv/xenstore.c b/sys/dev/pv/xenstore.c
index c1262cf9590..95b1fdc7fa2 100644
--- a/sys/dev/pv/xenstore.c
+++ b/sys/dev/pv/xenstore.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: xenstore.c,v 1.24 2016/01/29 19:04:30 mikeb Exp $ */
+/* $OpenBSD: xenstore.c,v 1.25 2016/02/02 17:52:46 mikeb Exp $ */
/*
* Copyright (c) 2015 Mike Belopuhov
@@ -850,15 +850,22 @@ xs_watch(struct xen_softc *sc, const char *path, const char *property,
iov.iov_len = sizeof(xsw->xsw_token);
iov_cnt = 1;
+ /*
+ * xs_watches must be prepared pre-emptively because a xenstore
+ * event is raised immediately after a watch is established.
+ */
+ mtx_enter(&xs->xs_watchlck);
+ TAILQ_INSERT_TAIL(&xs->xs_watches, xsw, xsw_entry);
+ mtx_leave(&xs->xs_watchlck);
+
if ((error = xs_cmd(&xst, XS_WATCH, key, &iovp, &iov_cnt)) != 0) {
+ mtx_enter(&xs->xs_watchlck);
+ TAILQ_REMOVE(&xs->xs_watches, xsw, xsw_entry);
+ mtx_leave(&xs->xs_watchlck);
free(xsw, M_DEVBUF, sizeof(*xsw));
return (error);
}
- mtx_enter(&xs->xs_watchlck);
- TAILQ_INSERT_TAIL(&xs->xs_watches, xsw, xsw_entry);
- mtx_leave(&xs->xs_watchlck);
-
return (0);
}
diff --git a/sys/dev/pv/xenvar.h b/sys/dev/pv/xenvar.h
index 29c013d2ad0..34f381b78a7 100644
--- a/sys/dev/pv/xenvar.h
+++ b/sys/dev/pv/xenvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: xenvar.h,v 1.28 2016/01/29 19:12:26 mikeb Exp $ */
+/* $OpenBSD: xenvar.h,v 1.29 2016/02/02 17:52:46 mikeb Exp $ */
/*
* Copyright (c) 2015 Mike Belopuhov
@@ -19,7 +19,7 @@
#ifndef _XENVAR_H_
#define _XENVAR_H_
-#define XEN_DEBUG
+/* #define XEN_DEBUG */
#ifdef XEN_DEBUG
#define DPRINTF(x...) printf(x)