From 50c3e4d7e687efc572d1c418f9ca4c7e0e5447d2 Mon Sep 17 00:00:00 2001 From: Dave Kleikamp Date: Fri, 9 Sep 2016 11:56:55 -0500 Subject: [PATCH] kexec: align crash_notes allocation to make it be inside one physical page Port of mainline commit bbb78b8f3 Orabug: 25071982 Signed-off-by: Baoquan He Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Dave Kleikamp (cherry picked from commit 45cbd27626d17d485ca0718b28add12513690921) Signed-off-by: Allen Pais --- kernel/kexec.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/kernel/kexec.c b/kernel/kexec.c index 7a36fdcca5bf..b4ac99c58ef4 100644 --- a/kernel/kexec.c +++ b/kernel/kexec.c @@ -1609,7 +1609,28 @@ void crash_save_cpu(struct pt_regs *regs, int cpu) static int __init crash_notes_memory_init(void) { /* Allocate memory for saving cpu registers. */ - crash_notes = alloc_percpu(note_buf_t); + size_t size, align; + + /* + * crash_notes could be allocated across 2 vmalloc pages when percpu + * is vmalloc based . vmalloc doesn't guarantee 2 continuous vmalloc + * pages are also on 2 continuous physical pages. In this case the + * 2nd part of crash_notes in 2nd page could be lost since only the + * starting address and size of crash_notes are exported through sysfs. + * Here round up the size of crash_notes to the nearest power of two + * and pass it to __alloc_percpu as align value. This can make sure + * crash_notes is allocated inside one physical page. + */ + size = sizeof(note_buf_t); + align = min(roundup_pow_of_two(sizeof(note_buf_t)), PAGE_SIZE); + + /* + * Break compile if size is bigger than PAGE_SIZE since crash_notes + * definitely will be in 2 pages with that. + */ + BUILD_BUG_ON(size > PAGE_SIZE); + + crash_notes = __alloc_percpu(size, align); if (!crash_notes) { pr_warn("Kexec: Memory allocation for saving cpu register states failed\n"); return -ENOMEM; -- 2.50.1