ia64/xen-unstable

view linux-2.6-xen-sparse/drivers/xen/core/reboot.c @ 13908:df25547d7638

[LINUX] Call ctrl_alt_del() to trigger a reboot so we benefit from the
generic infrastructure for cad_pid etc.

Add a ctrl_alt_del() implemenation to the PV on HVM compatibility
layer since ctrl_alt_del() is not exported on native kernels.

Signed-off-by: Ian Campbell <ian.campbell@xensource.com>
author Ian Campbell <ian.campbell@xensource.com>
date Tue Feb 13 15:32:25 2007 +0000 (2007-02-13)
parents f3fbe9549f5f
children 3ac19fda0bc2
line source
1 #define __KERNEL_SYSCALLS__
2 #include <linux/version.h>
3 #include <linux/kernel.h>
4 #include <linux/unistd.h>
5 #include <linux/module.h>
6 #include <linux/reboot.h>
7 #include <linux/sysrq.h>
8 #include <asm/hypervisor.h>
9 #include <xen/xenbus.h>
10 #include <linux/kthread.h>
12 MODULE_LICENSE("Dual BSD/GPL");
14 #define SHUTDOWN_INVALID -1
15 #define SHUTDOWN_POWEROFF 0
16 #define SHUTDOWN_SUSPEND 2
17 /* Code 3 is SHUTDOWN_CRASH, which we don't use because the domain can only
18 * report a crash, not be instructed to crash!
19 * HALT is the same as POWEROFF, as far as we're concerned. The tools use
20 * the distinction when we return the reason code to them.
21 */
22 #define SHUTDOWN_HALT 4
24 /* Ignore multiple shutdown requests. */
25 static int shutting_down = SHUTDOWN_INVALID;
27 static void __shutdown_handler(void *unused);
28 static DECLARE_WORK(shutdown_work, __shutdown_handler, NULL);
30 #ifdef CONFIG_XEN
31 int __xen_suspend(void);
32 #else
33 #define __xen_suspend() (void)0
34 #endif
36 static int shutdown_process(void *__unused)
37 {
38 static char *envp[] = { "HOME=/", "TERM=linux",
39 "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
40 static char *poweroff_argv[] = { "/sbin/poweroff", NULL };
42 extern asmlinkage long sys_reboot(int magic1, int magic2,
43 unsigned int cmd, void *arg);
45 if ((shutting_down == SHUTDOWN_POWEROFF) ||
46 (shutting_down == SHUTDOWN_HALT)) {
47 if (call_usermodehelper("/sbin/poweroff", poweroff_argv, envp, 0) < 0) {
48 #ifdef CONFIG_XEN
49 sys_reboot(LINUX_REBOOT_MAGIC1,
50 LINUX_REBOOT_MAGIC2,
51 LINUX_REBOOT_CMD_POWER_OFF,
52 NULL);
53 #endif /* CONFIG_XEN */
54 }
55 }
57 shutting_down = SHUTDOWN_INVALID; /* could try again */
59 return 0;
60 }
62 static int xen_suspend(void *__unused)
63 {
64 __xen_suspend();
65 shutting_down = SHUTDOWN_INVALID;
66 return 0;
67 }
69 static int kthread_create_on_cpu(int (*f)(void *arg),
70 void *arg,
71 const char *name,
72 int cpu)
73 {
74 struct task_struct *p;
75 p = kthread_create(f, arg, name);
76 if (IS_ERR(p))
77 return PTR_ERR(p);
78 kthread_bind(p, cpu);
79 wake_up_process(p);
80 return 0;
81 }
83 static void __shutdown_handler(void *unused)
84 {
85 int err;
87 if (shutting_down != SHUTDOWN_SUSPEND)
88 err = kernel_thread(shutdown_process, NULL,
89 CLONE_FS | CLONE_FILES);
90 else
91 err = kthread_create_on_cpu(xen_suspend, NULL, "suspend", 0);
93 if (err < 0) {
94 printk(KERN_WARNING "Error creating shutdown process (%d): "
95 "retrying...\n", -err);
96 schedule_delayed_work(&shutdown_work, HZ/2);
97 }
98 }
100 static void shutdown_handler(struct xenbus_watch *watch,
101 const char **vec, unsigned int len)
102 {
103 extern void ctrl_alt_del(void);
104 char *str;
105 struct xenbus_transaction xbt;
106 int err;
108 if (shutting_down != SHUTDOWN_INVALID)
109 return;
111 again:
112 err = xenbus_transaction_start(&xbt);
113 if (err)
114 return;
115 str = (char *)xenbus_read(xbt, "control", "shutdown", NULL);
116 /* Ignore read errors and empty reads. */
117 if (XENBUS_IS_ERR_READ(str)) {
118 xenbus_transaction_end(xbt, 1);
119 return;
120 }
122 xenbus_write(xbt, "control", "shutdown", "");
124 err = xenbus_transaction_end(xbt, 0);
125 if (err == -EAGAIN) {
126 kfree(str);
127 goto again;
128 }
130 if (strcmp(str, "poweroff") == 0)
131 shutting_down = SHUTDOWN_POWEROFF;
132 else if (strcmp(str, "reboot") == 0)
133 ctrl_alt_del();
134 else if (strcmp(str, "suspend") == 0)
135 shutting_down = SHUTDOWN_SUSPEND;
136 else if (strcmp(str, "halt") == 0)
137 shutting_down = SHUTDOWN_HALT;
138 else {
139 printk("Ignoring shutdown request: %s\n", str);
140 shutting_down = SHUTDOWN_INVALID;
141 }
143 if (shutting_down != SHUTDOWN_INVALID)
144 schedule_work(&shutdown_work);
146 kfree(str);
147 }
149 static void sysrq_handler(struct xenbus_watch *watch, const char **vec,
150 unsigned int len)
151 {
152 char sysrq_key = '\0';
153 struct xenbus_transaction xbt;
154 int err;
156 again:
157 err = xenbus_transaction_start(&xbt);
158 if (err)
159 return;
160 if (!xenbus_scanf(xbt, "control", "sysrq", "%c", &sysrq_key)) {
161 printk(KERN_ERR "Unable to read sysrq code in "
162 "control/sysrq\n");
163 xenbus_transaction_end(xbt, 1);
164 return;
165 }
167 if (sysrq_key != '\0')
168 xenbus_printf(xbt, "control", "sysrq", "%c", '\0');
170 err = xenbus_transaction_end(xbt, 0);
171 if (err == -EAGAIN)
172 goto again;
174 #ifdef CONFIG_MAGIC_SYSRQ
175 if (sysrq_key != '\0')
176 handle_sysrq(sysrq_key, NULL, NULL);
177 #endif
178 }
180 static struct xenbus_watch shutdown_watch = {
181 .node = "control/shutdown",
182 .callback = shutdown_handler
183 };
185 static struct xenbus_watch sysrq_watch = {
186 .node ="control/sysrq",
187 .callback = sysrq_handler
188 };
190 static int setup_shutdown_watcher(struct notifier_block *notifier,
191 unsigned long event,
192 void *data)
193 {
194 int err;
196 err = register_xenbus_watch(&shutdown_watch);
197 if (err)
198 printk(KERN_ERR "Failed to set shutdown watcher\n");
199 else
200 xenbus_write(XBT_NIL, "control", "feature-reboot", "1");
202 err = register_xenbus_watch(&sysrq_watch);
203 if (err)
204 printk(KERN_ERR "Failed to set sysrq watcher\n");
205 else
206 xenbus_write(XBT_NIL, "control", "feature-sysrq", "1");
208 return NOTIFY_DONE;
209 }
211 static int __init setup_shutdown_event(void)
212 {
213 static struct notifier_block xenstore_notifier = {
214 .notifier_call = setup_shutdown_watcher
215 };
216 register_xenstore_notifier(&xenstore_notifier);
218 return 0;
219 }
221 subsys_initcall(setup_shutdown_event);