aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2016-08-02 17:06:04 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-08-02 19:35:27 -0400
commit43546d8669d62d75fa69ca9a45d2f586665f56bd (patch)
tree3546ef2ae7ba4746671fef7bbfb8b1b3072c100a
parentdae28018f56645b61f5beb84d5831346d3c5e457 (diff)
kexec: allow architectures to override boot mapping
kexec physical addresses are the boot-time view of the system. For certain ARM systems (such as Keystone 2), the boot view of the system does not match the kernel's view of the system: the boot view uses a special alias in the lower 4GB of the physical address space. To cater for these kinds of setups, we need to translate between the boot view physical addresses and the normal kernel view physical addresses. This patch extracts the current transation points into linux/kexec.h, and allows an architecture to override the functions. Due to the translations required, we unfortunately end up with six translation functions, which are reduced down to four that the architecture can override. [akpm@linux-foundation.org: kexec.h needs asm/io.h for phys_to_virt()] Link: http://lkml.kernel.org/r/E1b8koP-0004HZ-Vf@rmk-PC.armlinux.org.uk Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> Cc: Keerthy <j-keerthy@ti.com> Cc: Pratyush Anand <panand@redhat.com> Cc: Vitaly Andrianov <vitalya@ti.com> Cc: Eric Biederman <ebiederm@xmission.com> Cc: Dave Young <dyoung@redhat.com> Cc: Baoquan He <bhe@redhat.com> Cc: Vivek Goyal <vgoyal@redhat.com> Cc: Simon Horman <horms@verge.net.au> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--include/linux/kexec.h40
-rw-r--r--kernel/kexec.c3
-rw-r--r--kernel/kexec_core.c26
3 files changed, 55 insertions, 14 deletions
diff --git a/include/linux/kexec.h b/include/linux/kexec.h
index 555227f0029f..23e14a460cfb 100644
--- a/include/linux/kexec.h
+++ b/include/linux/kexec.h
@@ -14,6 +14,8 @@
14 14
15#if !defined(__ASSEMBLY__) 15#if !defined(__ASSEMBLY__)
16 16
17#include <asm/io.h>
18
17#include <uapi/linux/kexec.h> 19#include <uapi/linux/kexec.h>
18 20
19#ifdef CONFIG_KEXEC_CORE 21#ifdef CONFIG_KEXEC_CORE
@@ -318,6 +320,44 @@ int __weak arch_kexec_apply_relocations(const Elf_Ehdr *ehdr, Elf_Shdr *sechdrs,
318void arch_kexec_protect_crashkres(void); 320void arch_kexec_protect_crashkres(void);
319void arch_kexec_unprotect_crashkres(void); 321void arch_kexec_unprotect_crashkres(void);
320 322
323#ifndef page_to_boot_pfn
324static inline unsigned long page_to_boot_pfn(struct page *page)
325{
326 return page_to_pfn(page);
327}
328#endif
329
330#ifndef boot_pfn_to_page
331static inline struct page *boot_pfn_to_page(unsigned long boot_pfn)
332{
333 return pfn_to_page(boot_pfn);
334}
335#endif
336
337#ifndef phys_to_boot_phys
338static inline unsigned long phys_to_boot_phys(phys_addr_t phys)
339{
340 return phys;
341}
342#endif
343
344#ifndef boot_phys_to_phys
345static inline phys_addr_t boot_phys_to_phys(unsigned long boot_phys)
346{
347 return boot_phys;
348}
349#endif
350
351static inline unsigned long virt_to_boot_phys(void *addr)
352{
353 return phys_to_boot_phys(__pa((unsigned long)addr));
354}
355
356static inline void *boot_phys_to_virt(unsigned long entry)
357{
358 return phys_to_virt(boot_phys_to_phys(entry));
359}
360
321#else /* !CONFIG_KEXEC_CORE */ 361#else /* !CONFIG_KEXEC_CORE */
322struct pt_regs; 362struct pt_regs;
323struct task_struct; 363struct task_struct;
diff --git a/kernel/kexec.c b/kernel/kexec.c
index 4384672d3245..980936a90ee6 100644
--- a/kernel/kexec.c
+++ b/kernel/kexec.c
@@ -48,7 +48,8 @@ static int kimage_alloc_init(struct kimage **rimage, unsigned long entry,
48 48
49 if (kexec_on_panic) { 49 if (kexec_on_panic) {
50 /* Verify we have a valid entry point */ 50 /* Verify we have a valid entry point */
51 if ((entry < crashk_res.start) || (entry > crashk_res.end)) 51 if ((entry < phys_to_boot_phys(crashk_res.start)) ||
52 (entry > phys_to_boot_phys(crashk_res.end)))
52 return -EADDRNOTAVAIL; 53 return -EADDRNOTAVAIL;
53 } 54 }
54 55
diff --git a/kernel/kexec_core.c b/kernel/kexec_core.c
index dab03f17be25..73d4c5f57dd8 100644
--- a/kernel/kexec_core.c
+++ b/kernel/kexec_core.c
@@ -225,8 +225,8 @@ int sanity_check_segment_list(struct kimage *image)
225 mstart = image->segment[i].mem; 225 mstart = image->segment[i].mem;
226 mend = mstart + image->segment[i].memsz - 1; 226 mend = mstart + image->segment[i].memsz - 1;
227 /* Ensure we are within the crash kernel limits */ 227 /* Ensure we are within the crash kernel limits */
228 if ((mstart < crashk_res.start) || 228 if ((mstart < phys_to_boot_phys(crashk_res.start)) ||
229 (mend > crashk_res.end)) 229 (mend > phys_to_boot_phys(crashk_res.end)))
230 return -EADDRNOTAVAIL; 230 return -EADDRNOTAVAIL;
231 } 231 }
232 } 232 }
@@ -350,7 +350,7 @@ static struct page *kimage_alloc_normal_control_pages(struct kimage *image,
350 pages = kimage_alloc_pages(KEXEC_CONTROL_MEMORY_GFP, order); 350 pages = kimage_alloc_pages(KEXEC_CONTROL_MEMORY_GFP, order);
351 if (!pages) 351 if (!pages)
352 break; 352 break;
353 pfn = page_to_pfn(pages); 353 pfn = page_to_boot_pfn(pages);
354 epfn = pfn + count; 354 epfn = pfn + count;
355 addr = pfn << PAGE_SHIFT; 355 addr = pfn << PAGE_SHIFT;
356 eaddr = epfn << PAGE_SHIFT; 356 eaddr = epfn << PAGE_SHIFT;
@@ -476,7 +476,7 @@ static int kimage_add_entry(struct kimage *image, kimage_entry_t entry)
476 return -ENOMEM; 476 return -ENOMEM;
477 477
478 ind_page = page_address(page); 478 ind_page = page_address(page);
479 *image->entry = virt_to_phys(ind_page) | IND_INDIRECTION; 479 *image->entry = virt_to_boot_phys(ind_page) | IND_INDIRECTION;
480 image->entry = ind_page; 480 image->entry = ind_page;
481 image->last_entry = ind_page + 481 image->last_entry = ind_page +
482 ((PAGE_SIZE/sizeof(kimage_entry_t)) - 1); 482 ((PAGE_SIZE/sizeof(kimage_entry_t)) - 1);
@@ -531,13 +531,13 @@ void kimage_terminate(struct kimage *image)
531#define for_each_kimage_entry(image, ptr, entry) \ 531#define for_each_kimage_entry(image, ptr, entry) \
532 for (ptr = &image->head; (entry = *ptr) && !(entry & IND_DONE); \ 532 for (ptr = &image->head; (entry = *ptr) && !(entry & IND_DONE); \
533 ptr = (entry & IND_INDIRECTION) ? \ 533 ptr = (entry & IND_INDIRECTION) ? \
534 phys_to_virt((entry & PAGE_MASK)) : ptr + 1) 534 boot_phys_to_virt((entry & PAGE_MASK)) : ptr + 1)
535 535
536static void kimage_free_entry(kimage_entry_t entry) 536static void kimage_free_entry(kimage_entry_t entry)
537{ 537{
538 struct page *page; 538 struct page *page;
539 539
540 page = pfn_to_page(entry >> PAGE_SHIFT); 540 page = boot_pfn_to_page(entry >> PAGE_SHIFT);
541 kimage_free_pages(page); 541 kimage_free_pages(page);
542} 542}
543 543
@@ -631,7 +631,7 @@ static struct page *kimage_alloc_page(struct kimage *image,
631 * have a match. 631 * have a match.
632 */ 632 */
633 list_for_each_entry(page, &image->dest_pages, lru) { 633 list_for_each_entry(page, &image->dest_pages, lru) {
634 addr = page_to_pfn(page) << PAGE_SHIFT; 634 addr = page_to_boot_pfn(page) << PAGE_SHIFT;
635 if (addr == destination) { 635 if (addr == destination) {
636 list_del(&page->lru); 636 list_del(&page->lru);
637 return page; 637 return page;
@@ -646,12 +646,12 @@ static struct page *kimage_alloc_page(struct kimage *image,
646 if (!page) 646 if (!page)
647 return NULL; 647 return NULL;
648 /* If the page cannot be used file it away */ 648 /* If the page cannot be used file it away */
649 if (page_to_pfn(page) > 649 if (page_to_boot_pfn(page) >
650 (KEXEC_SOURCE_MEMORY_LIMIT >> PAGE_SHIFT)) { 650 (KEXEC_SOURCE_MEMORY_LIMIT >> PAGE_SHIFT)) {
651 list_add(&page->lru, &image->unusable_pages); 651 list_add(&page->lru, &image->unusable_pages);
652 continue; 652 continue;
653 } 653 }
654 addr = page_to_pfn(page) << PAGE_SHIFT; 654 addr = page_to_boot_pfn(page) << PAGE_SHIFT;
655 655
656 /* If it is the destination page we want use it */ 656 /* If it is the destination page we want use it */
657 if (addr == destination) 657 if (addr == destination)
@@ -674,7 +674,7 @@ static struct page *kimage_alloc_page(struct kimage *image,
674 struct page *old_page; 674 struct page *old_page;
675 675
676 old_addr = *old & PAGE_MASK; 676 old_addr = *old & PAGE_MASK;
677 old_page = pfn_to_page(old_addr >> PAGE_SHIFT); 677 old_page = boot_pfn_to_page(old_addr >> PAGE_SHIFT);
678 copy_highpage(page, old_page); 678 copy_highpage(page, old_page);
679 *old = addr | (*old & ~PAGE_MASK); 679 *old = addr | (*old & ~PAGE_MASK);
680 680
@@ -730,7 +730,7 @@ static int kimage_load_normal_segment(struct kimage *image,
730 result = -ENOMEM; 730 result = -ENOMEM;
731 goto out; 731 goto out;
732 } 732 }
733 result = kimage_add_page(image, page_to_pfn(page) 733 result = kimage_add_page(image, page_to_boot_pfn(page)
734 << PAGE_SHIFT); 734 << PAGE_SHIFT);
735 if (result < 0) 735 if (result < 0)
736 goto out; 736 goto out;
@@ -791,7 +791,7 @@ static int kimage_load_crash_segment(struct kimage *image,
791 char *ptr; 791 char *ptr;
792 size_t uchunk, mchunk; 792 size_t uchunk, mchunk;
793 793
794 page = pfn_to_page(maddr >> PAGE_SHIFT); 794 page = boot_pfn_to_page(maddr >> PAGE_SHIFT);
795 if (!page) { 795 if (!page) {
796 result = -ENOMEM; 796 result = -ENOMEM;
797 goto out; 797 goto out;
@@ -919,7 +919,7 @@ void __weak crash_free_reserved_phys_range(unsigned long begin,
919 unsigned long addr; 919 unsigned long addr;
920 920
921 for (addr = begin; addr < end; addr += PAGE_SIZE) 921 for (addr = begin; addr < end; addr += PAGE_SIZE)
922 free_reserved_page(pfn_to_page(addr >> PAGE_SHIFT)); 922 free_reserved_page(boot_pfn_to_page(addr >> PAGE_SHIFT));
923} 923}
924 924
925int crash_shrink_memory(unsigned long new_size) 925int crash_shrink_memory(unsigned long new_size)