home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2006 November (DVD) / PCWELT_11_2006.ISO / casper / filesystem.squashfs / usr / src / linux-headers-2.6.17-6 / include / asm-x86_64 / alternative.h < prev    next >
Encoding:
C/C++ Source or Header  |  2006-08-11  |  5.4 KB  |  147 lines

  1. #ifndef _X86_64_ALTERNATIVE_H
  2. #define _X86_64_ALTERNATIVE_H
  3.  
  4. #ifdef __KERNEL__
  5.  
  6. #include <linux/types.h>
  7.  
  8. struct alt_instr {
  9.     u8 *instr;         /* original instruction */
  10.     u8 *replacement;
  11.     u8  cpuid;        /* cpuid bit set for replacement */
  12.     u8  instrlen;        /* length of original instruction */
  13.     u8  replacementlen;     /* length of new instruction, <= instrlen */
  14.     u8  pad[5];
  15. };
  16.  
  17. extern void apply_alternatives(struct alt_instr *start, struct alt_instr *end);
  18.  
  19. struct module;
  20. extern void alternatives_smp_module_add(struct module *mod, char *name,
  21.                     void *locks, void *locks_end,
  22.                     void *text, void *text_end);
  23. extern void alternatives_smp_module_del(struct module *mod);
  24. extern void alternatives_smp_switch(int smp);
  25.  
  26. #endif
  27.  
  28. /*
  29.  * Alternative instructions for different CPU types or capabilities.
  30.  *
  31.  * This allows to use optimized instructions even on generic binary
  32.  * kernels.
  33.  *
  34.  * length of oldinstr must be longer or equal the length of newinstr
  35.  * It can be padded with nops as needed.
  36.  *
  37.  * For non barrier like inlines please define new variants
  38.  * without volatile and memory clobber.
  39.  */
  40. #define alternative(oldinstr, newinstr, feature)     \
  41.     asm volatile ("661:\n\t" oldinstr "\n662:\n"              \
  42.               ".section .altinstructions,\"a\"\n"              \
  43.               "  .align 8\n"                       \
  44.               "  .quad 661b\n"            /* label */          \
  45.               "  .quad 663f\n"          /* new instruction */ \
  46.               "  .byte %c0\n"             /* feature bit */    \
  47.               "  .byte 662b-661b\n"       /* sourcelen */      \
  48.               "  .byte 664f-663f\n"       /* replacementlen */ \
  49.               ".previous\n"                    \
  50.               ".section .altinstr_replacement,\"ax\"\n"        \
  51.               "663:\n\t" newinstr "\n664:\n"   /* replacement */ \
  52.               ".previous" :: "i" (feature) : "memory")
  53.  
  54. /*
  55.  * Alternative inline assembly with input.
  56.  *
  57.  * Pecularities:
  58.  * No memory clobber here.
  59.  * Argument numbers start with 1.
  60.  * Best is to use constraints that are fixed size (like (%1) ... "r")
  61.  * If you use variable sized constraints like "m" or "g" in the
  62.  * replacement make sure to pad to the worst case length.
  63.  */
  64. #define alternative_input(oldinstr, newinstr, feature, input...)    \
  65.     asm volatile ("661:\n\t" oldinstr "\n662:\n"            \
  66.               ".section .altinstructions,\"a\"\n"        \
  67.               "  .align 8\n"                    \
  68.               "  .quad 661b\n"            /* label */        \
  69.               "  .quad 663f\n"          /* new instruction */    \
  70.               "  .byte %c0\n"             /* feature bit */    \
  71.               "  .byte 662b-661b\n"       /* sourcelen */    \
  72.               "  .byte 664f-663f\n"       /* replacementlen */    \
  73.               ".previous\n"                    \
  74.               ".section .altinstr_replacement,\"ax\"\n"        \
  75.               "663:\n\t" newinstr "\n664:\n"   /* replacement */ \
  76.               ".previous" :: "i" (feature), ##input)
  77.  
  78. /* Like alternative_input, but with a single output argument */
  79. #define alternative_io(oldinstr, newinstr, feature, output, input...) \
  80.     asm volatile ("661:\n\t" oldinstr "\n662:\n"            \
  81.               ".section .altinstructions,\"a\"\n"        \
  82.               "  .align 8\n"                    \
  83.               "  .quad 661b\n"            /* label */        \
  84.               "  .quad 663f\n"          /* new instruction */    \
  85.               "  .byte %c[feat]\n"        /* feature bit */    \
  86.               "  .byte 662b-661b\n"       /* sourcelen */    \
  87.               "  .byte 664f-663f\n"       /* replacementlen */    \
  88.               ".previous\n"                    \
  89.               ".section .altinstr_replacement,\"ax\"\n"        \
  90.               "663:\n\t" newinstr "\n664:\n"   /* replacement */ \
  91.               ".previous" : output : [feat] "i" (feature), ##input)
  92.  
  93. /*
  94.  * Alternative inline assembly for SMP.
  95.  *
  96.  * alternative_smp() takes two versions (SMP first, UP second) and is
  97.  * for more complex stuff such as spinlocks.
  98.  *
  99.  * The LOCK_PREFIX macro defined here replaces the LOCK and
  100.  * LOCK_PREFIX macros used everywhere in the source tree.
  101.  *
  102.  * SMP alternatives use the same data structures as the other
  103.  * alternatives and the X86_FEATURE_UP flag to indicate the case of a
  104.  * UP system running a SMP kernel.  The existing apply_alternatives()
  105.  * works fine for patching a SMP kernel for UP.
  106.  *
  107.  * The SMP alternative tables can be kept after boot and contain both
  108.  * UP and SMP versions of the instructions to allow switching back to
  109.  * SMP at runtime, when hotplugging in a new CPU, which is especially
  110.  * useful in virtualized environments.
  111.  *
  112.  * The very common lock prefix is handled as special case in a
  113.  * separate table which is a pure address list without replacement ptr
  114.  * and size information.  That keeps the table sizes small.
  115.  */
  116.  
  117. #ifdef CONFIG_SMP
  118. #define alternative_smp(smpinstr, upinstr, args...)            \
  119.     asm volatile ("661:\n\t" smpinstr "\n662:\n"            \
  120.               ".section .smp_altinstructions,\"a\"\n"        \
  121.               "  .align 8\n"                    \
  122.               "  .quad 661b\n"            /* label */        \
  123.               "  .quad 663f\n"          /* new instruction */    \
  124.               "  .byte 0x66\n"            /* X86_FEATURE_UP */    \
  125.               "  .byte 662b-661b\n"       /* sourcelen */    \
  126.               "  .byte 664f-663f\n"       /* replacementlen */    \
  127.               ".previous\n"                    \
  128.               ".section .smp_altinstr_replacement,\"awx\"\n"    \
  129.               "663:\n\t" upinstr "\n"     /* replacement */    \
  130.               "664:\n\t.fill 662b-661b,1,0x42\n" /* space for original */ \
  131.               ".previous" : args)
  132.  
  133. #define LOCK_PREFIX \
  134.         ".section .smp_locks,\"a\"\n"    \
  135.         "  .align 8\n"            \
  136.         "  .quad 661f\n" /* address */    \
  137.         ".previous\n"            \
  138.                "661:\n\tlock; "
  139.  
  140. #else /* ! CONFIG_SMP */
  141. #define alternative_smp(smpinstr, upinstr, args...) \
  142.     asm volatile (upinstr : args)
  143. #define LOCK_PREFIX ""
  144. #endif
  145.  
  146. #endif /* _X86_64_ALTERNATIVE_H */
  147.