📄 head_4xx.s
字号:
/* * Copyright (c) 1995-1996 Gary Thomas <gdt@linuxppc.org> * Initial PowerPC version. * Copyright (c) 1996 Cort Dougan <cort@cs.nmt.edu> * Rewritten for PReP * Copyright (c) 1996 Paul Mackerras <paulus@cs.anu.edu.au> * Low-level exception handers, MMU support, and rewrite. * Copyright (c) 1997 Dan Malek <dmalek@jlc.net> * PowerPC 8xx modifications. * Copyright (c) 1998-1999 TiVo, Inc. * PowerPC 403GCX modifications. * Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu> * PowerPC 403GCX/405GP modifications. * * Module name: head_4xx.S * * Description: * Kernel execution entry point code. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * */#include <linux/config.h>#include <asm/processor.h>#include <asm/page.h>#include <asm/pgtable.h>#include <asm/mmu.h>#include "ppc_asm.h"/* Preprocessor Defines */#define STND_EXC 0#define CRIT_EXC 1###### Check to make sure the right processor has been defined.####if !defined(CONFIG_4xx)#error "This file is only appropriate for kernels supporting the PPC4xx."#endif###### Execution entry point.######### As with the other PowerPC ports, it is expected that when code### execution begins here, the following registers contain valid, yet### optional, information:###### r3 - Board info structure pointer (DRAM, frequency, MAC address, etc.)### r4 - Starting address of the init RAM disk### r5 - Ending address of the init RAM disk### r6 - Start of kernel command line string (e.g. "mem=96m")### r7 - End of kernel command line string### .text_GLOBAL(_stext)_GLOBAL(_start) ## Save residual data, init RAM disk, and command line parameters mr r31,r3 mr r30,r4 mr r29,r5 mr r28,r6 mr r27,r7 ## Set the ID for this CPU li r24,0 ## Invalidate all TLB entries tlbia ## We should still be executing code at physical address 0x0000xxxx ## at this point. However, start_here is at virtual address ## 0xC000xxxx. So, set up a TLB mapping to cover this once ## translation is enabled. lis r3,KERNELBASE@h # Load the kernel virtual address ori r3,r3,KERNELBASE@l tophys(r4,r3) # Load the kernel physical address ## Save the existing PID and load the kernel PID. mfspr r7,SPRN_PID # Save the old PID li r0,0 mtspr SPRN_PID,r0 # Load the kernel PID ## Configure and load entry into TLB slot 0. clrrwi r4,r4,10 # Mask off the real page number ori r4,r4,(TLB_WR | TLB_EX) # Set the write and execute bits clrrwi r3,r3,10 # Mask off the effective page number ori r3,r3,(TLB_VALID | TLB_PAGESZ(PAGESZ_16M)) tlbwe r4,r0,TLB_DATA # Load the data portion of the entry tlbwe r3,r0,TLB_TAG # Load the tag portion of the entry isync mtspr SPRN_PID,r7 # Restore the existing PID ## Establish the exception vector base lis r4,KERNELBASE@h # EVPR only uses the high 16-bits tophys(r0,r4) # Use the physical address mtspr SPRN_EVPR,r0 ## Enable the MMU and jump to the main PowerPC kernel start-up code mfmsr r0 # Get the machine state register ori r0,r0,(MSR_DR | MSR_IR) # Enable data and instr. translation mtspr SPRN_SRR1,r0 # Set up the new machine state register lis r0,start_here@h ori r0,r0,start_here@l mtspr SPRN_SRR0,r0 # Set up the new instruction pointer rfi # Jump to start_here w/ translation on###### Exception vector entry code. This code runs with address translation### turned off (i.e. using physical addresses). We assume SPRG3 has the### physical address of the current task thread_struct.### ## Common exception code for all exception types.#define COMMON_PROLOG \0: mtspr SPRN_SPRG0,r20; /* We need r20, move it to SPRG0 */\ mtspr SPRN_SPRG1,r21; /* We need r21, move it to SPRG1 */\ mfcr r20; /* We need the CR, move it to r20 */\ mfspr r21,SPRN_SPRG2; /* Exception stack to use */\ cmpwi cr0,r21,0; /* From user mode or RTAS? */\ bne 1f; /* Not RTAS, branch */\ tophys(r21, r1); /* Convert vka in r1 to pka in r21 */\ subi r21,r21,INT_FRAME_SIZE; /* Allocate an exception frame */\1: stw r20,_CCR(r21); /* Save CR on the stack */\ stw r22,GPR22(r21); /* Save r22 on the stack */\ stw r23,GPR23(r21); /* r23 Save on the stack */\ mfspr r20,SPRN_SPRG0; /* Get r20 back out of SPRG0 */\ stw r20,GPR20(r21); /* Save r20 on the stack */\ mfspr r22,SPRN_SPRG1; /* Get r21 back out of SPRG0 */\ stw r22,GPR21(r21); /* Save r21 on the stack */\ mflr r20; \ stw r20,_LINK(r21); /* Save LR on the stack */\ mfctr r22; \ stw r22,_CTR(r21); /* Save CTR on the stack */\ mfspr r20,XER; \ stw r20,_XER(r21); /* Save XER on the stack */#define COMMON_EPILOG \ stw r0,GPR0(r21); /* Save r0 on the stack */\ stw r1,GPR1(r21); /* Save r1 on the stack */\ stw r2,GPR2(r21); /* Save r2 on the stack */\ stw r1,0(r21); \ tovirt(r1,r21); /* Set-up new kernel stack pointer */\ SAVE_4GPRS(3, r21); /* Save r3 through r6 on the stack */\ SAVE_GPR(7, r21); /* Save r7 on the stack */ ## Common exception code for standard (non-critical) exceptions.#define STND_EXCEPTION_PROLOG \ COMMON_PROLOG; \ mfspr r22,SPRN_SRR0; /* Faulting instruction address */\ mfspr r23,SPRN_SRR1; /* MSR at the time of fault */\ COMMON_EPILOG; ## Common exception code for critical exceptions. #define CRIT_EXCEPTION_PROLOG \ COMMON_PROLOG; \ mfspr r22,SPRN_SRR2; /* Faulting instruction address */\ mfspr r23,SPRN_SRR3; /* MSR at the time of fault */\ COMMON_EPILOG;###### Macros for specific exception types### #define START_EXCEPTION(n, label) \ . = n; \label:#define FINISH_EXCEPTION(func) \ bl transfer_to_handler; \ .long func; \ .long ret_from_except #define STND_EXCEPTION(n, label, func) \ START_EXCEPTION(n, label); \ STND_EXCEPTION_PROLOG; \ addi r3,r1,STACK_FRAME_OVERHEAD; \ li r7,STND_EXC; \ li r20,MSR_KERNEL; \ FINISH_EXCEPTION(func) #define CRIT_EXCEPTION(n, label, func) \ START_EXCEPTION(n, label); \ CRIT_EXCEPTION_PROLOG; \ addi r3,r1,STACK_FRAME_OVERHEAD; \ li r7,CRIT_EXC; \ li r20,MSR_KERNEL; \ FINISH_EXCEPTION(func) ###### Exception vectors.### ### 0x0100 - Critical Interrupt Exception CRIT_EXCEPTION(0x0100, CriticalInterrupt, UnknownException)### 0x0200 - Machine Check Exception CRIT_EXCEPTION(0x0200, MachineCheck, MachineCheckException)### 0x0300 - Data Storage Exception START_EXCEPTION(0x0300, DataAccess) STND_EXCEPTION_PROLOG mfspr r5,SPRN_ESR # Grab the ESR, save it, pass as arg3 stw r5,_ESR(r21) mfspr r4,SPRN_DEAR # Grab the DEAR, save it, pass as arg2 stw r4,_DEAR(r21) addi r3,r1,STACK_FRAME_OVERHEAD li r7,STND_EXC # This is a standard exception li r20,MSR_KERNEL rlwimi r20,r23,0,16,16 # Copy EE bit from the saved MSR FINISH_EXCEPTION(do_page_fault) # do_page_fault(regs, ESR, DEAR) ### 0x0400 - Instruction Storage Exception START_EXCEPTION(0x0400, InstructionAccess) STND_EXCEPTION_PROLOG mr r4,r22 # Pass SRR0 as arg2 mr r5,r23 # Pass SRR1 as arg3 addi r3,r1,STACK_FRAME_OVERHEAD li r7,STND_EXC # This is a standard exception li r20,MSR_KERNEL rlwimi r20,r23,0,16,16 # Copy EE bit from the saved MSR FINISH_EXCEPTION(do_page_fault) # do_page_fault(regs, SRR0, SRR1) ### 0x0500 - External Interrupt Exception START_EXCEPTION(0x0500, HardwareInterrupt) STND_EXCEPTION_PROLOG addi r3,r1,STACK_FRAME_OVERHEAD li r7,STND_EXC li r20,MSR_KERNEL li r4,0 bl transfer_to_handler_GLOBAL(do_IRQ_intercept) .long do_IRQ .long ret_from_intercept### 0x0600 - Alignment Exception START_EXCEPTION(0x0600, Alignment) STND_EXCEPTION_PROLOG mfspr r4,SPRN_DEAR # Grab the DEAR and save it stw r4,_DEAR(r21) addi r3,r1,STACK_FRAME_OVERHEAD li r7,STND_EXC # This is a standard exception li r20,MSR_KERNEL rlwimi r20,r23,0,16,16 # Copy EE bit from the saved MSR FINISH_EXCEPTION(AlignmentException)### 0x0700 - Program Exception START_EXCEPTION(0x0700, ProgramCheck) STND_EXCEPTION_PROLOG addi r3,r1,STACK_FRAME_OVERHEAD
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -