ia64/xen-unstable

view linux-2.6-xen-sparse/arch/xen/kernel/reboot.c @ 6191:430ce2bade9b

Trivial fixes for a couple of xenlinux compile warnings.

Signed-off-by: <andrew.warfield@cl.cam.ac.uk>
author akw27@arcadians.cl.cam.ac.uk
date Mon Aug 15 13:50:39 2005 +0000 (2005-08-15)
parents 194f6230b62c
children 35f3f9424c93
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-xen/hypervisor.h>
14 #include <asm-xen/xen-public/dom0_ops.h>
15 #include <asm-xen/linux-public/suspend.h>
16 #include <asm-xen/queues.h>
17 #include <asm-xen/xenbus.h>
18 #include <asm-xen/ctrl_if.h>
20 #define SHUTDOWN_INVALID -1
21 #define SHUTDOWN_POWEROFF 0
22 #define SHUTDOWN_REBOOT 1
23 #define SHUTDOWN_SUSPEND 2
25 void machine_restart(char * __unused)
26 {
27 /* We really want to get pending console data out before we die. */
28 extern void xencons_force_flush(void);
29 xencons_force_flush();
30 HYPERVISOR_reboot();
31 }
33 void machine_halt(void)
34 {
35 machine_power_off();
36 }
38 void machine_power_off(void)
39 {
40 /* We really want to get pending console data out before we die. */
41 extern void xencons_force_flush(void);
42 xencons_force_flush();
43 HYPERVISOR_shutdown();
44 }
46 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
47 int reboot_thru_bios = 0; /* for dmi_scan.c */
48 EXPORT_SYMBOL(machine_restart);
49 EXPORT_SYMBOL(machine_halt);
50 EXPORT_SYMBOL(machine_power_off);
51 #endif
54 /******************************************************************************
55 * Stop/pickle callback handling.
56 */
58 /* Ignore multiple shutdown requests. */
59 static int shutting_down = SHUTDOWN_INVALID;
61 static void __do_suspend(void)
62 {
63 int i, j;
64 suspend_record_t *suspend_record;
66 /* Hmmm... a cleaner interface to suspend/resume blkdevs would be nice. */
67 /* XXX SMH: yes it would :-( */
68 #ifdef CONFIG_XEN_BLKDEV_FRONTEND
69 extern void blkdev_suspend(void);
70 extern void blkdev_resume(void);
71 #else
72 #define blkdev_suspend() do{}while(0)
73 #define blkdev_resume() do{}while(0)
74 #endif
76 #ifdef CONFIG_XEN_NETDEV_FRONTEND
77 extern void netif_suspend(void);
78 extern void netif_resume(void);
79 #else
80 #define netif_suspend() do{}while(0)
81 #define netif_resume() do{}while(0)
82 #endif
84 #ifdef CONFIG_XEN_USB_FRONTEND
85 extern void usbif_resume();
86 #else
87 #define usbif_resume() do{}while(0)
88 #endif
90 #ifdef CONFIG_XEN_BLKDEV_GRANT
91 extern int gnttab_suspend(void);
92 extern int gnttab_resume(void);
93 #else
94 #define gnttab_suspend() do{}while(0)
95 #define gnttab_resume() do{}while(0)
96 #endif
98 #ifdef CONFIG_SMP
99 extern void smp_suspend(void);
100 extern void smp_resume(void);
101 #endif
102 extern void time_suspend(void);
103 extern void time_resume(void);
104 extern unsigned long max_pfn;
105 extern unsigned int *pfn_to_mfn_frame_list;
107 suspend_record = (suspend_record_t *)__get_free_page(GFP_KERNEL);
108 if ( suspend_record == NULL )
109 goto out;
111 suspend_record->nr_pfns = max_pfn; /* final number of pfns */
113 __cli();
115 #ifdef __i386__
116 mm_pin_all();
117 kmem_cache_shrink(pgd_cache);
118 #endif
120 netif_suspend();
122 blkdev_suspend();
124 time_suspend();
126 #ifdef CONFIG_SMP
127 smp_suspend();
128 #endif
130 xenbus_suspend();
132 ctrl_if_suspend();
134 irq_suspend();
136 gnttab_suspend();
138 HYPERVISOR_shared_info = (shared_info_t *)empty_zero_page;
139 clear_fixmap(FIX_SHARED_INFO);
141 memcpy(&suspend_record->resume_info, &xen_start_info,
142 sizeof(xen_start_info));
144 HYPERVISOR_suspend(virt_to_machine(suspend_record) >> PAGE_SHIFT);
146 shutting_down = SHUTDOWN_INVALID;
148 memcpy(&xen_start_info, &suspend_record->resume_info,
149 sizeof(xen_start_info));
151 set_fixmap(FIX_SHARED_INFO, xen_start_info.shared_info);
153 HYPERVISOR_shared_info = (shared_info_t *)fix_to_virt(FIX_SHARED_INFO);
155 memset(empty_zero_page, 0, PAGE_SIZE);
157 for ( i=0, j=0; i < max_pfn; i+=(PAGE_SIZE/sizeof(unsigned long)), j++ )
158 {
159 pfn_to_mfn_frame_list[j] =
160 virt_to_machine(&phys_to_machine_mapping[i]) >> PAGE_SHIFT;
161 }
162 HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list =
163 virt_to_machine(pfn_to_mfn_frame_list) >> PAGE_SHIFT;
165 gnttab_resume();
167 irq_resume();
169 ctrl_if_resume();
171 xenbus_resume();
173 #ifdef CONFIG_SMP
174 smp_resume();
175 #endif
177 time_resume();
179 blkdev_resume();
181 netif_resume();
183 usbif_resume();
185 __sti();
187 out:
188 if ( suspend_record != NULL )
189 free_page((unsigned long)suspend_record);
190 }
192 static int shutdown_process(void *__unused)
193 {
194 static char *envp[] = { "HOME=/", "TERM=linux",
195 "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
196 static char *restart_argv[] = { "/sbin/reboot", NULL };
197 static char *poweroff_argv[] = { "/sbin/poweroff", NULL };
199 extern asmlinkage long sys_reboot(int magic1, int magic2,
200 unsigned int cmd, void *arg);
202 daemonize(
203 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
204 "shutdown"
205 #endif
206 );
208 switch ( shutting_down )
209 {
210 case SHUTDOWN_POWEROFF:
211 if ( execve("/sbin/poweroff", poweroff_argv, envp) < 0 )
212 {
213 sys_reboot(LINUX_REBOOT_MAGIC1,
214 LINUX_REBOOT_MAGIC2,
215 LINUX_REBOOT_CMD_POWER_OFF,
216 NULL);
217 }
218 break;
220 case SHUTDOWN_REBOOT:
221 if ( execve("/sbin/reboot", restart_argv, envp) < 0 )
222 {
223 sys_reboot(LINUX_REBOOT_MAGIC1,
224 LINUX_REBOOT_MAGIC2,
225 LINUX_REBOOT_CMD_RESTART,
226 NULL);
227 }
228 break;
229 }
231 shutting_down = SHUTDOWN_INVALID; /* could try again */
233 return 0;
234 }
236 static void __shutdown_handler(void *unused)
237 {
238 int err;
240 if ( shutting_down != SHUTDOWN_SUSPEND )
241 {
242 err = kernel_thread(shutdown_process, NULL, CLONE_FS | CLONE_FILES);
243 if ( err < 0 )
244 printk(KERN_ALERT "Error creating shutdown process!\n");
245 }
246 else
247 {
248 __do_suspend();
249 }
250 }
252 static void shutdown_handler(struct xenbus_watch *watch, const char *node)
253 {
254 static DECLARE_WORK(shutdown_work, __shutdown_handler, NULL);
256 char *str;
258 str = (char *)xenbus_read("control", "shutdown", NULL);
259 /* Ignore read errors and recursive shutdown events. */
260 if (IS_ERR(str) || !strcmp(str, __stringify(SHUTDOWN_INVALID)))
261 return;
263 xenbus_printf("control", "shutdown", "%i", SHUTDOWN_INVALID);
265 if (strcmp(str, "poweroff") == 0) {
266 shutting_down = SHUTDOWN_POWEROFF;
267 } else if (strcmp(str, "reboot") == 0) {
268 shutting_down = SHUTDOWN_REBOOT;
269 } else if (strcmp(str, "suspend") == 0) {
270 shutting_down = SHUTDOWN_SUSPEND;
271 } else {
272 printk("Ignoring shutdown request: %s\n", str);
273 shutting_down = SHUTDOWN_INVALID;
274 }
276 kfree(str);
278 if (shutting_down != SHUTDOWN_INVALID)
279 schedule_work(&shutdown_work);
280 }
282 #ifdef CONFIG_MAGIC_SYSRQ
283 static void sysrq_handler(struct xenbus_watch *watch, const char *node)
284 {
285 char sysrq_key = '\0';
287 if (!xenbus_scanf("control", "sysrq", "%c", &sysrq_key)) {
288 printk(KERN_ERR "Unable to read sysrq code in control/sysrq\n");
289 return;
290 }
292 xenbus_printf("control", "sysrq", "%c", '\0');
294 if (sysrq_key != '\0') {
296 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
297 handle_sysrq(sysrq_key, NULL, NULL);
298 #else
299 handle_sysrq(sysrq_key, NULL, NULL, NULL);
300 #endif
301 }
302 }
303 #endif
305 static struct xenbus_watch shutdown_watch = {
306 .node = "control/shutdown",
307 .callback = shutdown_handler
308 };
310 #ifdef CONFIG_MAGIC_SYSRQ
311 static struct xenbus_watch sysrq_watch = {
312 .node ="control/sysrq",
313 .callback = sysrq_handler
314 };
315 #endif
317 static struct notifier_block xenstore_notifier;
319 /* Setup our watcher
320 NB: Assumes xenbus_lock is held!
321 */
322 static int setup_shutdown_watcher(struct notifier_block *notifier,
323 unsigned long event,
324 void *data)
325 {
326 int err1 = 0;
327 #ifdef CONFIG_MAGIC_SYSRQ
328 int err2 = 0;
329 #endif
331 BUG_ON(down_trylock(&xenbus_lock) == 0);
333 err1 = register_xenbus_watch(&shutdown_watch);
334 #ifdef CONFIG_MAGIC_SYSRQ
335 err2 = register_xenbus_watch(&sysrq_watch);
336 #endif
338 if (err1) {
339 printk(KERN_ERR "Failed to set shutdown watcher\n");
340 }
342 #ifdef CONFIG_MAGIC_SYSRQ
343 if (err2) {
344 printk(KERN_ERR "Failed to set sysrq watcher\n");
345 }
346 #endif
348 return NOTIFY_DONE;
349 }
351 static int __init setup_shutdown_event(void)
352 {
354 xenstore_notifier.notifier_call = setup_shutdown_watcher;
356 register_xenstore_notifier(&xenstore_notifier);
358 return 0;
359 }
361 subsys_initcall(setup_shutdown_event);