diff options
Diffstat (limited to 'arch/x86_64/kernel/setup.c')
-rw-r--r-- | arch/x86_64/kernel/setup.c | 12 |
1 files changed, 10 insertions, 2 deletions
diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c index e7a4d2cd3968..8090a0a46882 100644 --- a/arch/x86_64/kernel/setup.c +++ b/arch/x86_64/kernel/setup.c @@ -478,6 +478,8 @@ static unsigned char *k8_nops[ASM_NOP_MAX+1] = { k8nops + 1 + 2 + 3 + 4 + 5 + 6 + 7, }; +extern char __vsyscall_0; + /* Replace instructions with better alternatives for this CPU type. This runs before SMP is initialized to avoid SMP problems with @@ -489,11 +491,17 @@ void apply_alternatives(void *start, void *end) struct alt_instr *a; int diff, i, k; for (a = start; (void *)a < end; a++) { + u8 *instr; + if (!boot_cpu_has(a->cpuid)) continue; BUG_ON(a->replacementlen > a->instrlen); - __inline_memcpy(a->instr, a->replacement, a->replacementlen); + instr = a->instr; + /* vsyscall code is not mapped yet. resolve it manually. */ + if (instr >= (u8 *)VSYSCALL_START && instr < (u8*)VSYSCALL_END) + instr = __va(instr - (u8*)VSYSCALL_START + (u8*)__pa_symbol(&__vsyscall_0)); + __inline_memcpy(instr, a->replacement, a->replacementlen); diff = a->instrlen - a->replacementlen; /* Pad the rest with nops */ @@ -501,7 +509,7 @@ void apply_alternatives(void *start, void *end) k = diff; if (k > ASM_NOP_MAX) k = ASM_NOP_MAX; - __inline_memcpy(a->instr + i, k8_nops[k], k); + __inline_memcpy(instr + i, k8_nops[k], k); } } } |