head_64.s
来自「LINUX 2.6.17.4的源码」· S 代码 · 共 2,003 行 · 第 1/4 页
S
2,003 行
addi r8,r8,-8 li r0,0 mtctr r11 /* zero this many doublewords */3: stdu r0,8(r8) bdnz 3b4: LOAD_REG_IMMEDIATE(r1,init_thread_union) addi r1,r1,THREAD_SIZE li r0,0 stdu r0,-STACK_FRAME_OVERHEAD(r1) LOAD_REG_IMMEDIATE(r3,cpu_specs) LOAD_REG_IMMEDIATE(r4,cur_cpu_spec) li r5,0 bl .identify_cpu LOAD_REG_IMMEDIATE(r2,__toc_start) addi r2,r2,0x4000 addi r2,r2,0x4000 bl .iSeries_early_setup bl .early_setup /* relocation is on at this point */ b .start_here_common#endif /* CONFIG_PPC_ISERIES */#ifdef CONFIG_PPC_MULTIPLATFORM_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)#ifdef CONFIG_PPC_MULTIPLATFORM /* * Are we booted from a PROM Of-type client-interface ? */ cmpldi cr0,r5,0 bne .__boot_from_prom /* yes -> prom */#endif /* 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 */ bl .__970_cpu_preinit /* cpu # */ li r24,0 /* 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#ifdef CONFIG_PPC_MULTIPLATFORM_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#endif/* * At this point, r3 contains the physical address we are running at, * returned by prom_init() */_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 */ 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#endif /* CONFIG_PPC_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,16 /* Use the least 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 isync /* Copy some CPU settings from CPU 0 */ bl .__restore_cpu_setup /* 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 */_GLOBAL(__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 DO_SOFT_DISABLE ori r4,r4,MSR_EE#endif 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#ifdef CONFIG_PPC_MULTIPLATFORM/* * This is where the main kernel code starts. */_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 LOAD_REG_IMMEDIATE(r3, cpu_specs) add r3,r3,r26 LOAD_REG_IMMEDIATE(r4,cur_cpu_spec) add r4,r4,r26 mr r5,r26 bl .identify_cpu /* Save some low level config HIDs of CPU0 to be copied to * other CPUs later on, or used for suspend/resume */ bl .__save_cpu_setup sync /* 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 */#endif /* CONFIG_PPC_MULTIPLATFORM */ /* This is where all platforms converge execution */_STATIC(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) /* Apply the CPUs-specific fixups (nop out sections not relevant * to this CPU */ li r3,0 bl .do_cpu_ftr_fixups LOAD_REG_IMMEDIATE(r26, boot_cpuid) lwz r26,0(r26) LOAD_REG_IMMEDIATE(r24, paca) /* Get base vaddr of paca array */ mulli r13,r26,PACA_SIZE /* Calculate vaddr of right paca */ add r13,r13,r24 /* for this processor. */ mtspr SPRN_SPRG3,r13 /* 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:#ifdef DO_SOFT_DISABLE li r5,0 stb r5,PACAPROCENABLED(r13) /* Soft Disabled */ mfmsr r5 ori r5,r5,MSR_EE /* Hard Enabled */ mtmsrd r5#endif bl .start_kernel /* Not reached */ BUG_OPCODE/* Put the paca pointer into r13 and SPRG3 */_GLOBAL(setup_boot_paca) LOAD_REG_IMMEDIATE(r3, boot_cpuid) lwz r3,0(r3) LOAD_REG_IMMEDIATE(r4, paca) /* Get base vaddr of paca array */ mulli r3,r3,PACA_SIZE /* Calculate vaddr of right paca */ add r13,r3,r4 /* for this processor. */ mtspr SPRN_SPRG3,r13 blr/* * 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 PAGE_SIZE/* * This space gets a copy of optional info passed to us by the bootstrap * Used to pass parameters into the kernel like root=/dev/sda1, etc. */ .globl cmd_linecmd_line: .space COMMAND_LINE_SIZE
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?