diff options
Diffstat (limited to 'arch/x86/kernel/alternative.c')
-rw-r--r-- | arch/x86/kernel/alternative.c | 22 |
1 files changed, 21 insertions, 1 deletions
diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c index de7353c0ce9c..e6ea0342c8f8 100644 --- a/arch/x86/kernel/alternative.c +++ b/arch/x86/kernel/alternative.c | |||
@@ -205,7 +205,7 @@ void __init_or_module apply_alternatives(struct alt_instr *start, | |||
205 | struct alt_instr *end) | 205 | struct alt_instr *end) |
206 | { | 206 | { |
207 | struct alt_instr *a; | 207 | struct alt_instr *a; |
208 | char insnbuf[MAX_PATCH_LEN]; | 208 | u8 insnbuf[MAX_PATCH_LEN]; |
209 | 209 | ||
210 | DPRINTK("%s: alt table %p -> %p\n", __func__, start, end); | 210 | DPRINTK("%s: alt table %p -> %p\n", __func__, start, end); |
211 | for (a = start; a < end; a++) { | 211 | for (a = start; a < end; a++) { |
@@ -223,6 +223,8 @@ void __init_or_module apply_alternatives(struct alt_instr *start, | |||
223 | } | 223 | } |
224 | #endif | 224 | #endif |
225 | memcpy(insnbuf, a->replacement, a->replacementlen); | 225 | memcpy(insnbuf, a->replacement, a->replacementlen); |
226 | if (*insnbuf == 0xe8 && a->replacementlen == 5) | ||
227 | *(s32 *)(insnbuf + 1) += a->replacement - a->instr; | ||
226 | add_nops(insnbuf + a->replacementlen, | 228 | add_nops(insnbuf + a->replacementlen, |
227 | a->instrlen - a->replacementlen); | 229 | a->instrlen - a->replacementlen); |
228 | text_poke_early(instr, insnbuf, a->instrlen); | 230 | text_poke_early(instr, insnbuf, a->instrlen); |
@@ -390,6 +392,24 @@ void alternatives_smp_switch(int smp) | |||
390 | mutex_unlock(&smp_alt); | 392 | mutex_unlock(&smp_alt); |
391 | } | 393 | } |
392 | 394 | ||
395 | /* Return 1 if the address range is reserved for smp-alternatives */ | ||
396 | int alternatives_text_reserved(void *start, void *end) | ||
397 | { | ||
398 | struct smp_alt_module *mod; | ||
399 | u8 **ptr; | ||
400 | u8 *text_start = start; | ||
401 | u8 *text_end = end; | ||
402 | |||
403 | list_for_each_entry(mod, &smp_alt_modules, next) { | ||
404 | if (mod->text > text_end || mod->text_end < text_start) | ||
405 | continue; | ||
406 | for (ptr = mod->locks; ptr < mod->locks_end; ptr++) | ||
407 | if (text_start <= *ptr && text_end >= *ptr) | ||
408 | return 1; | ||
409 | } | ||
410 | |||
411 | return 0; | ||
412 | } | ||
393 | #endif | 413 | #endif |
394 | 414 | ||
395 | #ifdef CONFIG_PARAVIRT | 415 | #ifdef CONFIG_PARAVIRT |