aboutsummaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/x86_64/kernel/setup.c12
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);
}
}
}