summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr/src/cmd/bhyve/pm.c47
1 files changed, 47 insertions, 0 deletions
diff --git a/usr/src/cmd/bhyve/pm.c b/usr/src/cmd/bhyve/pm.c
index 1313fbfb1d..4a35726d24 100644
--- a/usr/src/cmd/bhyve/pm.c
+++ b/usr/src/cmd/bhyve/pm.c
@@ -24,6 +24,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
+/*
+ * Copyright 2018 Joyent, Inc.
+ */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
@@ -52,6 +55,8 @@ static pthread_mutex_t pm_lock = PTHREAD_MUTEX_INITIALIZER;
#ifdef __FreeBSD__
static struct mevent *power_button;
static sig_t old_power_handler;
+#else
+struct vmctx *pwr_ctx;
#endif
/*
@@ -219,6 +224,34 @@ power_button_handler(int signal, enum ev_type type, void *arg)
}
pthread_mutex_unlock(&pm_lock);
}
+
+#else
+/*
+ * Initiate graceful power off.
+ */
+/*ARGSUSED*/
+static void
+power_button_handler(int signal, siginfo_t *type, void *cp)
+{
+ /*
+ * In theory, taking the 'pm_lock' mutex from within this signal
+ * handler could lead to deadlock if the main thread already held this
+ * mutex. In reality, this mutex is local to this file and all of the
+ * other usage in this file only occurs in functions which are FreeBSD
+ * specific (and thus currently not used). Thus, for consistency with
+ * the other code in this file, we take the mutex, but in the future,
+ * if these other functions are ever enabled for use on non-FreeBSD
+ * systems and these functions could be called directly by a thread
+ * (which would then hold the mutex), then we need to revisit the use
+ * of this mutex in this signal handler.
+ */
+ pthread_mutex_lock(&pm_lock);
+ if (!(pm1_status & PM1_PWRBTN_STS)) {
+ pm1_status |= PM1_PWRBTN_STS;
+ sci_update(pwr_ctx);
+ }
+ pthread_mutex_unlock(&pm_lock);
+}
#endif
/*
@@ -326,4 +359,18 @@ sci_init(struct vmctx *ctx)
*/
pci_irq_use(SCI_INT);
vm_isa_set_irq_trigger(ctx, SCI_INT, LEVEL_TRIGGER);
+
+#ifndef __FreeBSD__
+ {
+ /*
+ * Install SIGTERM signal handler for graceful power off.
+ */
+ struct sigaction act;
+
+ pwr_ctx = ctx;
+ act.sa_flags = 0;
+ act.sa_sigaction = power_button_handler;
+ (void) sigaction(SIGTERM, &act, NULL);
+ }
+#endif
}