ia64/xen-unstable

view linux-2.6-xen-sparse/drivers/xen/core/reboot.c @ 10692:306d7857928c

[IA64] Save & restore.

xc_ia64_linux_save.c and xc_ia64_linux_restore.c added.
vcpu context has more registers and states (eg: tr registers).
Per cpu irqs are deallocated when cpu is switched off.
#if/#endif added in reboot.c for ia64.

Signed-off-by: Tristan Gingold <tristan.gingold@bull.net>
author awilliam@xenbuild.aw
date Tue Jul 11 12:51:18 2006 -0600 (2006-07-11)
parents cede50ca1704
children 7ee2c02c6db0
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 <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>
22 #if defined(__i386__) || defined(__x86_64__)
23 /*
24 * Power off function, if any
25 */
26 void (*pm_power_off)(void);
27 EXPORT_SYMBOL(pm_power_off);
28 #endif
30 extern void ctrl_alt_del(void);
32 #define SHUTDOWN_INVALID -1
33 #define SHUTDOWN_POWEROFF 0
34 #define SHUTDOWN_SUSPEND 2
35 /* Code 3 is SHUTDOWN_CRASH, which we don't use because the domain can only
36 * report a crash, not be instructed to crash!
37 * HALT is the same as POWEROFF, as far as we're concerned. The tools use
38 * the distinction when we return the reason code to them.
39 */
40 #define SHUTDOWN_HALT 4
42 #if defined(__i386__) || defined(__x86_64__)
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 }
50 void machine_restart(char * __unused)
51 {
52 machine_emergency_restart();
53 }
55 void machine_halt(void)
56 {
57 machine_power_off();
58 }
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 }
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 #endif
75 /******************************************************************************
76 * Stop/pickle callback handling.
77 */
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);
84 #if defined(__i386__) || defined(__x86_64__)
85 /* Ensure we run on the idle task page tables so that we will
86 switch page tables before running user space. This is needed
87 on architectures with separate kernel and user page tables
88 because the user page table pointer is not saved/restored. */
89 static void switch_idle_mm(void)
90 {
91 struct mm_struct *mm = current->active_mm;
93 if (mm == &init_mm)
94 return;
96 atomic_inc(&init_mm.mm_count);
97 switch_mm(mm, &init_mm, current);
98 current->active_mm = &init_mm;
99 mmdrop(mm);
100 }
101 #endif
103 static int __do_suspend(void *ignore)
104 {
105 int err;
106 #if defined(__i386__) || defined(__x86_64__)
107 int i, j, k, fpp;
108 extern unsigned long max_pfn;
109 extern unsigned long *pfn_to_mfn_frame_list_list;
110 extern unsigned long *pfn_to_mfn_frame_list[];
111 #endif
113 extern void time_resume(void);
115 BUG_ON(smp_processor_id() != 0);
116 BUG_ON(in_interrupt());
118 #if defined(__i386__) || defined(__x86_64__)
119 if (xen_feature(XENFEAT_auto_translated_physmap)) {
120 printk(KERN_WARNING "Cannot suspend in "
121 "auto_translated_physmap mode.\n");
122 return -EOPNOTSUPP;
123 }
124 #endif
126 err = smp_suspend();
127 if (err)
128 return err;
130 xenbus_suspend();
132 preempt_disable();
134 #ifdef __i386__
135 kmem_cache_shrink(pgd_cache);
136 #endif
137 #if defined(__i386__) || defined(__x86_64__)
138 mm_pin_all();
140 __cli();
141 #elif defined(__ia64__)
142 local_irq_disable();
143 #endif
144 preempt_enable();
146 gnttab_suspend();
148 #if defined(__i386__) || defined(__x86_64__)
149 HYPERVISOR_shared_info = (shared_info_t *)empty_zero_page;
150 clear_fixmap(FIX_SHARED_INFO);
152 xen_start_info->store_mfn = mfn_to_pfn(xen_start_info->store_mfn);
153 xen_start_info->console_mfn = mfn_to_pfn(xen_start_info->console_mfn);
154 #endif
156 /*
157 * We'll stop somewhere inside this hypercall. When it returns,
158 * we'll start resuming after the restore.
159 */
160 HYPERVISOR_suspend(virt_to_mfn(xen_start_info));
162 shutting_down = SHUTDOWN_INVALID;
164 #if defined(__i386__) || defined(__x86_64__)
165 set_fixmap(FIX_SHARED_INFO, xen_start_info->shared_info);
167 HYPERVISOR_shared_info = (shared_info_t *)fix_to_virt(FIX_SHARED_INFO);
169 memset(empty_zero_page, 0, PAGE_SIZE);
171 HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list =
172 virt_to_mfn(pfn_to_mfn_frame_list_list);
174 fpp = PAGE_SIZE/sizeof(unsigned long);
175 for (i = 0, j = 0, k = -1; i < max_pfn; i += fpp, j++) {
176 if ((j % fpp) == 0) {
177 k++;
178 pfn_to_mfn_frame_list_list[k] =
179 virt_to_mfn(pfn_to_mfn_frame_list[k]);
180 j = 0;
181 }
182 pfn_to_mfn_frame_list[k][j] =
183 virt_to_mfn(&phys_to_machine_mapping[i]);
184 }
185 HYPERVISOR_shared_info->arch.max_pfn = max_pfn;
186 #endif
188 gnttab_resume();
190 irq_resume();
192 time_resume();
194 #if defined(__i386__) || defined(__x86_64__)
195 switch_idle_mm();
197 __sti();
198 #elif defined(__ia64__)
199 local_irq_enable();
200 #endif
202 xencons_resume();
204 xenbus_resume();
206 smp_resume();
208 return err;
209 }
211 static int shutdown_process(void *__unused)
212 {
213 static char *envp[] = { "HOME=/", "TERM=linux",
214 "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
215 static char *poweroff_argv[] = { "/sbin/poweroff", NULL };
217 extern asmlinkage long sys_reboot(int magic1, int magic2,
218 unsigned int cmd, void *arg);
220 if ((shutting_down == SHUTDOWN_POWEROFF) ||
221 (shutting_down == SHUTDOWN_HALT)) {
222 if (execve("/sbin/poweroff", poweroff_argv, envp) < 0) {
223 sys_reboot(LINUX_REBOOT_MAGIC1,
224 LINUX_REBOOT_MAGIC2,
225 LINUX_REBOOT_CMD_POWER_OFF,
226 NULL);
227 }
228 }
230 shutting_down = SHUTDOWN_INVALID; /* could try again */
232 return 0;
233 }
235 static int kthread_create_on_cpu(int (*f)(void *arg),
236 void *arg,
237 const char *name,
238 int cpu)
239 {
240 struct task_struct *p;
241 p = kthread_create(f, arg, name);
242 if (IS_ERR(p))
243 return PTR_ERR(p);
244 kthread_bind(p, cpu);
245 wake_up_process(p);
246 return 0;
247 }
249 static void __shutdown_handler(void *unused)
250 {
251 int err;
253 if (shutting_down != SHUTDOWN_SUSPEND)
254 err = kernel_thread(shutdown_process, NULL,
255 CLONE_FS | CLONE_FILES);
256 else
257 err = kthread_create_on_cpu(__do_suspend, NULL, "suspend", 0);
259 if (err < 0) {
260 printk(KERN_WARNING "Error creating shutdown process (%d): "
261 "retrying...\n", -err);
262 schedule_delayed_work(&shutdown_work, HZ/2);
263 }
264 }
266 static void shutdown_handler(struct xenbus_watch *watch,
267 const char **vec, unsigned int len)
268 {
269 char *str;
270 struct xenbus_transaction xbt;
271 int err;
273 if (shutting_down != SHUTDOWN_INVALID)
274 return;
276 again:
277 err = xenbus_transaction_start(&xbt);
278 if (err)
279 return;
280 str = (char *)xenbus_read(xbt, "control", "shutdown", NULL);
281 /* Ignore read errors and empty reads. */
282 if (XENBUS_IS_ERR_READ(str)) {
283 xenbus_transaction_end(xbt, 1);
284 return;
285 }
287 xenbus_write(xbt, "control", "shutdown", "");
289 err = xenbus_transaction_end(xbt, 0);
290 if (err == -EAGAIN) {
291 kfree(str);
292 goto again;
293 }
295 if (strcmp(str, "poweroff") == 0)
296 shutting_down = SHUTDOWN_POWEROFF;
297 else if (strcmp(str, "reboot") == 0)
298 ctrl_alt_del();
299 else if (strcmp(str, "suspend") == 0)
300 shutting_down = SHUTDOWN_SUSPEND;
301 else if (strcmp(str, "halt") == 0)
302 shutting_down = SHUTDOWN_HALT;
303 else {
304 printk("Ignoring shutdown request: %s\n", str);
305 shutting_down = SHUTDOWN_INVALID;
306 }
308 if (shutting_down != SHUTDOWN_INVALID)
309 schedule_work(&shutdown_work);
311 kfree(str);
312 }
314 static void sysrq_handler(struct xenbus_watch *watch, const char **vec,
315 unsigned int len)
316 {
317 char sysrq_key = '\0';
318 struct xenbus_transaction xbt;
319 int err;
321 again:
322 err = xenbus_transaction_start(&xbt);
323 if (err)
324 return;
325 if (!xenbus_scanf(xbt, "control", "sysrq", "%c", &sysrq_key)) {
326 printk(KERN_ERR "Unable to read sysrq code in "
327 "control/sysrq\n");
328 xenbus_transaction_end(xbt, 1);
329 return;
330 }
332 if (sysrq_key != '\0')
333 xenbus_printf(xbt, "control", "sysrq", "%c", '\0');
335 err = xenbus_transaction_end(xbt, 0);
336 if (err == -EAGAIN)
337 goto again;
339 #ifdef CONFIG_MAGIC_SYSRQ
340 if (sysrq_key != '\0')
341 handle_sysrq(sysrq_key, NULL, NULL);
342 #endif
343 }
345 static struct xenbus_watch shutdown_watch = {
346 .node = "control/shutdown",
347 .callback = shutdown_handler
348 };
350 static struct xenbus_watch sysrq_watch = {
351 .node ="control/sysrq",
352 .callback = sysrq_handler
353 };
355 static int setup_shutdown_watcher(struct notifier_block *notifier,
356 unsigned long event,
357 void *data)
358 {
359 int err;
361 err = register_xenbus_watch(&shutdown_watch);
362 if (err)
363 printk(KERN_ERR "Failed to set shutdown watcher\n");
365 err = register_xenbus_watch(&sysrq_watch);
366 if (err)
367 printk(KERN_ERR "Failed to set sysrq watcher\n");
369 return NOTIFY_DONE;
370 }
372 static int __init setup_shutdown_event(void)
373 {
374 static struct notifier_block xenstore_notifier = {
375 .notifier_call = setup_shutdown_watcher
376 };
377 register_xenstore_notifier(&xenstore_notifier);
378 return 0;
379 }
381 subsys_initcall(setup_shutdown_event);