Skip to content

Commit b270beb

Browse files
npigginmpe
authored andcommitted
powerpc/64s: Run at the kernel virtual address earlier in boot
This mostly consolidates the Book3E and Book3S behaviour in boot WRT executing from the physical or virtual address. Book3E sets up kernel virtual linear map in start_initialization_book3e and runs from the virtual linear alias after that. This change makes Book3S begin to execute from the virtual alias at the same point. Book3S can not use its MMU for that at this point, but when the MMU is disabled, the virtual linear address correctly aliases to physical memory because the top bits of the address are ignored with MMU disabled. Secondaries execute from the virtual address similarly early. This reduces the differences between subarchs, but the main motivation was to enable the PC-relative addressing ABI for Book3S, where pointer calculations must execute from the virtual address or the top bits of the pointer will be lost. This is similar to the requirement the TOC relative addressing already has that the TOC pointer use its virtual address. Signed-off-by: Nicholas Piggin <[email protected]> Signed-off-by: Michael Ellerman <[email protected]> Link: https://msgid.link/[email protected]
1 parent 4f18b9e commit b270beb

File tree

1 file changed

+44
-38
lines changed

1 file changed

+44
-38
lines changed

arch/powerpc/kernel/head_64.S

Lines changed: 44 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,13 @@
7676
* 2. The kernel is entered at __start
7777
*/
7878

79+
/*
80+
* boot_from_prom and prom_init run at the physical address. Everything
81+
* after prom and kexec entry run at the virtual address (PAGE_OFFSET).
82+
* Secondaries run at the virtual address from generic_secondary_common_init
83+
* onward.
84+
*/
85+
7986
OPEN_FIXED_SECTION(first_256B, 0x0, 0x100)
8087
USE_FIXED_SECTION(first_256B)
8188
/*
@@ -303,13 +310,11 @@ _GLOBAL(fsl_secondary_thread_init)
303310
/* turn on 64-bit mode */
304311
bl enable_64b_mode
305312

306-
/* get a valid TOC pointer, wherever we're mapped at */
307-
bl relative_toc
308-
tovirt(r2,r2)
309-
310313
/* Book3E initialization */
311314
mr r3,r24
312315
bl book3e_secondary_thread_init
316+
bl relative_toc
317+
313318
b generic_secondary_common_init
314319

315320
#endif /* CONFIG_PPC_BOOK3E_64 */
@@ -331,16 +336,12 @@ _GLOBAL(generic_secondary_smp_init)
331336
/* turn on 64-bit mode */
332337
bl enable_64b_mode
333338

334-
/* get a valid TOC pointer, wherever we're mapped at */
335-
bl relative_toc
336-
tovirt(r2,r2)
337-
338339
#ifdef CONFIG_PPC_BOOK3E_64
339340
/* Book3E initialization */
340341
mr r3,r24
341342
mr r4,r25
342343
bl book3e_secondary_core_init
343-
344+
/* Now NIA and r2 are relocated to PAGE_OFFSET if not already */
344345
/*
345346
* After common core init has finished, check if the current thread is the
346347
* one we wanted to boot. If not, start the specified thread and stop the
@@ -378,6 +379,16 @@ _GLOBAL(generic_secondary_smp_init)
378379
10:
379380
b 10b
380381
20:
382+
#else
383+
/* Now the MMU is off, can branch to our PAGE_OFFSET address */
384+
bcl 20,31,$+4
385+
1: mflr r11
386+
addi r11,r11,(2f - 1b)
387+
tovirt(r11, r11)
388+
mtctr r11
389+
bctr
390+
2:
391+
bl relative_toc
381392
#endif
382393

383394
generic_secondary_common_init:
@@ -492,6 +503,8 @@ SYM_FUNC_START_LOCAL(start_initialization_book3s)
492503
/* Switch off MMU if not already off */
493504
bl __mmu_off
494505

506+
/* Now the MMU is off, can return to our PAGE_OFFSET address */
507+
tovirt(r25,r25)
495508
mtlr r25
496509
blr
497510
SYM_FUNC_END(start_initialization_book3s)
@@ -534,16 +547,19 @@ __start_initialization_multiplatform:
534547
/* Get TOC pointer (current runtime address) */
535548
bl relative_toc
536549

550+
/* These functions return to the virtual (PAGE_OFFSET) address */
537551
#ifdef CONFIG_PPC_BOOK3E_64
538552
bl start_initialization_book3e
539553
#else
540554
bl start_initialization_book3s
541555
#endif /* CONFIG_PPC_BOOK3E_64 */
542556

543-
/* Get TOC pointer */
557+
/* Get TOC pointer, virtual */
544558
bl relative_toc
545559

546560
/* find out where we are now */
561+
562+
/* OPAL doesn't pass base address in r4, have to derive it. */
547563
bcl 20,31,$+4
548564
0: mflr r26 /* r26 = runtime addr here */
549565
addis r26,r26,(_stext - 0b)@ha
@@ -554,7 +570,7 @@ __start_initialization_multiplatform:
554570
__REF
555571
__boot_from_prom:
556572
#ifdef CONFIG_PPC_OF_BOOT_TRAMPOLINE
557-
/* Get TOC pointer */
573+
/* Get TOC pointer, non-virtual */
558574
bl relative_toc
559575

560576
/* find out where we are now */
@@ -603,18 +619,11 @@ __boot_from_prom:
603619
__after_prom_start:
604620
#ifdef CONFIG_RELOCATABLE
605621
/* process relocations for the final address of the kernel */
606-
lis r25,PAGE_OFFSET@highest /* compute virtual base of kernel */
607-
sldi r25,r25,32
608-
#if defined(CONFIG_PPC_BOOK3E_64)
609-
tovirt(r26,r26) /* on booke, we already run at PAGE_OFFSET */
610-
#endif
611622
lwz r7,(FIXED_SYMBOL_ABS_ADDR(__run_at_load))(r26)
612-
#if defined(CONFIG_PPC_BOOK3E_64)
613-
tophys(r26,r26)
614-
#endif
615623
cmplwi cr0,r7,1 /* flagged to stay where we are ? */
616-
bne 1f
617-
add r25,r25,r26
624+
mr r25,r26 /* then use current kernel base */
625+
beq 1f
626+
LOAD_REG_IMMEDIATE(r25, PAGE_OFFSET) /* else use static kernel base */
618627
1: mr r3,r25
619628
bl relocate
620629
#if defined(CONFIG_PPC_BOOK3E_64)
@@ -630,14 +639,8 @@ __after_prom_start:
630639
*
631640
* Note: This process overwrites the OF exception vectors.
632641
*/
633-
li r3,0 /* target addr */
634-
#ifdef CONFIG_PPC_BOOK3E_64
635-
tovirt(r3,r3) /* on booke, we already run at PAGE_OFFSET */
636-
#endif
642+
LOAD_REG_IMMEDIATE(r3, PAGE_OFFSET)
637643
mr. r4,r26 /* In some cases the loader may */
638-
#if defined(CONFIG_PPC_BOOK3E_64)
639-
tovirt(r4,r4)
640-
#endif
641644
beq 9f /* have already put us at zero */
642645
li r6,0x100 /* Start offset, the first 0x100 */
643646
/* bytes were copied earlier. */
@@ -648,9 +651,6 @@ __after_prom_start:
648651
* variable __run_at_load, if it is set the kernel is treated as relocatable
649652
* kernel, otherwise it will be moved to PHYSICAL_START
650653
*/
651-
#if defined(CONFIG_PPC_BOOK3E_64)
652-
tovirt(r26,r26) /* on booke, we already run at PAGE_OFFSET */
653-
#endif
654654
lwz r7,(FIXED_SYMBOL_ABS_ADDR(__run_at_load))(r26)
655655
cmplwi cr0,r7,1
656656
bne 3f
@@ -769,9 +769,15 @@ _GLOBAL(pmac_secondary_start)
769769
sync
770770
slbia
771771

772-
/* get TOC pointer (real address) */
772+
/* Branch to our PAGE_OFFSET address */
773+
bcl 20,31,$+4
774+
1: mflr r11
775+
addi r11,r11,(2f - 1b)
776+
tovirt(r11, r11)
777+
mtctr r11
778+
bctr
779+
2:
773780
bl relative_toc
774-
tovirt(r2,r2)
775781

776782
/* Copy some CPU settings from CPU 0 */
777783
bl __restore_cpu_ppc970
@@ -910,8 +916,9 @@ SYM_FUNC_END(enable_64b_mode)
910916
* TOC in -mcmodel=medium mode. After we relocate to 0 but before
911917
* the MMU is on we need our TOC to be a virtual address otherwise
912918
* these pointers will be real addresses which may get stored and
913-
* accessed later with the MMU on. We use tovirt() at the call
914-
* sites to handle this.
919+
* accessed later with the MMU on. We branch to the virtual address
920+
* while still in real mode then call relative_toc again to handle
921+
* this.
915922
*/
916923
_GLOBAL(relative_toc)
917924
mflr r0
@@ -930,9 +937,8 @@ p_toc: .8byte .TOC. - 0b
930937
*/
931938
__REF
932939
start_here_multiplatform:
933-
/* set up the TOC */
934-
bl relative_toc
935-
tovirt(r2,r2)
940+
/* Adjust TOC for moved kernel. Could adjust when moving it instead. */
941+
bl relative_toc
936942

937943
/* Clear out the BSS. It may have been done in prom_init,
938944
* already but that's irrelevant since prom_init will soon

0 commit comments

Comments
 (0)