direct-io.hg

view linux-2.6-xen-sparse/arch/xen/kernel/reboot.c @ 7551:47ba7a4bed45

Remove out: label, to silence warning.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
author emellor@leeni.uk.xensource.com
date Sun Oct 30 15:42:02 2005 +0100 (2005-10-30)
parents dc36edf1102f
children 25599e222c33
line source
1 #define __KERNEL_SYSCALLS__
2 #include <linux/version.h>
3 #include <linux/kernel.h>
4 #include <linux/mm.h>
5 #include <linux/unistd.h>
6 #include <linux/module.h>
7 #include <linux/reboot.h>
8 #include <linux/sysrq.h>
9 #include <linux/stringify.h>
10 #include <asm/irq.h>
11 #include <asm/mmu_context.h>
12 #include <asm-xen/evtchn.h>
13 #include <asm/hypervisor.h>
14 #include <asm-xen/xen-public/dom0_ops.h>
15 #include <asm-xen/xenbus.h>
16 #include <linux/cpu.h>
17 #include <linux/kthread.h>
19 #define SHUTDOWN_INVALID -1
20 #define SHUTDOWN_POWEROFF 0
21 #define SHUTDOWN_REBOOT 1
22 #define SHUTDOWN_SUSPEND 2
23 // Code 3 is SHUTDOWN_CRASH, which we don't use because the domain can only
24 // report a crash, not be instructed to crash!
25 // HALT is the same as POWEROFF, as far as we're concerned. The tools use
26 // the distinction when we return the reason code to them.
27 #define SHUTDOWN_HALT 4
29 void machine_restart(char * __unused)
30 {
31 /* We really want to get pending console data out before we die. */
32 extern void xencons_force_flush(void);
33 xencons_force_flush();
34 HYPERVISOR_sched_op(SCHEDOP_shutdown, SHUTDOWN_reboot);
35 }
37 void machine_halt(void)
38 {
39 machine_power_off();
40 }
42 void machine_power_off(void)
43 {
44 /* We really want to get pending console data out before we die. */
45 extern void xencons_force_flush(void);
46 xencons_force_flush();
47 HYPERVISOR_sched_op(SCHEDOP_shutdown, SHUTDOWN_poweroff);
48 }
50 int reboot_thru_bios = 0; /* for dmi_scan.c */
51 EXPORT_SYMBOL(machine_restart);
52 EXPORT_SYMBOL(machine_halt);
53 EXPORT_SYMBOL(machine_power_off);
56 /******************************************************************************
57 * Stop/pickle callback handling.
58 */
60 /* Ignore multiple shutdown requests. */
61 static int shutting_down = SHUTDOWN_INVALID;
62 static void __shutdown_handler(void *unused);
63 static DECLARE_WORK(shutdown_work, __shutdown_handler, NULL);
65 #ifndef CONFIG_HOTPLUG_CPU
66 #define cpu_down(x) (-EOPNOTSUPP)
67 #define cpu_up(x) (-EOPNOTSUPP)
68 #endif
71 static int __do_suspend(void *ignore)
72 {
73 int i, j, k, fpp;
75 extern int gnttab_suspend(void);
76 extern int gnttab_resume(void);
78 extern void time_resume(void);
79 extern unsigned long max_pfn;
80 extern unsigned long *pfn_to_mfn_frame_list_list;
81 extern unsigned long *pfn_to_mfn_frame_list[];
83 #ifdef CONFIG_SMP
84 cpumask_t prev_online_cpus;
85 int vcpu_prepare(int vcpu);
86 #endif
88 extern void xencons_resume(void);
90 int err = 0;
92 BUG_ON(smp_processor_id() != 0);
93 BUG_ON(in_interrupt());
95 #if defined(CONFIG_SMP) && !defined(CONFIG_HOTPLUG_CPU)
96 if (num_online_cpus() > 1) {
97 printk(KERN_WARNING "Can't suspend SMP guests "
98 "without CONFIG_HOTPLUG_CPU\n");
99 return -EOPNOTSUPP;
100 }
101 #endif
103 xenbus_suspend();
105 lock_cpu_hotplug();
106 #ifdef CONFIG_SMP
107 /*
108 * Take all other CPUs offline. We hold the hotplug semaphore to
109 * avoid other processes bringing up CPUs under our feet.
110 */
111 cpus_clear(prev_online_cpus);
112 while (num_online_cpus() > 1) {
113 for_each_online_cpu(i) {
114 if (i == 0)
115 continue;
116 unlock_cpu_hotplug();
117 err = cpu_down(i);
118 lock_cpu_hotplug();
119 if (err != 0) {
120 printk(KERN_CRIT "Failed to take all CPUs "
121 "down: %d.\n", err);
122 goto out_reenable_cpus;
123 }
124 cpu_set(i, prev_online_cpus);
125 }
126 }
127 #endif
129 preempt_disable();
131 #ifdef __i386__
132 mm_pin_all();
133 kmem_cache_shrink(pgd_cache);
134 #endif
136 __cli();
137 preempt_enable();
138 unlock_cpu_hotplug();
140 gnttab_suspend();
142 HYPERVISOR_shared_info = (shared_info_t *)empty_zero_page;
143 clear_fixmap(FIX_SHARED_INFO);
145 xen_start_info->store_mfn = mfn_to_pfn(xen_start_info->store_mfn);
146 xen_start_info->console_mfn = mfn_to_pfn(xen_start_info->console_mfn);
148 /*
149 * We'll stop somewhere inside this hypercall. When it returns,
150 * we'll start resuming after the restore.
151 */
152 HYPERVISOR_suspend(virt_to_mfn(xen_start_info));
154 shutting_down = SHUTDOWN_INVALID;
156 set_fixmap(FIX_SHARED_INFO, xen_start_info->shared_info);
158 HYPERVISOR_shared_info = (shared_info_t *)fix_to_virt(FIX_SHARED_INFO);
160 memset(empty_zero_page, 0, PAGE_SIZE);
162 HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list =
163 virt_to_mfn(pfn_to_mfn_frame_list_list);
165 fpp = PAGE_SIZE/sizeof(unsigned long);
166 for (i = 0, j = 0, k = -1; i < max_pfn; i += fpp, j++) {
167 if ((j % fpp) == 0) {
168 k++;
169 pfn_to_mfn_frame_list_list[k] =
170 virt_to_mfn(pfn_to_mfn_frame_list[k]);
171 j = 0;
172 }
173 pfn_to_mfn_frame_list[k][j] =
174 virt_to_mfn(&phys_to_machine_mapping[i]);
175 }
176 HYPERVISOR_shared_info->arch.max_pfn = max_pfn;
178 gnttab_resume();
180 irq_resume();
182 time_resume();
184 __sti();
186 xencons_resume();
188 xenbus_resume();
190 #ifdef CONFIG_SMP
191 for_each_present_cpu(i)
192 vcpu_prepare(i);
194 out_reenable_cpus:
195 for_each_cpu_mask(i, prev_online_cpus) {
196 j = cpu_up(i);
197 if (j != 0) {
198 printk(KERN_CRIT "Failed to bring cpu "
199 "%d back up (%d).\n",
200 i, j);
201 err = j;
202 }
203 }
204 #endif
206 return err;
207 }
209 static int shutdown_process(void *__unused)
210 {
211 static char *envp[] = { "HOME=/", "TERM=linux",
212 "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
213 static char *restart_argv[] = { "/sbin/reboot", NULL };
214 static char *poweroff_argv[] = { "/sbin/poweroff", NULL };
216 extern asmlinkage long sys_reboot(int magic1, int magic2,
217 unsigned int cmd, void *arg);
219 daemonize("shutdown");
221 switch (shutting_down) {
222 case SHUTDOWN_POWEROFF:
223 case SHUTDOWN_HALT:
224 if (execve("/sbin/poweroff", poweroff_argv, envp) < 0) {
225 sys_reboot(LINUX_REBOOT_MAGIC1,
226 LINUX_REBOOT_MAGIC2,
227 LINUX_REBOOT_CMD_POWER_OFF,
228 NULL);
229 }
230 break;
232 case SHUTDOWN_REBOOT:
233 if (execve("/sbin/reboot", restart_argv, envp) < 0) {
234 sys_reboot(LINUX_REBOOT_MAGIC1,
235 LINUX_REBOOT_MAGIC2,
236 LINUX_REBOOT_CMD_RESTART,
237 NULL);
238 }
239 break;
240 }
242 shutting_down = SHUTDOWN_INVALID; /* could try again */
244 return 0;
245 }
247 static int kthread_create_on_cpu(int (*f)(void *arg),
248 void *arg,
249 const char *name,
250 int cpu)
251 {
252 struct task_struct *p;
253 p = kthread_create(f, arg, name);
254 if (IS_ERR(p))
255 return PTR_ERR(p);
256 kthread_bind(p, cpu);
257 wake_up_process(p);
258 return 0;
259 }
261 static void __shutdown_handler(void *unused)
262 {
263 int err;
265 if (shutting_down != SHUTDOWN_SUSPEND)
266 err = kernel_thread(shutdown_process, NULL,
267 CLONE_FS | CLONE_FILES);
268 else
269 err = kthread_create_on_cpu(__do_suspend, NULL, "suspend", 0);
271 if ( err < 0 ) {
272 printk(KERN_WARNING "Error creating shutdown process (%d): "
273 "retrying...\n", -err);
274 schedule_delayed_work(&shutdown_work, HZ/2);
275 }
276 }
278 static void shutdown_handler(struct xenbus_watch *watch,
279 const char **vec, unsigned int len)
280 {
281 char *str;
282 struct xenbus_transaction *xbt;
283 int err;
285 if (shutting_down != SHUTDOWN_INVALID)
286 return;
288 again:
289 xbt = xenbus_transaction_start();
290 if (IS_ERR(xbt))
291 return;
292 str = (char *)xenbus_read(xbt, "control", "shutdown", NULL);
293 /* Ignore read errors and empty reads. */
294 if (XENBUS_IS_ERR_READ(str)) {
295 xenbus_transaction_end(xbt, 1);
296 return;
297 }
299 xenbus_write(xbt, "control", "shutdown", "");
301 err = xenbus_transaction_end(xbt, 0);
302 if (err == -EAGAIN) {
303 kfree(str);
304 goto again;
305 }
307 if (strcmp(str, "poweroff") == 0)
308 shutting_down = SHUTDOWN_POWEROFF;
309 else if (strcmp(str, "reboot") == 0)
310 shutting_down = SHUTDOWN_REBOOT;
311 else if (strcmp(str, "suspend") == 0)
312 shutting_down = SHUTDOWN_SUSPEND;
313 else if (strcmp(str, "halt") == 0)
314 shutting_down = SHUTDOWN_HALT;
315 else {
316 printk("Ignoring shutdown request: %s\n", str);
317 shutting_down = SHUTDOWN_INVALID;
318 }
320 if (shutting_down != SHUTDOWN_INVALID)
321 schedule_work(&shutdown_work);
323 kfree(str);
324 }
326 #ifdef CONFIG_MAGIC_SYSRQ
327 static void sysrq_handler(struct xenbus_watch *watch, const char **vec,
328 unsigned int len)
329 {
330 char sysrq_key = '\0';
331 struct xenbus_transaction *xbt;
332 int err;
334 again:
335 xbt = xenbus_transaction_start();
336 if (IS_ERR(xbt))
337 return;
338 if (!xenbus_scanf(xbt, "control", "sysrq", "%c", &sysrq_key)) {
339 printk(KERN_ERR "Unable to read sysrq code in "
340 "control/sysrq\n");
341 xenbus_transaction_end(xbt, 1);
342 return;
343 }
345 if (sysrq_key != '\0')
346 xenbus_printf(xbt, "control", "sysrq", "%c", '\0');
348 err = xenbus_transaction_end(xbt, 0);
349 if (err == -EAGAIN)
350 goto again;
352 if (sysrq_key != '\0') {
353 handle_sysrq(sysrq_key, NULL, NULL);
354 }
355 }
356 #endif
358 static struct xenbus_watch shutdown_watch = {
359 .node = "control/shutdown",
360 .callback = shutdown_handler
361 };
363 #ifdef CONFIG_MAGIC_SYSRQ
364 static struct xenbus_watch sysrq_watch = {
365 .node ="control/sysrq",
366 .callback = sysrq_handler
367 };
368 #endif
370 static struct notifier_block xenstore_notifier;
372 static int setup_shutdown_watcher(struct notifier_block *notifier,
373 unsigned long event,
374 void *data)
375 {
376 int err1 = 0;
377 #ifdef CONFIG_MAGIC_SYSRQ
378 int err2 = 0;
379 #endif
381 err1 = register_xenbus_watch(&shutdown_watch);
382 #ifdef CONFIG_MAGIC_SYSRQ
383 err2 = register_xenbus_watch(&sysrq_watch);
384 #endif
386 if (err1) {
387 printk(KERN_ERR "Failed to set shutdown watcher\n");
388 }
390 #ifdef CONFIG_MAGIC_SYSRQ
391 if (err2) {
392 printk(KERN_ERR "Failed to set sysrq watcher\n");
393 }
394 #endif
396 return NOTIFY_DONE;
397 }
399 static int __init setup_shutdown_event(void)
400 {
402 xenstore_notifier.notifier_call = setup_shutdown_watcher;
404 register_xenstore_notifier(&xenstore_notifier);
406 return 0;
407 }
409 subsys_initcall(setup_shutdown_event);
411 /*
412 * Local variables:
413 * c-file-style: "linux"
414 * indent-tabs-mode: t
415 * c-indent-level: 8
416 * c-basic-offset: 8
417 * tab-width: 8
418 * End:
419 */