Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v2.6.26-rc3 181 lines 6.5 kB view raw
1#ifndef _ASM_X86_ALTERNATIVE_H 2#define _ASM_X86_ALTERNATIVE_H 3 4#include <linux/types.h> 5#include <linux/stddef.h> 6#include <asm/asm.h> 7 8/* 9 * Alternative inline assembly for SMP. 10 * 11 * The LOCK_PREFIX macro defined here replaces the LOCK and 12 * LOCK_PREFIX macros used everywhere in the source tree. 13 * 14 * SMP alternatives use the same data structures as the other 15 * alternatives and the X86_FEATURE_UP flag to indicate the case of a 16 * UP system running a SMP kernel. The existing apply_alternatives() 17 * works fine for patching a SMP kernel for UP. 18 * 19 * The SMP alternative tables can be kept after boot and contain both 20 * UP and SMP versions of the instructions to allow switching back to 21 * SMP at runtime, when hotplugging in a new CPU, which is especially 22 * useful in virtualized environments. 23 * 24 * The very common lock prefix is handled as special case in a 25 * separate table which is a pure address list without replacement ptr 26 * and size information. That keeps the table sizes small. 27 */ 28 29#ifdef CONFIG_SMP 30#define LOCK_PREFIX \ 31 ".section .smp_locks,\"a\"\n" \ 32 _ASM_ALIGN "\n" \ 33 _ASM_PTR "661f\n" /* address */ \ 34 ".previous\n" \ 35 "661:\n\tlock; " 36 37#else /* ! CONFIG_SMP */ 38#define LOCK_PREFIX "" 39#endif 40 41/* This must be included *after* the definition of LOCK_PREFIX */ 42#include <asm/cpufeature.h> 43 44struct alt_instr { 45 u8 *instr; /* original instruction */ 46 u8 *replacement; 47 u8 cpuid; /* cpuid bit set for replacement */ 48 u8 instrlen; /* length of original instruction */ 49 u8 replacementlen; /* length of new instruction, <= instrlen */ 50 u8 pad1; 51#ifdef CONFIG_X86_64 52 u32 pad2; 53#endif 54}; 55 56extern void alternative_instructions(void); 57extern void apply_alternatives(struct alt_instr *start, struct alt_instr *end); 58 59struct module; 60 61#ifdef CONFIG_SMP 62extern void alternatives_smp_module_add(struct module *mod, char *name, 63 void *locks, void *locks_end, 64 void *text, void *text_end); 65extern void alternatives_smp_module_del(struct module *mod); 66extern void alternatives_smp_switch(int smp); 67#else 68static inline void alternatives_smp_module_add(struct module *mod, char *name, 69 void *locks, void *locks_end, 70 void *text, void *text_end) {} 71static inline void alternatives_smp_module_del(struct module *mod) {} 72static inline void alternatives_smp_switch(int smp) {} 73#endif /* CONFIG_SMP */ 74 75/* 76 * Alternative instructions for different CPU types or capabilities. 77 * 78 * This allows to use optimized instructions even on generic binary 79 * kernels. 80 * 81 * length of oldinstr must be longer or equal the length of newinstr 82 * It can be padded with nops as needed. 83 * 84 * For non barrier like inlines please define new variants 85 * without volatile and memory clobber. 86 */ 87#define alternative(oldinstr, newinstr, feature) \ 88 asm volatile ("661:\n\t" oldinstr "\n662:\n" \ 89 ".section .altinstructions,\"a\"\n" \ 90 _ASM_ALIGN "\n" \ 91 _ASM_PTR "661b\n" /* label */ \ 92 _ASM_PTR "663f\n" /* new instruction */ \ 93 " .byte %c0\n" /* feature bit */ \ 94 " .byte 662b-661b\n" /* sourcelen */ \ 95 " .byte 664f-663f\n" /* replacementlen */ \ 96 ".previous\n" \ 97 ".section .altinstr_replacement,\"ax\"\n" \ 98 "663:\n\t" newinstr "\n664:\n" /* replacement */ \ 99 ".previous" :: "i" (feature) : "memory") 100 101/* 102 * Alternative inline assembly with input. 103 * 104 * Pecularities: 105 * No memory clobber here. 106 * Argument numbers start with 1. 107 * Best is to use constraints that are fixed size (like (%1) ... "r") 108 * If you use variable sized constraints like "m" or "g" in the 109 * replacement make sure to pad to the worst case length. 110 */ 111#define alternative_input(oldinstr, newinstr, feature, input...) \ 112 asm volatile ("661:\n\t" oldinstr "\n662:\n" \ 113 ".section .altinstructions,\"a\"\n" \ 114 _ASM_ALIGN "\n" \ 115 _ASM_PTR "661b\n" /* label */ \ 116 _ASM_PTR "663f\n" /* new instruction */ \ 117 " .byte %c0\n" /* feature bit */ \ 118 " .byte 662b-661b\n" /* sourcelen */ \ 119 " .byte 664f-663f\n" /* replacementlen */ \ 120 ".previous\n" \ 121 ".section .altinstr_replacement,\"ax\"\n" \ 122 "663:\n\t" newinstr "\n664:\n" /* replacement */ \ 123 ".previous" :: "i" (feature), ##input) 124 125/* Like alternative_input, but with a single output argument */ 126#define alternative_io(oldinstr, newinstr, feature, output, input...) \ 127 asm volatile ("661:\n\t" oldinstr "\n662:\n" \ 128 ".section .altinstructions,\"a\"\n" \ 129 _ASM_ALIGN "\n" \ 130 _ASM_PTR "661b\n" /* label */ \ 131 _ASM_PTR "663f\n" /* new instruction */ \ 132 " .byte %c[feat]\n" /* feature bit */ \ 133 " .byte 662b-661b\n" /* sourcelen */ \ 134 " .byte 664f-663f\n" /* replacementlen */ \ 135 ".previous\n" \ 136 ".section .altinstr_replacement,\"ax\"\n" \ 137 "663:\n\t" newinstr "\n664:\n" /* replacement */ \ 138 ".previous" : output : [feat] "i" (feature), ##input) 139 140/* 141 * use this macro(s) if you need more than one output parameter 142 * in alternative_io 143 */ 144#define ASM_OUTPUT2(a, b) a, b 145 146struct paravirt_patch_site; 147#ifdef CONFIG_PARAVIRT 148void apply_paravirt(struct paravirt_patch_site *start, 149 struct paravirt_patch_site *end); 150#else 151static inline void apply_paravirt(struct paravirt_patch_site *start, 152 struct paravirt_patch_site *end) 153{} 154#define __parainstructions NULL 155#define __parainstructions_end NULL 156#endif 157 158extern void add_nops(void *insns, unsigned int len); 159 160/* 161 * Clear and restore the kernel write-protection flag on the local CPU. 162 * Allows the kernel to edit read-only pages. 163 * Side-effect: any interrupt handler running between save and restore will have 164 * the ability to write to read-only pages. 165 * 166 * Warning: 167 * Code patching in the UP case is safe if NMIs and MCE handlers are stopped and 168 * no thread can be preempted in the instructions being modified (no iret to an 169 * invalid instruction possible) or if the instructions are changed from a 170 * consistent state to another consistent state atomically. 171 * More care must be taken when modifying code in the SMP case because of 172 * Intel's errata. 173 * On the local CPU you need to be protected again NMI or MCE handlers seeing an 174 * inconsistent instruction while you patch. 175 * The _early version expects the memory to already be RW. 176 */ 177 178extern void *text_poke(void *addr, const void *opcode, size_t len); 179extern void *text_poke_early(void *addr, const void *opcode, size_t len); 180 181#endif /* _ASM_X86_ALTERNATIVE_H */