Skip to content
Snippets Groups Projects
Commit 7f6c5b04 authored by Andi Kleen's avatar Andi Kleen Committed by Linus Torvalds
Browse files

[PATCH] x86_64: Support alternative() in vsyscalls


The real vsyscall .text addresses are not mapped when the alternative()
replacement runs early, so use some black magic to access them using
the direct mapping.

Signed-off-by: default avatarAndi Kleen <ak@suse.de>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 6e54d95f
No related branches found
No related tags found
No related merge requests found
...@@ -478,6 +478,8 @@ static unsigned char *k8_nops[ASM_NOP_MAX+1] = { ...@@ -478,6 +478,8 @@ static unsigned char *k8_nops[ASM_NOP_MAX+1] = {
k8nops + 1 + 2 + 3 + 4 + 5 + 6 + 7, k8nops + 1 + 2 + 3 + 4 + 5 + 6 + 7,
}; };
extern char __vsyscall_0;
/* Replace instructions with better alternatives for this CPU type. /* Replace instructions with better alternatives for this CPU type.
This runs before SMP is initialized to avoid SMP problems with This runs before SMP is initialized to avoid SMP problems with
...@@ -489,11 +491,17 @@ void apply_alternatives(void *start, void *end) ...@@ -489,11 +491,17 @@ void apply_alternatives(void *start, void *end)
struct alt_instr *a; struct alt_instr *a;
int diff, i, k; int diff, i, k;
for (a = start; (void *)a < end; a++) { for (a = start; (void *)a < end; a++) {
u8 *instr;
if (!boot_cpu_has(a->cpuid)) if (!boot_cpu_has(a->cpuid))
continue; continue;
BUG_ON(a->replacementlen > a->instrlen); 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; diff = a->instrlen - a->replacementlen;
/* Pad the rest with nops */ /* Pad the rest with nops */
...@@ -501,7 +509,7 @@ void apply_alternatives(void *start, void *end) ...@@ -501,7 +509,7 @@ void apply_alternatives(void *start, void *end)
k = diff; k = diff;
if (k > ASM_NOP_MAX) if (k > ASM_NOP_MAX)
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);
} }
} }
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment