linux/arch/x86/include/asm/system.h
<<
>>
Prefs
   1#ifndef _ASM_X86_SYSTEM_H
   2#define _ASM_X86_SYSTEM_H
   3
   4#include <asm/asm.h>
   5#include <asm/segment.h>
   6#include <asm/cpufeature.h>
   7#include <asm/cmpxchg.h>
   8#include <asm/nops.h>
   9
  10#include <linux/kernel.h>
  11#include <linux/irqflags.h>
  12
  13/* entries in ARCH_DLINFO: */
  14#ifdef CONFIG_IA32_EMULATION
  15# define AT_VECTOR_SIZE_ARCH 2
  16#else
  17# define AT_VECTOR_SIZE_ARCH 1
  18#endif
  19
  20#ifdef CONFIG_X86_32
  21
  22struct task_struct; /* one of the stranger aspects of C forward declarations */
  23struct task_struct *__switch_to(struct task_struct *prev,
  24                                struct task_struct *next);
  25
  26/*
  27 * Saving eflags is important. It switches not only IOPL between tasks,
  28 * it also protects other tasks from NT leaking through sysenter etc.
  29 */
  30#define switch_to(prev, next, last)                                     \
  31do {                                                                    \
  32        /*                                                              \
  33         * Context-switching clobbers all registers, so we clobber      \
  34         * them explicitly, via unused output variables.                \
  35         * (EAX and EBP is not listed because EBP is saved/restored     \
  36         * explicitly for wchan access and EAX is the return value of   \
  37         * __switch_to())                                               \
  38         */                                                             \
  39        unsigned long ebx, ecx, edx, esi, edi;                          \
  40                                                                        \
  41        asm volatile("pushfl\n\t"               /* save    flags */     \
  42                     "pushl %%ebp\n\t"          /* save    EBP   */     \
  43                     "movl %%esp,%[prev_sp]\n\t"        /* save    ESP   */ \
  44                     "movl %[next_sp],%%esp\n\t"        /* restore ESP   */ \
  45                     "movl $1f,%[prev_ip]\n\t"  /* save    EIP   */     \
  46                     "pushl %[next_ip]\n\t"     /* restore EIP   */     \
  47                     "jmp __switch_to\n"        /* regparm call  */     \
  48                     "1:\t"                                             \
  49                     "popl %%ebp\n\t"           /* restore EBP   */     \
  50                     "popfl\n"                  /* restore flags */     \
  51                                                                        \
  52                     /* output parameters */                            \
  53                     : [prev_sp] "=m" (prev->thread.sp),                \
  54                       [prev_ip] "=m" (prev->thread.ip),                \
  55                       "=a" (last),                                     \
  56                                                                        \
  57                       /* clobbered output registers: */                \
  58                       "=b" (ebx), "=c" (ecx), "=d" (edx),              \
  59                       "=S" (esi), "=D" (edi)                           \
  60                                                                        \
  61                       /* input parameters: */                          \
  62                     : [next_sp]  "m" (next->thread.sp),                \
  63                       [next_ip]  "m" (next->thread.ip),                \
  64                                                                        \
  65                       /* regparm parameters for __switch_to(): */      \
  66                       [prev]     "a" (prev),                           \
  67                       [next]     "d" (next)                            \
  68                                                                        \
  69                     : /* reloaded segment registers */                 \
  70                        "memory");                                      \
  71} while (0)
  72
  73/*
  74 * disable hlt during certain critical i/o operations
  75 */
  76#define HAVE_DISABLE_HLT
  77#else
  78#define __SAVE(reg, offset) "movq %%" #reg ",(14-" #offset ")*8(%%rsp)\n\t"
  79#define __RESTORE(reg, offset) "movq (14-" #offset ")*8(%%rsp),%%" #reg "\n\t"
  80
  81/* frame pointer must be last for get_wchan */
  82#define SAVE_CONTEXT    "pushf ; pushq %%rbp ; movq %%rsi,%%rbp\n\t"
  83#define RESTORE_CONTEXT "movq %%rbp,%%rsi ; popq %%rbp ; popf\t"
  84
  85#define __EXTRA_CLOBBER  \
  86        , "rcx", "rbx", "rdx", "r8", "r9", "r10", "r11", \
  87          "r12", "r13", "r14", "r15"
  88
  89/* Save restore flags to clear handle leaking NT */
  90#define switch_to(prev, next, last) \
  91        asm volatile(SAVE_CONTEXT                                                   \
  92             "movq %%rsp,%P[threadrsp](%[prev])\n\t" /* save RSP */       \
  93             "movq %P[threadrsp](%[next]),%%rsp\n\t" /* restore RSP */    \
  94             "call __switch_to\n\t"                                       \
  95             ".globl thread_return\n"                                     \
  96             "thread_return:\n\t"                                         \
  97             "movq %%gs:%P[pda_pcurrent],%%rsi\n\t"                       \
  98             "movq %P[thread_info](%%rsi),%%r8\n\t"                       \
  99             LOCK_PREFIX "btr  %[tif_fork],%P[ti_flags](%%r8)\n\t"        \
 100             "movq %%rax,%%rdi\n\t"                                       \
 101             "jc   ret_from_fork\n\t"                                     \
 102             RESTORE_CONTEXT                                              \
 103             : "=a" (last)                                                \
 104             : [next] "S" (next), [prev] "D" (prev),                      \
 105               [threadrsp] "i" (offsetof(struct task_struct, thread.sp)), \
 106               [ti_flags] "i" (offsetof(struct thread_info, flags)),      \
 107               [tif_fork] "i" (TIF_FORK),                                 \
 108               [thread_info] "i" (offsetof(struct task_struct, stack)),   \
 109               [pda_pcurrent] "i" (offsetof(struct x8664_pda, pcurrent))  \
 110             : "memory", "cc" __EXTRA_CLOBBER)
 111#endif
 112
 113#ifdef __KERNEL__
 114#define _set_base(addr, base) do { unsigned long __pr; \
 115__asm__ __volatile__ ("movw %%dx,%1\n\t" \
 116        "rorl $16,%%edx\n\t" \
 117        "movb %%dl,%2\n\t" \
 118        "movb %%dh,%3" \
 119        :"=&d" (__pr) \
 120        :"m" (*((addr)+2)), \
 121         "m" (*((addr)+4)), \
 122         "m" (*((addr)+7)), \
 123         "0" (base) \
 124        ); } while (0)
 125
 126#define _set_limit(addr, limit) do { unsigned long __lr; \
 127__asm__ __volatile__ ("movw %%dx,%1\n\t" \
 128        "rorl $16,%%edx\n\t" \
 129        "movb %2,%%dh\n\t" \
 130        "andb $0xf0,%%dh\n\t" \
 131        "orb %%dh,%%dl\n\t" \
 132        "movb %%dl,%2" \
 133        :"=&d" (__lr) \
 134        :"m" (*(addr)), \
 135         "m" (*((addr)+6)), \
 136         "0" (limit) \
 137        ); } while (0)
 138
 139#define set_base(ldt, base) _set_base(((char *)&(ldt)) , (base))
 140#define set_limit(ldt, limit) _set_limit(((char *)&(ldt)) , ((limit)-1))
 141
 142extern void native_load_gs_index(unsigned);
 143
 144/*
 145 * Load a segment. Fall back on loading the zero
 146 * segment if something goes wrong..
 147 */
 148#define loadsegment(seg, value)                 \
 149        asm volatile("\n"                       \
 150                     "1:\t"                     \
 151                     "movl %k0,%%" #seg "\n"    \
 152                     "2:\n"                     \
 153                     ".section .fixup,\"ax\"\n" \
 154                     "3:\t"                     \
 155                     "movl %k1, %%" #seg "\n\t" \
 156                     "jmp 2b\n"                 \
 157                     ".previous\n"              \
 158                     _ASM_EXTABLE(1b,3b)        \
 159                     : :"r" (value), "r" (0) : "memory")
 160
 161
 162/*
 163 * Save a segment register away
 164 */
 165#define savesegment(seg, value)                         \
 166        asm("mov %%" #seg ",%0":"=r" (value) : : "memory")
 167
 168static inline unsigned long get_limit(unsigned long segment)
 169{
 170        unsigned long __limit;
 171        asm("lsll %1,%0" : "=r" (__limit) : "r" (segment));
 172        return __limit + 1;
 173}
 174
 175static inline void native_clts(void)
 176{
 177        asm volatile("clts");
 178}
 179
 180/*
 181 * Volatile isn't enough to prevent the compiler from reordering the
 182 * read/write functions for the control registers and messing everything up.
 183 * A memory clobber would solve the problem, but would prevent reordering of
 184 * all loads stores around it, which can hurt performance. Solution is to
 185 * use a variable and mimic reads and writes to it to enforce serialization
 186 */
 187static unsigned long __force_order;
 188
 189static inline unsigned long native_read_cr0(void)
 190{
 191        unsigned long val;
 192        asm volatile("mov %%cr0,%0\n\t" : "=r" (val), "=m" (__force_order));
 193        return val;
 194}
 195
 196static inline void native_write_cr0(unsigned long val)
 197{
 198        asm volatile("mov %0,%%cr0": : "r" (val), "m" (__force_order));
 199}
 200
 201static inline unsigned long native_read_cr2(void)
 202{
 203        unsigned long val;
 204        asm volatile("mov %%cr2,%0\n\t" : "=r" (val), "=m" (__force_order));
 205        return val;
 206}
 207
 208static inline void native_write_cr2(unsigned long val)
 209{
 210        asm volatile("mov %0,%%cr2": : "r" (val), "m" (__force_order));
 211}
 212
 213static inline unsigned long native_read_cr3(void)
 214{
 215        unsigned long val;
 216        asm volatile("mov %%cr3,%0\n\t" : "=r" (val), "=m" (__force_order));
 217        return val;
 218}
 219
 220static inline void native_write_cr3(unsigned long val)
 221{
 222        asm volatile("mov %0,%%cr3": : "r" (val), "m" (__force_order));
 223}
 224
 225static inline unsigned long native_read_cr4(void)
 226{
 227        unsigned long val;
 228        asm volatile("mov %%cr4,%0\n\t" : "=r" (val), "=m" (__force_order));
 229        return val;
 230}
 231
 232static inline unsigned long native_read_cr4_safe(void)
 233{
 234        unsigned long val;
 235        /* This could fault if %cr4 does not exist. In x86_64, a cr4 always
 236         * exists, so it will never fail. */
 237#ifdef CONFIG_X86_32
 238        asm volatile("1: mov %%cr4, %0\n"
 239                     "2:\n"
 240                     _ASM_EXTABLE(1b, 2b)
 241                     : "=r" (val), "=m" (__force_order) : "0" (0));
 242#else
 243        val = native_read_cr4();
 244#endif
 245        return val;
 246}
 247
 248static inline void native_write_cr4(unsigned long val)
 249{
 250        asm volatile("mov %0,%%cr4": : "r" (val), "m" (__force_order));
 251}
 252
 253#ifdef CONFIG_X86_64
 254static inline unsigned long native_read_cr8(void)
 255{
 256        unsigned long cr8;
 257        asm volatile("movq %%cr8,%0" : "=r" (cr8));
 258        return cr8;
 259}
 260
 261static inline void native_write_cr8(unsigned long val)
 262{
 263        asm volatile("movq %0,%%cr8" :: "r" (val) : "memory");
 264}
 265#endif
 266
 267static inline void native_wbinvd(void)
 268{
 269        asm volatile("wbinvd": : :"memory");
 270}
 271
 272#ifdef CONFIG_PARAVIRT
 273#include <asm/paravirt.h>
 274#else
 275#define read_cr0()      (native_read_cr0())
 276#define write_cr0(x)    (native_write_cr0(x))
 277#define read_cr2()      (native_read_cr2())
 278#define write_cr2(x)    (native_write_cr2(x))
 279#define read_cr3()      (native_read_cr3())
 280#define write_cr3(x)    (native_write_cr3(x))
 281#define read_cr4()      (native_read_cr4())
 282#define read_cr4_safe() (native_read_cr4_safe())
 283#define write_cr4(x)    (native_write_cr4(x))
 284#define wbinvd()        (native_wbinvd())
 285#ifdef CONFIG_X86_64
 286#define read_cr8()      (native_read_cr8())
 287#define write_cr8(x)    (native_write_cr8(x))
 288#define load_gs_index   native_load_gs_index
 289#endif
 290
 291/* Clear the 'TS' bit */
 292#define clts()          (native_clts())
 293
 294#endif/* CONFIG_PARAVIRT */
 295
 296#define stts() write_cr0(read_cr0() | X86_CR0_TS)
 297
 298#endif /* __KERNEL__ */
 299
 300static inline void clflush(volatile void *__p)
 301{
 302        asm volatile("clflush %0" : "+m" (*(volatile char __force *)__p));
 303}
 304
 305#define nop() asm volatile ("nop")
 306
 307void disable_hlt(void);
 308void enable_hlt(void);
 309
 310void cpu_idle_wait(void);
 311
 312extern unsigned long arch_align_stack(unsigned long sp);
 313extern void free_init_pages(char *what, unsigned long begin, unsigned long end);
 314
 315void default_idle(void);
 316
 317/*
 318 * Force strict CPU ordering.
 319 * And yes, this is required on UP too when we're talking
 320 * to devices.
 321 */
 322#ifdef CONFIG_X86_32
 323/*
 324 * Some non-Intel clones support out of order store. wmb() ceases to be a
 325 * nop for these.
 326 */
 327#define mb() alternative("lock; addl $0,0(%%esp)", "mfence", X86_FEATURE_XMM2)
 328#define rmb() alternative("lock; addl $0,0(%%esp)", "lfence", X86_FEATURE_XMM2)
 329#define wmb() alternative("lock; addl $0,0(%%esp)", "sfence", X86_FEATURE_XMM)
 330#else
 331#define mb()    asm volatile("mfence":::"memory")
 332#define rmb()   asm volatile("lfence":::"memory")
 333#define wmb()   asm volatile("sfence" ::: "memory")
 334#endif
 335
 336/**
 337 * read_barrier_depends - Flush all pending reads that subsequents reads
 338 * depend on.
 339 *
 340 * No data-dependent reads from memory-like regions are ever reordered
 341 * over this barrier.  All reads preceding this primitive are guaranteed
 342 * to access memory (but not necessarily other CPUs' caches) before any
 343 * reads following this primitive that depend on the data return by
 344 * any of the preceding reads.  This primitive is much lighter weight than
 345 * rmb() on most CPUs, and is never heavier weight than is
 346 * rmb().
 347 *
 348 * These ordering constraints are respected by both the local CPU
 349 * and the compiler.
 350 *
 351 * Ordering is not guaranteed by anything other than these primitives,
 352 * not even by data dependencies.  See the documentation for
 353 * memory_barrier() for examples and URLs to more information.
 354 *
 355 * For example, the following code would force ordering (the initial
 356 * value of "a" is zero, "b" is one, and "p" is "&a"):
 357 *
 358 * <programlisting>
 359 *      CPU 0                           CPU 1
 360 *
 361 *      b = 2;
 362 *      memory_barrier();
 363 *      p = &b;                         q = p;
 364 *                                      read_barrier_depends();
 365 *                                      d = *q;
 366 * </programlisting>
 367 *
 368 * because the read of "*q" depends on the read of "p" and these
 369 * two reads are separated by a read_barrier_depends().  However,
 370 * the following code, with the same initial values for "a" and "b":
 371 *
 372 * <programlisting>
 373 *      CPU 0                           CPU 1
 374 *
 375 *      a = 2;
 376 *      memory_barrier();
 377 *      b = 3;                          y = b;
 378 *                                      read_barrier_depends();
 379 *                                      x = a;
 380 * </programlisting>
 381 *
 382 * does not enforce ordering, since there is no data dependency between
 383 * the read of "a" and the read of "b".  Therefore, on some CPUs, such
 384 * as Alpha, "y" could be set to 3 and "x" to 0.  Use rmb()
 385 * in cases like this where there are no data dependencies.
 386 **/
 387
 388#define read_barrier_depends()  do { } while (0)
 389
 390#ifdef CONFIG_SMP
 391#define smp_mb()        mb()
 392#ifdef CONFIG_X86_PPRO_FENCE
 393# define smp_rmb()      rmb()
 394#else
 395# define smp_rmb()      barrier()
 396#endif
 397#ifdef CONFIG_X86_OOSTORE
 398# define smp_wmb()      wmb()
 399#else
 400# define smp_wmb()      barrier()
 401#endif
 402#define smp_read_barrier_depends()      read_barrier_depends()
 403#define set_mb(var, value) do { (void)xchg(&var, value); } while (0)
 404#else
 405#define smp_mb()        barrier()
 406#define smp_rmb()       barrier()
 407#define smp_wmb()       barrier()
 408#define smp_read_barrier_depends()      do { } while (0)
 409#define set_mb(var, value) do { var = value; barrier(); } while (0)
 410#endif
 411
 412/*
 413 * Stop RDTSC speculation. This is needed when you need to use RDTSC
 414 * (or get_cycles or vread that possibly accesses the TSC) in a defined
 415 * code region.
 416 *
 417 * (Could use an alternative three way for this if there was one.)
 418 */
 419static inline void rdtsc_barrier(void)
 420{
 421        alternative(ASM_NOP3, "mfence", X86_FEATURE_MFENCE_RDTSC);
 422        alternative(ASM_NOP3, "lfence", X86_FEATURE_LFENCE_RDTSC);
 423}
 424
 425#endif /* _ASM_X86_SYSTEM_H */
 426
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.