53
51
#include <asm/syscalls.h>
54
52
#include <asm/debugreg.h>
56
DEFINE_TRACE(pm_idle_exit);
57
DEFINE_TRACE(pm_idle_entry);
59
54
asmlinkage extern void ret_from_fork(void);
61
56
DEFINE_PER_CPU(unsigned long, old_rsp);
62
57
static DEFINE_PER_CPU(unsigned char, is_idle);
59
static ATOMIC_NOTIFIER_HEAD(idle_notifier);
61
void idle_notifier_register(struct notifier_block *n)
63
atomic_notifier_chain_register(&idle_notifier, n);
65
EXPORT_SYMBOL_GPL(idle_notifier_register);
67
void idle_notifier_unregister(struct notifier_block *n)
69
atomic_notifier_chain_unregister(&idle_notifier, n);
71
EXPORT_SYMBOL_GPL(idle_notifier_unregister);
64
73
void enter_idle(void)
66
75
percpu_write(is_idle, 1);
68
* Trace last event before calling notifiers. Notifiers flush
69
* data from buffers before going to idle.
71
trace_pm_idle_entry();
72
notify_idle(IDLE_START);
76
atomic_notifier_call_chain(&idle_notifier, IDLE_START, NULL);
74
EXPORT_SYMBOL_GPL(enter_idle);
76
void __exit_idle(void)
79
static void __exit_idle(void)
78
81
if (x86_test_and_clear_bit_percpu(0, is_idle) == 0)
80
notify_idle(IDLE_END);
83
atomic_notifier_call_chain(&idle_notifier, IDLE_END, NULL);
83
EXPORT_SYMBOL_GPL(__exit_idle);
85
86
/* Called from interrupts to signify idle end */
86
87
void exit_idle(void)
501
500
/* Make sure to be in 64bit mode */
502
501
clear_thread_flag(TIF_IA32);
503
/* Ensure the corresponding mm is not marked. */
505
current->mm->context.ia32_compat = 0;
504
507
/* TBD: overwrites user setup. Should have two bits.
505
508
But 64bit processes have always behaved this way,
506
509
so it's not too bad. The main problem is just that
516
519
set_thread_flag(TIF_IA32);
517
520
current->personality |= force_personality32;
522
/* Mark the associated mm as containing 32-bit tasks. */
524
current->mm->context.ia32_compat = 1;
519
526
/* Prepare the first "return" to user space */
520
527
current_thread_info()->status |= TS_COMPAT;