Skip to content

Commit f01d862

Browse files
Russell Kingsfrothwell
authored andcommitted
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. 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>
1 parent 8391635 commit f01d862

File tree

3 files changed

+53
-14
lines changed

3 files changed

+53
-14
lines changed

include/linux/kexec.h

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,44 @@ int __weak arch_kexec_apply_relocations(const Elf_Ehdr *ehdr, Elf_Shdr *sechdrs,
318318
void arch_kexec_protect_crashkres(void);
319319
void arch_kexec_unprotect_crashkres(void);
320320

321+
#ifndef page_to_boot_pfn
322+
static inline unsigned long page_to_boot_pfn(struct page *page)
323+
{
324+
return page_to_pfn(page);
325+
}
326+
#endif
327+
328+
#ifndef boot_pfn_to_page
329+
static inline struct page *boot_pfn_to_page(unsigned long boot_pfn)
330+
{
331+
return pfn_to_page(boot_pfn);
332+
}
333+
#endif
334+
335+
#ifndef phys_to_boot_phys
336+
static inline unsigned long phys_to_boot_phys(phys_addr_t phys)
337+
{
338+
return phys;
339+
}
340+
#endif
341+
342+
#ifndef boot_phys_to_phys
343+
static inline phys_addr_t boot_phys_to_phys(unsigned long boot_phys)
344+
{
345+
return boot_phys;
346+
}
347+
#endif
348+
349+
static inline unsigned long virt_to_boot_phys(void *addr)
350+
{
351+
return phys_to_boot_phys(__pa((unsigned long)addr));
352+
}
353+
354+
static inline void *boot_phys_to_virt(unsigned long entry)
355+
{
356+
return phys_to_virt(boot_phys_to_phys(entry));
357+
}
358+
321359
#else /* !CONFIG_KEXEC_CORE */
322360
struct pt_regs;
323361
struct task_struct;

kernel/kexec.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ static int kimage_alloc_init(struct kimage **rimage, unsigned long entry,
4848

4949
if (kexec_on_panic) {
5050
/* 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)))
5253
return -EADDRNOTAVAIL;
5354
}
5455

kernel/kexec_core.c

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -225,8 +225,8 @@ int sanity_check_segment_list(struct kimage *image)
225225
mstart = image->segment[i].mem;
226226
mend = mstart + image->segment[i].memsz - 1;
227227
/* Ensure we are within the crash kernel limits */
228-
if ((mstart < crashk_res.start) ||
229-
(mend > crashk_res.end))
228+
if ((mstart < phys_to_boot_phys(crashk_res.start)) ||
229+
(mend > phys_to_boot_phys(crashk_res.end)))
230230
return -EADDRNOTAVAIL;
231231
}
232232
}
@@ -350,7 +350,7 @@ static struct page *kimage_alloc_normal_control_pages(struct kimage *image,
350350
pages = kimage_alloc_pages(KEXEC_CONTROL_MEMORY_GFP, order);
351351
if (!pages)
352352
break;
353-
pfn = page_to_pfn(pages);
353+
pfn = page_to_boot_pfn(pages);
354354
epfn = pfn + count;
355355
addr = pfn << PAGE_SHIFT;
356356
eaddr = epfn << PAGE_SHIFT;
@@ -476,7 +476,7 @@ static int kimage_add_entry(struct kimage *image, kimage_entry_t entry)
476476
return -ENOMEM;
477477

478478
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;
480480
image->entry = ind_page;
481481
image->last_entry = ind_page +
482482
((PAGE_SIZE/sizeof(kimage_entry_t)) - 1);
@@ -531,13 +531,13 @@ void kimage_terminate(struct kimage *image)
531531
#define for_each_kimage_entry(image, ptr, entry) \
532532
for (ptr = &image->head; (entry = *ptr) && !(entry & IND_DONE); \
533533
ptr = (entry & IND_INDIRECTION) ? \
534-
phys_to_virt((entry & PAGE_MASK)) : ptr + 1)
534+
boot_phys_to_virt((entry & PAGE_MASK)) : ptr + 1)
535535

536536
static void kimage_free_entry(kimage_entry_t entry)
537537
{
538538
struct page *page;
539539

540-
page = pfn_to_page(entry >> PAGE_SHIFT);
540+
page = boot_pfn_to_page(entry >> PAGE_SHIFT);
541541
kimage_free_pages(page);
542542
}
543543

@@ -631,7 +631,7 @@ static struct page *kimage_alloc_page(struct kimage *image,
631631
* have a match.
632632
*/
633633
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;
635635
if (addr == destination) {
636636
list_del(&page->lru);
637637
return page;
@@ -646,12 +646,12 @@ static struct page *kimage_alloc_page(struct kimage *image,
646646
if (!page)
647647
return NULL;
648648
/* If the page cannot be used file it away */
649-
if (page_to_pfn(page) >
649+
if (page_to_boot_pfn(page) >
650650
(KEXEC_SOURCE_MEMORY_LIMIT >> PAGE_SHIFT)) {
651651
list_add(&page->lru, &image->unusable_pages);
652652
continue;
653653
}
654-
addr = page_to_pfn(page) << PAGE_SHIFT;
654+
addr = page_to_boot_pfn(page) << PAGE_SHIFT;
655655

656656
/* If it is the destination page we want use it */
657657
if (addr == destination)
@@ -674,7 +674,7 @@ static struct page *kimage_alloc_page(struct kimage *image,
674674
struct page *old_page;
675675

676676
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);
678678
copy_highpage(page, old_page);
679679
*old = addr | (*old & ~PAGE_MASK);
680680

@@ -730,7 +730,7 @@ static int kimage_load_normal_segment(struct kimage *image,
730730
result = -ENOMEM;
731731
goto out;
732732
}
733-
result = kimage_add_page(image, page_to_pfn(page)
733+
result = kimage_add_page(image, page_to_boot_pfn(page)
734734
<< PAGE_SHIFT);
735735
if (result < 0)
736736
goto out;
@@ -791,7 +791,7 @@ static int kimage_load_crash_segment(struct kimage *image,
791791
char *ptr;
792792
size_t uchunk, mchunk;
793793

794-
page = pfn_to_page(maddr >> PAGE_SHIFT);
794+
page = boot_pfn_to_page(maddr >> PAGE_SHIFT);
795795
if (!page) {
796796
result = -ENOMEM;
797797
goto out;
@@ -919,7 +919,7 @@ void __weak crash_free_reserved_phys_range(unsigned long begin,
919919
unsigned long addr;
920920

921921
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));
923923
}
924924

925925
int crash_shrink_memory(unsigned long new_size)

0 commit comments

Comments
 (0)