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 |
