2008-01-30 15:30:33 +03:00
# ifndef _X86_IRQFLAGS_H_
# define _X86_IRQFLAGS_H_
# include <asm/processor-flags.h>
# ifndef __ASSEMBLY__
/*
* Interrupt control :
*/
static inline unsigned long native_save_fl ( void )
{
unsigned long flags ;
2008-03-23 11:02:30 +03:00
asm volatile ( " # __raw_save_flags \n \t "
" pushf ; pop %0 "
: " =g " ( flags )
: /* no input */
: " memory " ) ;
2008-01-30 15:30:33 +03:00
return flags ;
}
static inline void native_restore_fl ( unsigned long flags )
{
2008-03-23 11:02:30 +03:00
asm volatile ( " push %0 ; popf "
: /* no output */
: " g " ( flags )
: " memory " , " cc " ) ;
2008-01-30 15:30:33 +03:00
}
static inline void native_irq_disable ( void )
{
asm volatile ( " cli " : : : " memory " ) ;
}
static inline void native_irq_enable ( void )
{
asm volatile ( " sti " : : : " memory " ) ;
}
static inline void native_safe_halt ( void )
{
asm volatile ( " sti; hlt " : : : " memory " ) ;
}
static inline void native_halt ( void )
{
asm volatile ( " hlt " : : : " memory " ) ;
}
# endif
# ifdef CONFIG_PARAVIRT
# include <asm/paravirt.h>
# else
# ifndef __ASSEMBLY__
static inline unsigned long __raw_local_save_flags ( void )
{
return native_save_fl ( ) ;
}
static inline void raw_local_irq_restore ( unsigned long flags )
{
native_restore_fl ( flags ) ;
}
static inline void raw_local_irq_disable ( void )
{
native_irq_disable ( ) ;
}
static inline void raw_local_irq_enable ( void )
{
native_irq_enable ( ) ;
}
/*
* Used in the idle loop ; sti takes one instruction cycle
* to complete :
*/
static inline void raw_safe_halt ( void )
{
native_safe_halt ( ) ;
}
/*
* Used when interrupts are already enabled or to
* shutdown the processor :
*/
static inline void halt ( void )
{
native_halt ( ) ;
}
/*
* For spinlocks , etc :
*/
static inline unsigned long __raw_local_irq_save ( void )
{
unsigned long flags = __raw_local_save_flags ( ) ;
raw_local_irq_disable ( ) ;
return flags ;
}
# else
# define ENABLE_INTERRUPTS(x) sti
# define DISABLE_INTERRUPTS(x) cli
# ifdef CONFIG_X86_64
2008-06-27 23:04:03 +04:00
# define SWAPGS swapgs
/*
* Currently paravirt can ' t handle swapgs nicely when we
* don ' t have a stack we can rely on ( such as a user space
* stack ) . So we either find a way around these or just fault
* and emulate if a guest tries to call swapgs directly .
*
* Either way , this is a good way to document that we don ' t
* have a reliable stack . x86_64 only .
*/
2008-06-25 08:19:30 +04:00
# define SWAPGS_UNSAFE_STACK swapgs
2008-06-27 23:04:03 +04:00
# define PARAVIRT_ADJUST_EXCEPTION_FRAME /* */
2008-01-30 15:30:33 +03:00
# define INTERRUPT_RETURN iretq
2008-06-25 08:19:28 +04:00
# define USERGS_SYSRET64 \
swapgs ; \
sysretq ;
# define USERGS_SYSRET32 \
swapgs ; \
sysretl
# define ENABLE_INTERRUPTS_SYSEXIT32 \
swapgs ; \
sti ; \
sysexit
2008-01-30 15:30:33 +03:00
# else
# define INTERRUPT_RETURN iret
2008-06-25 08:19:26 +04:00
# define ENABLE_INTERRUPTS_SYSEXIT sti; sysexit
2008-01-30 15:30:33 +03:00
# define GET_CR0_INTO_EAX movl %cr0, %eax
# endif
# endif /* __ASSEMBLY__ */
# endif /* CONFIG_PARAVIRT */
# ifndef __ASSEMBLY__
2008-03-23 11:02:30 +03:00
# define raw_local_save_flags(flags) \
do { ( flags ) = __raw_local_save_flags ( ) ; } while ( 0 )
2008-01-30 15:30:33 +03:00
2008-03-23 11:02:30 +03:00
# define raw_local_irq_save(flags) \
do { ( flags ) = __raw_local_irq_save ( ) ; } while ( 0 )
2008-01-30 15:30:33 +03:00
static inline int raw_irqs_disabled_flags ( unsigned long flags )
{
return ! ( flags & X86_EFLAGS_IF ) ;
}
static inline int raw_irqs_disabled ( void )
{
unsigned long flags = __raw_local_save_flags ( ) ;
return raw_irqs_disabled_flags ( flags ) ;
}
2007-10-11 13:20:03 +04:00
# else
2008-01-30 15:30:33 +03:00
# ifdef CONFIG_X86_64
# define ARCH_LOCKDEP_SYS_EXIT call lockdep_sys_exit_thunk
# define ARCH_LOCKDEP_SYS_EXIT_IRQ \
TRACE_IRQS_ON ; \
sti ; \
SAVE_REST ; \
LOCKDEP_SYS_EXIT ; \
RESTORE_REST ; \
cli ; \
TRACE_IRQS_OFF ;
# else
# define ARCH_LOCKDEP_SYS_EXIT \
pushl % eax ; \
pushl % ecx ; \
pushl % edx ; \
call lockdep_sys_exit ; \
popl % edx ; \
popl % ecx ; \
popl % eax ;
# define ARCH_LOCKDEP_SYS_EXIT_IRQ
# endif
# ifdef CONFIG_TRACE_IRQFLAGS
2008-05-12 23:20:42 +04:00
# define TRACE_IRQS_ON call trace_hardirqs_on_thunk;
# define TRACE_IRQS_OFF call trace_hardirqs_off_thunk;
2008-01-30 15:30:33 +03:00
# else
# define TRACE_IRQS_ON
# define TRACE_IRQS_OFF
# endif
# ifdef CONFIG_DEBUG_LOCK_ALLOC
# define LOCKDEP_SYS_EXIT ARCH_LOCKDEP_SYS_EXIT
# define LOCKDEP_SYS_EXIT_IRQ ARCH_LOCKDEP_SYS_EXIT_IRQ
# else
# define LOCKDEP_SYS_EXIT
# define LOCKDEP_SYS_EXIT_IRQ
# endif
# endif /* __ASSEMBLY__ */
2007-10-11 13:20:03 +04:00
# endif