Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

kexec: provide arch_kexec_protect(unprotect)_crashkres()

Implement the protection method for the crash kernel memory reservation
for the 64-bit x86 kdump.

Signed-off-by: Xunlei Pang <xlpang@redhat.com>
Cc: Eric Biederman <ebiederm@xmission.com>
Cc: Dave Young <dyoung@redhat.com>
Cc: Minfei Huang <mhuang@redhat.com>
Cc: Vivek Goyal <vgoyal@redhat.com>
Cc: Baoquan He <bhe@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Xunlei Pang and committed by
Linus Torvalds
1e5768ae 9b492cf5

+45
+45
arch/x86/kernel/machine_kexec_64.c
··· 538 538 return -ENOEXEC; 539 539 } 540 540 #endif /* CONFIG_KEXEC_FILE */ 541 + 542 + static int 543 + kexec_mark_range(unsigned long start, unsigned long end, bool protect) 544 + { 545 + struct page *page; 546 + unsigned int nr_pages; 547 + 548 + /* 549 + * For physical range: [start, end]. We must skip the unassigned 550 + * crashk resource with zero-valued "end" member. 551 + */ 552 + if (!end || start > end) 553 + return 0; 554 + 555 + page = pfn_to_page(start >> PAGE_SHIFT); 556 + nr_pages = (end >> PAGE_SHIFT) - (start >> PAGE_SHIFT) + 1; 557 + if (protect) 558 + return set_pages_ro(page, nr_pages); 559 + else 560 + return set_pages_rw(page, nr_pages); 561 + } 562 + 563 + static void kexec_mark_crashkres(bool protect) 564 + { 565 + unsigned long control; 566 + 567 + kexec_mark_range(crashk_low_res.start, crashk_low_res.end, protect); 568 + 569 + /* Don't touch the control code page used in crash_kexec().*/ 570 + control = PFN_PHYS(page_to_pfn(kexec_crash_image->control_code_page)); 571 + /* Control code page is located in the 2nd page. */ 572 + kexec_mark_range(crashk_res.start, control + PAGE_SIZE - 1, protect); 573 + control += KEXEC_CONTROL_PAGE_SIZE; 574 + kexec_mark_range(control, crashk_res.end, protect); 575 + } 576 + 577 + void arch_kexec_protect_crashkres(void) 578 + { 579 + kexec_mark_crashkres(true); 580 + } 581 + 582 + void arch_kexec_unprotect_crashkres(void) 583 + { 584 + kexec_mark_crashkres(false); 585 + }