📄 head_64.s
字号:
.quad HvEsidsToMap /* xNumberEsids */ .quad HvRangesToMap /* xNumberRanges */ .quad STAB0_PAGE /* xSegmentTableOffs */ .zero 40 /* xRsvd */ /* xEsids (HvEsidsToMap entries of 2 quads) */ .quad PAGE_OFFSET_ESID /* xKernelEsid */ .quad PAGE_OFFSET_VSID /* xKernelVsid */ .quad VMALLOC_START_ESID /* xKernelEsid */ .quad VMALLOC_START_VSID /* xKernelVsid */ /* xRanges (HvRangesToMap entries of 3 quads) */ .quad HvPagesToMap /* xPages */ .quad 0 /* xOffset */ .quad PAGE_OFFSET_VSID << (SID_SHIFT - HW_PAGE_SHIFT) /* xVPN */#endif /* CONFIG_PPC_ISERIES */#ifdef CONFIG_PPC_PSERIES . = 0x8000#endif /* CONFIG_PPC_PSERIES *//* * On pSeries and most other platforms, secondary processors spin * in the following code. * At entry, r3 = this processor's number (physical cpu id) */_GLOBAL(generic_secondary_smp_init) mr r24,r3 /* turn on 64-bit mode */ bl .enable_64b_mode /* Set up a paca value for this processor. Since we have the * physical cpu id in r24, we need to search the pacas to find * which logical id maps to our physical one. */ LOAD_REG_IMMEDIATE(r13, paca) /* Get base vaddr of paca array */ li r5,0 /* logical cpu id */1: lhz r6,PACAHWCPUID(r13) /* Load HW procid from paca */ cmpw r6,r24 /* Compare to our id */ beq 2f addi r13,r13,PACA_SIZE /* Loop to next PACA on miss */ addi r5,r5,1 cmpwi r5,NR_CPUS blt 1b mr r3,r24 /* not found, copy phys to r3 */ b .kexec_wait /* next kernel might do better */2: mtspr SPRN_SPRG3,r13 /* Save vaddr of paca in SPRG3 */ /* From now on, r24 is expected to be logical cpuid */ mr r24,r53: HMT_LOW lbz r23,PACAPROCSTART(r13) /* Test if this processor should */ /* start. */ sync#ifndef CONFIG_SMP b 3b /* Never go on non-SMP */#else cmpwi 0,r23,0 beq 3b /* Loop until told to go */ /* See if we need to call a cpu state restore handler */ LOAD_REG_IMMEDIATE(r23, cur_cpu_spec) ld r23,0(r23) ld r23,CPU_SPEC_RESTORE(r23) cmpdi 0,r23,0 beq 4f ld r23,0(r23) mtctr r23 bctrl4: /* Create a temp kernel stack for use before relocation is on. */ ld r1,PACAEMERGSP(r13) subi r1,r1,STACK_FRAME_OVERHEAD b __secondary_start#endif_STATIC(__mmu_off) mfmsr r3 andi. r0,r3,MSR_IR|MSR_DR beqlr andc r3,r3,r0 mtspr SPRN_SRR0,r4 mtspr SPRN_SRR1,r3 sync rfid b . /* prevent speculative execution *//* * Here is our main kernel entry point. We support currently 2 kind of entries * depending on the value of r5. * * r5 != NULL -> OF entry, we go to prom_init, "legacy" parameter content * in r3...r7 * * r5 == NULL -> kexec style entry. r3 is a physical pointer to the * DT block, r4 is a physical pointer to the kernel itself * */_GLOBAL(__start_initialization_multiplatform) /* * Are we booted from a PROM Of-type client-interface ? */ cmpldi cr0,r5,0 beq 1f b .__boot_from_prom /* yes -> prom */1: /* Save parameters */ mr r31,r3 mr r30,r4 /* Make sure we are running in 64 bits mode */ bl .enable_64b_mode /* Setup some critical 970 SPRs before switching MMU off */ mfspr r0,SPRN_PVR srwi r0,r0,16 cmpwi r0,0x39 /* 970 */ beq 1f cmpwi r0,0x3c /* 970FX */ beq 1f cmpwi r0,0x44 /* 970MP */ beq 1f cmpwi r0,0x45 /* 970GX */ bne 2f1: bl .__cpu_preinit_ppc9702: /* Switch off MMU if not already */ LOAD_REG_IMMEDIATE(r4, .__after_prom_start - KERNELBASE) add r4,r4,r30 bl .__mmu_off b .__after_prom_start_INIT_STATIC(__boot_from_prom) /* Save parameters */ mr r31,r3 mr r30,r4 mr r29,r5 mr r28,r6 mr r27,r7 /* * Align the stack to 16-byte boundary * Depending on the size and layout of the ELF sections in the initial * boot binary, the stack pointer will be unalignet on PowerMac */ rldicr r1,r1,0,59 /* Make sure we are running in 64 bits mode */ bl .enable_64b_mode /* put a relocation offset into r3 */ bl .reloc_offset LOAD_REG_IMMEDIATE(r2,__toc_start) addi r2,r2,0x4000 addi r2,r2,0x4000 /* Relocate the TOC from a virt addr to a real addr */ add r2,r2,r3 /* Restore parameters */ mr r3,r31 mr r4,r30 mr r5,r29 mr r6,r28 mr r7,r27 /* Do all of the interaction with OF client interface */ bl .prom_init /* We never return */ trap_STATIC(__after_prom_start)/* * We need to run with __start at physical address PHYSICAL_START. * This will leave some code in the first 256B of * real memory, which are reserved for software use. * The remainder of the first page is loaded with the fixed * interrupt vectors. The next two pages are filled with * unknown exception placeholders. * * Note: This process overwrites the OF exception vectors. * r26 == relocation offset * r27 == KERNELBASE */ bl .reloc_offset mr r26,r3 LOAD_REG_IMMEDIATE(r27, KERNELBASE) LOAD_REG_IMMEDIATE(r3, PHYSICAL_START) /* target addr */ // XXX FIXME: Use phys returned by OF (r30) add r4,r27,r26 /* source addr */ /* current address of _start */ /* i.e. where we are running */ /* the source addr */ cmpdi r4,0 /* In some cases the loader may */ bne 1f b .start_here_multiplatform /* have already put us at zero */ /* so we can skip the copy. */1: LOAD_REG_IMMEDIATE(r5,copy_to_here) /* # bytes of memory to copy */ sub r5,r5,r27 li r6,0x100 /* Start offset, the first 0x100 */ /* bytes were copied earlier. */ bl .copy_and_flush /* copy the first n bytes */ /* this includes the code being */ /* executed here. */ LOAD_REG_IMMEDIATE(r0, 4f) /* Jump to the copy of this code */ mtctr r0 /* that we just made/relocated */ bctr4: LOAD_REG_IMMEDIATE(r5,klimit) add r5,r5,r26 ld r5,0(r5) /* get the value of klimit */ sub r5,r5,r27 bl .copy_and_flush /* copy the rest */ b .start_here_multiplatform/* * Copy routine used to copy the kernel to start at physical address 0 * and flush and invalidate the caches as needed. * r3 = dest addr, r4 = source addr, r5 = copy limit, r6 = start offset * on exit, r3, r4, r5 are unchanged, r6 is updated to be >= r5. * * Note: this routine *only* clobbers r0, r6 and lr */_GLOBAL(copy_and_flush) addi r5,r5,-8 addi r6,r6,-84: li r0,8 /* Use the smallest common */ /* denominator cache line */ /* size. This results in */ /* extra cache line flushes */ /* but operation is correct. */ /* Can't get cache line size */ /* from NACA as it is being */ /* moved too. */ mtctr r0 /* put # words/line in ctr */3: addi r6,r6,8 /* copy a cache line */ ldx r0,r6,r4 stdx r0,r6,r3 bdnz 3b dcbst r6,r3 /* write it to memory */ sync icbi r6,r3 /* flush the icache line */ cmpld 0,r6,r5 blt 4b sync addi r5,r5,8 addi r6,r6,8 blr.align 8copy_to_here:#ifdef CONFIG_SMP#ifdef CONFIG_PPC_PMAC/* * On PowerMac, secondary processors starts from the reset vector, which * is temporarily turned into a call to one of the functions below. */ .section ".text"; .align 2 ; .globl __secondary_start_pmac_0__secondary_start_pmac_0: /* NB the entries for cpus 0, 1, 2 must each occupy 8 bytes. */ li r24,0 b 1f li r24,1 b 1f li r24,2 b 1f li r24,31: _GLOBAL(pmac_secondary_start) /* turn on 64-bit mode */ bl .enable_64b_mode /* Copy some CPU settings from CPU 0 */ bl .__restore_cpu_ppc970 /* pSeries do that early though I don't think we really need it */ mfmsr r3 ori r3,r3,MSR_RI mtmsrd r3 /* RI on */ /* Set up a paca value for this processor. */ LOAD_REG_IMMEDIATE(r4, paca) /* Get base vaddr of paca array */ mulli r13,r24,PACA_SIZE /* Calculate vaddr of right paca */ add r13,r13,r4 /* for this processor. */ mtspr SPRN_SPRG3,r13 /* Save vaddr of paca in SPRG3 */ /* Create a temp kernel stack for use before relocation is on. */ ld r1,PACAEMERGSP(r13) subi r1,r1,STACK_FRAME_OVERHEAD b __secondary_start#endif /* CONFIG_PPC_PMAC *//* * This function is called after the master CPU has released the * secondary processors. The execution environment is relocation off. * The paca for this processor has the following fields initialized at * this point: * 1. Processor number * 2. Segment table pointer (virtual address) * On entry the following are set: * r1 = stack pointer. vaddr for iSeries, raddr (temp stack) for pSeries * r24 = cpu# (in Linux terms) * r13 = paca virtual address * SPRG3 = paca virtual address */ .globl __secondary_start__secondary_start: /* Set thread priority to MEDIUM */ HMT_MEDIUM /* Load TOC */ ld r2,PACATOC(r13) /* Do early setup for that CPU (stab, slb, hash table pointer) */ bl .early_setup_secondary /* Initialize the kernel stack. Just a repeat for iSeries. */ LOAD_REG_ADDR(r3, current_set) sldi r28,r24,3 /* get current_set[cpu#] */ ldx r1,r3,r28 addi r1,r1,THREAD_SIZE-STACK_FRAME_OVERHEAD std r1,PACAKSAVE(r13) /* Clear backchain so we get nice backtraces */ li r7,0 mtlr r7 /* enable MMU and jump to start_secondary */ LOAD_REG_ADDR(r3, .start_secondary_prolog) LOAD_REG_IMMEDIATE(r4, MSR_KERNEL)#ifdef CONFIG_PPC_ISERIESBEGIN_FW_FTR_SECTION ori r4,r4,MSR_EEEND_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)#endifBEGIN_FW_FTR_SECTION stb r7,PACASOFTIRQEN(r13) stb r7,PACAHARDIRQEN(r13)END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES) mtspr SPRN_SRR0,r3 mtspr SPRN_SRR1,r4 rfid b . /* prevent speculative execution *//* * Running with relocation on at this point. All we want to do is * zero the stack back-chain pointer before going into C code. */_GLOBAL(start_secondary_prolog) li r3,0 std r3,0(r1) /* Zero the stack frame pointer */ bl .start_secondary b .#endif/* * This subroutine clobbers r11 and r12 */_GLOBAL(enable_64b_mode) mfmsr r11 /* grab the current MSR */ li r12,1 rldicr r12,r12,MSR_SF_LG,(63-MSR_SF_LG) or r11,r11,r12 li r12,1 rldicr r12,r12,MSR_ISF_LG,(63-MSR_ISF_LG) or r11,r11,r12 mtmsrd r11 isync blr/* * This is where the main kernel code starts. */_INIT_STATIC(start_here_multiplatform) /* get a new offset, now that the kernel has moved. */ bl .reloc_offset mr r26,r3 /* Clear out the BSS. It may have been done in prom_init, * already but that's irrelevant since prom_init will soon * be detached from the kernel completely. Besides, we need * to clear it now for kexec-style entry. */ LOAD_REG_IMMEDIATE(r11,__bss_stop) LOAD_REG_IMMEDIATE(r8,__bss_start) sub r11,r11,r8 /* bss size */ addi r11,r11,7 /* round up to an even double word */ rldicl. r11,r11,61,3 /* shift right by 3 */ beq 4f addi r8,r8,-8 li r0,0 mtctr r11 /* zero this many doublewords */3: stdu r0,8(r8) bdnz 3b4: mfmsr r6 ori r6,r6,MSR_RI mtmsrd r6 /* RI on */ /* The following gets the stack and TOC set up with the regs */ /* pointing to the real addr of the kernel stack. This is */ /* all done to support the C function call below which sets */ /* up the htab. This is done because we have relocated the */ /* kernel but are still running in real mode. */ LOAD_REG_IMMEDIATE(r3,init_thread_union) add r3,r3,r26 /* set up a stack pointer (physical address) */ addi r1,r3,THREAD_SIZE li r0,0 stdu r0,-STACK_FRAME_OVERHEAD(r1) /* set up the TOC (physical address) */ LOAD_REG_IMMEDIATE(r2,__toc_start) addi r2,r2,0x4000 addi r2,r2,0x4000 add r2,r2,r26 /* Do very early kernel initializations, including initial hash table, * stab and slb setup before we turn on relocation. */ /* Restore parameters passed from prom_init/kexec */ mr r3,r31 bl .early_setup LOAD_REG_IMMEDIATE(r3, .start_here_common) LOAD_REG_IMMEDIATE(r4, MSR_KERNEL) mtspr SPRN_SRR0,r3 mtspr SPRN_SRR1,r4 rfid b . /* prevent speculative execution */ /* This is where all platforms converge execution */_INIT_GLOBAL(start_here_common) /* relocation is on at this point */ /* The following code sets up the SP and TOC now that we are */ /* running with translation enabled. */ LOAD_REG_IMMEDIATE(r3,init_thread_union) /* set up the stack */ addi r1,r3,THREAD_SIZE li r0,0 stdu r0,-STACK_FRAME_OVERHEAD(r1) /* ptr to current */ LOAD_REG_IMMEDIATE(r4, init_task) std r4,PACACURRENT(r13) /* Load the TOC */ ld r2,PACATOC(r13) std r1,PACAKSAVE(r13) bl .setup_system /* Load up the kernel context */5: li r5,0 stb r5,PACASOFTIRQEN(r13) /* Soft Disabled */#ifdef CONFIG_PPC_ISERIESBEGIN_FW_FTR_SECTION mfmsr r5 ori r5,r5,MSR_EE /* Hard Enabled */ mtmsrd r5END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)#endifBEGIN_FW_FTR_SECTION stb r5,PACAHARDIRQEN(r13)END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES) bl .start_kernel /* Not reached */ BUG_OPCODE/* * We put a few things here that have to be page-aligned. * This stuff goes at the beginning of the bss, which is page-aligned. */ .section ".bss" .align PAGE_SHIFT .globl empty_zero_pageempty_zero_page: .space PAGE_SIZE .globl swapper_pg_dirswapper_pg_dir: .space PGD_TABLE_SIZE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -