x86: merge asm-x86/alternative.h
PATCH 1/1 x86: merge asm-x86/alternative.h
Straightforward merge. Kind of a pity that gas doesn't really have the concept of a "long" (long is 4-bytes for some reason.) Nor is it able to pad to a non-power of two boundary (for struct alignment) to get rid of the struct alt_instr padding.
Build tested on i386, i386 with lguest & xen paravirt enabled, and x86_64. Boot tested on x86_64.
---
include/asm-x86/alternative.h | 169 +++++++++++++++++++++++++++++++++++++- include/asm-x86/alternative_32.h | 154 ---------------------------------- include/asm-x86/alternative_64.h | 159 ----------------------------------- 3 files changed, 166 insertions(+), 316 deletions(-) delete mode 100644 include/asm-x86/alternative_32.h delete mode 100644 include/asm-x86/alternative_64.h
include/asm-x86/alternative.h +166 -3
@@ -1,5 +1,168 @@ -#ifdef CONFIG_X86_32 -# include "alternative_32.h" +#ifndef _X86_ALTERNATIVE_H +#define _X86_ALTERNATIVE_H + +#ifdef __KERNEL__ + +#include <linux/types.h> +#include <linux/stddef.h> + +#ifdef CONFIG_X86_64 +# define ALT_ASMPTR ".quad" +# define ALT_ALIGN "8" +# define ALT_INSTR_PAD 5#else -# include "alternative_64.h" +# define ALT_ASMPTR ".long" +# define ALT_ALIGN "4" +# define ALT_INSTR_PAD 1#endif + +struct alt_instr { +u8 *instr;/* original instruction */ +u8 *replacement; +u8 cpuid;/* cpuid bit set for replacement */ +u8 instrlen;/* length of original instruction */ +u8 replacementlen;/* length of new instruction, <= instrlen */ +u8 _pad[ALT_INSTR_PAD ]; +}; + +/* +* Alternative inline assembly for SMP. +* +* The LOCK_PREFIX macro defined here replaces the LOCK and +* LOCK_PREFIX macros used everywhere in the source tree. +* +* SMP alternatives use the same data structures as the other +* alternatives and the X86_FEATURE_UP flag to indicate the case of a +* UP system running a SMP kernel. The existing apply_alternatives() +* works fine for patching a SMP kernel for UP. +* +* The SMP alternative tables can be kept after boot and contain both +* UP and SMP versions of the instructions to allow switching back to +* SMP at runtime, when hotplugging in a new CPU, which is especially +* useful in virtualized environments. +* +* The very common lock prefix is handled as special case in a +* separate table which is a pure address list without replacement ptr +* and size information. That keeps the table sizes small. +*/ + +#ifdef CONFIG_SMP +#define LOCK_PREFIX \ + ".section .smp_locks,\"a\"\n" \ + " .align " ALT_ALIGN "\n" \ + " " ALT_ASMPTR " 661f\n"/* address */ \ +".previous\n" \ + "661:\n\tlock; " +#else /* ! CONFIG_SMP */ +#define LOCK_PREFIX "" +#endif + +/* This must be included *after* the definition of LOCK_PREFIX */ +#include <asm/cpufeature.h> + +extern void alternative_instructions (void ); +extern void apply_alternatives (struct alt_instr *start,struct alt_instr *end); + +struct module ; + +#ifdef CONFIG_SMP +extern void alternatives_smp_module_add (struct module *mod,char *name, +void *locks,void *locks_end, +void *text,void *text_end); +extern void alternatives_smp_module_del (struct module *mod); +extern void alternatives_smp_switch (int smp); +#else +static inline void alternatives_smp_module_add (struct module *mod,char *name, +void *locks,void *locks_end, +void *text,void *text_end) {} +static inline void alternatives_smp_module_del (struct module *mod) {} +static inline void alternatives_smp_switch (int smp) {} +#endif + +#endif + +/* +* Alternative instructions for different CPU types or capabilities. +* +* This allows to use optimized instructions even on generic binary +* kernels. +* +* length of oldinstr must be longer or equal the length of newinstr +* It can be padded with nops as needed. +* +* For non barrier like inlines please define new variants +* without volatile and memory clobber. +*/ +#define alternative (oldinstr, newinstr, feature) \ + asm volatile ("661:\n\t" oldinstr "\n662:\n" \ + ".section .altinstructions,\"a\"\n" \ + " .align " ALT_ALIGN " \n" \ + " " ALT_ASMPTR " 661b\n"/* label */ \ + " " ALT_ASMPTR " 663f\n" /* new instruction */ \ + " .byte %c0\n" /* feature bit */ \ + " .byte 662b-661b\n" /* sourcelen */ \ + " .byte 664f-663f\n" /* replacementlen */ \ + ".previous\n" \ + ".section .altinstr_replacement,\"ax\"\n" \ + "663:\n\t" newinstr "\n664:\n" /* replacement */ \ + ".previous" :: "i" (feature) : "memory") + +/* +* Alternative inline assembly with input. +* +* Pecularities: +* No memory clobber here. +* Argument numbers start with 1. +* Best is to use constraints that are fixed size (like (%1) ... "r") +* If you use variable sized constraints like "m" or "g" in the +* replacement make sure to pad to the worst case length. +*/ +#define alternative_input(oldinstr, newinstr, feature, input...) \ + asm volatile ("661:\n\t" oldinstr "\n662:\n" \ + ".section .altinstructions,\"a\"\n" \ + " .align " ALT_ALIGN " \n" \ + " " ALT_ASMPTR " 661b\n"/* label */ \ + " " ALT_ASMPTR " 663f\n" /* new instruction */ \ + " .byte %c0\n" /* feature bit */ \ + " .byte 662b-661b\n" /* sourcelen */ \ + " .byte 664f-663f\n" /* replacementlen */ \ + ".previous\n" \ + ".section .altinstr_replacement,\"ax\"\n" \ + "663:\n\t" newinstr "\n664:\n" /* replacement */ \ + ".previous" :: "i" (feature), ##input) + +/* Like alternative_input, but with a single output argument */ +#define alternative_io(oldinstr, newinstr, feature, output, input...) \ + asm volatile ("661:\n\t" oldinstr "\n662:\n" \ + ".section .altinstructions,\"a\"\n" \ + " .align " ALT_ALIGN " \n" \ + " " ALT_ASMPTR " 661b\n"/* label */ \ +" " ALT_ASMPTR " 663f\n" /* new instruction */ \ +" .byte %c[feat]\n" /* feature bit */ \ +" .byte 662b-661b\n" /* sourcelen */ \ +" .byte 664f-663f\n" /* replacementlen */ \ +".previous\n" \ +".section .altinstr_replacement,\"ax\"\n" \ +"663:\n\t" newinstr"\n664:\n" /* replacement */ \ + ".previous" : output : [feat] "i" (feature), ##input) + +/* +* use this macro(s) if you need more than one output parameter +* in alternative_io +*/ +#define ASM_OUTPUT2 (a, b) a, b + +struct paravirt_patch_site ; +#ifdef CONFIG_PARAVIRT +void apply_paravirt (struct paravirt_patch_site *start,struct paravirt_patch_site *end); +#else +static inline void +apply_paravirt (struct paravirt_patch_site *start,struct paravirt_patch_site *end) +{} +#define __parainstructions NULL +#define __parainstructions_end NULL +#endif + +extern void text_poke (void *addr,unsigned char *opcode,int len); + +#endif /* _X86_ALTERNATIVE_H */
include/asm-x86/alternative_32.h deleted +0 -154
154 lines not on this page · raw message
include/asm-x86/alternative_64.h deleted +0 -159
159 lines not on this page · raw message
Signature · 1 line
1.5.3.7
Quoted 24 lines · Kyle McMartin
Straightforward merge. Kind of a pity that gas doesn't really have the concept of a "long" (long is 4-bytes for some reason.) Nor is it able to pad to a non-power of two boundary (for struct alignment) to get rid of the struct
alt_instrpadding.Build tested on i386, i386 with lguest & xen paravirt enabled, and
x86_64. Boot tested onx86_64.include/asm-x86/alternative.h +8
-2@@ -1,5 +1,168 @@ -#ifdef CONFIG_X86_32 -# include "alternative_32.h" +#ifndef _X86_ALTERNATIVE_H +#define _X86_ALTERNATIVE_H + +#ifdef __KERNEL__ + +#include <linux/types.h> +#include <linux/stddef.h> +
include/asm-x86/alternative.h line 17
Quoted 10 lines
include/asm-x86/alternative.h +7
-1+#ifdef CONFIG_X86_64 +# define ALT_ASMPTR ".quad" +# define ALT_ALIGN "8" +# define ALT_INSTR_PAD 5#else -# include "alternative_64.h" +# define ALT_ASMPTR ".long" +# define ALT_ALIGN "4" +# define ALT_INSTR_PAD 1#endif
Please use existing macros from <asm/asm.h> (in the x86 tree.)
-hpa
Quoted 1 line · H. Peter Anvin
Meh. Waste of my time, you've already done it, but the patch wasn't on linux-kernel, so I didn't notice.
--Kyle