summaryrefslogtreecommitdiff
path: root/usr/src/uts
diff options
context:
space:
mode:
authorjohnlev <none@none>2008-05-21 16:00:05 -0700
committerjohnlev <none@none>2008-05-21 16:00:05 -0700
commitc48ac12eb805b96b1b8d7582c4168b4e4fa56865 (patch)
tree89f6e64352bda38778f0899dc7820980ab185bde /usr/src/uts
parentb08d8a121e3928c888b68a3e56445554ced82733 (diff)
downloadillumos-joyent-c48ac12eb805b96b1b8d7582c4168b4e4fa56865.tar.gz
6677804 Can't shutdown Solaris HVM guest with PV drivers
Diffstat (limited to 'usr/src/uts')
-rw-r--r--usr/src/uts/common/sys/uadmin.h3
-rw-r--r--usr/src/uts/i86pc/i86hvm/io/xpv/xpv_support.c63
-rw-r--r--usr/src/uts/i86pc/os/machdep.c10
-rw-r--r--usr/src/uts/i86pc/sys/machsystm.h4
-rw-r--r--usr/src/uts/i86xpv/os/xen_machdep.c59
5 files changed, 67 insertions, 72 deletions
diff --git a/usr/src/uts/common/sys/uadmin.h b/usr/src/uts/common/sys/uadmin.h
index e307462896..2bf889c9b7 100644
--- a/usr/src/uts/common/sys/uadmin.h
+++ b/usr/src/uts/common/sys/uadmin.h
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -50,6 +50,7 @@ extern "C" {
#define A_SWAPCTL 16
/* 17-21 reserved for obsolete interface */
+#define AD_UNKNOWN -1 /* no method */
#define AD_HALT 0 /* halt the processor */
#define AD_BOOT 1 /* multi-user reboot */
#define AD_IBOOT 2 /* multi-user reboot, ask for name of file */
diff --git a/usr/src/uts/i86pc/i86hvm/io/xpv/xpv_support.c b/usr/src/uts/i86pc/i86hvm/io/xpv/xpv_support.c
index f5de99a175..b7122d09a1 100644
--- a/usr/src/uts/i86pc/i86hvm/io/xpv/xpv_support.c
+++ b/usr/src/uts/i86pc/i86hvm/io/xpv/xpv_support.c
@@ -327,13 +327,6 @@ taskq_t *xen_shutdown_tq;
#define SHUTDOWN_TIMEOUT_SECS (60 * 5)
-static const char *cmd_strings[SHUTDOWN_MAX] = {
- "poweroff",
- "reboot",
- "suspend",
- "halt"
-};
-
int
xen_suspend_devices(dev_info_t *dip)
{
@@ -588,11 +581,8 @@ xen_dirty_shutdown(void *arg)
static void
xen_shutdown(void *arg)
{
- nvlist_t *attr_list = NULL;
- sysevent_t *event = NULL;
- sysevent_id_t eid;
int cmd = (uintptr_t)arg;
- int err;
+ proc_t *initpp;
ASSERT(cmd > SHUTDOWN_INVALID && cmd < SHUTDOWN_MAX);
@@ -601,38 +591,37 @@ xen_shutdown(void *arg)
return;
}
- err = nvlist_alloc(&attr_list, NV_UNIQUE_NAME, KM_SLEEP);
- if (err != DDI_SUCCESS)
- goto failure;
-
- err = nvlist_add_string(attr_list, "shutdown", cmd_strings[cmd]);
- if (err != DDI_SUCCESS)
- goto failure;
-
- if ((event = sysevent_alloc("EC_xpvsys", "control", "SUNW:kern:xpv",
- SE_SLEEP)) == NULL)
- goto failure;
- (void) sysevent_attach_attributes(event,
- (sysevent_attr_list_t *)attr_list);
+ switch (cmd) {
+ case SHUTDOWN_POWEROFF:
+ force_shutdown_method = AD_POWEROFF;
+ break;
+ case SHUTDOWN_HALT:
+ force_shutdown_method = AD_HALT;
+ break;
+ case SHUTDOWN_REBOOT:
+ force_shutdown_method = AD_BOOT;
+ break;
+ }
- err = log_sysevent(event, SE_SLEEP, &eid);
- sysevent_detach_attributes(event);
- sysevent_free(event);
+ /*
+ * If we're still booting and init(1) isn't set up yet, simply halt.
+ */
+ mutex_enter(&pidlock);
+ initpp = prfind(P_INITPID);
+ mutex_exit(&pidlock);
+ if (initpp == NULL) {
+ extern void halt(char *);
+ halt("Power off the System"); /* just in case */
+ }
- if (err != 0)
- goto failure;
+ /*
+ * else, graceful shutdown with inittab and all getting involved
+ */
+ psignal(initpp, SIGPWR);
(void) timeout(xen_dirty_shutdown, arg,
SHUTDOWN_TIMEOUT_SECS * drv_usectohz(MICROSEC));
-
- nvlist_free(attr_list);
- return;
-
-failure:
- if (attr_list != NULL)
- nvlist_free(attr_list);
- xen_dirty_shutdown(arg);
}
/*ARGSUSED*/
diff --git a/usr/src/uts/i86pc/os/machdep.c b/usr/src/uts/i86pc/os/machdep.c
index 30861022a6..d39fde3140 100644
--- a/usr/src/uts/i86pc/os/machdep.c
+++ b/usr/src/uts/i86pc/os/machdep.c
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -130,6 +130,11 @@ extern void audit_enterprom(int);
extern void audit_exitprom(int);
/*
+ * Occassionally the kernel knows better whether to power-off or reboot.
+ */
+int force_shutdown_method = AD_UNKNOWN;
+
+/*
* The panicbuf array is used to record messages and state:
*/
char panicbuf[PANICBUFSIZE];
@@ -174,6 +179,9 @@ mdboot(int cmd, int fcn, char *mdep, boolean_t invoke_cb)
affinity_set(CPU_CURRENT);
}
+ if (force_shutdown_method != AD_UNKNOWN)
+ fcn = force_shutdown_method;
+
/*
* XXX - rconsvp is set to NULL to ensure that output messages
* are sent to the underlying "hardware" device using the
diff --git a/usr/src/uts/i86pc/sys/machsystm.h b/usr/src/uts/i86pc/sys/machsystm.h
index 7f5cb22437..8f0036af91 100644
--- a/usr/src/uts/i86pc/sys/machsystm.h
+++ b/usr/src/uts/i86pc/sys/machsystm.h
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -136,6 +136,8 @@ extern page_t *page_get_physical(uintptr_t);
extern int linear_pc(struct regs *rp, proc_t *p, caddr_t *linearp);
extern int dtrace_linear_pc(struct regs *rp, proc_t *p, caddr_t *linearp);
+extern int force_shutdown_method;
+
#ifdef __xpv
#include <sys/xen_mmu.h>
extern page_t *page_get_high_mfn(mfn_t);
diff --git a/usr/src/uts/i86xpv/os/xen_machdep.c b/usr/src/uts/i86xpv/os/xen_machdep.c
index 2ddfc1841f..4f832a3eaa 100644
--- a/usr/src/uts/i86xpv/os/xen_machdep.c
+++ b/usr/src/uts/i86xpv/os/xen_machdep.c
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -756,11 +756,8 @@ xen_dirty_shutdown(void *arg)
static void
xen_shutdown(void *arg)
{
- nvlist_t *attr_list = NULL;
- sysevent_t *event = NULL;
- sysevent_id_t eid;
int cmd = (uintptr_t)arg;
- int err;
+ proc_t *initpp;
ASSERT(cmd > SHUTDOWN_INVALID && cmd < SHUTDOWN_MAX);
@@ -769,38 +766,36 @@ xen_shutdown(void *arg)
return;
}
- err = nvlist_alloc(&attr_list, NV_UNIQUE_NAME, KM_SLEEP);
- if (err != DDI_SUCCESS)
- goto failure;
-
- err = nvlist_add_string(attr_list, "shutdown", cmd_strings[cmd]);
- if (err != DDI_SUCCESS)
- goto failure;
-
- if ((event = sysevent_alloc("EC_xpvsys", "control", "SUNW:kern:xpv",
- SE_SLEEP)) == NULL)
- goto failure;
- (void) sysevent_attach_attributes(event,
- (sysevent_attr_list_t *)attr_list);
-
- err = log_sysevent(event, SE_SLEEP, &eid);
+ switch (cmd) {
+ case SHUTDOWN_POWEROFF:
+ force_shutdown_method = AD_POWEROFF;
+ break;
+ case SHUTDOWN_HALT:
+ force_shutdown_method = AD_HALT;
+ break;
+ case SHUTDOWN_REBOOT:
+ force_shutdown_method = AD_BOOT;
+ break;
+ }
- sysevent_detach_attributes(event);
- sysevent_free(event);
+ /*
+ * If we're still booting and init(1) isn't set up yet, simply halt.
+ */
+ mutex_enter(&pidlock);
+ initpp = prfind(P_INITPID);
+ mutex_exit(&pidlock);
+ if (initpp == NULL) {
+ extern void halt(char *);
+ halt("Power off the System"); /* just in case */
+ }
- if (err != 0)
- goto failure;
+ /*
+ * else, graceful shutdown with inittab and all getting involved
+ */
+ psignal(initpp, SIGPWR);
(void) timeout(xen_dirty_shutdown, arg,
SHUTDOWN_TIMEOUT_SECS * drv_usectohz(MICROSEC));
-
- nvlist_free(attr_list);
- return;
-
-failure:
- if (attr_list != NULL)
- nvlist_free(attr_list);
- xen_dirty_shutdown(arg);
}
/*ARGSUSED*/