📄 head.s
字号:
mfspr 13,SPRG3 /* Get paca address */ lhz r24,PACAPACAINDEX(r13) /* Get processor # */ cmpi 0,r24,0 /* Are we processor 0? */ beq .__start_initialization_iSeries /* Start up the first processor */ mfspr r4,CTRLF li r5,RUNLATCH /* Turn off the run light */ andc r4,r4,r5 mtspr CTRLT,r41: HMT_LOW#ifdef CONFIG_SMP lbz r23,PACAPROCSTART(r13) /* Test if this processor * should start */ sync LOADADDR(r3,current_set) sldi r28,r24,4 /* get current_set[cpu#] */ ldx r3,r3,r28 addi r1,r3,TASK_UNION_SIZE subi r1,r1,STACK_FRAME_OVERHEAD cmpi 0,r23,0 beq iseries_secondary_smp_loop /* Loop until told to go */#ifdef SECONDARY_PROCESSORS bne .__secondary_start /* Loop until told to go */#endifiseries_secondary_smp_loop: /* Let the Hypervisor know we are alive */ /* 8002 is a call to HvCallCfg::getLps, a harmless Hypervisor function */ lis r3,0x8002 rldicr r3,r3,32,15 /* r0 = (r3 << 32) & 0xffff000000000000 */#else /* CONFIG_SMP */ /* Yield the processor. This is required for non-SMP kernels which are running on multi-threaded machines. */ lis r3,0x8000 rldicr r3,r3,32,15 /* r3 = (r3 << 32) & 0xffff000000000000 */ addi r3,r3,18 /* r3 = 0x8000000000000012 which is "yield" */ li r4,0 /* "yield timed" */ li r5,-1 /* "yield forever" */#endif /* CONFIG_SMP */ li r0,-1 /* r0=-1 indicates a Hypervisor call */ sc /* Invoke the hypervisor via a system call */ mfspr r13,SPRG3 /* Put r13 back - why???? */ b 1b /* If SMP not configured, secondaries * loop forever */ .globl HardwareInterrupt_Iseries_maskedHardwareInterrupt_Iseries_masked: b maskable_exception_exit .globl PerformanceMonitor_Iseries_maskedPerformanceMonitor_Iseries_masked: li r22,1 stb r22,PACALPPACA+LPPACAPDCINT(r20) b maskable_exception_exit .globl Decrementer_Iseries_maskedDecrementer_Iseries_masked: li r22,1 stb r22,PACALPPACA+LPPACADECRINT(r20) lwz r22,PACADEFAULTDECR(r20) mtspr DEC,r22maskable_exception_exit: mtcrf 0xff,r23 /* Restore regs and free exception frame */ ld r22,EX_SRR0(r21) ld r23,EX_SRR1(r21) mtspr SRR0,r22 mtspr SRR1,r23 ld r22,EX_R22(r21) ld r23,EX_R23(r21) mfspr r21,SPRG1 mfspr r20,SPRG2 rfid/* * Data area reserved for FWNMI option. */ .= 0x7000 .globl fwnmi_data_areafwnmi_data_area:/* * Vectors for the FWNMI option. Share common code. */ . = 0x8000 .globl SystemReset_FWNMISystemReset_FWNMI: EXCEPTION_PROLOG_PSERIES(0x100, SystemReset_common) .globl MachineCheck_FWNMIMachineCheck_FWNMI: EXCEPTION_PROLOG_PSERIES(0x200, MachineCheck_common) /* * Space for the initial segment table * For LPAR, the hypervisor must fill in at least one entry * before we get control (with relocate on) */ . = STAB0_PHYS_ADDR .globl __start_stab__start_stab: . = (STAB0_PHYS_ADDR + PAGE_SIZE) .globl __end_stab__end_stab:/*** Common interrupt handlers ***/ STD_EXCEPTION_COMMON( 0x100, SystemReset, .SystemResetException ) STD_EXCEPTION_COMMON( 0x200, MachineCheck, .MachineCheckException ) STD_EXCEPTION_COMMON( 0x900, Decrementer, .timer_interrupt ) STD_EXCEPTION_COMMON( 0xa00, Trap_0a, .UnknownException ) STD_EXCEPTION_COMMON( 0xb00, Trap_0b, .UnknownException ) STD_EXCEPTION_COMMON( 0xd00, SingleStep, .SingleStepException ) STD_EXCEPTION_COMMON( 0xe00, Trap_0e, .UnknownException ) .globl AltiVecUnavailable_commonAltiVecUnavailable_common: EXCEPTION_PROLOG_COMMON#ifdef CONFIG_ALTIVEC bne .load_up_altivec /* if from user, just load it up */#endif addi r3,r1,STACK_FRAME_OVERHEAD DO_COPY_EE() li r6,0xf20 bl .save_remaining_regs#ifndef CONFIG_ALTIVEC beq 1f bl .IllegalAltiVecInstruction b .ret_from_except1:#endif bl .KernelAltiVecUnavailableException BUG_OPCODE .global AltiVecAssist_commonAltiVecAssist_common: EXCEPTION_PROLOG_COMMON addi r3,r1,STACK_FRAME_OVERHEAD DO_COPY_EE() li r6,0x1700 bl .save_remaining_regs bl .AltiVecAssistException b .ret_from_except .global ThermalInterrupt_commonThermalInterrupt_common: EXCEPTION_PROLOG_COMMON addi r3,r1,STACK_FRAME_OVERHEAD DO_COPY_EE() li r6,0x1800 bl .save_remaining_regs bl .ThermalInterrupt BUG_OPCODE STD_EXCEPTION_COMMON(0x1300, InstructionBreakpoint, .InstructionBreakpointException )/* * Return from an exception which is handled without calling * save_remaining_regs. The caller is assumed to have done * EXCEPTION_PROLOG_COMMON. */fast_exception_return: ld r3,_CCR(r1) ld r4,_LINK(r1) ld r5,_CTR(r1) ld r6,_XER(r1) mtcr r3 mtlr r4 mtctr r5 mtspr XER,r6 REST_GPR(0, r1) REST_8GPRS(2, r1) REST_4GPRS(10, r1) mfmsr r20 li r21, MSR_RI andc r20,r20,r21 mtmsrd r20,1 mtspr SRR1,r23 mtspr SRR0,r22 REST_4GPRS(20, r1) ld r1,GPR1(r1) rfid/* * Here r20 points to the PACA, r21 to the exception frame, * r23 contains the saved CR. * r20 - r23, SRR0 and SRR1 are saved in the exception frame. */ .globl DataAccess_commonDataAccess_common: mfspr r22,DSISR andis. r22,r22,0x0020 beq 1f mfspr r22,DAR /* if it's a segment table miss, */ srdi r22,r22,60 /* check if it is in kernel region */ cmpi 0,r22,0xc /* and call do_stab_bolted if so */ beq .do_stab_bolted cmpi 0,r22,0xb beq .do_stab_bolted1: EXCEPTION_PROLOG_COMMON ld r3,_DSISR(r1) andis. r0,r3,0xa450 /* weird error? */ bne 1f /* if not, try to put a PTE */ andis. r0,r3,0x0020 /* Is it a page table fault? */ rlwinm r4,r3,32-23,29,29 /* DSISR_STORE -> _PAGE_RW */ ld r3,_DAR(r1) /* into the hash table */ beq 2f /* If so handle it */ li r4,0x300 /* Trap number */ bl .do_stab_SI b 1f2: li r5,0x300 bl .do_hash_page_DSI /* Try to handle as hpte fault */1: ld r4,_DAR(r1) ld r5,_DSISR(r1) addi r3,r1,STACK_FRAME_OVERHEAD DO_COPY_EE() li r6,0x300 bl .save_remaining_regs bl .do_page_fault b .ret_from_except .globl DataAccessSLB_commonDataAccessSLB_common: mfspr r22,DAR srdi r22,r22,60 cmpi 0,r22,0xc beq .do_slb_bolted cmpi 0,r22,0xb beq .do_slb_bolted EXCEPTION_PROLOG_COMMON ld r3,_DAR(r1) li r4,0x380 /* Exception vector */ bl .ste_allocate or. r3,r3,r3 /* Check return code */ beq fast_exception_return /* Return if we succeeded */ addi r3,r1,STACK_FRAME_OVERHEAD DO_COPY_EE() li r6,0x380 li r5,0 bl .save_remaining_regs bl .do_page_fault b .ret_from_except .globl InstructionAccess_commonInstructionAccess_common: EXCEPTION_PROLOG_COMMON andis. r0,r23,0x0020 /* no ste found? */ beq 2f mr r3,r22 /* SRR0 at interrupt */ li r4,0x400 /* Trap number */ bl .do_stab_SI b 1f2: andis. r0,r23,0x4000 /* no pte found? */ beq 1f /* if so, try to put a PTE */ mr r3,r22 /* into the hash table */ bl .do_hash_page_ISI /* Try to handle as hpte fault */1: mr r4,r22 rlwinm r5,r23,0,4,4 /* We only care about PR in error_code */ addi r3,r1,STACK_FRAME_OVERHEAD DO_COPY_EE() li r6,0x400 bl .save_remaining_regs bl .do_page_fault b .ret_from_except .globl InstructionAccessSLB_commonInstructionAccessSLB_common: EXCEPTION_PROLOG_COMMON mr r3,r22 /* SRR0 = NIA */ li r4,0x480 /* Exception vector */ bl .ste_allocate or. r3,r3,r3 /* Check return code */ beq fast_exception_return /* Return if we succeeded */ addi r3,r1,STACK_FRAME_OVERHEAD DO_COPY_EE() li r6,0x480 li r5,0 bl .save_remaining_regs bl .do_page_fault b .ret_from_except .globl HardwareInterrupt_commonHardwareInterrupt_common: EXCEPTION_PROLOG_COMMONHardwareInterrupt_entry: addi r3,r1,STACK_FRAME_OVERHEAD li r20,0 li r6,0x500 bl .save_remaining_regs /* Determine if need to run do_irq on a hardware interrupt stack */ /* The first invocation of do_irq will occur on the kernel */ /* stack in the current stack */ /* All other invocations of do_irq will run on the hardware */ /* interrupt stack associated with the PACA of the current */ /* processor. */ /* */ /* The call to do_irq will preserve the value of r14 - r31 */ /* */ mfspr r20,SPRG3 /* get paca */ lbz r21,PACAHRDWINTCOUNT(r20) /* get hardware interrupt cnt */ cmpi 0,r21,0 /* */ addi r21,r21,1 /* incr hardware interrupt cnt*/ stb r21,PACAHRDWINTCOUNT(r20) /* */ bne 2f /* */ mr r14,r1 /* preserve current r1 */ ld r1,PACAHRDWINTSTACK(r20) /* */ std r14,0(r1) /* set the back chain */ bl .do_IRQ lbz r22,PACAHRDWINTCOUNT(r20) /* get hardware interrupt cnt */ cmp 0,r22,r21 /* debug test */ bne 3f subi r21,r21,1 stb r21,PACAHRDWINTCOUNT(r20) /* */ mr r1,r14 /* */ b .ret_from_except2: bl .do_IRQ lbz r22,PACAHRDWINTCOUNT(r20) /* get hardware interrupt cnt */ cmp 0,r22,r21 /* debug test */ bne 3f /* */ subi r21,r21,1 /* decr hardware interrupt cnt*/ stb r21,PACAHRDWINTCOUNT(r20) /* */ b .ret_from_except3: /* error - counts out of sync */#ifdef CONFIG_XMON bl .xmon#endif#ifdef CONFIG_KDB /* kdb(KDB_REASON_FAULT,regs->trap,regs); */ li r3,1 li r4,0x200 li r5,0 bl .kdb#endif4: b 4b .globl Alignment_commonAlignment_common: EXCEPTION_PROLOG_COMMON addi r3,r1,STACK_FRAME_OVERHEAD DO_COPY_EE() li r6,0x600 bl .save_remaining_regs bl .AlignmentException b .ret_from_except .globl ProgramCheck_commonProgramCheck_common: EXCEPTION_PROLOG_COMMON addi r3,r1,STACK_FRAME_OVERHEAD DO_COPY_EE() li r6,0x700 bl .save_remaining_regs bl .ProgramCheckException b .ret_from_except .globl FPUnavailable_commonFPUnavailable_common: EXCEPTION_PROLOG_COMMON bne .load_up_fpu /* if from user, just load it up */ addi r3,r1,STACK_FRAME_OVERHEAD DO_COPY_EE() li r6,0x800 bl .save_remaining_regs bl .KernelFPUnavailableException BUG_OPCODE .globl SystemCall_commonSystemCall_common: EXCEPTION_PROLOG_COMMON#ifdef CONFIG_PPC_ISERIES cmpi 0,r0,0x5555 /* Special syscall to handle pending */ bne+ 1f /* interrupts */ andi. r6,r23,MSR_PR /* Only allowed from kernel */ beq+ HardwareInterrupt_entry1:#endif std r3,ORIG_GPR3(r1) DO_COPY_EE() li r6,0xC00 bl .save_remaining_regs bl .DoSyscall b .ret_from_except .globl PerformanceMonitor_commonPerformanceMonitor_common: EXCEPTION_PROLOG_COMMON bl .PerformanceMonitorException b fast_exception_return _GLOBAL(PerformanceMonitorException) sync mfspr r7,SPRG3 lbz r8,PACAPROFMODE(r7) cmpi 0,r8,PMC_STATE_PROFILE_KERN beq 5f cmpi 0,r8,PMC_STATE_TRACE_KERN beq 6f cmpi 0,r8,PMC_STATE_TRACE_USER beq 9f cmpi 0,r8,PMC_STATE_TIMESLICE beq 10f blr /* PMC Profile Kernel */5: mfspr r9,SIAR srdi r8,r9,60 cmpi 0,r8,0xc beq 3f li r9,0xc sldi r9,r9,603: ld r8,PACAPROFSTEXT(r7) /* _stext */ subf r9,r8,r9 /* offset into kernel */ lwz r8,PACAPROFSHIFT(r7) srd r9,r9,r8 lwz r8,PACAPROFLEN(r7) /* length of profile table (-1) */ srdi r8,r8,2 cmpd r9,r8 /* off end? */ ble 1f mr r9,r8 /* force into last entry */ srdi r9,r9,21: sldi r9,r9,2 /* convert to offset into buffer */ ld r8,PACAPROFBUFFER(r7) /* profile buffer */ add r8,r8,r92: lwarx r9,0,r8 /* atomically increment */ addi r9,r9,1 stwcx. r9,0,r8 bne- 2b addi r10,r7,PACAPMC1 addi r7,r7,PACAPMCC1 b 7f /* PMC Trace Kernel */6: LOADADDR(r11, perfmon_base) addi r8,r11,32 ld r12,24(r11) subi r12,r12,18: ldarx r10,0,r8 addi r9,r10,16 and r9,r9,r12 stdcx. r9,0,r8 bne- 8b ld r9,16(r11) /* profile buffer */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -