aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86_64/kernel
diff options
context:
space:
mode:
authorAndi Kleen <ak@suse.de>2006-01-11 16:45:21 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-11 22:04:58 -0500
commit7f6c5b046978d68e69bdc73433ead41612a2a1c9 (patch)
tree60f74adc6166496fbd84143272ad3b88254f9b72 /arch/x86_64/kernel
parent6e54d95f73bbc79171802a1983e0c3835676db88 (diff)
[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: Andi Kleen <ak@suse.de> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/x86_64/kernel')
-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] = {
478 k8nops + 1 + 2 + 3 + 4 + 5 + 6 + 7, 478 k8nops + 1 + 2 + 3 + 4 + 5 + 6 + 7,
479}; 479};
480 480
481extern char __vsyscall_0;
482
481/* Replace instructions with better alternatives for this CPU type. 483/* Replace instructions with better alternatives for this CPU type.
482 484
483 This runs before SMP is initialized to avoid SMP problems with 485 This runs before SMP is initialized to avoid SMP problems with
@@ -489,11 +491,17 @@ void apply_alternatives(void *start, void *end)
489 struct alt_instr *a; 491 struct alt_instr *a;
490 int diff, i, k; 492 int diff, i, k;
491 for (a = start; (void *)a < end; a++) { 493 for (a = start; (void *)a < end; a++) {
494 u8 *instr;
495
492 if (!boot_cpu_has(a->cpuid)) 496 if (!boot_cpu_has(a->cpuid))
493 continue; 497 continue;
494 498
495 BUG_ON(a->replacementlen > a->instrlen); 499 BUG_ON(a->replacementlen > a->instrlen);
496 __inline_memcpy(a->instr, a->replacement, a->replacementlen); 500 instr = a->instr;
501 /* vsyscall code is not mapped yet. resolve it manually. */
502 if (instr >= (u8 *)VSYSCALL_START && instr < (u8*)VSYSCALL_END)
503 instr = __va(instr - (u8*)VSYSCALL_START + (u8*)__pa_symbol(&__vsyscall_0));
504 __inline_memcpy(instr, a->replacement, a->replacementlen);
497 diff = a->instrlen - a->replacementlen; 505 diff = a->instrlen - a->replacementlen;
498 506
499 /* Pad the rest with nops */ 507 /* Pad the rest with nops */
@@ -501,7 +509,7 @@ void apply_alternatives(void *start, void *end)
501 k = diff; 509 k = diff;
502 if (k > ASM_NOP_MAX) 510 if (k > ASM_NOP_MAX)
503 k = ASM_NOP_MAX; 511 k = ASM_NOP_MAX;
504 __inline_memcpy(a->instr + i, k8_nops[k], k); 512 __inline_memcpy(instr + i, k8_nops[k], k);
505 } 513 }
506 } 514 }
507} 515}