ia64/xen-unstable

view linux-2.6.11-xen-sparse/arch/xen/kernel/reboot.c @ 4614:1de9eed58522

bitkeeper revision 1.1353 (42679008eE6ft7E62R0UneGs51hd-w)

Enable grant table suspend and resume when CONFIG_XEN_BLKDEV_GRANT
is defined.

Signed-off-by: Bin Ren <bin.ren@cl.cam.ac.uk>
author bren@br260.wolfson.cam.ac.uk
date Thu Apr 21 11:35:36 2005 +0000 (2005-04-21)
parents 260db0c4de3b
children c9edf0896f07 f23e5c9c3f1b 65b28c74cec2
line source
2 #define __KERNEL_SYSCALLS__
3 static int errno;
4 #include <linux/errno.h>
5 #include <linux/version.h>
6 #include <linux/kernel.h>
7 #include <linux/mm.h>
8 #include <linux/unistd.h>
9 #include <linux/module.h>
10 #include <linux/reboot.h>
11 #include <linux/sysrq.h>
12 #include <asm/irq.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)
21 {
22 /* We really want to get pending console data out before we die. */
23 extern void xencons_force_flush(void);
24 xencons_force_flush();
25 HYPERVISOR_reboot();
26 }
28 void machine_halt(void)
29 {
30 machine_power_off();
31 }
33 void machine_power_off(void)
34 {
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();
39 }
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);
46 #endif
49 /******************************************************************************
50 * Stop/pickle callback handling.
51 */
53 /* Ignore multiple shutdown requests. */
54 static int shutting_down = -1;
55 static int pending_sysrq = -1;
57 static void __do_suspend(void)
58 {
59 int i, j;
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);
67 #else
68 #define blkdev_suspend() do{}while(0)
69 #define blkdev_resume() do{}while(0)
70 #endif
72 #ifdef CONFIG_XEN_NETDEV_FRONTEND
73 extern void netif_suspend(void);
74 extern void netif_resume(void);
75 #else
76 #define netif_suspend() do{}while(0)
77 #define netif_resume() do{}while(0)
78 #endif
80 #ifdef CONFIG_XEN_USB_FRONTEND
81 extern void usbif_resume();
82 #else
83 #define usbif_resume() do{}while(0)
84 #endif
86 #ifdef CONFIG_XEN_BLKDEV_GRANT
87 extern int gnttab_suspend(void);
88 extern int gnttab_resume(void);
89 #else
90 #define gnttab_suspend() do{}while(0)
91 #define gnttab_resume() do{}while(0)
92 #endif
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 )
101 goto out;
103 suspend_record->nr_pfns = max_pfn; /* final number of pfns */
105 __cli();
107 netif_suspend();
109 blkdev_suspend();
111 time_suspend();
113 ctrl_if_suspend();
115 irq_suspend();
117 gnttab_suspend();
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);
127 shutting_down = -1;
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);
134 #else
135 set_fixmap(FIX_SHARED_INFO, xen_start_info.shared_info);
136 #endif
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++ )
143 {
144 pfn_to_mfn_frame_list[j] =
145 virt_to_machine(&phys_to_machine_mapping[i]) >> PAGE_SHIFT;
146 }
147 HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list =
148 virt_to_machine(pfn_to_mfn_frame_list) >> PAGE_SHIFT;
150 gnttab_resume();
152 irq_resume();
154 ctrl_if_resume();
156 time_resume();
158 blkdev_resume();
160 netif_resume();
162 usbif_resume();
164 __sti();
166 out:
167 if ( suspend_record != NULL )
168 free_page((unsigned long)suspend_record);
169 }
171 static int shutdown_process(void *__unused)
172 {
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);
181 daemonize(
182 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
183 "shutdown"
184 #endif
185 );
187 switch ( shutting_down )
188 {
189 case CMSG_SHUTDOWN_POWEROFF:
190 if ( execve("/sbin/halt", poweroff_argv, envp) < 0 )
191 {
192 sys_reboot(LINUX_REBOOT_MAGIC1,
193 LINUX_REBOOT_MAGIC2,
194 LINUX_REBOOT_CMD_POWER_OFF,
195 NULL);
196 }
197 break;
199 case CMSG_SHUTDOWN_REBOOT:
200 if ( execve("/sbin/shutdown", restart_argv, envp) < 0 )
201 {
202 sys_reboot(LINUX_REBOOT_MAGIC1,
203 LINUX_REBOOT_MAGIC2,
204 LINUX_REBOOT_CMD_RESTART,
205 NULL);
206 }
207 break;
208 }
210 shutting_down = -1; /* could try again */
212 return 0;
213 }
215 static void __shutdown_handler(void *unused)
216 {
217 int err;
219 if ( shutting_down != CMSG_SHUTDOWN_SUSPEND )
220 {
221 err = kernel_thread(shutdown_process, NULL, CLONE_FS | CLONE_FILES);
222 if ( err < 0 )
223 printk(KERN_ALERT "Error creating shutdown process!\n");
224 }
225 else
226 {
227 __do_suspend();
228 }
229 }
231 static void __sysrq_handler(void *unused)
232 {
233 #ifdef CONFIG_MAGIC_SYSRQ
234 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
235 handle_sysrq(pending_sysrq, NULL, NULL);
236 #else
237 handle_sysrq(pending_sysrq, NULL, NULL, NULL);
238 #endif
239 #endif
240 pending_sysrq = -1;
241 }
243 static void shutdown_handler(ctrl_msg_t *msg, unsigned long id)
244 {
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)) )
252 {
253 shutting_down = msg->subtype;
254 schedule_work(&shutdown_work);
255 }
256 else if ( (pending_sysrq == -1) &&
257 (msg->subtype == CMSG_SHUTDOWN_SYSRQ) )
258 {
259 pending_sysrq = ((shutdown_sysrq_t *)&msg->msg[0])->key;
260 schedule_work(&sysrq_work);
261 }
262 else
263 {
264 printk("Ignore spurious shutdown request\n");
265 }
267 ctrl_if_send_response(msg);
268 }
270 static int __init setup_shutdown_event(void)
271 {
272 ctrl_if_register_receiver(CMSG_SHUTDOWN, shutdown_handler, 0);
273 return 0;
274 }
276 __initcall(setup_shutdown_event);