2 #define __KERNEL_SYSCALLS__
4 #include <linux/errno.h>
5 #include <linux/version.h>
6 #include <linux/kernel.h>
8 #include <linux/unistd.h>
9 #include <linux/module.h>
10 #include <linux/reboot.h>
11 #include <linux/sysrq.h>
13 #include <asm/mmu_context.h>
14 #include <asm-xen/ctrl_if.h>
15 #include <asm-xen/hypervisor.h>
16 #include <asm-xen/xen-public/dom0_ops.h>
17 #include <asm-xen/linux-public/suspend.h>
18 #include <asm-xen/queues.h>
20 void machine_restart(char * __unused)
22 /* We really want to get pending console data out before we die. */
23 extern void xencons_force_flush(void);
24 xencons_force_flush();
28 void machine_halt(void)
33 void machine_power_off(void)
35 /* We really want to get pending console data out before we die. */
36 extern void xencons_force_flush(void);
37 xencons_force_flush();
38 HYPERVISOR_shutdown();
41 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
42 int reboot_thru_bios = 0; /* for dmi_scan.c */
43 EXPORT_SYMBOL(machine_restart);
44 EXPORT_SYMBOL(machine_halt);
45 EXPORT_SYMBOL(machine_power_off);
49 /******************************************************************************
50 * Stop/pickle callback handling.
53 /* Ignore multiple shutdown requests. */
54 static int shutting_down = -1;
55 static int pending_sysrq = -1;
57 static void __do_suspend(void)
60 suspend_record_t *suspend_record;
62 /* Hmmm... a cleaner interface to suspend/resume blkdevs would be nice. */
63 /* XXX SMH: yes it would :-( */
64 #ifdef CONFIG_XEN_BLKDEV_FRONTEND
65 extern void blkdev_suspend(void);
66 extern void blkdev_resume(void);
68 #define blkdev_suspend() do{}while(0)
69 #define blkdev_resume() do{}while(0)
72 #ifdef CONFIG_XEN_NETDEV_FRONTEND
73 extern void netif_suspend(void);
74 extern void netif_resume(void);
76 #define netif_suspend() do{}while(0)
77 #define netif_resume() do{}while(0)
80 #ifdef CONFIG_XEN_USB_FRONTEND
81 extern void usbif_resume();
83 #define usbif_resume() do{}while(0)
86 #ifdef CONFIG_XEN_BLKDEV_GRANT
87 extern int gnttab_suspend(void);
88 extern int gnttab_resume(void);
90 #define gnttab_suspend() do{}while(0)
91 #define gnttab_resume() do{}while(0)
94 extern void time_suspend(void);
95 extern void time_resume(void);
96 extern unsigned long max_pfn;
97 extern unsigned int *pfn_to_mfn_frame_list;
99 suspend_record = (suspend_record_t *)__get_free_page(GFP_KERNEL);
100 if ( suspend_record == NULL )
103 suspend_record->nr_pfns = max_pfn; /* final number of pfns */
119 HYPERVISOR_shared_info = (shared_info_t *)empty_zero_page;
120 clear_fixmap(FIX_SHARED_INFO);
122 memcpy(&suspend_record->resume_info, &xen_start_info,
123 sizeof(xen_start_info));
125 HYPERVISOR_suspend(virt_to_machine(suspend_record) >> PAGE_SHIFT);
129 memcpy(&xen_start_info, &suspend_record->resume_info,
130 sizeof(xen_start_info));
132 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
133 set_fixmap_ma(FIX_SHARED_INFO, xen_start_info.shared_info);
135 set_fixmap(FIX_SHARED_INFO, xen_start_info.shared_info);
138 HYPERVISOR_shared_info = (shared_info_t *)fix_to_virt(FIX_SHARED_INFO);
140 memset(empty_zero_page, 0, PAGE_SIZE);
142 for ( i=0, j=0; i < max_pfn; i+=(PAGE_SIZE/sizeof(unsigned long)), j++ )
144 pfn_to_mfn_frame_list[j] =
145 virt_to_machine(&phys_to_machine_mapping[i]) >> PAGE_SHIFT;
147 HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list =
148 virt_to_machine(pfn_to_mfn_frame_list) >> PAGE_SHIFT;
167 if ( suspend_record != NULL )
168 free_page((unsigned long)suspend_record);
171 static int shutdown_process(void *__unused)
173 static char *envp[] = { "HOME=/", "TERM=linux",
174 "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
175 static char *restart_argv[] = { "/sbin/shutdown", "-r", "now", NULL };
176 static char *poweroff_argv[] = { "/sbin/halt", "-p", NULL };
178 extern asmlinkage long sys_reboot(int magic1, int magic2,
179 unsigned int cmd, void *arg);
182 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
187 switch ( shutting_down )
189 case CMSG_SHUTDOWN_POWEROFF:
190 if ( execve("/sbin/halt", poweroff_argv, envp) < 0 )
192 sys_reboot(LINUX_REBOOT_MAGIC1,
194 LINUX_REBOOT_CMD_POWER_OFF,
199 case CMSG_SHUTDOWN_REBOOT:
200 if ( execve("/sbin/shutdown", restart_argv, envp) < 0 )
202 sys_reboot(LINUX_REBOOT_MAGIC1,
204 LINUX_REBOOT_CMD_RESTART,
210 shutting_down = -1; /* could try again */
215 static void __shutdown_handler(void *unused)
219 if ( shutting_down != CMSG_SHUTDOWN_SUSPEND )
221 err = kernel_thread(shutdown_process, NULL, CLONE_FS | CLONE_FILES);
223 printk(KERN_ALERT "Error creating shutdown process!\n");
231 static void __sysrq_handler(void *unused)
233 #ifdef CONFIG_MAGIC_SYSRQ
234 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
235 handle_sysrq(pending_sysrq, NULL, NULL);
237 handle_sysrq(pending_sysrq, NULL, NULL, NULL);
243 static void shutdown_handler(ctrl_msg_t *msg, unsigned long id)
245 static DECLARE_WORK(shutdown_work, __shutdown_handler, NULL);
246 static DECLARE_WORK(sysrq_work, __sysrq_handler, NULL);
248 if ( (shutting_down == -1) &&
249 ((msg->subtype == CMSG_SHUTDOWN_POWEROFF) ||
250 (msg->subtype == CMSG_SHUTDOWN_REBOOT) ||
251 (msg->subtype == CMSG_SHUTDOWN_SUSPEND)) )
253 shutting_down = msg->subtype;
254 schedule_work(&shutdown_work);
256 else if ( (pending_sysrq == -1) &&
257 (msg->subtype == CMSG_SHUTDOWN_SYSRQ) )
259 pending_sysrq = ((shutdown_sysrq_t *)&msg->msg[0])->key;
260 schedule_work(&sysrq_work);
264 printk("Ignore spurious shutdown request\n");
267 ctrl_if_send_response(msg);
270 static int __init setup_shutdown_event(void)
272 ctrl_if_register_receiver(CMSG_SHUTDOWN, shutdown_handler, 0);
276 __initcall(setup_shutdown_event);