summaryrefslogtreecommitdiffstats
path: root/arch/parisc/mm
diff options
context:
space:
mode:
authorHelge Deller <deller@gmx.de>2013-11-30 22:07:51 +0100
committerHelge Deller <deller@gmx.de>2013-11-30 22:09:21 +0100
commit161bd3bf60ee2c5765455ad3e3da967d03449f4a (patch)
tree5287e2c53bdc876b7bf2660237dc926efcb50d9c /arch/parisc/mm
parentc790b41bac83512dc67da89b582daa6f4e1fab07 (diff)
downloadop-kernel-dev-161bd3bf60ee2c5765455ad3e3da967d03449f4a.zip
op-kernel-dev-161bd3bf60ee2c5765455ad3e3da967d03449f4a.tar.gz
parisc: fix kernel memory layout in vmlinux.ld.S
When building a 64bit kernel sometimes functions in the .init section were not able to reach the standard kernel function. Main reason for this problem is, that the linkage tables (.plt, .opd, .dlt) tend to become pretty huge and thus the distance gets too big for short calls. One option to avoid this is to use the -mlong-calls compiler option, but this increases the binary size and introduces a performance penalty. Instead, with this patch we just lay out the binary differently. Init code is stored first, followed by text, R/O and finally R/W data. This means, that init and text code is now much closer to each other, which is sufficient to reach each other by short calls. Signed-off-by: Helge Deller <deller@gmx.de>
Diffstat (limited to 'arch/parisc/mm')
-rw-r--r--arch/parisc/mm/init.c19
1 files changed, 16 insertions, 3 deletions
diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c
index b0f96c0..96f8168 100644
--- a/arch/parisc/mm/init.c
+++ b/arch/parisc/mm/init.c
@@ -32,6 +32,7 @@
#include <asm/sections.h>
extern int data_start;
+extern void parisc_kernel_start(void); /* Kernel entry point in head.S */
#if PT_NLEVELS == 3
/* NOTE: This layout exactly conforms to the hybrid L2/L3 page table layout
@@ -324,8 +325,9 @@ static void __init setup_bootmem(void)
reserve_bootmem_node(NODE_DATA(0), 0UL,
(unsigned long)(PAGE0->mem_free +
PDC_CONSOLE_IO_IODC_SIZE), BOOTMEM_DEFAULT);
- reserve_bootmem_node(NODE_DATA(0), __pa((unsigned long)_text),
- (unsigned long)(_end - _text), BOOTMEM_DEFAULT);
+ reserve_bootmem_node(NODE_DATA(0), __pa(KERNEL_BINARY_TEXT_START),
+ (unsigned long)(_end - KERNEL_BINARY_TEXT_START),
+ BOOTMEM_DEFAULT);
reserve_bootmem_node(NODE_DATA(0), (bootmap_start_pfn << PAGE_SHIFT),
((bootmap_pfn - bootmap_start_pfn) << PAGE_SHIFT),
BOOTMEM_DEFAULT);
@@ -378,6 +380,17 @@ static void __init setup_bootmem(void)
request_resource(&sysram_resources[0], &pdcdata_resource);
}
+static int __init parisc_text_address(unsigned long vaddr)
+{
+ static unsigned long head_ptr __initdata;
+
+ if (!head_ptr)
+ head_ptr = PAGE_MASK & (unsigned long)
+ dereference_function_descriptor(&parisc_kernel_start);
+
+ return core_kernel_text(vaddr) || vaddr == head_ptr;
+}
+
static void __init map_pages(unsigned long start_vaddr,
unsigned long start_paddr, unsigned long size,
pgprot_t pgprot, int force)
@@ -466,7 +479,7 @@ static void __init map_pages(unsigned long start_vaddr,
*/
if (force)
pte = __mk_pte(address, pgprot);
- else if (core_kernel_text(vaddr) &&
+ else if (parisc_text_address(vaddr) &&
address != fv_addr)
pte = __mk_pte(address, PAGE_KERNEL_EXEC);
else
OpenPOWER on IntegriCloud