Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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 <npiggin@gmail.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://msgid.link/20230408021752.862660-3-npiggin@gmail.com

authored by

Nicholas Piggin and committed by
Michael Ellerman
b270bebd 4f18b9e6

+44 -38
+44 -38
arch/powerpc/kernel/head_64.S
··· 76 76 * 2. The kernel is entered at __start 77 77 */ 78 78 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 + 79 86 OPEN_FIXED_SECTION(first_256B, 0x0, 0x100) 80 87 USE_FIXED_SECTION(first_256B) 81 88 /* ··· 310 303 /* turn on 64-bit mode */ 311 304 bl enable_64b_mode 312 305 313 - /* get a valid TOC pointer, wherever we're mapped at */ 314 - bl relative_toc 315 - tovirt(r2,r2) 316 - 317 306 /* Book3E initialization */ 318 307 mr r3,r24 319 308 bl book3e_secondary_thread_init 309 + bl relative_toc 310 + 320 311 b generic_secondary_common_init 321 312 322 313 #endif /* CONFIG_PPC_BOOK3E_64 */ ··· 336 331 /* turn on 64-bit mode */ 337 332 bl enable_64b_mode 338 333 339 - /* get a valid TOC pointer, wherever we're mapped at */ 340 - bl relative_toc 341 - tovirt(r2,r2) 342 - 343 334 #ifdef CONFIG_PPC_BOOK3E_64 344 335 /* Book3E initialization */ 345 336 mr r3,r24 346 337 mr r4,r25 347 338 bl book3e_secondary_core_init 348 - 339 + /* Now NIA and r2 are relocated to PAGE_OFFSET if not already */ 349 340 /* 350 341 * After common core init has finished, check if the current thread is the 351 342 * one we wanted to boot. If not, start the specified thread and stop the ··· 379 378 10: 380 379 b 10b 381 380 20: 381 + #else 382 + /* Now the MMU is off, can branch to our PAGE_OFFSET address */ 383 + bcl 20,31,$+4 384 + 1: mflr r11 385 + addi r11,r11,(2f - 1b) 386 + tovirt(r11, r11) 387 + mtctr r11 388 + bctr 389 + 2: 390 + bl relative_toc 382 391 #endif 383 392 384 393 generic_secondary_common_init: ··· 503 492 /* Switch off MMU if not already off */ 504 493 bl __mmu_off 505 494 495 + /* Now the MMU is off, can return to our PAGE_OFFSET address */ 496 + tovirt(r25,r25) 506 497 mtlr r25 507 498 blr 508 499 SYM_FUNC_END(start_initialization_book3s) ··· 547 534 /* Get TOC pointer (current runtime address) */ 548 535 bl relative_toc 549 536 537 + /* These functions return to the virtual (PAGE_OFFSET) address */ 550 538 #ifdef CONFIG_PPC_BOOK3E_64 551 539 bl start_initialization_book3e 552 540 #else 553 541 bl start_initialization_book3s 554 542 #endif /* CONFIG_PPC_BOOK3E_64 */ 555 543 556 - /* Get TOC pointer */ 544 + /* Get TOC pointer, virtual */ 557 545 bl relative_toc 558 546 559 547 /* find out where we are now */ 548 + 549 + /* OPAL doesn't pass base address in r4, have to derive it. */ 560 550 bcl 20,31,$+4 561 551 0: mflr r26 /* r26 = runtime addr here */ 562 552 addis r26,r26,(_stext - 0b)@ha ··· 570 554 __REF 571 555 __boot_from_prom: 572 556 #ifdef CONFIG_PPC_OF_BOOT_TRAMPOLINE 573 - /* Get TOC pointer */ 557 + /* Get TOC pointer, non-virtual */ 574 558 bl relative_toc 575 559 576 560 /* find out where we are now */ ··· 619 603 __after_prom_start: 620 604 #ifdef CONFIG_RELOCATABLE 621 605 /* process relocations for the final address of the kernel */ 622 - lis r25,PAGE_OFFSET@highest /* compute virtual base of kernel */ 623 - sldi r25,r25,32 624 - #if defined(CONFIG_PPC_BOOK3E_64) 625 - tovirt(r26,r26) /* on booke, we already run at PAGE_OFFSET */ 626 - #endif 627 606 lwz r7,(FIXED_SYMBOL_ABS_ADDR(__run_at_load))(r26) 628 - #if defined(CONFIG_PPC_BOOK3E_64) 629 - tophys(r26,r26) 630 - #endif 631 607 cmplwi cr0,r7,1 /* flagged to stay where we are ? */ 632 - bne 1f 633 - add r25,r25,r26 608 + mr r25,r26 /* then use current kernel base */ 609 + beq 1f 610 + LOAD_REG_IMMEDIATE(r25, PAGE_OFFSET) /* else use static kernel base */ 634 611 1: mr r3,r25 635 612 bl relocate 636 613 #if defined(CONFIG_PPC_BOOK3E_64) ··· 639 630 * 640 631 * Note: This process overwrites the OF exception vectors. 641 632 */ 642 - li r3,0 /* target addr */ 643 - #ifdef CONFIG_PPC_BOOK3E_64 644 - tovirt(r3,r3) /* on booke, we already run at PAGE_OFFSET */ 645 - #endif 633 + LOAD_REG_IMMEDIATE(r3, PAGE_OFFSET) 646 634 mr. r4,r26 /* In some cases the loader may */ 647 - #if defined(CONFIG_PPC_BOOK3E_64) 648 - tovirt(r4,r4) 649 - #endif 650 635 beq 9f /* have already put us at zero */ 651 636 li r6,0x100 /* Start offset, the first 0x100 */ 652 637 /* bytes were copied earlier. */ ··· 651 648 * variable __run_at_load, if it is set the kernel is treated as relocatable 652 649 * kernel, otherwise it will be moved to PHYSICAL_START 653 650 */ 654 - #if defined(CONFIG_PPC_BOOK3E_64) 655 - tovirt(r26,r26) /* on booke, we already run at PAGE_OFFSET */ 656 - #endif 657 651 lwz r7,(FIXED_SYMBOL_ABS_ADDR(__run_at_load))(r26) 658 652 cmplwi cr0,r7,1 659 653 bne 3f ··· 769 769 sync 770 770 slbia 771 771 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: 773 780 bl relative_toc 774 - tovirt(r2,r2) 775 781 776 782 /* Copy some CPU settings from CPU 0 */ 777 783 bl __restore_cpu_ppc970 ··· 916 910 * TOC in -mcmodel=medium mode. After we relocate to 0 but before 917 911 * the MMU is on we need our TOC to be a virtual address otherwise 918 912 * these pointers will be real addresses which may get stored and 919 - * accessed later with the MMU on. We use tovirt() at the call 920 - * sites to handle this. 913 + * accessed later with the MMU on. We branch to the virtual address 914 + * while still in real mode then call relative_toc again to handle 915 + * this. 921 916 */ 922 917 _GLOBAL(relative_toc) 923 918 mflr r0 ··· 937 930 */ 938 931 __REF 939 932 start_here_multiplatform: 940 - /* set up the TOC */ 941 - bl relative_toc 942 - tovirt(r2,r2) 933 + /* Adjust TOC for moved kernel. Could adjust when moving it instead. */ 934 + bl relative_toc 943 935 944 936 /* Clear out the BSS. It may have been done in prom_init, 945 937 * already but that's irrelevant since prom_init will soon