Merge to Fedora kernel-2.6.18-1.2224_FC5 patched with stable patch-2.6.18.1-vs2.0...
[linux-2.6.git] / drivers / xen / core / reboot.c
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 <xen/evtchn.h>
13 #include <asm/hypervisor.h>
14 #include <xen/interface/dom0_ops.h>
15 #include <xen/xenbus.h>
16 #include <linux/cpu.h>
17 #include <linux/kthread.h>
18 #include <xen/gnttab.h>
19 #include <xen/xencons.h>
20 #include <xen/cpu_hotplug.h>
21
22 extern void ctrl_alt_del(void);
23
24 #define SHUTDOWN_INVALID  -1
25 #define SHUTDOWN_POWEROFF  0
26 #define SHUTDOWN_SUSPEND   2
27 /* Code 3 is SHUTDOWN_CRASH, which we don't use because the domain can only
28  * report a crash, not be instructed to crash!
29  * HALT is the same as POWEROFF, as far as we're concerned.  The tools use
30  * the distinction when we return the reason code to them.
31  */
32 #define SHUTDOWN_HALT      4
33
34 #if defined(__i386__) || defined(__x86_64__)
35
36 /*
37  * Power off function, if any
38  */
39 void (*pm_power_off)(void);
40 EXPORT_SYMBOL(pm_power_off);
41
42 void machine_emergency_restart(void)
43 {
44         /* We really want to get pending console data out before we die. */
45         xencons_force_flush();
46         HYPERVISOR_shutdown(SHUTDOWN_reboot);
47 }
48
49 void machine_restart(char * __unused)
50 {
51         machine_emergency_restart();
52 }
53
54 void machine_halt(void)
55 {
56         machine_power_off();
57 }
58
59 void machine_power_off(void)
60 {
61         /* We really want to get pending console data out before we die. */
62         xencons_force_flush();
63         if (pm_power_off)
64                 pm_power_off();
65         HYPERVISOR_shutdown(SHUTDOWN_poweroff);
66 }
67
68 int reboot_thru_bios = 0;       /* for dmi_scan.c */
69 EXPORT_SYMBOL(machine_restart);
70 EXPORT_SYMBOL(machine_halt);
71 EXPORT_SYMBOL(machine_power_off);
72
73 #endif /* defined(__i386__) || defined(__x86_64__) */
74
75 /******************************************************************************
76  * Stop/pickle callback handling.
77  */
78
79 /* Ignore multiple shutdown requests. */
80 static int shutting_down = SHUTDOWN_INVALID;
81 static void __shutdown_handler(void *unused);
82 static DECLARE_WORK(shutdown_work, __shutdown_handler, NULL);
83
84 #if defined(__i386__) || defined(__x86_64__)
85
86 /* Ensure we run on the idle task page tables so that we will
87    switch page tables before running user space. This is needed
88    on architectures with separate kernel and user page tables
89    because the user page table pointer is not saved/restored. */
90 static void switch_idle_mm(void)
91 {
92         struct mm_struct *mm = current->active_mm;
93
94         if (mm == &init_mm)
95                 return;
96
97         atomic_inc(&init_mm.mm_count);
98         switch_mm(mm, &init_mm, current);
99         current->active_mm = &init_mm;
100         mmdrop(mm);
101 }
102
103 static void pre_suspend(void)
104 {
105         HYPERVISOR_shared_info = (shared_info_t *)empty_zero_page;
106         clear_fixmap(FIX_SHARED_INFO);
107
108         xen_start_info->store_mfn = mfn_to_pfn(xen_start_info->store_mfn);
109         xen_start_info->console.domU.mfn =
110                 mfn_to_pfn(xen_start_info->console.domU.mfn);
111 }
112
113 static void post_suspend(void)
114 {
115         int i, j, k, fpp;
116         extern unsigned long max_pfn;
117         extern unsigned long *pfn_to_mfn_frame_list_list;
118         extern unsigned long *pfn_to_mfn_frame_list[];
119
120         set_fixmap(FIX_SHARED_INFO, xen_start_info->shared_info);
121
122         HYPERVISOR_shared_info = (shared_info_t *)fix_to_virt(FIX_SHARED_INFO);
123
124         memset(empty_zero_page, 0, PAGE_SIZE);
125
126         HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list =
127                 virt_to_mfn(pfn_to_mfn_frame_list_list);
128
129         fpp = PAGE_SIZE/sizeof(unsigned long);
130         for (i = 0, j = 0, k = -1; i < max_pfn; i += fpp, j++) {
131                 if ((j % fpp) == 0) {
132                         k++;
133                         pfn_to_mfn_frame_list_list[k] =
134                                 virt_to_mfn(pfn_to_mfn_frame_list[k]);
135                         j = 0;
136                 }
137                 pfn_to_mfn_frame_list[k][j] =
138                         virt_to_mfn(&phys_to_machine_mapping[i]);
139         }
140         HYPERVISOR_shared_info->arch.max_pfn = max_pfn;
141 }
142
143 #else /* !(defined(__i386__) || defined(__x86_64__)) */
144
145 #define switch_idle_mm()        ((void)0)
146 #define mm_pin_all()            ((void)0)
147 #define pre_suspend()           ((void)0)
148 #define post_suspend()          ((void)0)
149
150 #endif
151
152 static int __do_suspend(void *ignore)
153 {
154         int err;
155
156         extern void time_resume(void);
157
158         BUG_ON(smp_processor_id() != 0);
159         BUG_ON(in_interrupt());
160
161 #if defined(__i386__) || defined(__x86_64__)
162         if (xen_feature(XENFEAT_auto_translated_physmap)) {
163                 printk(KERN_WARNING "Cannot suspend in "
164                        "auto_translated_physmap mode.\n");
165                 return -EOPNOTSUPP;
166         }
167 #endif
168
169         err = smp_suspend();
170         if (err)
171                 return err;
172
173         xenbus_suspend();
174
175         preempt_disable();
176
177         mm_pin_all();
178         local_irq_disable();
179         preempt_enable();
180
181         gnttab_suspend();
182
183         pre_suspend();
184
185         /*
186          * We'll stop somewhere inside this hypercall. When it returns,
187          * we'll start resuming after the restore.
188          */
189         HYPERVISOR_suspend(virt_to_mfn(xen_start_info));
190
191         shutting_down = SHUTDOWN_INVALID;
192
193         post_suspend();
194
195         gnttab_resume();
196
197         irq_resume();
198
199         time_resume();
200
201         switch_idle_mm();
202
203         local_irq_enable();
204
205         xencons_resume();
206
207         xenbus_resume();
208
209         smp_resume();
210
211         return err;
212 }
213
214 static int shutdown_process(void *__unused)
215 {
216         static char *envp[] = { "HOME=/", "TERM=linux",
217                                 "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
218         static char *poweroff_argv[] = { "/sbin/poweroff", NULL };
219
220         extern asmlinkage long sys_reboot(int magic1, int magic2,
221                                           unsigned int cmd, void *arg);
222
223         if ((shutting_down == SHUTDOWN_POWEROFF) ||
224             (shutting_down == SHUTDOWN_HALT)) {
225                 if (execve("/sbin/poweroff", poweroff_argv, envp) < 0) {
226                         sys_reboot(LINUX_REBOOT_MAGIC1,
227                                    LINUX_REBOOT_MAGIC2,
228                                    LINUX_REBOOT_CMD_POWER_OFF,
229                                    NULL);
230                 }
231         }
232
233         shutting_down = SHUTDOWN_INVALID; /* could try again */
234
235         return 0;
236 }
237
238 static int kthread_create_on_cpu(int (*f)(void *arg),
239                                  void *arg,
240                                  const char *name,
241                                  int cpu)
242 {
243         struct task_struct *p;
244         p = kthread_create(f, arg, name);
245         if (IS_ERR(p))
246                 return PTR_ERR(p);
247         kthread_bind(p, cpu);
248         wake_up_process(p);
249         return 0;
250 }
251
252 static void __shutdown_handler(void *unused)
253 {
254         int err;
255
256         if (shutting_down != SHUTDOWN_SUSPEND)
257                 err = kernel_thread(shutdown_process, NULL,
258                                     CLONE_FS | CLONE_FILES);
259         else
260                 err = kthread_create_on_cpu(__do_suspend, NULL, "suspend", 0);
261
262         if (err < 0) {
263                 printk(KERN_WARNING "Error creating shutdown process (%d): "
264                        "retrying...\n", -err);
265                 schedule_delayed_work(&shutdown_work, HZ/2);
266         }
267 }
268
269 static void shutdown_handler(struct xenbus_watch *watch,
270                              const char **vec, unsigned int len)
271 {
272         char *str;
273         struct xenbus_transaction xbt;
274         int err;
275
276         if (shutting_down != SHUTDOWN_INVALID)
277                 return;
278
279  again:
280         err = xenbus_transaction_start(&xbt);
281         if (err)
282                 return;
283         str = (char *)xenbus_read(xbt, "control", "shutdown", NULL);
284         /* Ignore read errors and empty reads. */
285         if (XENBUS_IS_ERR_READ(str)) {
286                 xenbus_transaction_end(xbt, 1);
287                 return;
288         }
289
290         xenbus_write(xbt, "control", "shutdown", "");
291
292         err = xenbus_transaction_end(xbt, 0);
293         if (err == -EAGAIN) {
294                 kfree(str);
295                 goto again;
296         }
297
298         if (strcmp(str, "poweroff") == 0)
299                 shutting_down = SHUTDOWN_POWEROFF;
300         else if (strcmp(str, "reboot") == 0)
301                 ctrl_alt_del();
302         else if (strcmp(str, "suspend") == 0)
303                 shutting_down = SHUTDOWN_SUSPEND;
304         else if (strcmp(str, "halt") == 0)
305                 shutting_down = SHUTDOWN_HALT;
306         else {
307                 printk("Ignoring shutdown request: %s\n", str);
308                 shutting_down = SHUTDOWN_INVALID;
309         }
310
311         if (shutting_down != SHUTDOWN_INVALID)
312                 schedule_work(&shutdown_work);
313
314         kfree(str);
315 }
316
317 static void sysrq_handler(struct xenbus_watch *watch, const char **vec,
318                           unsigned int len)
319 {
320         char sysrq_key = '\0';
321         struct xenbus_transaction xbt;
322         int err;
323
324  again:
325         err = xenbus_transaction_start(&xbt);
326         if (err)
327                 return;
328         if (!xenbus_scanf(xbt, "control", "sysrq", "%c", &sysrq_key)) {
329                 printk(KERN_ERR "Unable to read sysrq code in "
330                        "control/sysrq\n");
331                 xenbus_transaction_end(xbt, 1);
332                 return;
333         }
334
335         if (sysrq_key != '\0')
336                 xenbus_printf(xbt, "control", "sysrq", "%c", '\0');
337
338         err = xenbus_transaction_end(xbt, 0);
339         if (err == -EAGAIN)
340                 goto again;
341
342 #ifdef CONFIG_MAGIC_SYSRQ
343         if (sysrq_key != '\0')
344                 handle_sysrq(sysrq_key, NULL, NULL);
345 #endif
346 }
347
348 static struct xenbus_watch shutdown_watch = {
349         .node = "control/shutdown",
350         .callback = shutdown_handler
351 };
352
353 static struct xenbus_watch sysrq_watch = {
354         .node ="control/sysrq",
355         .callback = sysrq_handler
356 };
357
358 static int setup_shutdown_watcher(struct notifier_block *notifier,
359                                   unsigned long event,
360                                   void *data)
361 {
362         int err;
363
364         err = register_xenbus_watch(&shutdown_watch);
365         if (err)
366                 printk(KERN_ERR "Failed to set shutdown watcher\n");
367
368         err = register_xenbus_watch(&sysrq_watch);
369         if (err)
370                 printk(KERN_ERR "Failed to set sysrq watcher\n");
371
372         return NOTIFY_DONE;
373 }
374
375 static int __init setup_shutdown_event(void)
376 {
377         static struct notifier_block xenstore_notifier = {
378                 .notifier_call = setup_shutdown_watcher
379         };
380         register_xenstore_notifier(&xenstore_notifier);
381         return 0;
382 }
383
384 subsys_initcall(setup_shutdown_event);