diff options
Diffstat (limited to 'arch/x86/kernel/alternative.c')
-rw-r--r-- | arch/x86/kernel/alternative.c | 23 |
1 files changed, 14 insertions, 9 deletions
diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c index a84ac7b570e6..4c80f1557433 100644 --- a/arch/x86/kernel/alternative.c +++ b/arch/x86/kernel/alternative.c | |||
@@ -414,9 +414,17 @@ void __init alternative_instructions(void) | |||
414 | that might execute the to be patched code. | 414 | that might execute the to be patched code. |
415 | Other CPUs are not running. */ | 415 | Other CPUs are not running. */ |
416 | stop_nmi(); | 416 | stop_nmi(); |
417 | #ifdef CONFIG_X86_MCE | 417 | |
418 | stop_mce(); | 418 | /* |
419 | #endif | 419 | * Don't stop machine check exceptions while patching. |
420 | * MCEs only happen when something got corrupted and in this | ||
421 | * case we must do something about the corruption. | ||
422 | * Ignoring it is worse than a unlikely patching race. | ||
423 | * Also machine checks tend to be broadcast and if one CPU | ||
424 | * goes into machine check the others follow quickly, so we don't | ||
425 | * expect a machine check to cause undue problems during to code | ||
426 | * patching. | ||
427 | */ | ||
420 | 428 | ||
421 | apply_alternatives(__alt_instructions, __alt_instructions_end); | 429 | apply_alternatives(__alt_instructions, __alt_instructions_end); |
422 | 430 | ||
@@ -456,9 +464,6 @@ void __init alternative_instructions(void) | |||
456 | (unsigned long)__smp_locks_end); | 464 | (unsigned long)__smp_locks_end); |
457 | 465 | ||
458 | restart_nmi(); | 466 | restart_nmi(); |
459 | #ifdef CONFIG_X86_MCE | ||
460 | restart_mce(); | ||
461 | #endif | ||
462 | } | 467 | } |
463 | 468 | ||
464 | /** | 469 | /** |
@@ -498,12 +503,12 @@ void *text_poke_early(void *addr, const void *opcode, size_t len) | |||
498 | */ | 503 | */ |
499 | void *__kprobes text_poke(void *addr, const void *opcode, size_t len) | 504 | void *__kprobes text_poke(void *addr, const void *opcode, size_t len) |
500 | { | 505 | { |
501 | unsigned long flags; | ||
502 | char *vaddr; | 506 | char *vaddr; |
503 | int nr_pages = 2; | 507 | int nr_pages = 2; |
504 | struct page *pages[2]; | 508 | struct page *pages[2]; |
505 | int i; | 509 | int i; |
506 | 510 | ||
511 | might_sleep(); | ||
507 | if (!core_kernel_text((unsigned long)addr)) { | 512 | if (!core_kernel_text((unsigned long)addr)) { |
508 | pages[0] = vmalloc_to_page(addr); | 513 | pages[0] = vmalloc_to_page(addr); |
509 | pages[1] = vmalloc_to_page(addr + PAGE_SIZE); | 514 | pages[1] = vmalloc_to_page(addr + PAGE_SIZE); |
@@ -517,9 +522,9 @@ void *__kprobes text_poke(void *addr, const void *opcode, size_t len) | |||
517 | nr_pages = 1; | 522 | nr_pages = 1; |
518 | vaddr = vmap(pages, nr_pages, VM_MAP, PAGE_KERNEL); | 523 | vaddr = vmap(pages, nr_pages, VM_MAP, PAGE_KERNEL); |
519 | BUG_ON(!vaddr); | 524 | BUG_ON(!vaddr); |
520 | local_irq_save(flags); | 525 | local_irq_disable(); |
521 | memcpy(&vaddr[(unsigned long)addr & ~PAGE_MASK], opcode, len); | 526 | memcpy(&vaddr[(unsigned long)addr & ~PAGE_MASK], opcode, len); |
522 | local_irq_restore(flags); | 527 | local_irq_enable(); |
523 | vunmap(vaddr); | 528 | vunmap(vaddr); |
524 | sync_core(); | 529 | sync_core(); |
525 | /* Could also do a CLFLUSH here to speed up CPU recovery; but | 530 | /* Could also do a CLFLUSH here to speed up CPU recovery; but |