aboutsummaryrefslogtreecommitdiffstats
path: root/include/asm-i386
diff options
context:
space:
mode:
Diffstat (limited to 'include/asm-i386')
-rw-r--r--include/asm-i386/Kbuild5
-rw-r--r--include/asm-i386/irqflags.h127
-rw-r--r--include/asm-i386/rwsem.h42
-rw-r--r--include/asm-i386/spinlock.h12
-rw-r--r--include/asm-i386/system.h20
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 @@
1include include/asm-generic/Kbuild.asm
2
3header-y += boot.h cpufeature.h debugreg.h ldt.h setup.h ucontext.h
4
5unifdef-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
15static 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
31static 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
41static inline void raw_local_irq_disable(void)
42{
43 __asm__ __volatile__("cli" : : : "memory");
44}
45
46static 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 */
55static 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 */
64static inline void halt(void)
65{
66 __asm__ __volatile__("hlt": : :"memory");
67}
68
69static inline int raw_irqs_disabled_flags(unsigned long flags)
70{
71 return !(flags & (1 << 9));
72}
73
74static 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 */
84static 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
44struct rwsem_waiter; 45struct 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
85static inline void init_rwsem(struct rw_semaphore *sem) 84extern 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); 88do { \
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 */
146static inline void __down_write(struct rw_semaphore *sem) 145static 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
169static 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
66static inline void __raw_spin_lock_flags(raw_spinlock_t *lock, unsigned long flags) 77static 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
74static inline int __raw_spin_trylock(raw_spinlock_t *lock) 86static 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