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