x86: unify load_segment macro
[sfrench/cifs-2.6.git] / include / asm-x86 / system_32.h
1 #ifndef __ASM_SYSTEM_H
2 #define __ASM_SYSTEM_H
3
4 #include <linux/kernel.h>
5 #include <asm/segment.h>
6 #include <asm/cpufeature.h>
7 #include <asm/cmpxchg.h>
8
9 #ifdef __KERNEL__
10 #define AT_VECTOR_SIZE_ARCH 2 /* entries in ARCH_DLINFO */
11
12 struct task_struct;     /* one of the stranger aspects of C forward declarations.. */
13 extern struct task_struct * FASTCALL(__switch_to(struct task_struct *prev, struct task_struct *next));
14
15 /*
16  * Saving eflags is important. It switches not only IOPL between tasks,
17  * it also protects other tasks from NT leaking through sysenter etc.
18  */
19 #define switch_to(prev,next,last) do {                                  \
20         unsigned long esi,edi;                                          \
21         asm volatile("pushfl\n\t"               /* Save flags */        \
22                      "pushl %%ebp\n\t"                                  \
23                      "movl %%esp,%0\n\t"        /* save ESP */          \
24                      "movl %5,%%esp\n\t"        /* restore ESP */       \
25                      "movl $1f,%1\n\t"          /* save EIP */          \
26                      "pushl %6\n\t"             /* restore EIP */       \
27                      "jmp __switch_to\n"                                \
28                      "1:\t"                                             \
29                      "popl %%ebp\n\t"                                   \
30                      "popfl"                                            \
31                      :"=m" (prev->thread.sp),"=m" (prev->thread.ip),    \
32                       "=a" (last),"=S" (esi),"=D" (edi)                 \
33                      :"m" (next->thread.sp),"m" (next->thread.ip),      \
34                       "2" (prev), "d" (next));                          \
35 } while (0)
36
37 static inline void native_clts(void)
38 {
39         asm volatile ("clts");
40 }
41
42 static inline unsigned long native_read_cr0(void)
43 {
44         unsigned long val;
45         asm volatile("movl %%cr0,%0\n\t" :"=r" (val));
46         return val;
47 }
48
49 static inline void native_write_cr0(unsigned long val)
50 {
51         asm volatile("movl %0,%%cr0": :"r" (val));
52 }
53
54 static inline unsigned long native_read_cr2(void)
55 {
56         unsigned long val;
57         asm volatile("movl %%cr2,%0\n\t" :"=r" (val));
58         return val;
59 }
60
61 static inline void native_write_cr2(unsigned long val)
62 {
63         asm volatile("movl %0,%%cr2": :"r" (val));
64 }
65
66 static inline unsigned long native_read_cr3(void)
67 {
68         unsigned long val;
69         asm volatile("movl %%cr3,%0\n\t" :"=r" (val));
70         return val;
71 }
72
73 static inline void native_write_cr3(unsigned long val)
74 {
75         asm volatile("movl %0,%%cr3": :"r" (val));
76 }
77
78 static inline unsigned long native_read_cr4(void)
79 {
80         unsigned long val;
81         asm volatile("movl %%cr4,%0\n\t" :"=r" (val));
82         return val;
83 }
84
85 static inline unsigned long native_read_cr4_safe(void)
86 {
87         unsigned long val;
88         /* This could fault if %cr4 does not exist */
89         asm volatile("1: movl %%cr4, %0         \n"
90                 "2:                             \n"
91                 ".section __ex_table,\"a\"      \n"
92                 ".long 1b,2b                    \n"
93                 ".previous                      \n"
94                 : "=r" (val): "0" (0));
95         return val;
96 }
97
98 static inline void native_write_cr4(unsigned long val)
99 {
100         asm volatile("movl %0,%%cr4": :"r" (val));
101 }
102
103 static inline void native_wbinvd(void)
104 {
105         asm volatile("wbinvd": : :"memory");
106 }
107
108 #ifdef CONFIG_PARAVIRT
109 #include <asm/paravirt.h>
110 #else
111 #define read_cr0()      (native_read_cr0())
112 #define write_cr0(x)    (native_write_cr0(x))
113 #define read_cr2()      (native_read_cr2())
114 #define write_cr2(x)    (native_write_cr2(x))
115 #define read_cr3()      (native_read_cr3())
116 #define write_cr3(x)    (native_write_cr3(x))
117 #define read_cr4()      (native_read_cr4())
118 #define read_cr4_safe() (native_read_cr4_safe())
119 #define write_cr4(x)    (native_write_cr4(x))
120 #define wbinvd()        (native_wbinvd())
121
122 /* Clear the 'TS' bit */
123 #define clts()          (native_clts())
124
125 #endif/* CONFIG_PARAVIRT */
126
127 /* Set the 'TS' bit */
128 #define stts() write_cr0(8 | read_cr0())
129
130 #endif  /* __KERNEL__ */
131
132
133 /*
134  * Force strict CPU ordering.
135  * And yes, this is required on UP too when we're talking
136  * to devices.
137  *
138  * For now, "wmb()" doesn't actually do anything, as all
139  * Intel CPU's follow what Intel calls a *Processor Order*,
140  * in which all writes are seen in the program order even
141  * outside the CPU.
142  *
143  * I expect future Intel CPU's to have a weaker ordering,
144  * but I'd also expect them to finally get their act together
145  * and add some real memory barriers if so.
146  *
147  * Some non intel clones support out of order store. wmb() ceases to be a
148  * nop for these.
149  */
150  
151
152 #define mb() alternative("lock; addl $0,0(%%esp)", "mfence", X86_FEATURE_XMM2)
153 #define rmb() alternative("lock; addl $0,0(%%esp)", "lfence", X86_FEATURE_XMM2)
154 #define wmb() alternative("lock; addl $0,0(%%esp)", "sfence", X86_FEATURE_XMM)
155
156 /**
157  * read_barrier_depends - Flush all pending reads that subsequents reads
158  * depend on.
159  *
160  * No data-dependent reads from memory-like regions are ever reordered
161  * over this barrier.  All reads preceding this primitive are guaranteed
162  * to access memory (but not necessarily other CPUs' caches) before any
163  * reads following this primitive that depend on the data return by
164  * any of the preceding reads.  This primitive is much lighter weight than
165  * rmb() on most CPUs, and is never heavier weight than is
166  * rmb().
167  *
168  * These ordering constraints are respected by both the local CPU
169  * and the compiler.
170  *
171  * Ordering is not guaranteed by anything other than these primitives,
172  * not even by data dependencies.  See the documentation for
173  * memory_barrier() for examples and URLs to more information.
174  *
175  * For example, the following code would force ordering (the initial
176  * value of "a" is zero, "b" is one, and "p" is "&a"):
177  *
178  * <programlisting>
179  *      CPU 0                           CPU 1
180  *
181  *      b = 2;
182  *      memory_barrier();
183  *      p = &b;                         q = p;
184  *                                      read_barrier_depends();
185  *                                      d = *q;
186  * </programlisting>
187  *
188  * because the read of "*q" depends on the read of "p" and these
189  * two reads are separated by a read_barrier_depends().  However,
190  * the following code, with the same initial values for "a" and "b":
191  *
192  * <programlisting>
193  *      CPU 0                           CPU 1
194  *
195  *      a = 2;
196  *      memory_barrier();
197  *      b = 3;                          y = b;
198  *                                      read_barrier_depends();
199  *                                      x = a;
200  * </programlisting>
201  *
202  * does not enforce ordering, since there is no data dependency between
203  * the read of "a" and the read of "b".  Therefore, on some CPUs, such
204  * as Alpha, "y" could be set to 3 and "x" to 0.  Use rmb()
205  * in cases like this where there are no data dependencies.
206  **/
207
208 #define read_barrier_depends()  do { } while(0)
209
210 #ifdef CONFIG_SMP
211 #define smp_mb()        mb()
212 #ifdef CONFIG_X86_PPRO_FENCE
213 # define smp_rmb()      rmb()
214 #else
215 # define smp_rmb()      barrier()
216 #endif
217 #ifdef CONFIG_X86_OOSTORE
218 # define smp_wmb()      wmb()
219 #else
220 # define smp_wmb()      barrier()
221 #endif
222 #define smp_read_barrier_depends()      read_barrier_depends()
223 #define set_mb(var, value) do { (void) xchg(&var, value); } while (0)
224 #else
225 #define smp_mb()        barrier()
226 #define smp_rmb()       barrier()
227 #define smp_wmb()       barrier()
228 #define smp_read_barrier_depends()      do { } while(0)
229 #define set_mb(var, value) do { var = value; barrier(); } while (0)
230 #endif
231
232 #include <linux/irqflags.h>
233
234 /*
235  * disable hlt during certain critical i/o operations
236  */
237 #define HAVE_DISABLE_HLT
238
239 #endif