Andi Kleen
2007-Apr-18 13:02 UTC
[patch 4/6] Rename the parainstructions symbols to be consistent with the others
On Wednesday 04 April 2007 03:06:59 Jeremy Fitzhardinge wrote:> The other symbols used to delineate the alt-instructions sections have > the form __foo/__foo_end. Rename parainstructions to match.This patch breaks x86-64 -Andi>
Jeremy Fitzhardinge
2007-Apr-18 17:50 UTC
[patch 1/6] Re-enable VDSO by default with PARAVIRT
Everyone wants VDSO to be enabled by default. COMPAT_VDSO still needs a fix, but with luck that will turn up soon. Signed-off-by: Jeremy Fitzhardinge <jeremy@xensource.com> --- arch/i386/kernel/sysenter.c | 4 ---- 1 file changed, 4 deletions(-) ==================================================================--- a/arch/i386/kernel/sysenter.c +++ b/arch/i386/kernel/sysenter.c @@ -27,11 +27,7 @@ * Should the kernel map a VDSO page into processes and pass its * address down to glibc upon exec()? */ -#ifdef CONFIG_PARAVIRT -unsigned int __read_mostly vdso_enabled = 0; -#else unsigned int __read_mostly vdso_enabled = 1; -#endif EXPORT_SYMBOL_GPL(vdso_enabled); --
Jeremy Fitzhardinge
2007-Apr-18 17:50 UTC
[patch 6/6] Allow boot-time disable of paravirt_ops patching
Add "noreplace-paravirt" to disable paravirt_ops patching. Signed-off-by: Jeremy Fitzhardinge <jeremy@xensource.com> Cc: Rusty Russell <rusty@rustcorp.com.au> --- Documentation/kernel-parameters.txt | 3 +++ arch/i386/kernel/alternative.c | 13 +++++++++++++ 2 files changed, 16 insertions(+) ==================================================================--- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -64,6 +64,7 @@ parameter is applicable: GENERIC_TIME The generic timeofday code is enabled. NFS Appropriate NFS support is enabled. OSS OSS sound support is enabled. + PV_OPS A paravirtualized kernel PARIDE The ParIDE subsystem is enabled. PARISC The PA-RISC architecture is enabled. PCI PCI bus support is enabled. @@ -1134,6 +1135,8 @@ and is between 256 and 4096 characters. nomca [IA-64] Disable machine check abort handling nomce [IA-32] Machine Check Exception + + noreplace-paravirt [IA-32,PV_OPS] Don't patch paravirt_ops noreplace-smp [IA-32,SMP] Don't replace SMP instructions with UP alternatives ==================================================================--- a/arch/i386/kernel/alternative.c +++ b/arch/i386/kernel/alternative.c @@ -30,6 +30,16 @@ static int __init setup_noreplace_smp(ch } __setup("noreplace-smp", setup_noreplace_smp); +#ifdef CONFIG_PARAVIRT +static int noreplace_paravirt = 0; + +static int __init setup_noreplace_paravirt(char *str) +{ + noreplace_paravirt = 1; + return 1; +} +__setup("noreplace-paravirt", setup_noreplace_paravirt); +#endif #define DPRINTK(fmt, args...) if (debug_alternative) \ printk(KERN_DEBUG fmt, args) @@ -329,6 +339,9 @@ void apply_paravirt(struct paravirt_patc { struct paravirt_patch *p; + if (noreplace_paravirt) + return; + for (p = start; p < end; p++) { unsigned int used; --
Jeremy Fitzhardinge
2007-Apr-18 17:50 UTC
[patch 4/6] Rename the parainstructions symbols to be consistent with the others
The other symbols used to delineate the alt-instructions sections have the form __foo/__foo_end. Rename parainstructions to match. Signed-off-by: Jeremy Fitzhardinge <jeremy@xensource.com> Cc: Andi Kleen <ak@suse.de> Cc: Rusty Russell <rusty@rustcorp.com.au> --- arch/i386/kernel/alternative.c | 6 +++--- arch/i386/kernel/vmi.c | 6 +++--- arch/i386/kernel/vmlinux.lds.S | 4 ++-- include/asm-i386/alternative.h | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) ==================================================================--- a/arch/i386/kernel/alternative.c +++ b/arch/i386/kernel/alternative.c @@ -327,8 +327,8 @@ void apply_paravirt(struct paravirt_patc /* Sync to be conservative, in case we patched following instructions */ sync_core(); } -extern struct paravirt_patch __start_parainstructions[], - __stop_parainstructions[]; +extern struct paravirt_patch __parainstructions[], + __parainstructions_end[]; #endif /* CONFIG_PARAVIRT */ void __init alternative_instructions(void) @@ -367,6 +367,6 @@ void __init alternative_instructions(voi alternatives_smp_switch(0); } #endif - apply_paravirt(__start_parainstructions, __stop_parainstructions); + apply_paravirt(__parainstructions, __parainstructions_end); local_irq_restore(flags); } ==================================================================--- a/arch/i386/kernel/vmi.c +++ b/arch/i386/kernel/vmi.c @@ -72,8 +72,8 @@ static struct { } vmi_ops; /* XXX move this to alternative.h */ -extern struct paravirt_patch __start_parainstructions[], - __stop_parainstructions[]; +extern struct paravirt_patch __parainstructions[], + __parainstructions_end[]; /* * VMI patching routines. @@ -917,7 +917,7 @@ static inline int __init activate_vmi(vo * to do this before IRQs get reenabled. Fortunately, it is * idempotent. */ - apply_paravirt(__start_parainstructions, __stop_parainstructions); + apply_paravirt(__parainstructions, __parainstructions_end); vmi_bringup(); ==================================================================--- a/arch/i386/kernel/vmlinux.lds.S +++ b/arch/i386/kernel/vmlinux.lds.S @@ -166,9 +166,9 @@ SECTIONS } . = ALIGN(4); .parainstructions : AT(ADDR(.parainstructions) - LOAD_OFFSET) { - __start_parainstructions = .; + __parainstructions = .; *(.parainstructions) - __stop_parainstructions = .; + __parainstructions_end = .; } /* .exit.text is discard at runtime, not link time, to deal with references from .altinstructions and .eh_frame */ ==================================================================--- a/include/asm-i386/alternative.h +++ b/include/asm-i386/alternative.h @@ -121,8 +121,8 @@ static inline void static inline void apply_paravirt(struct paravirt_patch *start, struct paravirt_patch *end) {} -#define __start_parainstructions NULL -#define __stop_parainstructions NULL +#define __parainstructions NULL +#define __parainstructions_end NULL #endif #endif /* _I386_ALTERNATIVE_H */ --
The .smp_altinstructions section and its corresponding symbols are completely unused, so remove them. Also, remove stray #ifdef __KENREL__ in asm-i386/alternative.h Signed-off-by: Jeremy Fitzhardinge <jeremy@xensource.com> Cc: Andi Kleen <ak@suse.de> --- arch/i386/kernel/alternative.c | 38 ++------------------------------------ arch/i386/kernel/vmlinux.lds.S | 11 ----------- include/asm-i386/alternative.h | 6 +----- 3 files changed, 3 insertions(+), 52 deletions(-) ==================================================================--- a/arch/i386/kernel/alternative.c +++ b/arch/i386/kernel/alternative.c @@ -132,10 +132,7 @@ static void nop_out(void *insns, unsigne } extern struct alt_instr __alt_instructions[], __alt_instructions_end[]; -extern struct alt_instr __smp_alt_instructions[], __smp_alt_instructions_end[]; extern u8 *__smp_locks[], *__smp_locks_end[]; - -extern u8 __smp_alt_begin[], __smp_alt_end[]; /* Replace instructions with better alternatives for this CPU type. This runs before SMP is initialized to avoid SMP problems with @@ -170,29 +167,6 @@ void apply_alternatives(struct alt_instr } #ifdef CONFIG_SMP - -static void alternatives_smp_save(struct alt_instr *start, struct alt_instr *end) -{ - struct alt_instr *a; - - DPRINTK("%s: alt table %p-%p\n", __FUNCTION__, start, end); - for (a = start; a < end; a++) { - memcpy(a->replacement + a->replacementlen, - a->instr, - a->instrlen); - } -} - -static void alternatives_smp_apply(struct alt_instr *start, struct alt_instr *end) -{ - struct alt_instr *a; - - for (a = start; a < end; a++) { - memcpy(a->instr, - a->replacement + a->replacementlen, - a->instrlen); - } -} static void alternatives_smp_lock(u8 **start, u8 **end, u8 *text, u8 *text_end) { @@ -319,8 +293,6 @@ void alternatives_smp_switch(int smp) printk(KERN_INFO "SMP alternatives: switching to SMP code\n"); clear_bit(X86_FEATURE_UP, boot_cpu_data.x86_capability); clear_bit(X86_FEATURE_UP, cpu_data[0].x86_capability); - alternatives_smp_apply(__smp_alt_instructions, - __smp_alt_instructions_end); list_for_each_entry(mod, &smp_alt_modules, next) alternatives_smp_lock(mod->locks, mod->locks_end, mod->text, mod->text_end); @@ -328,8 +300,6 @@ void alternatives_smp_switch(int smp) printk(KERN_INFO "SMP alternatives: switching to UP code\n"); set_bit(X86_FEATURE_UP, boot_cpu_data.x86_capability); set_bit(X86_FEATURE_UP, cpu_data[0].x86_capability); - apply_alternatives(__smp_alt_instructions, - __smp_alt_instructions_end); list_for_each_entry(mod, &smp_alt_modules, next) alternatives_smp_unlock(mod->locks, mod->locks_end, mod->text, mod->text_end); @@ -384,17 +354,13 @@ void __init alternative_instructions(voi printk(KERN_INFO "SMP alternatives: switching to UP code\n"); set_bit(X86_FEATURE_UP, boot_cpu_data.x86_capability); set_bit(X86_FEATURE_UP, cpu_data[0].x86_capability); - apply_alternatives(__smp_alt_instructions, - __smp_alt_instructions_end); alternatives_smp_unlock(__smp_locks, __smp_locks_end, _text, _etext); } free_init_pages("SMP alternatives", - __pa_symbol(&__smp_alt_begin), - __pa_symbol(&__smp_alt_end)); + __pa_symbol(&__smp_locks), + __pa_symbol(&__smp_locks_end)); } else { - alternatives_smp_save(__smp_alt_instructions, - __smp_alt_instructions_end); alternatives_smp_module_add(NULL, "core kernel", __smp_locks, __smp_locks_end, _text, _etext); ==================================================================--- a/arch/i386/kernel/vmlinux.lds.S +++ b/arch/i386/kernel/vmlinux.lds.S @@ -116,21 +116,10 @@ SECTIONS /* might get freed after init */ . = ALIGN(4096); - .smp_altinstructions : AT(ADDR(.smp_altinstructions) - LOAD_OFFSET) { - __smp_alt_begin = .; - __smp_alt_instructions = .; - *(.smp_altinstructions) - __smp_alt_instructions_end = .; - } - . = ALIGN(4); .smp_locks : AT(ADDR(.smp_locks) - LOAD_OFFSET) { __smp_locks = .; *(.smp_locks) __smp_locks_end = .; - } - .smp_altinstr_replacement : AT(ADDR(.smp_altinstr_replacement) - LOAD_OFFSET) { - *(.smp_altinstr_replacement) - __smp_alt_end = .; } /* will be freed after init * Following ALIGN() is required to make sure no other data falls on the ==================================================================--- a/include/asm-i386/alternative.h +++ b/include/asm-i386/alternative.h @@ -1,7 +1,5 @@ #ifndef _I386_ALTERNATIVE_H #define _I386_ALTERNATIVE_H - -#ifdef __KERNEL__ #include <asm/types.h> #include <linux/stddef.h> @@ -31,9 +29,7 @@ static inline void alternatives_smp_modu 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 +#endif /* CONFIG_SMP */ /* * Alternative instructions for different CPU types or capabilities. --
Hi Andi, Here's a little batch of cleanups: - re-enable VDSO when PARAVIRT is enabled - make the parainstructions symbols match the other altinstructions naming convention - add kernel command-line options to disable altinstructions for smp and pv_ops Oh, and I'm mailing your noreplacement patch back at you, for no particularly good reason. J --
Jeremy Fitzhardinge
2007-Apr-18 17:50 UTC
[patch 5/6] Allow boot-time disable of SMP altinstructions
Add "noreplace-smp" to disable SMP instruction replacement. Signed-off-by: Jeremy Fitzhardinge <jeremy@xensource.com> --- Documentation/kernel-parameters.txt | 6 ++++++ arch/i386/kernel/alternative.c | 23 +++++++++++++++++++---- 2 files changed, 25 insertions(+), 4 deletions(-) ==================================================================--- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -1134,6 +1134,9 @@ and is between 256 and 4096 characters. nomca [IA-64] Disable machine check abort handling nomce [IA-32] Machine Check Exception + + noreplace-smp [IA-32,SMP] Don't replace SMP instructions + with UP alternatives noresidual [PPC] Don't use residual data on PReP machines. @@ -1540,6 +1543,9 @@ and is between 256 and 4096 characters. smart2= [HW] Format: <io1>[,<io2>[,...,<io8>]] + smp-alt-once [IA-32,SMP] On a hotplug CPU system, only + attempt to substitute SMP alternatives once at boot. + snd-ad1816a= [HW,ALSA] snd-ad1848= [HW,ALSA] ==================================================================--- a/arch/i386/kernel/alternative.c +++ b/arch/i386/kernel/alternative.c @@ -5,6 +5,7 @@ #include <asm/alternative.h> #include <asm/sections.h> +static int noreplace_smp = 0; static int smp_alt_once = 0; static int debug_alternative = 0; @@ -13,14 +14,22 @@ static int __init bootonly(char *str) smp_alt_once = 1; return 1; } +__setup("smp-alt-boot", bootonly); + static int __init debug_alt(char *str) { debug_alternative = 1; return 1; } - -__setup("smp-alt-boot", bootonly); __setup("debug-alternative", debug_alt); + +static int __init setup_noreplace_smp(char *str) +{ + noreplace_smp = 1; + return 1; +} +__setup("noreplace-smp", setup_noreplace_smp); + #define DPRINTK(fmt, args...) if (debug_alternative) \ printk(KERN_DEBUG fmt, args) @@ -185,6 +194,9 @@ static void alternatives_smp_unlock(u8 * { u8 **ptr; + if (noreplace_smp) + return; + for (ptr = start; ptr < end; ptr++) { if (*ptr < text) continue; @@ -218,6 +230,9 @@ void alternatives_smp_module_add(struct { struct smp_alt_module *smp; unsigned long flags; + + if (noreplace_smp) + return; if (smp_alt_once) { if (boot_cpu_has(X86_FEATURE_UP)) @@ -253,7 +268,7 @@ void alternatives_smp_module_del(struct struct smp_alt_module *item; unsigned long flags; - if (smp_alt_once) + if (smp_alt_once || noreplace_smp) return; spin_lock_irqsave(&smp_alt, flags); @@ -284,7 +299,7 @@ void alternatives_smp_switch(int smp) return; #endif - if (smp_alt_once) + if (noreplace_smp || smp_alt_once) return; BUG_ON(!smp && (num_online_cpus() > 1)); --
noreplacement is dangerous on modern systems because it will not replace the context switch FNSAVE with SSE aware FXSAVE. But other places in the kernel still assume SSE and do FXSAVE and the CPU will then access FXSAVE information with FNSAVE and cause corruption. Easiest way to avoid this is to remove the option. It was mostly for paranoia reasons anyways and alternative()s have been stable for some time. Thanks to Jeremy F. for reporting and helping debug it. Signed-off-by: Andi Kleen <ak@suse.de> --- Documentation/x86_64/boot-options.txt | 4 ---- arch/i386/kernel/alternative.c | 21 ++------------------- 2 files changed, 2 insertions(+), 23 deletions(-) ==================================================================--- a/Documentation/x86_64/boot-options.txt +++ b/Documentation/x86_64/boot-options.txt @@ -305,7 +305,3 @@ Debugging stuck (default) Miscellaneous - - noreplacement Don't replace instructions with more appropriate ones - for the CPU. This may be useful on asymmetric MP systems - where some CPUs have less capabilities than others. ==================================================================--- a/arch/i386/kernel/alternative.c +++ b/arch/i386/kernel/alternative.c @@ -5,15 +5,9 @@ #include <asm/alternative.h> #include <asm/sections.h> -static int no_replacement = 0; static int smp_alt_once = 0; static int debug_alternative = 0; -static int __init noreplacement_setup(char *s) -{ - no_replacement = 1; - return 1; -} static int __init bootonly(char *str) { smp_alt_once = 1; @@ -25,7 +19,6 @@ static int __init debug_alt(char *str) return 1; } -__setup("noreplacement", noreplacement_setup); __setup("smp-alt-boot", bootonly); __setup("debug-alternative", debug_alt); @@ -252,9 +245,6 @@ void alternatives_smp_module_add(struct struct smp_alt_module *smp; unsigned long flags; - if (no_replacement) - return; - if (smp_alt_once) { if (boot_cpu_has(X86_FEATURE_UP)) alternatives_smp_unlock(locks, locks_end, @@ -289,7 +279,7 @@ void alternatives_smp_module_del(struct struct smp_alt_module *item; unsigned long flags; - if (no_replacement || smp_alt_once) + if (smp_alt_once) return; spin_lock_irqsave(&smp_alt, flags); @@ -320,7 +310,7 @@ void alternatives_smp_switch(int smp) return; #endif - if (no_replacement || smp_alt_once) + if (smp_alt_once) return; BUG_ON(!smp && (num_online_cpus() > 1)); @@ -374,13 +364,6 @@ void __init alternative_instructions(voi void __init alternative_instructions(void) { unsigned long flags; - if (no_replacement) { - printk(KERN_INFO "(SMP-)alternatives turned off\n"); - free_init_pages("SMP alternatives", - __pa_symbol(&__smp_alt_begin), - __pa_symbol(&__smp_alt_end)); - return; - } local_irq_save(flags); apply_alternatives(__alt_instructions, __alt_instructions_end); --