Messages in this thread Patch in this message | | | Date | Tue, 15 Nov 2005 17:01:13 +0100 | From | Gerd Knorr <> | Subject | Re: [PATCH 1/10] Cr4 is valid on some 486s |
| |
> Yep, extending alternatives is probably better than duplicating the > code. Maybe having some alternative_smp() macro which places both code > versions into the .altinstr_replacement table? If that sounds ok I'll > try to come up with a experimental patch.
i.e. something like this (as basic idea, patch is far away from doing anything useful ...)?
Gerd diff -pu -urp linux-2.6.14/arch/i386/kernel/setup.c work-2.6.14/arch/i386/kernel/setup.c --- linux-2.6.14/arch/i386/kernel/setup.c 2005-10-28 02:02:08.000000000 +0200 +++ work-2.6.14/arch/i386/kernel/setup.c 2005-11-15 16:49:13.000000000 +0100 @@ -1435,9 +1435,9 @@ void apply_alternatives(void *start, voi } } for (a = start; (void *)a < end; a++) { + BUG_ON(a->replacementlen > a->instrlen); if (!boot_cpu_has(a->cpuid)) continue; - BUG_ON(a->replacementlen > a->instrlen); memcpy(a->instr, a->replacement, a->replacementlen); diff = a->instrlen - a->replacementlen; /* Pad the rest with nops */ @@ -1450,6 +1450,19 @@ void apply_alternatives(void *start, voi } } +void apply_alternatives_smp(void *start, void *end) +{ + struct alt_instr *a; + + for (a = start; (void *)a < end; a++) { + if (X86_FEATURE_UP != a->cpuid) + continue; + memcpy(a->instr, + a->replacement + a->replacementlen, + a->instrlen); + } +} + void __init alternative_instructions(void) { extern struct alt_instr __alt_instructions[], __alt_instructions_end[]; diff -pu -urp linux-2.6.14/include/asm-i386/cpufeature.h work-2.6.14/include/asm-i386/cpufeature.h --- linux-2.6.14/include/asm-i386/cpufeature.h 2005-10-28 02:02:08.000000000 +0200 +++ work-2.6.14/include/asm-i386/cpufeature.h 2005-11-15 15:52:03.000000000 +0100 @@ -70,6 +70,8 @@ #define X86_FEATURE_P3 (3*32+ 6) /* P3 */ #define X86_FEATURE_P4 (3*32+ 7) /* P4 */ +#define X86_FEATURE_UP (3*32+ 8) /* smp kernel running on up */ + /* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */ #define X86_FEATURE_XMM3 (4*32+ 0) /* Streaming SIMD Extensions-3 */ #define X86_FEATURE_MWAIT (4*32+ 3) /* Monitor/Mwait support */ diff -pu -urp linux-2.6.14/include/asm-i386/system.h work-2.6.14/include/asm-i386/system.h --- linux-2.6.14/include/asm-i386/system.h 2005-10-28 02:02:08.000000000 +0200 +++ work-2.6.14/include/asm-i386/system.h 2005-11-15 15:47:43.000000000 +0100 @@ -329,6 +329,25 @@ struct alt_instr { "663:\n\t" newinstr "\n664:\n" /* replacement */ \ ".previous" :: "i" (feature) : "memory") +#ifdef CONFIG_SMP +#define alternative_smp(smpinstr, upinstr, input) \ + asm volatile ("661:\n\t" smpinstr "\n662:\n" \ + ".section .altinstructions,\"a\"\n" \ + " .align 4\n" \ + " .long 661b\n" /* label */ \ + " .long 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" upinstr "\n" /* replacement */ \ + "664:\n\t" smpinstr "\n" /* original again */ \ + ".previous" :: "i" (X86_FEATURE_UP), ##input) +#else +#define alternative_smp(smpinstr, upinstr) asm(upinstr, ##input) +#endif + /* * Alternative inline assembly with input. * | |