aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/head_64.S
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2008-08-29 21:41:12 -0400
committerPaul Mackerras <paulus@samba.org>2008-09-15 14:08:35 -0400
commite31aa453bbc4886a7bd33e5c2afa526d6f55bd7a (patch)
treefefa13c13d7b1803fdaeb92143f83b1971f0ec8d /arch/powerpc/kernel/head_64.S
parent1f6a93e4c35e75d547b51f56ba8139ab1a91628c (diff)
powerpc: Use LOAD_REG_IMMEDIATE only for constants on 64-bit
Using LOAD_REG_IMMEDIATE to get the address of kernel symbols generates 5 instructions where LOAD_REG_ADDR can do it in one, and will generate R_PPC64_ADDR16_* relocations in the output when we get to making the kernel as a position-independent executable, which we'd rather not have to handle. This changes various bits of assembly code to use LOAD_REG_ADDR when we need to get the address of a symbol, or to use suitable position-independent code for cases where we can't access the TOC for various reasons, or if we're not running at the address we were linked at. It also cleans up a few minor things; there's no reason to save and restore SRR0/1 around RTAS calls, __mmu_off can get the return address from LR more conveniently than the caller can supply it in R4 (and we already assume elsewhere that EA == RA if the MMU is on in early boot), and enable_64b_mode was using 5 instructions where 2 would do. 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.S181
1 files changed, 82 insertions, 99 deletions
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index 97bb6e6f67b1..6cdfd44d8efe 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -128,11 +128,11 @@ __secondary_hold:
128 /* Tell the master cpu we're here */ 128 /* Tell the master cpu we're here */
129 /* Relocation is off & we are located at an address less */ 129 /* Relocation is off & we are located at an address less */
130 /* than 0x100, so only need to grab low order offset. */ 130 /* than 0x100, so only need to grab low order offset. */
131 std r24,__secondary_hold_acknowledge@l(0) 131 std r24,__secondary_hold_acknowledge-_stext(0)
132 sync 132 sync
133 133
134 /* All secondary cpus wait here until told to start. */ 134 /* All secondary cpus wait here until told to start. */
135100: ld r4,__secondary_hold_spinloop@l(0) 135100: ld r4,__secondary_hold_spinloop-_stext(0)
136 cmpdi 0,r4,0 136 cmpdi 0,r4,0
137 beq 100b 137 beq 100b
138 138
@@ -1223,11 +1223,14 @@ _GLOBAL(generic_secondary_smp_init)
1223 /* turn on 64-bit mode */ 1223 /* turn on 64-bit mode */
1224 bl .enable_64b_mode 1224 bl .enable_64b_mode
1225 1225
1226 /* get the TOC pointer (real address) */
1227 bl .relative_toc
1228
1226 /* Set up a paca value for this processor. Since we have the 1229 /* Set up a paca value for this processor. Since we have the
1227 * physical cpu id in r24, we need to search the pacas to find 1230 * physical cpu id in r24, we need to search the pacas to find
1228 * which logical id maps to our physical one. 1231 * which logical id maps to our physical one.
1229 */ 1232 */
1230 LOAD_REG_IMMEDIATE(r13, paca) /* Get base vaddr of paca array */ 1233 LOAD_REG_ADDR(r13, paca) /* Get base vaddr of paca array */
1231 li r5,0 /* logical cpu id */ 1234 li r5,0 /* logical cpu id */
12321: lhz r6,PACAHWCPUID(r13) /* Load HW procid from paca */ 12351: lhz r6,PACAHWCPUID(r13) /* Load HW procid from paca */
1233 cmpw r6,r24 /* Compare to our id */ 1236 cmpw r6,r24 /* Compare to our id */
@@ -1256,7 +1259,7 @@ _GLOBAL(generic_secondary_smp_init)
1256 sync /* order paca.run and cur_cpu_spec */ 1259 sync /* order paca.run and cur_cpu_spec */
1257 1260
1258 /* See if we need to call a cpu state restore handler */ 1261 /* See if we need to call a cpu state restore handler */
1259 LOAD_REG_IMMEDIATE(r23, cur_cpu_spec) 1262 LOAD_REG_ADDR(r23, cur_cpu_spec)
1260 ld r23,0(r23) 1263 ld r23,0(r23)
1261 ld r23,CPU_SPEC_RESTORE(r23) 1264 ld r23,CPU_SPEC_RESTORE(r23)
1262 cmpdi 0,r23,0 1265 cmpdi 0,r23,0
@@ -1272,10 +1275,15 @@ _GLOBAL(generic_secondary_smp_init)
1272 b __secondary_start 1275 b __secondary_start
1273#endif 1276#endif
1274 1277
1278/*
1279 * Turn the MMU off.
1280 * Assumes we're mapped EA == RA if the MMU is on.
1281 */
1275_STATIC(__mmu_off) 1282_STATIC(__mmu_off)
1276 mfmsr r3 1283 mfmsr r3
1277 andi. r0,r3,MSR_IR|MSR_DR 1284 andi. r0,r3,MSR_IR|MSR_DR
1278 beqlr 1285 beqlr
1286 mflr r4
1279 andc r3,r3,r0 1287 andc r3,r3,r0
1280 mtspr SPRN_SRR0,r4 1288 mtspr SPRN_SRR0,r4
1281 mtspr SPRN_SRR1,r3 1289 mtspr SPRN_SRR1,r3
@@ -1296,6 +1304,18 @@ _STATIC(__mmu_off)
1296 * 1304 *
1297 */ 1305 */
1298_GLOBAL(__start_initialization_multiplatform) 1306_GLOBAL(__start_initialization_multiplatform)
1307 /* Make sure we are running in 64 bits mode */
1308 bl .enable_64b_mode
1309
1310 /* Get TOC pointer (current runtime address) */
1311 bl .relative_toc
1312
1313 /* find out where we are now */
1314 bcl 20,31,$+4
13150: mflr r26 /* r26 = runtime addr here */
1316 addis r26,r26,(_stext - 0b)@ha
1317 addi r26,r26,(_stext - 0b)@l /* current runtime base addr */
1318
1299 /* 1319 /*
1300 * Are we booted from a PROM Of-type client-interface ? 1320 * Are we booted from a PROM Of-type client-interface ?
1301 */ 1321 */
@@ -1307,9 +1327,6 @@ _GLOBAL(__start_initialization_multiplatform)
1307 mr r31,r3 1327 mr r31,r3
1308 mr r30,r4 1328 mr r30,r4
1309 1329
1310 /* Make sure we are running in 64 bits mode */
1311 bl .enable_64b_mode
1312
1313 /* Setup some critical 970 SPRs before switching MMU off */ 1330 /* Setup some critical 970 SPRs before switching MMU off */
1314 mfspr r0,SPRN_PVR 1331 mfspr r0,SPRN_PVR
1315 srwi r0,r0,16 1332 srwi r0,r0,16
@@ -1324,9 +1341,7 @@ _GLOBAL(__start_initialization_multiplatform)
13241: bl .__cpu_preinit_ppc970 13411: bl .__cpu_preinit_ppc970
13252: 13422:
1326 1343
1327 /* Switch off MMU if not already */ 1344 /* Switch off MMU if not already off */
1328 LOAD_REG_IMMEDIATE(r4, .__after_prom_start - KERNELBASE)
1329 add r4,r4,r30
1330 bl .__mmu_off 1345 bl .__mmu_off
1331 b .__after_prom_start 1346 b .__after_prom_start
1332 1347
@@ -1341,23 +1356,10 @@ _INIT_STATIC(__boot_from_prom)
1341 /* 1356 /*
1342 * Align the stack to 16-byte boundary 1357 * Align the stack to 16-byte boundary
1343 * Depending on the size and layout of the ELF sections in the initial 1358 * Depending on the size and layout of the ELF sections in the initial
1344 * boot binary, the stack pointer will be unalignet on PowerMac 1359 * boot binary, the stack pointer may be unaligned on PowerMac
1345 */ 1360 */
1346 rldicr r1,r1,0,59 1361 rldicr r1,r1,0,59
1347 1362
1348 /* Make sure we are running in 64 bits mode */
1349 bl .enable_64b_mode
1350
1351 /* put a relocation offset into r3 */
1352 bl .reloc_offset
1353
1354 LOAD_REG_IMMEDIATE(r2,__toc_start)
1355 addi r2,r2,0x4000
1356 addi r2,r2,0x4000
1357
1358 /* Relocate the TOC from a virt addr to a real addr */
1359 add r2,r2,r3
1360
1361 /* Restore parameters */ 1363 /* Restore parameters */
1362 mr r3,r31 1364 mr r3,r31
1363 mr r4,r30 1365 mr r4,r30
@@ -1373,53 +1375,37 @@ _INIT_STATIC(__boot_from_prom)
1373_STATIC(__after_prom_start) 1375_STATIC(__after_prom_start)
1374 1376
1375/* 1377/*
1376 * We need to run with __start at physical address PHYSICAL_START. 1378 * We need to run with _stext at physical address PHYSICAL_START.
1377 * This will leave some code in the first 256B of 1379 * This will leave some code in the first 256B of
1378 * real memory, which are reserved for software use. 1380 * real memory, which are reserved for software use.
1379 * The remainder of the first page is loaded with the fixed
1380 * interrupt vectors. The next two pages are filled with
1381 * unknown exception placeholders.
1382 * 1381 *
1383 * Note: This process overwrites the OF exception vectors. 1382 * Note: This process overwrites the OF exception vectors.
1384 * r26 == relocation offset
1385 * r27 == KERNELBASE
1386 */ 1383 */
1387 bl .reloc_offset
1388 mr r26,r3
1389 LOAD_REG_IMMEDIATE(r27, KERNELBASE)
1390
1391 LOAD_REG_IMMEDIATE(r3, PHYSICAL_START) /* target addr */ 1384 LOAD_REG_IMMEDIATE(r3, PHYSICAL_START) /* target addr */
1392 1385 cmpd r3,r26 /* In some cases the loader may */
1393 // XXX FIXME: Use phys returned by OF (r30) 1386 beq 9f /* have already put us at zero */
1394 add r4,r27,r26 /* source addr */ 1387 mr r4,r26 /* source address */
1395 /* current address of _start */ 1388 lis r5,(copy_to_here - _stext)@ha
1396 /* i.e. where we are running */ 1389 addi r5,r5,(copy_to_here - _stext)@l /* # bytes of memory to copy */
1397 /* the source addr */
1398
1399 cmpdi r4,0 /* In some cases the loader may */
1400 bne 1f
1401 b .start_here_multiplatform /* have already put us at zero */
1402 /* so we can skip the copy. */
14031: LOAD_REG_IMMEDIATE(r5,copy_to_here) /* # bytes of memory to copy */
1404 sub r5,r5,r27
1405
1406 li r6,0x100 /* Start offset, the first 0x100 */ 1390 li r6,0x100 /* Start offset, the first 0x100 */
1407 /* bytes were copied earlier. */ 1391 /* bytes were copied earlier. */
1408 1392
1409 bl .copy_and_flush /* copy the first n bytes */ 1393 bl .copy_and_flush /* copy the first n bytes */
1410 /* this includes the code being */ 1394 /* this includes the code being */
1411 /* executed here. */ 1395 /* executed here. */
1412 1396 addis r8,r3,(4f - _stext)@ha /* Jump to the copy of this code */
1413 LOAD_REG_IMMEDIATE(r0, 4f) /* Jump to the copy of this code */ 1397 addi r8,r8,(4f - _stext)@l /* that we just made */
1414 mtctr r0 /* that we just made/relocated */ 1398 mtctr r8
1415 bctr 1399 bctr
1416 1400
14174: LOAD_REG_IMMEDIATE(r5,klimit) 14014: /* Now copy the rest of the kernel up to _end */
1418 add r5,r5,r26 1402 addis r5,r26,(p_end - _stext)@ha
1419 ld r5,0(r5) /* get the value of klimit */ 1403 ld r5,(p_end - _stext)@l(r5) /* get _end */
1420 sub r5,r5,r27
1421 bl .copy_and_flush /* copy the rest */ 1404 bl .copy_and_flush /* copy the rest */
1422 b .start_here_multiplatform 1405
14069: b .start_here_multiplatform
1407
1408p_end: .llong _end - _stext
1423 1409
1424/* 1410/*
1425 * Copy routine used to copy the kernel to start at physical address 0 1411 * Copy routine used to copy the kernel to start at physical address 0
@@ -1484,6 +1470,9 @@ _GLOBAL(pmac_secondary_start)
1484 /* turn on 64-bit mode */ 1470 /* turn on 64-bit mode */
1485 bl .enable_64b_mode 1471 bl .enable_64b_mode
1486 1472
1473 /* get TOC pointer (real address) */
1474 bl .relative_toc
1475
1487 /* Copy some CPU settings from CPU 0 */ 1476 /* Copy some CPU settings from CPU 0 */
1488 bl .__restore_cpu_ppc970 1477 bl .__restore_cpu_ppc970
1489 1478
@@ -1493,10 +1482,10 @@ _GLOBAL(pmac_secondary_start)
1493 mtmsrd r3 /* RI on */ 1482 mtmsrd r3 /* RI on */
1494 1483
1495 /* Set up a paca value for this processor. */ 1484 /* Set up a paca value for this processor. */
1496 LOAD_REG_IMMEDIATE(r4, paca) /* Get base vaddr of paca array */ 1485 LOAD_REG_ADDR(r4,paca) /* Get base vaddr of paca array */
1497 mulli r13,r24,PACA_SIZE /* Calculate vaddr of right paca */ 1486 mulli r13,r24,PACA_SIZE /* Calculate vaddr of right paca */
1498 add r13,r13,r4 /* for this processor. */ 1487 add r13,r13,r4 /* for this processor. */
1499 mtspr SPRN_SPRG3,r13 /* Save vaddr of paca in SPRG3 */ 1488 mtspr SPRN_SPRG3,r13 /* Save vaddr of paca in SPRG3 */
1500 1489
1501 /* Create a temp kernel stack for use before relocation is on. */ 1490 /* Create a temp kernel stack for use before relocation is on. */
1502 ld r1,PACAEMERGSP(r13) 1491 ld r1,PACAEMERGSP(r13)
@@ -1524,9 +1513,6 @@ __secondary_start:
1524 /* Set thread priority to MEDIUM */ 1513 /* Set thread priority to MEDIUM */
1525 HMT_MEDIUM 1514 HMT_MEDIUM
1526 1515
1527 /* Load TOC */
1528 ld r2,PACATOC(r13)
1529
1530 /* Do early setup for that CPU (stab, slb, hash table pointer) */ 1516 /* Do early setup for that CPU (stab, slb, hash table pointer) */
1531 bl .early_setup_secondary 1517 bl .early_setup_secondary
1532 1518
@@ -1563,9 +1549,11 @@ END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES)
1563 1549
1564/* 1550/*
1565 * Running with relocation on at this point. All we want to do is 1551 * Running with relocation on at this point. All we want to do is
1566 * zero the stack back-chain pointer before going into C code. 1552 * zero the stack back-chain pointer and get the TOC virtual address
1553 * before going into C code.
1567 */ 1554 */
1568_GLOBAL(start_secondary_prolog) 1555_GLOBAL(start_secondary_prolog)
1556 ld r2,PACATOC(r13)
1569 li r3,0 1557 li r3,0
1570 std r3,0(r1) /* Zero the stack frame pointer */ 1558 std r3,0(r1) /* Zero the stack frame pointer */
1571 bl .start_secondary 1559 bl .start_secondary
@@ -1577,34 +1565,46 @@ _GLOBAL(start_secondary_prolog)
1577 */ 1565 */
1578_GLOBAL(enable_64b_mode) 1566_GLOBAL(enable_64b_mode)
1579 mfmsr r11 /* grab the current MSR */ 1567 mfmsr r11 /* grab the current MSR */
1580 li r12,1 1568 li r12,(MSR_SF | MSR_ISF)@highest
1581 rldicr r12,r12,MSR_SF_LG,(63-MSR_SF_LG) 1569 sldi r12,r12,48
1582 or r11,r11,r12
1583 li r12,1
1584 rldicr r12,r12,MSR_ISF_LG,(63-MSR_ISF_LG)
1585 or r11,r11,r12 1570 or r11,r11,r12
1586 mtmsrd r11 1571 mtmsrd r11
1587 isync 1572 isync
1588 blr 1573 blr
1589 1574
1590/* 1575/*
1576 * This puts the TOC pointer into r2, offset by 0x8000 (as expected
1577 * by the toolchain). It computes the correct value for wherever we
1578 * are running at the moment, using position-independent code.
1579 */
1580_GLOBAL(relative_toc)
1581 mflr r0
1582 bcl 20,31,$+4
15830: mflr r9
1584 ld r2,(p_toc - 0b)(r9)
1585 add r2,r2,r9
1586 mtlr r0
1587 blr
1588
1589p_toc: .llong __toc_start + 0x8000 - 0b
1590
1591/*
1591 * This is where the main kernel code starts. 1592 * This is where the main kernel code starts.
1592 */ 1593 */
1593_INIT_STATIC(start_here_multiplatform) 1594_INIT_STATIC(start_here_multiplatform)
1594 /* get a new offset, now that the kernel has moved. */ 1595 /* set up the TOC (real address) */
1595 bl .reloc_offset 1596 bl .relative_toc
1596 mr r26,r3
1597 1597
1598 /* Clear out the BSS. It may have been done in prom_init, 1598 /* Clear out the BSS. It may have been done in prom_init,
1599 * already but that's irrelevant since prom_init will soon 1599 * already but that's irrelevant since prom_init will soon
1600 * be detached from the kernel completely. Besides, we need 1600 * be detached from the kernel completely. Besides, we need
1601 * to clear it now for kexec-style entry. 1601 * to clear it now for kexec-style entry.
1602 */ 1602 */
1603 LOAD_REG_IMMEDIATE(r11,__bss_stop) 1603 LOAD_REG_ADDR(r11,__bss_stop)
1604 LOAD_REG_IMMEDIATE(r8,__bss_start) 1604 LOAD_REG_ADDR(r8,__bss_start)
1605 sub r11,r11,r8 /* bss size */ 1605 sub r11,r11,r8 /* bss size */
1606 addi r11,r11,7 /* round up to an even double word */ 1606 addi r11,r11,7 /* round up to an even double word */
1607 rldicl. r11,r11,61,3 /* shift right by 3 */ 1607 srdi. r11,r11,3 /* shift right by 3 */
1608 beq 4f 1608 beq 4f
1609 addi r8,r8,-8 1609 addi r8,r8,-8
1610 li r0,0 1610 li r0,0
@@ -1617,35 +1617,28 @@ _INIT_STATIC(start_here_multiplatform)
1617 ori r6,r6,MSR_RI 1617 ori r6,r6,MSR_RI
1618 mtmsrd r6 /* RI on */ 1618 mtmsrd r6 /* RI on */
1619 1619
1620 /* The following gets the stack and TOC set up with the regs */ 1620 /* The following gets the stack set up with the regs */
1621 /* pointing to the real addr of the kernel stack. This is */ 1621 /* pointing to the real addr of the kernel stack. This is */
1622 /* all done to support the C function call below which sets */ 1622 /* all done to support the C function call below which sets */
1623 /* up the htab. This is done because we have relocated the */ 1623 /* up the htab. This is done because we have relocated the */
1624 /* kernel but are still running in real mode. */ 1624 /* kernel but are still running in real mode. */
1625 1625
1626 LOAD_REG_IMMEDIATE(r3,init_thread_union) 1626 LOAD_REG_ADDR(r3,init_thread_union)
1627 add r3,r3,r26
1628 1627
1629 /* set up a stack pointer (physical address) */ 1628 /* set up a stack pointer */
1630 addi r1,r3,THREAD_SIZE 1629 addi r1,r3,THREAD_SIZE
1631 li r0,0 1630 li r0,0
1632 stdu r0,-STACK_FRAME_OVERHEAD(r1) 1631 stdu r0,-STACK_FRAME_OVERHEAD(r1)
1633 1632
1634 /* set up the TOC (physical address) */
1635 LOAD_REG_IMMEDIATE(r2,__toc_start)
1636 addi r2,r2,0x4000
1637 addi r2,r2,0x4000
1638 add r2,r2,r26
1639
1640 /* Do very early kernel initializations, including initial hash table, 1633 /* Do very early kernel initializations, including initial hash table,
1641 * stab and slb setup before we turn on relocation. */ 1634 * stab and slb setup before we turn on relocation. */
1642 1635
1643 /* Restore parameters passed from prom_init/kexec */ 1636 /* Restore parameters passed from prom_init/kexec */
1644 mr r3,r31 1637 mr r3,r31
1645 bl .early_setup 1638 bl .early_setup /* also sets r13 and SPRG3 */
1646 1639
1647 LOAD_REG_IMMEDIATE(r3, .start_here_common) 1640 LOAD_REG_ADDR(r3, .start_here_common)
1648 LOAD_REG_IMMEDIATE(r4, MSR_KERNEL) 1641 ld r4,PACAKMSR(r13)
1649 mtspr SPRN_SRR0,r3 1642 mtspr SPRN_SRR0,r3
1650 mtspr SPRN_SRR1,r4 1643 mtspr SPRN_SRR1,r4
1651 rfid 1644 rfid
@@ -1654,20 +1647,10 @@ _INIT_STATIC(start_here_multiplatform)
1654 /* This is where all platforms converge execution */ 1647 /* This is where all platforms converge execution */
1655_INIT_GLOBAL(start_here_common) 1648_INIT_GLOBAL(start_here_common)
1656 /* relocation is on at this point */ 1649 /* relocation is on at this point */
1650 std r1,PACAKSAVE(r13)
1657 1651
1658 /* The following code sets up the SP and TOC now that we are */ 1652 /* Load the TOC (virtual address) */
1659 /* running with translation enabled. */
1660
1661 LOAD_REG_IMMEDIATE(r3,init_thread_union)
1662
1663 /* set up the stack */
1664 addi r1,r3,THREAD_SIZE
1665 li r0,0
1666 stdu r0,-STACK_FRAME_OVERHEAD(r1)
1667
1668 /* Load the TOC */
1669 ld r2,PACATOC(r13) 1653 ld r2,PACATOC(r13)
1670 std r1,PACAKSAVE(r13)
1671 1654
1672 bl .setup_system 1655 bl .setup_system
1673 1656