1
2
3
4
5
6
7
8
9
10
11#include <linux/cpu.h>
12#include <linux/pm.h>
13#include <linux/elf.h>
14#include <linux/errno.h>
15#include <linux/kallsyms.h>
16#include <linux/kernel.h>
17#include <linux/mm.h>
18#include <linux/module.h>
19#include <linux/notifier.h>
20#include <linux/personality.h>
21#include <linux/sched.h>
22#include <linux/slab.h>
23#include <linux/stddef.h>
24#include <linux/thread_info.h>
25#include <linux/unistd.h>
26#include <linux/efi.h>
27#include <linux/interrupt.h>
28#include <linux/delay.h>
29#include <linux/kdebug.h>
30#include <linux/utsname.h>
31
32#include <asm/cpu.h>
33#include <asm/delay.h>
34#include <asm/elf.h>
35#include <asm/ia32.h>
36#include <asm/irq.h>
37#include <asm/kexec.h>
38#include <asm/pgalloc.h>
39#include <asm/processor.h>
40#include <asm/sal.h>
41#include <asm/tlbflush.h>
42#include <asm/uaccess.h>
43#include <asm/unwind.h>
44#include <asm/user.h>
45
46#include "entry.h"
47
48#ifdef CONFIG_PERFMON
49# include <asm/perfmon.h>
50#endif
51
52#include "sigframe.h"
53
54void (*ia64_mark_idle)(int);
55static DEFINE_PER_CPU(unsigned int, cpu_idle_state);
56
57unsigned long boot_option_idle_override = 0;
58EXPORT_SYMBOL(boot_option_idle_override);
59
60void
61ia64_do_show_stack (struct unw_frame_info *info, void *arg)
62{
63 unsigned long ip, sp, bsp;
64 char buf[128];
65
66 printk("\nCall Trace:\n");
67 do {
68 unw_get_ip(info, &ip);
69 if (ip == 0)
70 break;
71
72 unw_get_sp(info, &sp);
73 unw_get_bsp(info, &bsp);
74 snprintf(buf, sizeof(buf),
75 " [<%016lx>] %%s\n"
76 " sp=%016lx bsp=%016lx\n",
77 ip, sp, bsp);
78 print_symbol(buf, ip);
79 } while (unw_unwind(info) >= 0);
80}
81
82void
83show_stack (struct task_struct *task, unsigned long *sp)
84{
85 if (!task)
86 unw_init_running(ia64_do_show_stack, NULL);
87 else {
88 struct unw_frame_info info;
89
90 unw_init_from_blocked_task(&info, task);
91 ia64_do_show_stack(&info, NULL);
92 }
93}
94
95void
96dump_stack (void)
97{
98 show_stack(NULL, NULL);
99}
100
101EXPORT_SYMBOL(dump_stack);
102
103void
104show_regs (struct pt_regs *regs)
105{
106 unsigned long ip = regs->cr_iip + ia64_psr(regs)->ri;
107
108 print_modules();
109 printk("\nPid: %d, CPU %d, comm: %20s\n", task_pid_nr(current),
110 smp_processor_id(), current->comm);
111 printk("psr : %016lx ifs : %016lx ip : [<%016lx>] %s (%s)\n",
112 regs->cr_ipsr, regs->cr_ifs, ip, print_tainted(),
113 init_utsname()->release);
114 print_symbol("ip is at %s\n", ip);
115 printk("unat: %016lx pfs : %016lx rsc : %016lx\n",
116 regs->ar_unat, regs->ar_pfs, regs->ar_rsc);
117 printk("rnat: %016lx bsps: %016lx pr : %016lx\n",
118 regs->ar_rnat, regs->ar_bspstore, regs->pr);
119 printk("ldrs: %016lx ccv : %016lx fpsr: %016lx\n",
120 regs->loadrs, regs->ar_ccv, regs->ar_fpsr);
121 printk("csd : %016lx ssd : %016lx\n", regs->ar_csd, regs->ar_ssd);
122 printk("b0 : %016lx b6 : %016lx b7 : %016lx\n", regs->b0, regs->b6, regs->b7);
123 printk("f6 : %05lx%016lx f7 : %05lx%016lx\n",
124 regs->f6.u.bits[1], regs->f6.u.bits[0],
125 regs->f7.u.bits[1], regs->f7.u.bits[0]);
126 printk("f8 : %05lx%016lx f9 : %05lx%016lx\n",
127 regs->f8.u.bits[1], regs->f8.u.bits[0],
128 regs->f9.u.bits[1], regs->f9.u.bits[0]);
129 printk("f10 : %05lx%016lx f11 : %05lx%016lx\n",
130 regs->f10.u.bits[1], regs->f10.u.bits[0],
131 regs->f11.u.bits[1], regs->f11.u.bits[0]);
132
133 printk("r1 : %016lx r2 : %016lx r3 : %016lx\n", regs->r1, regs->r2, regs->r3);
134 printk("r8 : %016lx r9 : %016lx r10 : %016lx\n", regs->r8, regs->r9, regs->r10);
135 printk("r11 : %016lx r12 : %016lx r13 : %016lx\n", regs->r11, regs->r12, regs->r13);
136 printk("r14 : %016lx r15 : %016lx r16 : %016lx\n", regs->r14, regs->r15, regs->r16);
137 printk("r17 : %016lx r18 : %016lx r19 : %016lx\n", regs->r17, regs->r18, regs->r19);
138 printk("r20 : %016lx r21 : %016lx r22 : %016lx\n", regs->r20, regs->r21, regs->r22);
139 printk("r23 : %016lx r24 : %016lx r25 : %016lx\n", regs->r23, regs->r24, regs->r25);
140 printk("r26 : %016lx r27 : %016lx r28 : %016lx\n", regs->r26, regs->r27, regs->r28);
141 printk("r29 : %016lx r30 : %016lx r31 : %016lx\n", regs->r29, regs->r30, regs->r31);
142
143 if (user_mode(regs)) {
144
145 unsigned long val, *bsp, ndirty;
146 int i, sof, is_nat = 0;
147
148 sof = regs->cr_ifs & 0x7f;
149 ndirty = (regs->loadrs >> 19);
150 bsp = ia64_rse_skip_regs((unsigned long *) regs->ar_bspstore, ndirty);
151 for (i = 0; i < sof; ++i) {
152 get_user(val, (unsigned long __user *) ia64_rse_skip_regs(bsp, i));
153 printk("r%-3u:%c%016lx%s", 32 + i, is_nat ? '*' : ' ', val,
154 ((i == sof - 1) || (i % 3) == 2) ? "\n" : " ");
155 }
156 } else
157 show_stack(NULL, NULL);
158}
159
160void
161do_notify_resume_user (sigset_t *unused, struct sigscratch *scr, long in_syscall)
162{
163 if (fsys_mode(current, &scr->pt)) {
164
165 if (!ia64_psr(&scr->pt)->lp)
166 ia64_psr(&scr->pt)->lp = 1;
167 return;
168 }
169
170#ifdef CONFIG_PERFMON
171 if (current->thread.pfm_needs_checking)
172 pfm_handle_work();
173#endif
174
175
176 if (test_thread_flag(TIF_SIGPENDING)||test_thread_flag(TIF_RESTORE_SIGMASK))
177 ia64_do_signal(scr, in_syscall);
178}
179
180static int pal_halt = 1;
181static int can_do_pal_halt = 1;
182
183static int __init nohalt_setup(char * str)
184{
185 pal_halt = can_do_pal_halt = 0;
186 return 1;
187}
188__setup("nohalt", nohalt_setup);
189
190void
191update_pal_halt_status(int status)
192{
193 can_do_pal_halt = pal_halt && status;
194}
195
196
197
198
199void
200default_idle (void)
201{
202 local_irq_enable();
203 while (!need_resched()) {
204 if (can_do_pal_halt) {
205 local_irq_disable();
206 if (!need_resched()) {
207 safe_halt();
208 }
209 local_irq_enable();
210 } else
211 cpu_relax();
212 }
213}
214
215#ifdef CONFIG_HOTPLUG_CPU
216
217static inline void play_dead(void)
218{
219 extern void ia64_cpu_local_tick (void);
220 unsigned int this_cpu = smp_processor_id();
221
222
223 __get_cpu_var(cpu_state) = CPU_DEAD;
224
225 max_xtp();
226 local_irq_disable();
227 idle_task_exit();
228 ia64_jump_to_sal(&sal_boot_rendez_state[this_cpu]);
229
230
231
232
233 BUG();
234}
235#else
236static inline void play_dead(void)
237{
238 BUG();
239}
240#endif
241
242void cpu_idle_wait(void)
243{
244 unsigned int cpu, this_cpu = get_cpu();
245 cpumask_t map;
246 cpumask_t tmp = current->cpus_allowed;
247
248 set_cpus_allowed(current, cpumask_of_cpu(this_cpu));
249 put_cpu();
250
251 cpus_clear(map);
252 for_each_online_cpu(cpu) {
253 per_cpu(cpu_idle_state, cpu) = 1;
254 cpu_set(cpu, map);
255 }
256
257 __get_cpu_var(cpu_idle_state) = 0;
258
259 wmb();
260 do {
261 ssleep(1);
262 for_each_online_cpu(cpu) {
263 if (cpu_isset(cpu, map) && !per_cpu(cpu_idle_state, cpu))
264 cpu_clear(cpu, map);
265 }
266 cpus_and(map, map, cpu_online_map);
267 } while (!cpus_empty(map));
268 set_cpus_allowed(current, tmp);
269}
270EXPORT_SYMBOL_GPL(cpu_idle_wait);
271
272void __attribute__((noreturn))
273cpu_idle (void)
274{
275 void (*mark_idle)(int) = ia64_mark_idle;
276 int cpu = smp_processor_id();
277
278
279 while (1) {
280 if (can_do_pal_halt) {
281 current_thread_info()->status &= ~TS_POLLING;
282
283
284
285
286 smp_mb();
287 } else {
288 current_thread_info()->status |= TS_POLLING;
289 }
290
291 if (!need_resched()) {
292 void (*idle)(void);
293#ifdef CONFIG_SMP
294 min_xtp();
295#endif
296 if (__get_cpu_var(cpu_idle_state))
297 __get_cpu_var(cpu_idle_state) = 0;
298
299 rmb();
300 if (mark_idle)
301 (*mark_idle)(1);
302
303 idle = pm_idle;
304 if (!idle)
305 idle = default_idle;
306 (*idle)();
307 if (mark_idle)
308 (*mark_idle)(0);
309#ifdef CONFIG_SMP
310 normal_xtp();
311#endif
312 }
313 preempt_enable_no_resched();
314 schedule();
315 preempt_disable();
316 check_pgt_cache();
317 if (cpu_is_offline(cpu))
318 play_dead();
319 }
320}
321
322void
323ia64_save_extra (struct task_struct *task)
324{
325#ifdef CONFIG_PERFMON
326 unsigned long info;
327#endif
328
329 if ((task->thread.flags & IA64_THREAD_DBG_VALID) != 0)
330 ia64_save_debug_regs(&task->thread.dbr[0]);
331
332#ifdef CONFIG_PERFMON
333 if ((task->thread.flags & IA64_THREAD_PM_VALID) != 0)
334 pfm_save_regs(task);
335
336 info = __get_cpu_var(pfm_syst_info);
337 if (info & PFM_CPUINFO_SYST_WIDE)
338 pfm_syst_wide_update_task(task, info, 0);
339#endif
340
341#ifdef CONFIG_IA32_SUPPORT
342 if (IS_IA32_PROCESS(task_pt_regs(task)))
343 ia32_save_state(task);
344#endif
345}
346
347void
348ia64_load_extra (struct task_struct *task)
349{
350#ifdef CONFIG_PERFMON
351 unsigned long info;
352#endif
353
354 if ((task->thread.flags & IA64_THREAD_DBG_VALID) != 0)
355 ia64_load_debug_regs(&task->thread.dbr[0]);
356
357#ifdef CONFIG_PERFMON
358 if ((task->thread.flags & IA64_THREAD_PM_VALID) != 0)
359 pfm_load_regs(task);
360
361 info = __get_cpu_var(pfm_syst_info);
362 if (info & PFM_CPUINFO_SYST_WIDE)
363 pfm_syst_wide_update_task(task, info, 1);
364#endif
365
366#ifdef CONFIG_IA32_SUPPORT
367 if (IS_IA32_PROCESS(task_pt_regs(task)))
368 ia32_load_state(task);
369#endif
370}
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403int
404copy_thread (int nr, unsigned long clone_flags,
405 unsigned long user_stack_base, unsigned long user_stack_size,
406 struct task_struct *p, struct pt_regs *regs)
407{
408 extern char ia64_ret_from_clone, ia32_ret_from_clone;
409 struct switch_stack *child_stack, *stack;
410 unsigned long rbs, child_rbs, rbs_size;
411 struct pt_regs *child_ptregs;
412 int retval = 0;
413
414#ifdef CONFIG_SMP
415
416
417
418
419 if (!regs)
420 return 0;
421#endif
422
423 stack = ((struct switch_stack *) regs) - 1;
424
425 child_ptregs = (struct pt_regs *) ((unsigned long) p + IA64_STK_OFFSET) - 1;
426 child_stack = (struct switch_stack *) child_ptregs - 1;
427
428
429 memcpy(child_stack, stack, sizeof(*child_ptregs) + sizeof(*child_stack));
430
431 rbs = (unsigned long) current + IA64_RBS_OFFSET;
432 child_rbs = (unsigned long) p + IA64_RBS_OFFSET;
433 rbs_size = stack->ar_bspstore - rbs;
434
435
436 memcpy((void *) child_rbs, (void *) rbs, rbs_size);
437
438 if (likely(user_mode(child_ptregs))) {
439 if ((clone_flags & CLONE_SETTLS) && !IS_IA32_PROCESS(regs))
440 child_ptregs->r13 = regs->r16;
441 if (user_stack_base) {
442 child_ptregs->r12 = user_stack_base + user_stack_size - 16;
443 child_ptregs->ar_bspstore = user_stack_base;
444 child_ptregs->ar_rnat = 0;
445 child_ptregs->loadrs = 0;
446 }
447 } else {
448
449
450
451
452
453
454
455 child_ptregs->r12 = (unsigned long) child_ptregs - 16;
456 child_ptregs->r13 = (unsigned long) p;
457 }
458 child_stack->ar_bspstore = child_rbs + rbs_size;
459 if (IS_IA32_PROCESS(regs))
460 child_stack->b0 = (unsigned long) &ia32_ret_from_clone;
461 else
462 child_stack->b0 = (unsigned long) &ia64_ret_from_clone;
463
464
465 p->thread.ksp = (unsigned long) child_stack - 16;
466
467
468
469
470
471
472 child_ptregs->cr_ipsr = ((child_ptregs->cr_ipsr | IA64_PSR_BITS_TO_SET)
473 & ~(IA64_PSR_BITS_TO_CLEAR | IA64_PSR_PP | IA64_PSR_UP));
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491# define THREAD_FLAGS_TO_CLEAR (IA64_THREAD_FPH_VALID | IA64_THREAD_DBG_VALID \
492 | IA64_THREAD_PM_VALID)
493# define THREAD_FLAGS_TO_SET 0
494 p->thread.flags = ((current->thread.flags & ~THREAD_FLAGS_TO_CLEAR)
495 | THREAD_FLAGS_TO_SET);
496 ia64_drop_fpu(p);
497#ifdef CONFIG_IA32_SUPPORT
498
499
500
501
502 if (IS_IA32_PROCESS(task_pt_regs(current))) {
503 ia32_save_state(p);
504 if (clone_flags & CLONE_SETTLS)
505 retval = ia32_clone_tls(p, child_ptregs);
506
507
508 if (!retval)
509 retval = ia32_copy_ia64_partial_page_list(p,
510 clone_flags);
511 }
512#endif
513
514#ifdef CONFIG_PERFMON
515 if (current->thread.pfm_context)
516 pfm_inherit(p, child_ptregs);
517#endif
518 return retval;
519}
520
521static void
522do_copy_task_regs (struct task_struct *task, struct unw_frame_info *info, void *arg)
523{
524 unsigned long mask, sp, nat_bits = 0, ar_rnat, urbs_end, cfm;
525 unsigned long uninitialized_var(ip);
526 elf_greg_t *dst = arg;
527 struct pt_regs *pt;
528 char nat;
529 int i;
530
531 memset(dst, 0, sizeof(elf_gregset_t));
532
533 if (unw_unwind_to_user(info) < 0)
534 return;
535
536 unw_get_sp(info, &sp);
537 pt = (struct pt_regs *) (sp + 16);
538
539 urbs_end = ia64_get_user_rbs_end(task, pt, &cfm);
540
541 if (ia64_sync_user_rbs(task, info->sw, pt->ar_bspstore, urbs_end) < 0)
542 return;
543
544 ia64_peek(task, info->sw, urbs_end, (long) ia64_rse_rnat_addr((long *) urbs_end),
545 &ar_rnat);
546
547
548
549
550
551
552
553
554
555
556
557
558
559 for (i = 1, mask = (1UL << i); i < 32; ++i) {
560 unw_get_gr(info, i, &dst[i], &nat);
561 if (nat)
562 nat_bits |= mask;
563 mask <<= 1;
564 }
565 dst[32] = nat_bits;
566 unw_get_pr(info, &dst[33]);
567
568 for (i = 0; i < 8; ++i)
569 unw_get_br(info, i, &dst[34 + i]);
570
571 unw_get_rp(info, &ip);
572 dst[42] = ip + ia64_psr(pt)->ri;
573 dst[43] = cfm;
574 dst[44] = pt->cr_ipsr & IA64_PSR_UM;
575
576 unw_get_ar(info, UNW_AR_RSC, &dst[45]);
577
578
579
580
581 dst[46] = urbs_end;
582 dst[47] = pt->ar_bspstore;
583 dst[48] = ar_rnat;
584 unw_get_ar(info, UNW_AR_CCV, &dst[49]);
585 unw_get_ar(info, UNW_AR_UNAT, &dst[50]);
586 unw_get_ar(info, UNW_AR_FPSR, &dst[51]);
587 dst[52] = pt->ar_pfs;
588 unw_get_ar(info, UNW_AR_LC, &dst[53]);
589 unw_get_ar(info, UNW_AR_EC, &dst[54]);
590 unw_get_ar(info, UNW_AR_CSD, &dst[55]);
591 unw_get_ar(info, UNW_AR_SSD, &dst[56]);
592}
593
594void
595do_dump_task_fpu (struct task_struct *task, struct unw_frame_info *info, void *arg)
596{
597 elf_fpreg_t *dst = arg;
598 int i;
599
600 memset(dst, 0, sizeof(elf_fpregset_t));
601
602 if (unw_unwind_to_user(info) < 0)
603 return;
604
605
606
607 for (i = 2; i < 32; ++i)
608 unw_get_fr(info, i, dst + i);
609
610 ia64_flush_fph(task);
611 if ((task->thread.flags & IA64_THREAD_FPH_VALID) != 0)
612 memcpy(dst + 32, task->thread.fph, 96*16);
613}
614
615void
616do_copy_regs (struct unw_frame_info *info, void *arg)
617{
618 do_copy_task_regs(current, info, arg);
619}
620
621void
622do_dump_fpu (struct unw_frame_info *info, void *arg)
623{
624 do_dump_task_fpu(current, info, arg);
625}
626
627int
628dump_task_regs(struct task_struct *task, elf_gregset_t *regs)
629{
630 struct unw_frame_info tcore_info;
631
632 if (current == task) {
633 unw_init_running(do_copy_regs, regs);
634 } else {
635 memset(&tcore_info, 0, sizeof(tcore_info));
636 unw_init_from_blocked_task(&tcore_info, task);
637 do_copy_task_regs(task, &tcore_info, regs);
638 }
639 return 1;
640}
641
642void
643ia64_elf_core_copy_regs (struct pt_regs *pt, elf_gregset_t dst)
644{
645 unw_init_running(do_copy_regs, dst);
646}
647
648int
649dump_task_fpu (struct task_struct *task, elf_fpregset_t *dst)
650{
651 struct unw_frame_info tcore_info;
652
653 if (current == task) {
654 unw_init_running(do_dump_fpu, dst);
655 } else {
656 memset(&tcore_info, 0, sizeof(tcore_info));
657 unw_init_from_blocked_task(&tcore_info, task);
658 do_dump_task_fpu(task, &tcore_info, dst);
659 }
660 return 1;
661}
662
663int
664dump_fpu (struct pt_regs *pt, elf_fpregset_t dst)
665{
666 unw_init_running(do_dump_fpu, dst);
667 return 1;
668}
669
670long
671sys_execve (char __user *filename, char __user * __user *argv, char __user * __user *envp,
672 struct pt_regs *regs)
673{
674 char *fname;
675 int error;
676
677 fname = getname(filename);
678 error = PTR_ERR(fname);
679 if (IS_ERR(fname))
680 goto out;
681 error = do_execve(fname, argv, envp, regs);
682 putname(fname);
683out:
684 return error;
685}
686
687pid_t
688kernel_thread (int (*fn)(void *), void *arg, unsigned long flags)
689{
690 extern void start_kernel_thread (void);
691 unsigned long *helper_fptr = (unsigned long *) &start_kernel_thread;
692 struct {
693 struct switch_stack sw;
694 struct pt_regs pt;
695 } regs;
696
697 memset(®s, 0, sizeof(regs));
698 regs.pt.cr_iip = helper_fptr[0];
699 regs.pt.r1 = helper_fptr[1];
700 regs.pt.r9 = (unsigned long) fn;
701 regs.pt.r11 = (unsigned long) arg;
702
703 regs.pt.cr_ipsr = ia64_getreg(_IA64_REG_PSR) | IA64_PSR_BN;
704 regs.pt.cr_ifs = 1UL << 63;
705 regs.sw.ar_fpsr = regs.pt.ar_fpsr = ia64_getreg(_IA64_REG_AR_FPSR);
706 regs.sw.ar_bspstore = (unsigned long) current + IA64_RBS_OFFSET;
707 regs.sw.pr = (1 << PRED_KERNEL_STACK);
708 return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s.pt, 0, NULL, NULL);
709}
710EXPORT_SYMBOL(kernel_thread);
711
712
713int
714kernel_thread_helper (int (*fn)(void *), void *arg)
715{
716#ifdef CONFIG_IA32_SUPPORT
717 if (IS_IA32_PROCESS(task_pt_regs(current))) {
718
719 current->thread.map_base = DEFAULT_MAP_BASE;
720 current->thread.task_size = DEFAULT_TASK_SIZE;
721 ia64_set_kr(IA64_KR_IO_BASE, current->thread.old_iob);
722 ia64_set_kr(IA64_KR_TSSD, current->thread.old_k1);
723 }
724#endif
725 return (*fn)(arg);
726}
727
728
729
730
731void
732flush_thread (void)
733{
734
735 current->thread.flags &= ~(IA64_THREAD_FPH_VALID | IA64_THREAD_DBG_VALID);
736 ia64_drop_fpu(current);
737#ifdef CONFIG_IA32_SUPPORT
738 if (IS_IA32_PROCESS(task_pt_regs(current))) {
739 ia32_drop_ia64_partial_page_list(current);
740 current->thread.task_size = IA32_PAGE_OFFSET;
741 set_fs(USER_DS);
742 memset(current->thread.tls_array, 0, sizeof(current->thread.tls_array));
743 }
744#endif
745}
746
747
748
749
750
751void
752exit_thread (void)
753{
754
755 ia64_drop_fpu(current);
756#ifdef CONFIG_PERFMON
757
758 if (current->thread.pfm_context)
759 pfm_exit_thread(current);
760
761
762 if (current->thread.flags & IA64_THREAD_DBG_VALID)
763 pfm_release_debug_registers(current);
764#endif
765 if (IS_IA32_PROCESS(task_pt_regs(current)))
766 ia32_drop_ia64_partial_page_list(current);
767}
768
769unsigned long
770get_wchan (struct task_struct *p)
771{
772 struct unw_frame_info info;
773 unsigned long ip;
774 int count = 0;
775
776 if (!p || p == current || p->state == TASK_RUNNING)
777 return 0;
778
779
780
781
782
783
784
785
786
787 unw_init_from_blocked_task(&info, p);
788 do {
789 if (p->state == TASK_RUNNING)
790 return 0;
791 if (unw_unwind(&info) < 0)
792 return 0;
793 unw_get_ip(&info, &ip);
794 if (!in_sched_functions(ip))
795 return ip;
796 } while (count++ < 16);
797 return 0;
798}
799
800void
801cpu_halt (void)
802{
803 pal_power_mgmt_info_u_t power_info[8];
804 unsigned long min_power;
805 int i, min_power_state;
806
807 if (ia64_pal_halt_info(power_info) != 0)
808 return;
809
810 min_power_state = 0;
811 min_power = power_info[0].pal_power_mgmt_info_s.power_consumption;
812 for (i = 1; i < 8; ++i)
813 if (power_info[i].pal_power_mgmt_info_s.im
814 && power_info[i].pal_power_mgmt_info_s.power_consumption < min_power) {
815 min_power = power_info[i].pal_power_mgmt_info_s.power_consumption;
816 min_power_state = i;
817 }
818
819 while (1)
820 ia64_pal_halt(min_power_state);
821}
822
823void machine_shutdown(void)
824{
825#ifdef CONFIG_HOTPLUG_CPU
826 int cpu;
827
828 for_each_online_cpu(cpu) {
829 if (cpu != smp_processor_id())
830 cpu_down(cpu);
831 }
832#endif
833#ifdef CONFIG_KEXEC
834 kexec_disable_iosapic();
835#endif
836}
837
838void
839machine_restart (char *restart_cmd)
840{
841 (void) notify_die(DIE_MACHINE_RESTART, restart_cmd, NULL, 0, 0, 0);
842 (*efi.reset_system)(EFI_RESET_WARM, 0, 0, NULL);
843}
844
845void
846machine_halt (void)
847{
848 (void) notify_die(DIE_MACHINE_HALT, "", NULL, 0, 0, 0);
849 cpu_halt();
850}
851
852void
853machine_power_off (void)
854{
855 if (pm_power_off)
856 pm_power_off();
857 machine_halt();
858}
859
860