Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.15 556 lines 16 kB view raw
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 <asm/cpufeature.h> 8#include <linux/bitops.h> /* for LOCK_PREFIX */ 9 10#ifdef __KERNEL__ 11 12struct task_struct; /* one of the stranger aspects of C forward declarations.. */ 13extern struct task_struct * FASTCALL(__switch_to(struct task_struct *prev, struct task_struct *next)); 14 15#define switch_to(prev,next,last) do { \ 16 unsigned long esi,edi; \ 17 asm volatile("pushl %%ebp\n\t" \ 18 "movl %%esp,%0\n\t" /* save ESP */ \ 19 "movl %5,%%esp\n\t" /* restore ESP */ \ 20 "movl $1f,%1\n\t" /* save EIP */ \ 21 "pushl %6\n\t" /* restore EIP */ \ 22 "jmp __switch_to\n" \ 23 "1:\t" \ 24 "popl %%ebp\n\t" \ 25 :"=m" (prev->thread.esp),"=m" (prev->thread.eip), \ 26 "=a" (last),"=S" (esi),"=D" (edi) \ 27 :"m" (next->thread.esp),"m" (next->thread.eip), \ 28 "2" (prev), "d" (next)); \ 29} while (0) 30 31#define _set_base(addr,base) do { unsigned long __pr; \ 32__asm__ __volatile__ ("movw %%dx,%1\n\t" \ 33 "rorl $16,%%edx\n\t" \ 34 "movb %%dl,%2\n\t" \ 35 "movb %%dh,%3" \ 36 :"=&d" (__pr) \ 37 :"m" (*((addr)+2)), \ 38 "m" (*((addr)+4)), \ 39 "m" (*((addr)+7)), \ 40 "0" (base) \ 41 ); } while(0) 42 43#define _set_limit(addr,limit) do { unsigned long __lr; \ 44__asm__ __volatile__ ("movw %%dx,%1\n\t" \ 45 "rorl $16,%%edx\n\t" \ 46 "movb %2,%%dh\n\t" \ 47 "andb $0xf0,%%dh\n\t" \ 48 "orb %%dh,%%dl\n\t" \ 49 "movb %%dl,%2" \ 50 :"=&d" (__lr) \ 51 :"m" (*(addr)), \ 52 "m" (*((addr)+6)), \ 53 "0" (limit) \ 54 ); } while(0) 55 56#define set_base(ldt,base) _set_base( ((char *)&(ldt)) , (base) ) 57#define set_limit(ldt,limit) _set_limit( ((char *)&(ldt)) , ((limit)-1)>>12 ) 58 59static inline unsigned long _get_base(char * addr) 60{ 61 unsigned long __base; 62 __asm__("movb %3,%%dh\n\t" 63 "movb %2,%%dl\n\t" 64 "shll $16,%%edx\n\t" 65 "movw %1,%%dx" 66 :"=&d" (__base) 67 :"m" (*((addr)+2)), 68 "m" (*((addr)+4)), 69 "m" (*((addr)+7))); 70 return __base; 71} 72 73#define get_base(ldt) _get_base( ((char *)&(ldt)) ) 74 75/* 76 * Load a segment. Fall back on loading the zero 77 * segment if something goes wrong.. 78 */ 79#define loadsegment(seg,value) \ 80 asm volatile("\n" \ 81 "1:\t" \ 82 "mov %0,%%" #seg "\n" \ 83 "2:\n" \ 84 ".section .fixup,\"ax\"\n" \ 85 "3:\t" \ 86 "pushl $0\n\t" \ 87 "popl %%" #seg "\n\t" \ 88 "jmp 2b\n" \ 89 ".previous\n" \ 90 ".section __ex_table,\"a\"\n\t" \ 91 ".align 4\n\t" \ 92 ".long 1b,3b\n" \ 93 ".previous" \ 94 : :"rm" (value)) 95 96/* 97 * Save a segment register away 98 */ 99#define savesegment(seg, value) \ 100 asm volatile("mov %%" #seg ",%0":"=rm" (value)) 101 102/* 103 * Clear and set 'TS' bit respectively 104 */ 105#define clts() __asm__ __volatile__ ("clts") 106#define read_cr0() ({ \ 107 unsigned int __dummy; \ 108 __asm__ __volatile__( \ 109 "movl %%cr0,%0\n\t" \ 110 :"=r" (__dummy)); \ 111 __dummy; \ 112}) 113#define write_cr0(x) \ 114 __asm__ __volatile__("movl %0,%%cr0": :"r" (x)); 115 116#define read_cr2() ({ \ 117 unsigned int __dummy; \ 118 __asm__ __volatile__( \ 119 "movl %%cr2,%0\n\t" \ 120 :"=r" (__dummy)); \ 121 __dummy; \ 122}) 123#define write_cr2(x) \ 124 __asm__ __volatile__("movl %0,%%cr2": :"r" (x)); 125 126#define read_cr3() ({ \ 127 unsigned int __dummy; \ 128 __asm__ ( \ 129 "movl %%cr3,%0\n\t" \ 130 :"=r" (__dummy)); \ 131 __dummy; \ 132}) 133#define write_cr3(x) \ 134 __asm__ __volatile__("movl %0,%%cr3": :"r" (x)); 135 136#define read_cr4() ({ \ 137 unsigned int __dummy; \ 138 __asm__( \ 139 "movl %%cr4,%0\n\t" \ 140 :"=r" (__dummy)); \ 141 __dummy; \ 142}) 143#define write_cr4(x) \ 144 __asm__ __volatile__("movl %0,%%cr4": :"r" (x)); 145#define stts() write_cr0(8 | read_cr0()) 146 147#endif /* __KERNEL__ */ 148 149#define wbinvd() \ 150 __asm__ __volatile__ ("wbinvd": : :"memory"); 151 152static inline unsigned long get_limit(unsigned long segment) 153{ 154 unsigned long __limit; 155 __asm__("lsll %1,%0" 156 :"=r" (__limit):"r" (segment)); 157 return __limit+1; 158} 159 160#define nop() __asm__ __volatile__ ("nop") 161 162#define xchg(ptr,v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v),(ptr),sizeof(*(ptr)))) 163 164#define tas(ptr) (xchg((ptr),1)) 165 166struct __xchg_dummy { unsigned long a[100]; }; 167#define __xg(x) ((struct __xchg_dummy *)(x)) 168 169 170#ifdef CONFIG_X86_CMPXCHG64 171 172/* 173 * The semantics of XCHGCMP8B are a bit strange, this is why 174 * there is a loop and the loading of %%eax and %%edx has to 175 * be inside. This inlines well in most cases, the cached 176 * cost is around ~38 cycles. (in the future we might want 177 * to do an SIMD/3DNOW!/MMX/FPU 64-bit store here, but that 178 * might have an implicit FPU-save as a cost, so it's not 179 * clear which path to go.) 180 * 181 * cmpxchg8b must be used with the lock prefix here to allow 182 * the instruction to be executed atomically, see page 3-102 183 * of the instruction set reference 24319102.pdf. We need 184 * the reader side to see the coherent 64bit value. 185 */ 186static inline void __set_64bit (unsigned long long * ptr, 187 unsigned int low, unsigned int high) 188{ 189 __asm__ __volatile__ ( 190 "\n1:\t" 191 "movl (%0), %%eax\n\t" 192 "movl 4(%0), %%edx\n\t" 193 "lock cmpxchg8b (%0)\n\t" 194 "jnz 1b" 195 : /* no outputs */ 196 : "D"(ptr), 197 "b"(low), 198 "c"(high) 199 : "ax","dx","memory"); 200} 201 202static inline void __set_64bit_constant (unsigned long long *ptr, 203 unsigned long long value) 204{ 205 __set_64bit(ptr,(unsigned int)(value), (unsigned int)((value)>>32ULL)); 206} 207#define ll_low(x) *(((unsigned int*)&(x))+0) 208#define ll_high(x) *(((unsigned int*)&(x))+1) 209 210static inline void __set_64bit_var (unsigned long long *ptr, 211 unsigned long long value) 212{ 213 __set_64bit(ptr,ll_low(value), ll_high(value)); 214} 215 216#define set_64bit(ptr,value) \ 217(__builtin_constant_p(value) ? \ 218 __set_64bit_constant(ptr, value) : \ 219 __set_64bit_var(ptr, value) ) 220 221#define _set_64bit(ptr,value) \ 222(__builtin_constant_p(value) ? \ 223 __set_64bit(ptr, (unsigned int)(value), (unsigned int)((value)>>32ULL) ) : \ 224 __set_64bit(ptr, ll_low(value), ll_high(value)) ) 225 226#endif 227 228/* 229 * Note: no "lock" prefix even on SMP: xchg always implies lock anyway 230 * Note 2: xchg has side effect, so that attribute volatile is necessary, 231 * but generally the primitive is invalid, *ptr is output argument. --ANK 232 */ 233static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size) 234{ 235 switch (size) { 236 case 1: 237 __asm__ __volatile__("xchgb %b0,%1" 238 :"=q" (x) 239 :"m" (*__xg(ptr)), "0" (x) 240 :"memory"); 241 break; 242 case 2: 243 __asm__ __volatile__("xchgw %w0,%1" 244 :"=r" (x) 245 :"m" (*__xg(ptr)), "0" (x) 246 :"memory"); 247 break; 248 case 4: 249 __asm__ __volatile__("xchgl %0,%1" 250 :"=r" (x) 251 :"m" (*__xg(ptr)), "0" (x) 252 :"memory"); 253 break; 254 } 255 return x; 256} 257 258/* 259 * Atomic compare and exchange. Compare OLD with MEM, if identical, 260 * store NEW in MEM. Return the initial value in MEM. Success is 261 * indicated by comparing RETURN with OLD. 262 */ 263 264#ifdef CONFIG_X86_CMPXCHG 265#define __HAVE_ARCH_CMPXCHG 1 266#define cmpxchg(ptr,o,n)\ 267 ((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\ 268 (unsigned long)(n),sizeof(*(ptr)))) 269#endif 270 271static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old, 272 unsigned long new, int size) 273{ 274 unsigned long prev; 275 switch (size) { 276 case 1: 277 __asm__ __volatile__(LOCK_PREFIX "cmpxchgb %b1,%2" 278 : "=a"(prev) 279 : "q"(new), "m"(*__xg(ptr)), "0"(old) 280 : "memory"); 281 return prev; 282 case 2: 283 __asm__ __volatile__(LOCK_PREFIX "cmpxchgw %w1,%2" 284 : "=a"(prev) 285 : "r"(new), "m"(*__xg(ptr)), "0"(old) 286 : "memory"); 287 return prev; 288 case 4: 289 __asm__ __volatile__(LOCK_PREFIX "cmpxchgl %1,%2" 290 : "=a"(prev) 291 : "r"(new), "m"(*__xg(ptr)), "0"(old) 292 : "memory"); 293 return prev; 294 } 295 return old; 296} 297 298#ifndef CONFIG_X86_CMPXCHG 299/* 300 * Building a kernel capable running on 80386. It may be necessary to 301 * simulate the cmpxchg on the 80386 CPU. For that purpose we define 302 * a function for each of the sizes we support. 303 */ 304 305extern unsigned long cmpxchg_386_u8(volatile void *, u8, u8); 306extern unsigned long cmpxchg_386_u16(volatile void *, u16, u16); 307extern unsigned long cmpxchg_386_u32(volatile void *, u32, u32); 308 309static inline unsigned long cmpxchg_386(volatile void *ptr, unsigned long old, 310 unsigned long new, int size) 311{ 312 switch (size) { 313 case 1: 314 return cmpxchg_386_u8(ptr, old, new); 315 case 2: 316 return cmpxchg_386_u16(ptr, old, new); 317 case 4: 318 return cmpxchg_386_u32(ptr, old, new); 319 } 320 return old; 321} 322 323#define cmpxchg(ptr,o,n) \ 324({ \ 325 __typeof__(*(ptr)) __ret; \ 326 if (likely(boot_cpu_data.x86 > 3)) \ 327 __ret = __cmpxchg((ptr), (unsigned long)(o), \ 328 (unsigned long)(n), sizeof(*(ptr))); \ 329 else \ 330 __ret = cmpxchg_386((ptr), (unsigned long)(o), \ 331 (unsigned long)(n), sizeof(*(ptr))); \ 332 __ret; \ 333}) 334#endif 335 336#ifdef CONFIG_X86_CMPXCHG64 337 338static inline unsigned long long __cmpxchg64(volatile void *ptr, unsigned long long old, 339 unsigned long long new) 340{ 341 unsigned long long prev; 342 __asm__ __volatile__(LOCK_PREFIX "cmpxchg8b %3" 343 : "=A"(prev) 344 : "b"((unsigned long)new), 345 "c"((unsigned long)(new >> 32)), 346 "m"(*__xg(ptr)), 347 "0"(old) 348 : "memory"); 349 return prev; 350} 351 352#define cmpxchg64(ptr,o,n)\ 353 ((__typeof__(*(ptr)))__cmpxchg64((ptr),(unsigned long long)(o),\ 354 (unsigned long long)(n))) 355 356#endif 357 358#ifdef __KERNEL__ 359struct alt_instr { 360 __u8 *instr; /* original instruction */ 361 __u8 *replacement; 362 __u8 cpuid; /* cpuid bit set for replacement */ 363 __u8 instrlen; /* length of original instruction */ 364 __u8 replacementlen; /* length of new instruction, <= instrlen */ 365 __u8 pad; 366}; 367#endif 368 369/* 370 * Alternative instructions for different CPU types or capabilities. 371 * 372 * This allows to use optimized instructions even on generic binary 373 * kernels. 374 * 375 * length of oldinstr must be longer or equal the length of newinstr 376 * It can be padded with nops as needed. 377 * 378 * For non barrier like inlines please define new variants 379 * without volatile and memory clobber. 380 */ 381#define alternative(oldinstr, newinstr, feature) \ 382 asm volatile ("661:\n\t" oldinstr "\n662:\n" \ 383 ".section .altinstructions,\"a\"\n" \ 384 " .align 4\n" \ 385 " .long 661b\n" /* label */ \ 386 " .long 663f\n" /* new instruction */ \ 387 " .byte %c0\n" /* feature bit */ \ 388 " .byte 662b-661b\n" /* sourcelen */ \ 389 " .byte 664f-663f\n" /* replacementlen */ \ 390 ".previous\n" \ 391 ".section .altinstr_replacement,\"ax\"\n" \ 392 "663:\n\t" newinstr "\n664:\n" /* replacement */ \ 393 ".previous" :: "i" (feature) : "memory") 394 395/* 396 * Alternative inline assembly with input. 397 * 398 * Pecularities: 399 * No memory clobber here. 400 * Argument numbers start with 1. 401 * Best is to use constraints that are fixed size (like (%1) ... "r") 402 * If you use variable sized constraints like "m" or "g" in the 403 * replacement maake sure to pad to the worst case length. 404 */ 405#define alternative_input(oldinstr, newinstr, feature, input...) \ 406 asm volatile ("661:\n\t" oldinstr "\n662:\n" \ 407 ".section .altinstructions,\"a\"\n" \ 408 " .align 4\n" \ 409 " .long 661b\n" /* label */ \ 410 " .long 663f\n" /* new instruction */ \ 411 " .byte %c0\n" /* feature bit */ \ 412 " .byte 662b-661b\n" /* sourcelen */ \ 413 " .byte 664f-663f\n" /* replacementlen */ \ 414 ".previous\n" \ 415 ".section .altinstr_replacement,\"ax\"\n" \ 416 "663:\n\t" newinstr "\n664:\n" /* replacement */ \ 417 ".previous" :: "i" (feature), ##input) 418 419/* 420 * Force strict CPU ordering. 421 * And yes, this is required on UP too when we're talking 422 * to devices. 423 * 424 * For now, "wmb()" doesn't actually do anything, as all 425 * Intel CPU's follow what Intel calls a *Processor Order*, 426 * in which all writes are seen in the program order even 427 * outside the CPU. 428 * 429 * I expect future Intel CPU's to have a weaker ordering, 430 * but I'd also expect them to finally get their act together 431 * and add some real memory barriers if so. 432 * 433 * Some non intel clones support out of order store. wmb() ceases to be a 434 * nop for these. 435 */ 436 437 438/* 439 * Actually only lfence would be needed for mb() because all stores done 440 * by the kernel should be already ordered. But keep a full barrier for now. 441 */ 442 443#define mb() alternative("lock; addl $0,0(%%esp)", "mfence", X86_FEATURE_XMM2) 444#define rmb() alternative("lock; addl $0,0(%%esp)", "lfence", X86_FEATURE_XMM2) 445 446/** 447 * read_barrier_depends - Flush all pending reads that subsequents reads 448 * depend on. 449 * 450 * No data-dependent reads from memory-like regions are ever reordered 451 * over this barrier. All reads preceding this primitive are guaranteed 452 * to access memory (but not necessarily other CPUs' caches) before any 453 * reads following this primitive that depend on the data return by 454 * any of the preceding reads. This primitive is much lighter weight than 455 * rmb() on most CPUs, and is never heavier weight than is 456 * rmb(). 457 * 458 * These ordering constraints are respected by both the local CPU 459 * and the compiler. 460 * 461 * Ordering is not guaranteed by anything other than these primitives, 462 * not even by data dependencies. See the documentation for 463 * memory_barrier() for examples and URLs to more information. 464 * 465 * For example, the following code would force ordering (the initial 466 * value of "a" is zero, "b" is one, and "p" is "&a"): 467 * 468 * <programlisting> 469 * CPU 0 CPU 1 470 * 471 * b = 2; 472 * memory_barrier(); 473 * p = &b; q = p; 474 * read_barrier_depends(); 475 * d = *q; 476 * </programlisting> 477 * 478 * because the read of "*q" depends on the read of "p" and these 479 * two reads are separated by a read_barrier_depends(). However, 480 * the following code, with the same initial values for "a" and "b": 481 * 482 * <programlisting> 483 * CPU 0 CPU 1 484 * 485 * a = 2; 486 * memory_barrier(); 487 * b = 3; y = b; 488 * read_barrier_depends(); 489 * x = a; 490 * </programlisting> 491 * 492 * does not enforce ordering, since there is no data dependency between 493 * the read of "a" and the read of "b". Therefore, on some CPUs, such 494 * as Alpha, "y" could be set to 3 and "x" to 0. Use rmb() 495 * in cases like thiswhere there are no data dependencies. 496 **/ 497 498#define read_barrier_depends() do { } while(0) 499 500#ifdef CONFIG_X86_OOSTORE 501/* Actually there are no OOO store capable CPUs for now that do SSE, 502 but make it already an possibility. */ 503#define wmb() alternative("lock; addl $0,0(%%esp)", "sfence", X86_FEATURE_XMM) 504#else 505#define wmb() __asm__ __volatile__ ("": : :"memory") 506#endif 507 508#ifdef CONFIG_SMP 509#define smp_mb() mb() 510#define smp_rmb() rmb() 511#define smp_wmb() wmb() 512#define smp_read_barrier_depends() read_barrier_depends() 513#define set_mb(var, value) do { xchg(&var, value); } while (0) 514#else 515#define smp_mb() barrier() 516#define smp_rmb() barrier() 517#define smp_wmb() barrier() 518#define smp_read_barrier_depends() do { } while(0) 519#define set_mb(var, value) do { var = value; barrier(); } while (0) 520#endif 521 522#define set_wmb(var, value) do { var = value; wmb(); } while (0) 523 524/* interrupt control.. */ 525#define local_save_flags(x) do { typecheck(unsigned long,x); __asm__ __volatile__("pushfl ; popl %0":"=g" (x): /* no input */); } while (0) 526#define local_irq_restore(x) do { typecheck(unsigned long,x); __asm__ __volatile__("pushl %0 ; popfl": /* no output */ :"g" (x):"memory", "cc"); } while (0) 527#define local_irq_disable() __asm__ __volatile__("cli": : :"memory") 528#define local_irq_enable() __asm__ __volatile__("sti": : :"memory") 529/* used in the idle loop; sti takes one instruction cycle to complete */ 530#define safe_halt() __asm__ __volatile__("sti; hlt": : :"memory") 531/* used when interrupts are already enabled or to shutdown the processor */ 532#define halt() __asm__ __volatile__("hlt": : :"memory") 533 534#define irqs_disabled() \ 535({ \ 536 unsigned long flags; \ 537 local_save_flags(flags); \ 538 !(flags & (1<<9)); \ 539}) 540 541/* For spinlocks etc */ 542#define local_irq_save(x) __asm__ __volatile__("pushfl ; popl %0 ; cli":"=g" (x): /* no input */ :"memory") 543 544/* 545 * disable hlt during certain critical i/o operations 546 */ 547#define HAVE_DISABLE_HLT 548void disable_hlt(void); 549void enable_hlt(void); 550 551extern int es7000_plat; 552void cpu_idle_wait(void); 553 554extern unsigned long arch_align_stack(unsigned long sp); 555 556#endif