diff options
Diffstat (limited to 'include/asm-i386')
-rw-r--r-- | include/asm-i386/Kbuild | 5 | ||||
-rw-r--r-- | include/asm-i386/irqflags.h | 127 | ||||
-rw-r--r-- | include/asm-i386/rwsem.h | 42 | ||||
-rw-r--r-- | include/asm-i386/spinlock.h | 12 | ||||
-rw-r--r-- | include/asm-i386/system.h | 20 |
5 files changed, 168 insertions, 38 deletions
diff --git a/include/asm-i386/Kbuild b/include/asm-i386/Kbuild new file mode 100644 index 000000000000..c064a8e9170f --- /dev/null +++ b/include/asm-i386/Kbuild | |||
@@ -0,0 +1,5 @@ | |||
1 | include include/asm-generic/Kbuild.asm | ||
2 | |||
3 | header-y += boot.h cpufeature.h debugreg.h ldt.h setup.h ucontext.h | ||
4 | |||
5 | unifdef-y += mtrr.h vm86.h | ||
diff --git a/include/asm-i386/irqflags.h b/include/asm-i386/irqflags.h new file mode 100644 index 000000000000..e1bdb97c07fa --- /dev/null +++ b/include/asm-i386/irqflags.h | |||
@@ -0,0 +1,127 @@ | |||
1 | /* | ||
2 | * include/asm-i386/irqflags.h | ||
3 | * | ||
4 | * IRQ flags handling | ||
5 | * | ||
6 | * This file gets included from lowlevel asm headers too, to provide | ||
7 | * wrapped versions of the local_irq_*() APIs, based on the | ||
8 | * raw_local_irq_*() functions from the lowlevel headers. | ||
9 | */ | ||
10 | #ifndef _ASM_IRQFLAGS_H | ||
11 | #define _ASM_IRQFLAGS_H | ||
12 | |||
13 | #ifndef __ASSEMBLY__ | ||
14 | |||
15 | static inline unsigned long __raw_local_save_flags(void) | ||
16 | { | ||
17 | unsigned long flags; | ||
18 | |||
19 | __asm__ __volatile__( | ||
20 | "pushfl ; popl %0" | ||
21 | : "=g" (flags) | ||
22 | : /* no input */ | ||
23 | ); | ||
24 | |||
25 | return flags; | ||
26 | } | ||
27 | |||
28 | #define raw_local_save_flags(flags) \ | ||
29 | do { (flags) = __raw_local_save_flags(); } while (0) | ||
30 | |||
31 | static inline void raw_local_irq_restore(unsigned long flags) | ||
32 | { | ||
33 | __asm__ __volatile__( | ||
34 | "pushl %0 ; popfl" | ||
35 | : /* no output */ | ||
36 | :"g" (flags) | ||
37 | :"memory", "cc" | ||
38 | ); | ||
39 | } | ||
40 | |||
41 | static inline void raw_local_irq_disable(void) | ||
42 | { | ||
43 | __asm__ __volatile__("cli" : : : "memory"); | ||
44 | } | ||
45 | |||
46 | static inline void raw_local_irq_enable(void) | ||
47 | { | ||
48 | __asm__ __volatile__("sti" : : : "memory"); | ||
49 | } | ||
50 | |||
51 | /* | ||
52 | * Used in the idle loop; sti takes one instruction cycle | ||
53 | * to complete: | ||
54 | */ | ||
55 | static inline void raw_safe_halt(void) | ||
56 | { | ||
57 | __asm__ __volatile__("sti; hlt" : : : "memory"); | ||
58 | } | ||
59 | |||
60 | /* | ||
61 | * Used when interrupts are already enabled or to | ||
62 | * shutdown the processor: | ||
63 | */ | ||
64 | static inline void halt(void) | ||
65 | { | ||
66 | __asm__ __volatile__("hlt": : :"memory"); | ||
67 | } | ||
68 | |||
69 | static inline int raw_irqs_disabled_flags(unsigned long flags) | ||
70 | { | ||
71 | return !(flags & (1 << 9)); | ||
72 | } | ||
73 | |||
74 | static inline int raw_irqs_disabled(void) | ||
75 | { | ||
76 | unsigned long flags = __raw_local_save_flags(); | ||
77 | |||
78 | return raw_irqs_disabled_flags(flags); | ||
79 | } | ||
80 | |||
81 | /* | ||
82 | * For spinlocks, etc: | ||
83 | */ | ||
84 | static inline unsigned long __raw_local_irq_save(void) | ||
85 | { | ||
86 | unsigned long flags = __raw_local_save_flags(); | ||
87 | |||
88 | raw_local_irq_disable(); | ||
89 | |||
90 | return flags; | ||
91 | } | ||
92 | |||
93 | #define raw_local_irq_save(flags) \ | ||
94 | do { (flags) = __raw_local_irq_save(); } while (0) | ||
95 | |||
96 | #endif /* __ASSEMBLY__ */ | ||
97 | |||
98 | /* | ||
99 | * Do the CPU's IRQ-state tracing from assembly code. We call a | ||
100 | * C function, so save all the C-clobbered registers: | ||
101 | */ | ||
102 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
103 | |||
104 | # define TRACE_IRQS_ON \ | ||
105 | pushl %eax; \ | ||
106 | pushl %ecx; \ | ||
107 | pushl %edx; \ | ||
108 | call trace_hardirqs_on; \ | ||
109 | popl %edx; \ | ||
110 | popl %ecx; \ | ||
111 | popl %eax; | ||
112 | |||
113 | # define TRACE_IRQS_OFF \ | ||
114 | pushl %eax; \ | ||
115 | pushl %ecx; \ | ||
116 | pushl %edx; \ | ||
117 | call trace_hardirqs_off; \ | ||
118 | popl %edx; \ | ||
119 | popl %ecx; \ | ||
120 | popl %eax; | ||
121 | |||
122 | #else | ||
123 | # define TRACE_IRQS_ON | ||
124 | # define TRACE_IRQS_OFF | ||
125 | #endif | ||
126 | |||
127 | #endif | ||
diff --git a/include/asm-i386/rwsem.h b/include/asm-i386/rwsem.h index be4ab859238e..2f07601562e7 100644 --- a/include/asm-i386/rwsem.h +++ b/include/asm-i386/rwsem.h | |||
@@ -40,6 +40,7 @@ | |||
40 | 40 | ||
41 | #include <linux/list.h> | 41 | #include <linux/list.h> |
42 | #include <linux/spinlock.h> | 42 | #include <linux/spinlock.h> |
43 | #include <linux/lockdep.h> | ||
43 | 44 | ||
44 | struct rwsem_waiter; | 45 | struct rwsem_waiter; |
45 | 46 | ||
@@ -61,36 +62,34 @@ struct rw_semaphore { | |||
61 | #define RWSEM_ACTIVE_WRITE_BIAS (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS) | 62 | #define RWSEM_ACTIVE_WRITE_BIAS (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS) |
62 | spinlock_t wait_lock; | 63 | spinlock_t wait_lock; |
63 | struct list_head wait_list; | 64 | struct list_head wait_list; |
64 | #if RWSEM_DEBUG | 65 | #ifdef CONFIG_DEBUG_LOCK_ALLOC |
65 | int debug; | 66 | struct lockdep_map dep_map; |
66 | #endif | 67 | #endif |
67 | }; | 68 | }; |
68 | 69 | ||
69 | /* | 70 | #ifdef CONFIG_DEBUG_LOCK_ALLOC |
70 | * initialisation | 71 | # define __RWSEM_DEP_MAP_INIT(lockname) , .dep_map = { .name = #lockname } |
71 | */ | ||
72 | #if RWSEM_DEBUG | ||
73 | #define __RWSEM_DEBUG_INIT , 0 | ||
74 | #else | 72 | #else |
75 | #define __RWSEM_DEBUG_INIT /* */ | 73 | # define __RWSEM_DEP_MAP_INIT(lockname) |
76 | #endif | 74 | #endif |
77 | 75 | ||
76 | |||
78 | #define __RWSEM_INITIALIZER(name) \ | 77 | #define __RWSEM_INITIALIZER(name) \ |
79 | { RWSEM_UNLOCKED_VALUE, SPIN_LOCK_UNLOCKED, LIST_HEAD_INIT((name).wait_list) \ | 78 | { RWSEM_UNLOCKED_VALUE, SPIN_LOCK_UNLOCKED, LIST_HEAD_INIT((name).wait_list) \ |
80 | __RWSEM_DEBUG_INIT } | 79 | __RWSEM_DEP_MAP_INIT(name) } |
81 | 80 | ||
82 | #define DECLARE_RWSEM(name) \ | 81 | #define DECLARE_RWSEM(name) \ |
83 | struct rw_semaphore name = __RWSEM_INITIALIZER(name) | 82 | struct rw_semaphore name = __RWSEM_INITIALIZER(name) |
84 | 83 | ||
85 | static inline void init_rwsem(struct rw_semaphore *sem) | 84 | extern void __init_rwsem(struct rw_semaphore *sem, const char *name, |
86 | { | 85 | struct lock_class_key *key); |
87 | sem->count = RWSEM_UNLOCKED_VALUE; | 86 | |
88 | spin_lock_init(&sem->wait_lock); | 87 | #define init_rwsem(sem) \ |
89 | INIT_LIST_HEAD(&sem->wait_list); | 88 | do { \ |
90 | #if RWSEM_DEBUG | 89 | static struct lock_class_key __key; \ |
91 | sem->debug = 0; | 90 | \ |
92 | #endif | 91 | __init_rwsem((sem), #sem, &__key); \ |
93 | } | 92 | } while (0) |
94 | 93 | ||
95 | /* | 94 | /* |
96 | * lock for reading | 95 | * lock for reading |
@@ -143,7 +142,7 @@ LOCK_PREFIX " cmpxchgl %2,%0\n\t" | |||
143 | /* | 142 | /* |
144 | * lock for writing | 143 | * lock for writing |
145 | */ | 144 | */ |
146 | static inline void __down_write(struct rw_semaphore *sem) | 145 | static inline void __down_write_nested(struct rw_semaphore *sem, int subclass) |
147 | { | 146 | { |
148 | int tmp; | 147 | int tmp; |
149 | 148 | ||
@@ -167,6 +166,11 @@ LOCK_PREFIX " xadd %%edx,(%%eax)\n\t" /* subtract 0x0000ffff, returns the | |||
167 | : "memory", "cc"); | 166 | : "memory", "cc"); |
168 | } | 167 | } |
169 | 168 | ||
169 | static inline void __down_write(struct rw_semaphore *sem) | ||
170 | { | ||
171 | __down_write_nested(sem, 0); | ||
172 | } | ||
173 | |||
170 | /* | 174 | /* |
171 | * trylock for writing -- returns 1 if successful, 0 if contention | 175 | * trylock for writing -- returns 1 if successful, 0 if contention |
172 | */ | 176 | */ |
diff --git a/include/asm-i386/spinlock.h b/include/asm-i386/spinlock.h index 04ba30234c48..87c40f830653 100644 --- a/include/asm-i386/spinlock.h +++ b/include/asm-i386/spinlock.h | |||
@@ -31,6 +31,11 @@ | |||
31 | "jmp 1b\n" \ | 31 | "jmp 1b\n" \ |
32 | "3:\n\t" | 32 | "3:\n\t" |
33 | 33 | ||
34 | /* | ||
35 | * NOTE: there's an irqs-on section here, which normally would have to be | ||
36 | * irq-traced, but on CONFIG_TRACE_IRQFLAGS we never use | ||
37 | * __raw_spin_lock_string_flags(). | ||
38 | */ | ||
34 | #define __raw_spin_lock_string_flags \ | 39 | #define __raw_spin_lock_string_flags \ |
35 | "\n1:\t" \ | 40 | "\n1:\t" \ |
36 | "lock ; decb %0\n\t" \ | 41 | "lock ; decb %0\n\t" \ |
@@ -63,6 +68,12 @@ static inline void __raw_spin_lock(raw_spinlock_t *lock) | |||
63 | "=m" (lock->slock) : : "memory"); | 68 | "=m" (lock->slock) : : "memory"); |
64 | } | 69 | } |
65 | 70 | ||
71 | /* | ||
72 | * It is easier for the lock validator if interrupts are not re-enabled | ||
73 | * in the middle of a lock-acquire. This is a performance feature anyway | ||
74 | * so we turn it off: | ||
75 | */ | ||
76 | #ifndef CONFIG_PROVE_LOCKING | ||
66 | static inline void __raw_spin_lock_flags(raw_spinlock_t *lock, unsigned long flags) | 77 | static inline void __raw_spin_lock_flags(raw_spinlock_t *lock, unsigned long flags) |
67 | { | 78 | { |
68 | alternative_smp( | 79 | alternative_smp( |
@@ -70,6 +81,7 @@ static inline void __raw_spin_lock_flags(raw_spinlock_t *lock, unsigned long fla | |||
70 | __raw_spin_lock_string_up, | 81 | __raw_spin_lock_string_up, |
71 | "=m" (lock->slock) : "r" (flags) : "memory"); | 82 | "=m" (lock->slock) : "r" (flags) : "memory"); |
72 | } | 83 | } |
84 | #endif | ||
73 | 85 | ||
74 | static inline int __raw_spin_trylock(raw_spinlock_t *lock) | 86 | static inline int __raw_spin_trylock(raw_spinlock_t *lock) |
75 | { | 87 | { |
diff --git a/include/asm-i386/system.h b/include/asm-i386/system.h index cab0180567f9..db398d88b1d9 100644 --- a/include/asm-i386/system.h +++ b/include/asm-i386/system.h | |||
@@ -456,25 +456,7 @@ static inline unsigned long long __cmpxchg64(volatile void *ptr, unsigned long l | |||
456 | 456 | ||
457 | #define set_wmb(var, value) do { var = value; wmb(); } while (0) | 457 | #define set_wmb(var, value) do { var = value; wmb(); } while (0) |
458 | 458 | ||
459 | /* interrupt control.. */ | 459 | #include <linux/irqflags.h> |
460 | #define local_save_flags(x) do { typecheck(unsigned long,x); __asm__ __volatile__("pushfl ; popl %0":"=g" (x): /* no input */); } while (0) | ||
461 | #define local_irq_restore(x) do { typecheck(unsigned long,x); __asm__ __volatile__("pushl %0 ; popfl": /* no output */ :"g" (x):"memory", "cc"); } while (0) | ||
462 | #define local_irq_disable() __asm__ __volatile__("cli": : :"memory") | ||
463 | #define local_irq_enable() __asm__ __volatile__("sti": : :"memory") | ||
464 | /* used in the idle loop; sti takes one instruction cycle to complete */ | ||
465 | #define safe_halt() __asm__ __volatile__("sti; hlt": : :"memory") | ||
466 | /* used when interrupts are already enabled or to shutdown the processor */ | ||
467 | #define halt() __asm__ __volatile__("hlt": : :"memory") | ||
468 | |||
469 | #define irqs_disabled() \ | ||
470 | ({ \ | ||
471 | unsigned long flags; \ | ||
472 | local_save_flags(flags); \ | ||
473 | !(flags & (1<<9)); \ | ||
474 | }) | ||
475 | |||
476 | /* For spinlocks etc */ | ||
477 | #define local_irq_save(x) __asm__ __volatile__("pushfl ; popl %0 ; cli":"=g" (x): /* no input */ :"memory") | ||
478 | 460 | ||
479 | /* | 461 | /* |
480 | * disable hlt during certain critical i/o operations | 462 | * disable hlt during certain critical i/o operations |