File: /Users/paulross/dev/linux/linux-3.13/arch/x86/include/asm/special_insns.h

Green shading in the line number column means the source is part of the translation unit, red means it is conditionally excluded. Highlighted line numbers link to the translation unit page. Highlighted macros link to the macro page.

       1: #ifndef _ASM_X86_SPECIAL_INSNS_H
       2: #define _ASM_X86_SPECIAL_INSNS_H
       3: 
       4: 
       5: #ifdef __KERNEL__
       6: 
       7: static inline void native_clts(void)
       8: {
       9:     asm volatile("clts");
      10: }
      11: 
      12: /*
      13:  * Volatile isn't enough to prevent the compiler from reordering the
      14:  * read/write functions for the control registers and messing everything up.
      15:  * A memory clobber would solve the problem, but would prevent reordering of
      16:  * all loads stores around it, which can hurt performance. Solution is to
      17:  * use a variable and mimic reads and writes to it to enforce serialization
      18:  */
      19: extern unsigned long __force_order;
      20: 
      21: static inline unsigned long native_read_cr0(void)
      22: {
      23:     unsigned long val;
      24:     asm volatile("mov %%cr0,%0\n\t" : "=r" (val), "=m" (__force_order));
      25:     return val;
      26: }
      27: 
      28: static inline void native_write_cr0(unsigned long val)
      29: {
      30:     asm volatile("mov %0,%%cr0": : "r" (val), "m" (__force_order));
      31: }
      32: 
      33: static inline unsigned long native_read_cr2(void)
      34: {
      35:     unsigned long val;
      36:     asm volatile("mov %%cr2,%0\n\t" : "=r" (val), "=m" (__force_order));
      37:     return val;
      38: }
      39: 
      40: static inline void native_write_cr2(unsigned long val)
      41: {
      42:     asm volatile("mov %0,%%cr2": : "r" (val), "m" (__force_order));
      43: }
      44: 
      45: static inline unsigned long native_read_cr3(void)
      46: {
      47:     unsigned long val;
      48:     asm volatile("mov %%cr3,%0\n\t" : "=r" (val), "=m" (__force_order));
      49:     return val;
      50: }
      51: 
      52: static inline void native_write_cr3(unsigned long val)
      53: {
      54:     asm volatile("mov %0,%%cr3": : "r" (val), "m" (__force_order));
      55: }
      56: 
      57: static inline unsigned long native_read_cr4(void)
      58: {
      59:     unsigned long val;
      60:     asm volatile("mov %%cr4,%0\n\t" : "=r" (val), "=m" (__force_order));
      61:     return val;
      62: }
      63: 
      64: static inline unsigned long native_read_cr4_safe(void)
      65: {
      66:     unsigned long val;
      67:     /* This could fault if %cr4 does not exist. In x86_64, a cr4 always
      68:      * exists, so it will never fail. */
      69: #ifdef CONFIG_X86_32
      70:     asm volatile("1: mov %%cr4, %0\n"
      71:              "2:\n"
      72:              _ASM_EXTABLE(1b, 2b)
      73:              : "=r" (val), "=m" (__force_order) : "0" (0));
      74: #else
      75:     val = native_read_cr4();
      76: #endif
      77:     return val;
      78: }
      79: 
      80: static inline void native_write_cr4(unsigned long val)
      81: {
      82:     asm volatile("mov %0,%%cr4": : "r" (val), "m" (__force_order));
      83: }
      84: 
      85: #ifdef CONFIG_X86_64
      86: static inline unsigned long native_read_cr8(void)
      87: {
      88:     unsigned long cr8;
      89:     asm volatile("movq %%cr8,%0" : "=r" (cr8));
      90:     return cr8;
      91: }
      92: 
      93: static inline void native_write_cr8(unsigned long val)
      94: {
      95:     asm volatile("movq %0,%%cr8" :: "r" (val) : "memory");
      96: }
      97: #endif
      98: 
      99: static inline void native_wbinvd(void)
     100: {
     101:     asm volatile("wbinvd": : :"memory");
     102: }
     103: 
     104: extern asmlinkage void native_load_gs_index(unsigned);
     105: 
     106: #ifdef CONFIG_PARAVIRT
     107: #include <asm/paravirt.h>
     108: #else
     109: 
     110: static inline unsigned long read_cr0(void)
     111: {
     112:     return native_read_cr0();
     113: }
     114: 
     115: static inline void write_cr0(unsigned long x)
     116: {
     117:     native_write_cr0(x);
     118: }
     119: 
     120: static inline unsigned long read_cr2(void)
     121: {
     122:     return native_read_cr2();
     123: }
     124: 
     125: static inline void write_cr2(unsigned long x)
     126: {
     127:     native_write_cr2(x);
     128: }
     129: 
     130: static inline unsigned long read_cr3(void)
     131: {
     132:     return native_read_cr3();
     133: }
     134: 
     135: static inline void write_cr3(unsigned long x)
     136: {
     137:     native_write_cr3(x);
     138: }
     139: 
     140: static inline unsigned long read_cr4(void)
     141: {
     142:     return native_read_cr4();
     143: }
     144: 
     145: static inline unsigned long read_cr4_safe(void)
     146: {
     147:     return native_read_cr4_safe();
     148: }
     149: 
     150: static inline void write_cr4(unsigned long x)
     151: {
     152:     native_write_cr4(x);
     153: }
     154: 
     155: static inline void wbinvd(void)
     156: {
     157:     native_wbinvd();
     158: }
     159: 
     160: #ifdef CONFIG_X86_64
     161: 
     162: static inline unsigned long read_cr8(void)
     163: {
     164:     return native_read_cr8();
     165: }
     166: 
     167: static inline void write_cr8(unsigned long x)
     168: {
     169:     native_write_cr8(x);
     170: }
     171: 
     172: static inline void load_gs_index(unsigned selector)
     173: {
     174:     native_load_gs_index(selector);
     175: }
     176: 
     177: #endif
     178: 
     179: /* Clear the 'TS' bit */
     180: static inline void clts(void)
     181: {
     182:     native_clts();
     183: }
     184: 
     185: #endif/* CONFIG_PARAVIRT */
     186: 
     187: #define stts() write_cr0(read_cr0() | X86_CR0_TS)
     188: 
     189: static inline void clflush(volatile void *__p)
     190: {
     191:     asm volatile("clflush %0" : "+m" (*(volatile char __force *)__p));
     192: }
     193: 
     194: #define nop() asm volatile ("nop")
     195: 
     196: 
     197: #endif /* __KERNEL__ */
     198: 
     199: #endif /* _ASM_X86_SPECIAL_INSNS_H */
     200: