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-i386 / alternative.h < prev    next >
Encoding:
C/C++ Source or Header  |  2006-08-11  |  4.7 KB  |  134 lines

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