irqflags.h 3.1 KB
Newer Older
1 2 3 4 5 6 7
/*
 * include/asm-i386/irqflags.h
 *
 * IRQ flags handling
 *
 * This file gets included from lowlevel asm headers too, to provide
 * wrapped versions of the local_irq_*() APIs, based on the
8
 * raw_local_irq_*() functions from the lowlevel headers.
9 10 11
 */
#ifndef _ASM_IRQFLAGS_H
#define _ASM_IRQFLAGS_H
12
#include <asm/processor-flags.h>
13

14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
#ifndef __ASSEMBLY__
static inline unsigned long native_save_fl(void)
{
	unsigned long f;
	asm volatile("pushfl ; popl %0":"=g" (f): /* no input */);
	return f;
}

static inline void native_restore_fl(unsigned long f)
{
	asm volatile("pushl %0 ; popfl": /* no output */
			     :"g" (f)
			     :"memory", "cc");
}

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	/* __ASSEMBLY__ */

50 51 52
#ifdef CONFIG_PARAVIRT
#include <asm/paravirt.h>
#else
53
#ifndef __ASSEMBLY__
54

55 56
static inline unsigned long __raw_local_save_flags(void)
{
57
	return native_save_fl();
58 59 60 61
}

static inline void raw_local_irq_restore(unsigned long flags)
{
62
	native_restore_fl(flags);
63 64 65 66
}

static inline void raw_local_irq_disable(void)
{
67
	native_irq_disable();
68 69 70 71
}

static inline void raw_local_irq_enable(void)
{
72
	native_irq_enable();
73 74 75 76 77 78 79 80
}

/*
 * Used in the idle loop; sti takes one instruction cycle
 * to complete:
 */
static inline void raw_safe_halt(void)
{
81
	native_safe_halt();
82 83 84 85 86 87 88 89
}

/*
 * Used when interrupts are already enabled or to
 * shutdown the processor:
 */
static inline void halt(void)
{
90
	native_halt();
91 92 93 94 95 96 97 98 99 100 101 102 103 104
}

/*
 * 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;
}

105
#else
106 107
#define DISABLE_INTERRUPTS(clobbers)	cli
#define ENABLE_INTERRUPTS(clobbers)	sti
108 109 110 111 112 113 114 115 116 117
#define ENABLE_INTERRUPTS_SYSEXIT	sti; sysexit
#define INTERRUPT_RETURN		iret
#define GET_CR0_INTO_EAX		movl %cr0, %eax
#endif /* __ASSEMBLY__ */
#endif /* CONFIG_PARAVIRT */

#ifndef __ASSEMBLY__
#define raw_local_save_flags(flags) \
		do { (flags) = __raw_local_save_flags(); } while (0)

118 119 120
#define raw_local_irq_save(flags) \
		do { (flags) = __raw_local_irq_save(); } while (0)

121 122
static inline int raw_irqs_disabled_flags(unsigned long flags)
{
123
	return !(flags & X86_EFLAGS_IF);
124 125 126 127 128 129 130 131
}

static inline int raw_irqs_disabled(void)
{
	unsigned long flags = __raw_local_save_flags();

	return raw_irqs_disabled_flags(flags);
}
132
#endif /* __ASSEMBLY__ */
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163

/*
 * Do the CPU's IRQ-state tracing from assembly code. We call a
 * C function, so save all the C-clobbered registers:
 */
#ifdef CONFIG_TRACE_IRQFLAGS

# define TRACE_IRQS_ON				\
	pushl %eax;				\
	pushl %ecx;				\
	pushl %edx;				\
	call trace_hardirqs_on;			\
	popl %edx;				\
	popl %ecx;				\
	popl %eax;

# define TRACE_IRQS_OFF				\
	pushl %eax;				\
	pushl %ecx;				\
	pushl %edx;				\
	call trace_hardirqs_off;		\
	popl %edx;				\
	popl %ecx;				\
	popl %eax;

#else
# define TRACE_IRQS_ON
# define TRACE_IRQS_OFF
#endif

#endif