aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/head_64.S
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2008-08-29 21:43:47 -0400
committerPaul Mackerras <paulus@samba.org>2008-09-15 14:08:38 -0400
commit549e8152de8039506f69c677a4546e5427aa6ae7 (patch)
treee03a4f46143a23045e456f96fc08beba12e73073 /arch/powerpc/kernel/head_64.S
parente31aa453bbc4886a7bd33e5c2afa526d6f55bd7a (diff)
powerpc: Make the 64-bit kernel as a position-independent executable
This implements CONFIG_RELOCATABLE for 64-bit by making the kernel as a position-independent executable (PIE) when it is set. This involves processing the dynamic relocations in the image in the early stages of booting, even if the kernel is being run at the address it is linked at, since the linker does not necessarily fill in words in the image for which there are dynamic relocations. (In fact the linker does fill in such words for 64-bit executables, though not for 32-bit executables, so in principle we could avoid calling relocate() entirely when we're running a 64-bit kernel at the linked address.) The dynamic relocations are processed by a new function relocate(addr), where the addr parameter is the virtual address where the image will be run. In fact we call it twice; once before calling prom_init, and again when starting the main kernel. This means that reloc_offset() returns 0 in prom_init (since it has been relocated to the address it is running at), which necessitated a few adjustments. This also changes __va and __pa to use an equivalent definition that is simpler. With the relocatable kernel, PAGE_OFFSET and MEMORY_START are constants (for 64-bit) whereas PHYSICAL_START is a variable (and KERNELBASE ideally should be too, but isn't yet). With this, relocatable kernels still copy themselves down to physical address 0 and run there. Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/kernel/head_64.S')
-rw-r--r--arch/powerpc/kernel/head_64.S26
1 files changed, 23 insertions, 3 deletions
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index 6cdfd44d8efe..84856bee33a5 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -1360,6 +1360,12 @@ _INIT_STATIC(__boot_from_prom)
1360 */ 1360 */
1361 rldicr r1,r1,0,59 1361 rldicr r1,r1,0,59
1362 1362
1363#ifdef CONFIG_RELOCATABLE
1364 /* Relocate code for where we are now */
1365 mr r3,r26
1366 bl .relocate
1367#endif
1368
1363 /* Restore parameters */ 1369 /* Restore parameters */
1364 mr r3,r31 1370 mr r3,r31
1365 mr r4,r30 1371 mr r4,r30
@@ -1368,11 +1374,19 @@ _INIT_STATIC(__boot_from_prom)
1368 mr r7,r27 1374 mr r7,r27
1369 1375
1370 /* Do all of the interaction with OF client interface */ 1376 /* Do all of the interaction with OF client interface */
1377 mr r8,r26
1371 bl .prom_init 1378 bl .prom_init
1372 /* We never return */ 1379 /* We never return */
1373 trap 1380 trap
1374 1381
1375_STATIC(__after_prom_start) 1382_STATIC(__after_prom_start)
1383#ifdef CONFIG_RELOCATABLE
1384 /* process relocations for the final address of the kernel */
1385 lis r25,PAGE_OFFSET@highest /* compute virtual base of kernel */
1386 sldi r25,r25,32
1387 mr r3,r25
1388 bl .relocate
1389#endif
1376 1390
1377/* 1391/*
1378 * We need to run with _stext at physical address PHYSICAL_START. 1392 * We need to run with _stext at physical address PHYSICAL_START.
@@ -1381,10 +1395,9 @@ _STATIC(__after_prom_start)
1381 * 1395 *
1382 * Note: This process overwrites the OF exception vectors. 1396 * Note: This process overwrites the OF exception vectors.
1383 */ 1397 */
1384 LOAD_REG_IMMEDIATE(r3, PHYSICAL_START) /* target addr */ 1398 li r3,0 /* target addr */
1385 cmpd r3,r26 /* In some cases the loader may */ 1399 mr. r4,r26 /* In some cases the loader may */
1386 beq 9f /* have already put us at zero */ 1400 beq 9f /* have already put us at zero */
1387 mr r4,r26 /* source address */
1388 lis r5,(copy_to_here - _stext)@ha 1401 lis r5,(copy_to_here - _stext)@ha
1389 addi r5,r5,(copy_to_here - _stext)@l /* # bytes of memory to copy */ 1402 addi r5,r5,(copy_to_here - _stext)@l /* # bytes of memory to copy */
1390 li r6,0x100 /* Start offset, the first 0x100 */ 1403 li r6,0x100 /* Start offset, the first 0x100 */
@@ -1617,6 +1630,13 @@ _INIT_STATIC(start_here_multiplatform)
1617 ori r6,r6,MSR_RI 1630 ori r6,r6,MSR_RI
1618 mtmsrd r6 /* RI on */ 1631 mtmsrd r6 /* RI on */
1619 1632
1633#ifdef CONFIG_RELOCATABLE
1634 /* Save the physical address we're running at in kernstart_addr */
1635 LOAD_REG_ADDR(r4, kernstart_addr)
1636 clrldi r0,r25,2
1637 std r0,0(r4)
1638#endif
1639
1620 /* The following gets the stack set up with the regs */ 1640 /* The following gets the stack set up with the regs */
1621 /* pointing to the real addr of the kernel stack. This is */ 1641 /* pointing to the real addr of the kernel stack. This is */
1622 /* all done to support the C function call below which sets */ 1642 /* all done to support the C function call below which sets */