~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/include/asm-i386/system.h

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 #ifndef __ASM_SYSTEM_H
  2 #define __ASM_SYSTEM_H
  3 
  4 #include <linux/config.h>
  5 #include <linux/kernel.h>
  6 #include <asm/segment.h>
  7 #include <linux/bitops.h> /* for LOCK_PREFIX */
  8 
  9 #ifdef __KERNEL__
 10 
 11 struct task_struct;     /* one of the stranger aspects of C forward declarations.. */
 12 extern void FASTCALL(__switch_to(struct task_struct *prev, struct task_struct *next));
 13 
 14 #define prepare_to_switch()     do { } while(0)
 15 #define switch_to(prev,next,last) do {                                  \
 16         asm volatile("pushl %%esi\n\t"                                  \
 17                      "pushl %%edi\n\t"                                  \
 18                      "pushl %%ebp\n\t"                                  \
 19                      "movl %%esp,%0\n\t"        /* save ESP */          \
 20                      "movl %3,%%esp\n\t"        /* restore ESP */       \
 21                      "movl $1f,%1\n\t"          /* save EIP */          \
 22                      "pushl %4\n\t"             /* restore EIP */       \
 23                      "jmp __switch_to\n"                                \
 24                      "1:\t"                                             \
 25                      "popl %%ebp\n\t"                                   \
 26                      "popl %%edi\n\t"                                   \
 27                      "popl %%esi\n\t"                                   \
 28                      :"=m" (prev->thread.esp),"=m" (prev->thread.eip),  \
 29                       "=b" (last)                                       \
 30                      :"m" (next->thread.esp),"m" (next->thread.eip),    \
 31                       "a" (prev), "d" (next),                           \
 32                       "b" (prev));                                      \
 33 } while (0)
 34 
 35 #define _set_base(addr,base) do { unsigned long __pr; \
 36 __asm__ __volatile__ ("movw %%dx,%1\n\t" \
 37         "rorl $16,%%edx\n\t" \
 38         "movb %%dl,%2\n\t" \
 39         "movb %%dh,%3" \
 40         :"=&d" (__pr) \
 41         :"m" (*((addr)+2)), \
 42          "m" (*((addr)+4)), \
 43          "m" (*((addr)+7)), \
 44          "" (base) \
 45         ); } while(0)
 46 
 47 #define _set_limit(addr,limit) do { unsigned long __lr; \
 48 __asm__ __volatile__ ("movw %%dx,%1\n\t" \
 49         "rorl $16,%%edx\n\t" \
 50         "movb %2,%%dh\n\t" \
 51         "andb $0xf0,%%dh\n\t" \
 52         "orb %%dh,%%dl\n\t" \
 53         "movb %%dl,%2" \
 54         :"=&d" (__lr) \
 55         :"m" (*(addr)), \
 56          "m" (*((addr)+6)), \
 57          "" (limit) \
 58         ); } while(0)
 59 
 60 #define set_base(ldt,base) _set_base( ((char *)&(ldt)) , (base) )
 61 #define set_limit(ldt,limit) _set_limit( ((char *)&(ldt)) , ((limit)-1)>>12 )
 62 
 63 static inline unsigned long _get_base(char * addr)
 64 {
 65         unsigned long __base;
 66         __asm__("movb %3,%%dh\n\t"
 67                 "movb %2,%%dl\n\t"
 68                 "shll $16,%%edx\n\t"
 69                 "movw %1,%%dx"
 70                 :"=&d" (__base)
 71                 :"m" (*((addr)+2)),
 72                  "m" (*((addr)+4)),
 73                  "m" (*((addr)+7)));
 74         return __base;
 75 }
 76 
 77 #define get_base(ldt) _get_base( ((char *)&(ldt)) )
 78 
 79 /*
 80  * Load a segment. Fall back on loading the zero
 81  * segment if something goes wrong..
 82  */
 83 #define loadsegment(seg,value)                  \
 84         asm volatile("\n"                       \
 85                 "1:\t"                          \
 86                 "movl %0,%%" #seg "\n"          \
 87                 "2:\n"                          \
 88                 ".section .fixup,\"ax\"\n"      \
 89                 "3:\t"                          \
 90                 "pushl $0\n\t"                  \
 91                 "popl %%" #seg "\n\t"           \
 92                 "jmp 2b\n"                      \
 93                 ".previous\n"                   \
 94                 ".section __ex_table,\"a\"\n\t" \
 95                 ".align 4\n\t"                  \
 96                 ".long 1b,3b\n"                 \
 97                 ".previous"                     \
 98                 : :"m" (*(unsigned int *)&(value)))
 99 
100 /*
101  * Clear and set 'TS' bit respectively
102  */
103 #define clts() __asm__ __volatile__ ("clts")
104 #define read_cr0() ({ \
105         unsigned int __dummy; \
106         __asm__( \
107                 "movl %%cr0,%0\n\t" \
108                 :"=r" (__dummy)); \
109         __dummy; \
110 })
111 #define write_cr0(x) \
112         __asm__("movl %0,%%cr0": :"r" (x));
113 #define stts() write_cr0(8 | read_cr0())
114 
115 #endif  /* __KERNEL__ */
116 
117 static inline unsigned long get_limit(unsigned long segment)
118 {
119         unsigned long __limit;
120         __asm__("lsll %1,%0"
121                 :"=r" (__limit):"r" (segment));
122         return __limit+1;
123 }
124 
125 #define nop() __asm__ __volatile__ ("nop")
126 
127 #define xchg(ptr,v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v),(ptr),sizeof(*(ptr))))
128 
129 #define tas(ptr) (xchg((ptr),1))
130 
131 struct __xchg_dummy { unsigned long a[100]; };
132 #define __xg(x) ((struct __xchg_dummy *)(x))
133 
134 
135 /*
136  * The semantics of XCHGCMP8B are a bit strange, this is why
137  * there is a loop and the loading of %%eax and %%edx has to
138  * be inside. This inlines well in most cases, the cached
139  * cost is around ~38 cycles. (in the future we might want
140  * to do an SIMD/3DNOW!/MMX/FPU 64-bit store here, but that
141  * might have an implicit FPU-save as a cost, so it's not
142  * clear which path to go.)
143  */
144 extern inline void __set_64bit (unsigned long long * ptr,
145                 unsigned int low, unsigned int high)
146 {
147 __asm__ __volatile__ (
148         "1:     movl (%0), %%eax;
149                 movl 4(%0), %%edx;
150                 cmpxchg8b (%0);
151                 jnz 1b"
152         ::              "D"(ptr),
153                         "b"(low),
154                         "c"(high)
155         :
156                         "ax","dx","memory");
157 }
158 
159 extern void inline __set_64bit_constant (unsigned long long *ptr,
160                                                  unsigned long long value)
161 {
162         __set_64bit(ptr,(unsigned int)(value), (unsigned int)((value)>>32ULL));
163 }
164 #define ll_low(x)       *(((unsigned int*)&(x))+0)
165 #define ll_high(x)      *(((unsigned int*)&(x))+1)
166 
167 extern void inline __set_64bit_var (unsigned long long *ptr,
168                          unsigned long long value)
169 {
170         __set_64bit(ptr,ll_low(value), ll_high(value));
171 }
172 
173 #define set_64bit(ptr,value) \
174 (__builtin_constant_p(value) ? \
175  __set_64bit_constant(ptr, value) : \
176  __set_64bit_var(ptr, value) )
177 
178 #define _set_64bit(ptr,value) \
179 (__builtin_constant_p(value) ? \
180  __set_64bit(ptr, (unsigned int)(value), (unsigned int)((value)>>32ULL) ) : \
181  __set_64bit(ptr, ll_low(value), ll_high(value)) )
182 
183 /*
184  * Note: no "lock" prefix even on SMP: xchg always implies lock anyway
185  * Note 2: xchg has side effect, so that attribute volatile is necessary,
186  *        but generally the primitive is invalid, *ptr is output argument. --ANK
187  */
188 static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
189 {
190         switch (size) {
191                 case 1:
192                         __asm__ __volatile__("xchgb %b0,%1"
193                                 :"=q" (x)
194                                 :"m" (*__xg(ptr)), "" (x)
195                                 :"memory");
196                         break;
197                 case 2:
198                         __asm__ __volatile__("xchgw %w0,%1"
199                                 :"=r" (x)
200                                 :"m" (*__xg(ptr)), "" (x)
201                                 :"memory");
202                         break;
203                 case 4:
204                         __asm__ __volatile__("xchgl %0,%1"
205                                 :"=r" (x)
206                                 :"m" (*__xg(ptr)), "" (x)
207                                 :"memory");
208                         break;
209         }
210         return x;
211 }
212 
213 /*
214  * Atomic compare and exchange.  Compare OLD with MEM, if identical,
215  * store NEW in MEM.  Return the initial value in MEM.  Success is
216  * indicated by comparing RETURN with OLD.
217  */
218 
219 #ifdef CONFIG_X86_CMPXCHG
220 #define __HAVE_ARCH_CMPXCHG 1
221 
222 static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
223                                       unsigned long new, int size)
224 {
225         unsigned long prev;
226         switch (size) {
227         case 1:
228                 __asm__ __volatile__(LOCK_PREFIX "cmpxchgb %b1,%2"
229                                      : "=a"(prev)
230                                      : "q"(new), "m"(*__xg(ptr)), ""(old)
231                                      : "memory");
232                 return prev;
233         case 2:
234                 __asm__ __volatile__(LOCK_PREFIX "cmpxchgw %w1,%2"
235                                      : "=a"(prev)
236                                      : "q"(new), "m"(*__xg(ptr)), ""(old)
237                                      : "memory");
238                 return prev;
239         case 4:
240                 __asm__ __volatile__(LOCK_PREFIX "cmpxchgl %1,%2"
241                                      : "=a"(prev)
242                                      : "q"(new), "m"(*__xg(ptr)), ""(old)
243                                      : "memory");
244                 return prev;
245         }
246         return old;
247 }
248 
249 #define cmpxchg(ptr,o,n)\
250         ((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\
251                                         (unsigned long)(n),sizeof(*(ptr))))
252     
253 #else
254 /* Compiling for a 386 proper.  Is it worth implementing via cli/sti?  */
255 #endif
256 
257 /*
258  * Force strict CPU ordering.
259  * And yes, this is required on UP too when we're talking
260  * to devices.
261  *
262  * For now, "wmb()" doesn't actually do anything, as all
263  * Intel CPU's follow what Intel calls a *Processor Order*,
264  * in which all writes are seen in the program order even
265  * outside the CPU.
266  *
267  * I expect future Intel CPU's to have a weaker ordering,
268  * but I'd also expect them to finally get their act together
269  * and add some real memory barriers if so.
270  *
271  * The Pentium III does add a real memory barrier with the
272  * sfence instruction, so we use that where appropriate.
273  */
274 #ifndef CONFIG_X86_XMM
275 #define mb()    __asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory")
276 #else
277 #define mb()    __asm__ __volatile__ ("sfence": : :"memory")
278 #endif
279 #define rmb()   mb()
280 #define wmb()   __asm__ __volatile__ ("": : :"memory")
281 
282 #ifdef CONFIG_SMP
283 #define smp_mb()        mb()
284 #define smp_rmb()       rmb()
285 #define smp_wmb()       wmb()
286 #else
287 #define smp_mb()        barrier()
288 #define smp_rmb()       barrier()
289 #define smp_wmb()       barrier()
290 #endif
291 
292 #define set_mb(var, value) do { xchg(&var, value); } while (0)
293 #define set_wmb(var, value) do { var = value; wmb(); } while (0)
294 
295 /* interrupt control.. */
296 #define __save_flags(x)         __asm__ __volatile__("pushfl ; popl %0":"=g" (x): /* no input */)
297 #define __restore_flags(x)      __asm__ __volatile__("pushl %0 ; popfl": /* no output */ :"g" (x):"memory")
298 #define __cli()                 __asm__ __volatile__("cli": : :"memory")
299 #define __sti()                 __asm__ __volatile__("sti": : :"memory")
300 /* used in the idle loop; sti takes one instruction cycle to complete */
301 #define safe_halt()             __asm__ __volatile__("sti; hlt": : :"memory")
302 
303 /* For spinlocks etc */
304 #define local_irq_save(x)       __asm__ __volatile__("pushfl ; popl %0 ; cli":"=g" (x): /* no input */ :"memory")
305 #define local_irq_restore(x)    __restore_flags(x)
306 #define local_irq_disable()     __cli()
307 #define local_irq_enable()      __sti()
308 
309 #ifdef CONFIG_SMP
310 
311 extern void __global_cli(void);
312 extern void __global_sti(void);
313 extern unsigned long __global_save_flags(void);
314 extern void __global_restore_flags(unsigned long);
315 #define cli() __global_cli()
316 #define sti() __global_sti()
317 #define save_flags(x) ((x)=__global_save_flags())
318 #define restore_flags(x) __global_restore_flags(x)
319 
320 #else
321 
322 #define cli() __cli()
323 #define sti() __sti()
324 #define save_flags(x) __save_flags(x)
325 #define restore_flags(x) __restore_flags(x)
326 
327 #endif
328 
329 /*
330  * disable hlt during certain critical i/o operations
331  */
332 #define HAVE_DISABLE_HLT
333 void disable_hlt(void);
334 void enable_hlt(void);
335 
336 #endif
337 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.