head_4xx.S
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:16k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * BK Id: SCCS/s.head_4xx.S 1.6 05/21/01 11:50:00 paulus
  3.  */
  4. /*
  5.  *    Copyright (c) 1995-1996 Gary Thomas <gdt@linuxppc.org>
  6.  *      Initial PowerPC version.
  7.  *    Copyright (c) 1996 Cort Dougan <cort@cs.nmt.edu>
  8.  *      Rewritten for PReP
  9.  *    Copyright (c) 1996 Paul Mackerras <paulus@cs.anu.edu.au>
  10.  *      Low-level exception handers, MMU support, and rewrite.
  11.  *    Copyright (c) 1997 Dan Malek <dmalek@jlc.net>
  12.  *      PowerPC 8xx modifications.
  13.  *    Copyright (c) 1998-1999 TiVo, Inc.
  14.  *      PowerPC 403GCX modifications.
  15.  *    Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
  16.  *      PowerPC 403GCX/405GP modifications.
  17.  *
  18.  *    Module name: head_4xx.S
  19.  *
  20.  *    Description:
  21.  *      Kernel execution entry point code.
  22.  *
  23.  *    This program is free software; you can redistribute it and/or
  24.  *    modify it under the terms of the GNU General Public License
  25.  *    as published by the Free Software Foundation; either version
  26.  *    2 of the License, or (at your option) any later version.
  27.  *
  28.  */
  29. #include <linux/config.h>
  30. #include <asm/processor.h>
  31. #include <asm/page.h>
  32. #include <asm/pgtable.h>
  33. #include <asm/mmu.h>
  34. #include "ppc_asm.h"
  35. /* Preprocessor Defines */
  36. #define STND_EXC 0
  37. #define CRIT_EXC 1
  38. ###
  39. ### Check to make sure the right processor has been defined.
  40. ###
  41. #if !defined(CONFIG_4xx)
  42. #error "This file is only appropriate for kernels supporting the PPC4xx."
  43. #endif
  44. ###
  45. ### Execution entry point.
  46. ###
  47. ###
  48. ### As with the other PowerPC ports, it is expected that when code
  49. ### execution begins here, the following registers contain valid, yet
  50. ### optional, information:
  51. ###
  52. ###   r3 - Board info structure pointer (DRAM, frequency, MAC address, etc.)
  53. ###   r4 - Starting address of the init RAM disk
  54. ###   r5 - Ending address of the init RAM disk
  55. ###   r6 - Start of kernel command line string (e.g. "mem=96m")
  56. ###   r7 - End of kernel command line string
  57. ### 
  58. .text
  59. _GLOBAL(_stext)
  60. _GLOBAL(_start)
  61. ## Save residual data, init RAM disk, and command line parameters
  62. mr r31,r3
  63. mr r30,r4
  64. mr r29,r5
  65. mr r28,r6
  66. mr r27,r7
  67. ## Set the ID for this CPU
  68. li r24,0
  69. ## Invalidate all TLB entries
  70. tlbia
  71. ## We should still be executing code at physical address 0x0000xxxx
  72. ## at this point. However, start_here is at virtual address
  73. ## 0xC000xxxx. So, set up a TLB mapping to cover this once
  74. ## translation is enabled.
  75. lis r3,KERNELBASE@h # Load the kernel virtual address
  76. ori r3,r3,KERNELBASE@l
  77. tophys(r4,r3) # Load the kernel physical address
  78. ## Save the existing PID and load the kernel PID.
  79. mfspr r7,SPRN_PID # Save the old PID
  80. li r0,0
  81. mtspr SPRN_PID,r0 # Load the kernel PID
  82. ## Configure and load entry into TLB slot 0.
  83. clrrwi r4,r4,10 # Mask off the real page number
  84. ori r4,r4,(TLB_WR | TLB_EX) # Set the write and execute bits
  85. clrrwi r3,r3,10 # Mask off the effective page number
  86. ori r3,r3,(TLB_VALID | TLB_PAGESZ(PAGESZ_16M))
  87. tlbwe r4,r0,TLB_DATA # Load the data portion of the entry
  88. tlbwe r3,r0,TLB_TAG # Load the tag portion of the entry
  89. isync
  90. mtspr SPRN_PID,r7 # Restore the existing PID
  91. ## Establish the exception vector base
  92. lis r4,KERNELBASE@h # EVPR only uses the high 16-bits
  93. tophys(r0,r4) # Use the physical address
  94. mtspr SPRN_EVPR,r0
  95. ## Enable the MMU and jump to the main PowerPC kernel start-up code
  96. mfmsr r0 # Get the machine state register
  97. ori r0,r0,(MSR_DR | MSR_IR) # Enable data and instr. translation
  98. mtspr SPRN_SRR1,r0 # Set up the new machine state register
  99. lis r0,start_here@h
  100. ori r0,r0,start_here@l
  101. mtspr SPRN_SRR0,r0 # Set up the new instruction pointer
  102. rfi # Jump to start_here w/ translation on
  103. ###
  104. ### Exception vector entry code. This code runs with address translation
  105. ### turned off (i.e. using physical addresses). We assume SPRG3 has the
  106. ### physical address of the current task thread_struct.
  107. ### 
  108. ## Common exception code for all exception types.
  109. #define COMMON_PROLOG      
  110. 0: mtspr SPRN_SPRG0,r20; /* We need r20, move it to SPRG0   */
  111. mtspr SPRN_SPRG1,r21; /* We need r21, move it to SPRG1   */
  112. mfcr r20; /* We need the CR, move it to r20  */
  113. mfspr r21,SPRN_SPRG2; /* Exception stack to use    */
  114. cmpwi cr0,r21,0; /* From user mode or RTAS?    */
  115. bne 1f; /* Not RTAS, branch    */
  116. tophys(r21, r1); /* Convert vka in r1 to pka in r21 */
  117. subi r21,r21,INT_FRAME_SIZE; /* Allocate an exception frame    */
  118. 1: stw r20,_CCR(r21); /* Save CR on the stack    */
  119. stw r22,GPR22(r21); /* Save r22 on the stack    */
  120. stw r23,GPR23(r21); /* r23 Save on the stack    */
  121. mfspr r20,SPRN_SPRG0; /* Get r20 back out of SPRG0    */
  122. stw r20,GPR20(r21); /* Save r20 on the stack    */
  123. mfspr r22,SPRN_SPRG1; /* Get r21 back out of SPRG0    */
  124. stw r22,GPR21(r21); /* Save r21 on the stack    */
  125. mflr r20;      
  126. stw r20,_LINK(r21); /* Save LR on the stack    */
  127. mfctr r22;      
  128. stw r22,_CTR(r21); /* Save CTR on the stack    */
  129. mfspr r20,XER;      
  130. stw r20,_XER(r21); /* Save XER on the stack    */
  131. #define COMMON_EPILOG      
  132. stw r0,GPR0(r21); /* Save r0 on the stack    */
  133. stw r1,GPR1(r21); /* Save r1 on the stack    */
  134. stw r2,GPR2(r21); /* Save r2 on the stack    */
  135. stw r1,0(r21);      
  136. tovirt(r1,r21); /* Set-up new kernel stack pointer */
  137. SAVE_4GPRS(3, r21); /* Save r3 through r6 on the stack */
  138. SAVE_GPR(7, r21); /* Save r7 on the stack    */
  139. ## Common exception code for standard (non-critical) exceptions.
  140. #define STND_EXCEPTION_PROLOG      
  141. COMMON_PROLOG;      
  142. mfspr r22,SPRN_SRR0; /* Faulting instruction address    */
  143. mfspr r23,SPRN_SRR1; /* MSR at the time of fault    */
  144. COMMON_EPILOG;
  145. ## Common exception code for critical exceptions.
  146. #define CRIT_EXCEPTION_PROLOG      
  147. COMMON_PROLOG;      
  148. mfspr r22,SPRN_SRR2; /* Faulting instruction address    */
  149. mfspr r23,SPRN_SRR3; /* MSR at the time of fault    */
  150. COMMON_EPILOG;
  151. ###
  152. ### Macros for specific exception types
  153. ### 
  154. #define START_EXCEPTION(n, label)      
  155. . = n;      
  156. label:
  157. #define FINISH_EXCEPTION(func)      
  158. bl transfer_to_handler;      
  159. .long func;      
  160. .long ret_from_except
  161. #define STND_EXCEPTION(n, label, func)      
  162. START_EXCEPTION(n, label);      
  163. STND_EXCEPTION_PROLOG;      
  164. addi r3,r1,STACK_FRAME_OVERHEAD;      
  165. li r7,STND_EXC;      
  166. li r20,MSR_KERNEL;      
  167. FINISH_EXCEPTION(func)
  168. #define CRIT_EXCEPTION(n, label, func)      
  169. START_EXCEPTION(n, label);      
  170. CRIT_EXCEPTION_PROLOG;      
  171. addi r3,r1,STACK_FRAME_OVERHEAD;      
  172. li r7,CRIT_EXC;      
  173. li r20,MSR_KERNEL;      
  174. FINISH_EXCEPTION(func)
  175. ###
  176. ### Exception vectors.
  177. ### 
  178. ### 0x0100 - Critical Interrupt Exception
  179. CRIT_EXCEPTION(0x0100, CriticalInterrupt, UnknownException)
  180. ### 0x0200 - Machine Check Exception
  181. CRIT_EXCEPTION(0x0200, MachineCheck, MachineCheckException)
  182. ### 0x0300 - Data Storage Exception
  183. START_EXCEPTION(0x0300, DataAccess)
  184. STND_EXCEPTION_PROLOG
  185. mfspr r5,SPRN_ESR # Grab the ESR, save it, pass as arg3
  186. stw r5,_ESR(r21)
  187. mfspr r4,SPRN_DEAR # Grab the DEAR, save it, pass as arg2
  188. stw r4,_DEAR(r21)
  189. addi r3,r1,STACK_FRAME_OVERHEAD
  190. li r7,STND_EXC # This is a standard exception
  191. li r20,MSR_KERNEL
  192. rlwimi r20,r23,0,16,16 # Copy EE bit from the saved MSR
  193. FINISH_EXCEPTION(do_page_fault) # do_page_fault(regs, ESR, DEAR)
  194. ### 0x0400 - Instruction Storage Exception
  195. START_EXCEPTION(0x0400, InstructionAccess)
  196. STND_EXCEPTION_PROLOG
  197. mr r4,r22 # Pass SRR0 as arg2
  198. mr r5,r23 # Pass SRR1 as arg3
  199. addi r3,r1,STACK_FRAME_OVERHEAD
  200. li r7,STND_EXC # This is a standard exception
  201. li r20,MSR_KERNEL
  202. rlwimi r20,r23,0,16,16 # Copy EE bit from the saved MSR
  203. FINISH_EXCEPTION(do_page_fault) # do_page_fault(regs, SRR0, SRR1)
  204. ### 0x0500 - External Interrupt Exception
  205. START_EXCEPTION(0x0500, HardwareInterrupt)
  206. STND_EXCEPTION_PROLOG
  207. addi r3,r1,STACK_FRAME_OVERHEAD
  208. li r7,STND_EXC
  209. li r20,MSR_KERNEL
  210. li r4,0
  211. bl transfer_to_handler
  212. _GLOBAL(do_IRQ_intercept)
  213. .long do_IRQ
  214. .long ret_from_intercept
  215. ### 0x0600 - Alignment Exception
  216. START_EXCEPTION(0x0600, Alignment)
  217. STND_EXCEPTION_PROLOG
  218. mfspr r4,SPRN_DEAR # Grab the DEAR and save it
  219. stw r4,_DEAR(r21)
  220. addi r3,r1,STACK_FRAME_OVERHEAD
  221. li r7,STND_EXC # This is a standard exception
  222. li r20,MSR_KERNEL
  223. rlwimi r20,r23,0,16,16 # Copy EE bit from the saved MSR
  224. FINISH_EXCEPTION(AlignmentException)
  225. ### 0x0700 - Program Exception
  226. START_EXCEPTION(0x0700, ProgramCheck)
  227. STND_EXCEPTION_PROLOG
  228. addi r3,r1,STACK_FRAME_OVERHEAD
  229. li r7,STND_EXC # This is a standard exception
  230. li r20,MSR_KERNEL
  231. rlwimi r20,r23,0,16,16 # Copy EE bit from the saved MSR
  232. FINISH_EXCEPTION(ProgramCheckException)
  233. STND_EXCEPTION(0x0800, Trap_08, UnknownException)
  234. STND_EXCEPTION(0x0900, Trap_09, UnknownException)
  235. STND_EXCEPTION(0x0A00, Trap_0A, UnknownException)
  236. STND_EXCEPTION(0x0B00, Trap_0B, UnknownException)
  237. ### 0x0C00 - System Call Exception
  238. START_EXCEPTION(0x0C00, SystemCall)
  239. STND_EXCEPTION_PROLOG
  240. stw r3,ORIG_GPR3(r21)
  241. li r7,STND_EXC # This is a standard exception
  242. li r20,MSR_KERNEL
  243. rlwimi r20,r23,0,16,16 # Copy EE bit from the saved MSR
  244. FINISH_EXCEPTION(DoSyscall)
  245. STND_EXCEPTION(0x0D00, Trap_0D, UnknownException)
  246. STND_EXCEPTION(0x0E00, Trap_0E, UnknownException)
  247. STND_EXCEPTION(0x0F00, Trap_0F, UnknownException)
  248. ### 0x1000 - Programmable Interval Timer (PIT) Exception
  249. START_EXCEPTION(0x1000, Decrementer)
  250. STND_EXCEPTION_PROLOG
  251. lis r0,TSR_PIS@h # Set-up the PIT exception mask
  252. mtspr SPRN_TSR,r0 # Clear the PIT exception
  253. addi r3,r1,STACK_FRAME_OVERHEAD
  254. li r7,STND_EXC # This is a standard exception
  255. li r20,MSR_KERNEL
  256. bl transfer_to_handler
  257. _GLOBAL(timer_interrupt_intercept)
  258. .long timer_interrupt
  259. .long ret_from_intercept
  260. #if 0
  261. ### 0x1010 - Fixed Interval Timer (FIT) Exception
  262. STND_EXCEPTION(0x1010, FITException, UnknownException)
  263. ### 0x1020 - Watchdog Timer (WDT) Exception
  264. CRIT_EXCEPTION(0x1020, WDTException, UnknownException)
  265. #endif
  266. ### 0x1100 - Data TLB Miss Exception
  267. STND_EXCEPTION(0x1100, DTLBMiss,  PPC4xx_dtlb_miss)
  268. ### 0x1200 - Instruction TLB Miss Exception
  269. STND_EXCEPTION(0x1200, ITLBMiss,  PPC4xx_itlb_miss)
  270. STND_EXCEPTION(0x1300, Trap_13, UnknownException)
  271. STND_EXCEPTION(0x1400, Trap_14, UnknownException)
  272. STND_EXCEPTION(0x1500, Trap_15, UnknownException)
  273. STND_EXCEPTION(0x1600, Trap_16, UnknownException)
  274. STND_EXCEPTION(0x1700, Trap_17, UnknownException)
  275. STND_EXCEPTION(0x1800, Trap_18, UnknownException)
  276. STND_EXCEPTION(0x1900, Trap_19, UnknownException)
  277. STND_EXCEPTION(0x1A00, Trap_1A, UnknownException)
  278. STND_EXCEPTION(0x1B00, Trap_1B, UnknownException)
  279. STND_EXCEPTION(0x1C00, Trap_1C, UnknownException)
  280. STND_EXCEPTION(0x1D00, Trap_1D, UnknownException)
  281. STND_EXCEPTION(0x1E00, Trap_1E, UnknownException)
  282. STND_EXCEPTION(0x1F00, Trap_1F, UnknownException)
  283. ### 0x2000 - Debug Exception
  284. CRIT_EXCEPTION(0x2000, DebugTrap, UnknownException)
  285. ###
  286. ### Other PowerPC processors, namely those derived from the 6xx-series
  287. ### have vectors from 0x2100 through 0x2F00 defined, but marked as reserved.
  288. ### However, for the 4xx-series processors these are neither defined nor
  289. ### reserved.
  290. ### 
  291. ### 
  292. ### This code finishes saving the registers to the exception frame
  293. ### and jumps to the appropriate handler for the exception, turning
  294. ### on address translation.
  295. ###
  296. _GLOBAL(transfer_to_handler)
  297. stw r22,_NIP(r21) # Save the faulting IP on the stack
  298. stw r23,_MSR(r21) # Save the exception MSR on the stack
  299. SAVE_4GPRS(8, r21) # Save r8 through r11 on the stack
  300. SAVE_8GPRS(12, r21) # Save r12 through r19 on the stack
  301. SAVE_8GPRS(24, r21) # Save r24 through r31 on the stack
  302. andi. r23,r23,MSR_PR # Is this from user space?
  303. mfspr r23,SPRN_SPRG3 # If from user, fix up THREAD.regs
  304. beq 2f # No, it is from the kernel; branch.
  305. addi r24,r1,STACK_FRAME_OVERHEAD
  306. stw r24,PT_REGS(r23) # 
  307. 2: addi r2,r23,-THREAD # Set r2 to current thread
  308. tovirt(r2,r2)
  309. mflr r23
  310. andi. r24,r23,0x3f00 # Get vector offset
  311. stw r24,TRAP(r21)
  312. li r22,0
  313. stw r22,RESULT(r21)
  314. mtspr SPRN_SPRG2,r22 # r1 is now the kernel stack pointer
  315. addi r24,r2,TASK_STRUCT_SIZE # Check for kernel stack overflow
  316. cmplw cr0,r1,r2
  317. cmplw cr1,r1,r24
  318. crand cr1,cr1,cr4
  319. bgt- stack_ovf # If r2 < r1 < r2 + TASK_STRUCT_SIZE
  320. lwz r24,0(r23) # Virtual address of the handler
  321. lwz r23,4(r23) # Handler return pointer
  322. cmpwi cr0,r7,STND_EXC # What type of exception is this?
  323. bne 3f # It is a critical exception...
  324. ## Standard exception jump path
  325. mtspr SPRN_SRR0,r24 # Set up the instruction pointer
  326. mtspr SPRN_SRR1,r20 # Set up the machine state register
  327. mtlr r23 # Set up the return pointer
  328. SYNC
  329. rfi # Enable the MMU, jump to the handler
  330. ## Critical exception jump path
  331. 3: mtspr SPRN_SRR2,r24 # Set up the instruction pointer
  332. mtspr SPRN_SRR3,r20 # Set up the machine state register
  333. mtlr r23 # Set up the return pointer
  334. SYNC
  335. rfci # Enable the MMU, jump to the handler
  336. ###
  337. ### On kernel stack overlow, load up an initial stack pointer and call
  338. ### StackOverflow(regs), which should NOT return.
  339. ### 
  340. stack_ovf:
  341. addi r3,r1,STACK_FRAME_OVERHEAD
  342. lis r1,init_task_union@ha
  343. addi r1,r1,init_task_union@l
  344. addi r1,r1,TASK_UNION_SIZE - STACK_FRAME_OVERHEAD
  345. lis r24,StackOverflow@ha
  346. addi r24,r24,StackOverflow@l
  347. li r20,MSR_KERNEL
  348. mtspr SPRN_SRR0,r24 # Set up the instruction pointer
  349. mtspr SPRN_SRR1,r20 # Set up the machine state register
  350. SYNC
  351. rfi # Enable the MMU, jump to StackOverflow
  352. ###
  353. ### extern void giveup_altivec(struct task_struct *prev)
  354. ###
  355. ### The PowerPC 4xx family of processors do not have AltiVec capabilities, so
  356. ### this just returns.
  357. ###
  358. _GLOBAL(giveup_altivec)
  359. blr
  360. ###
  361. ### extern void giveup_fpu(struct task_struct *prev)
  362. ###
  363. ### The PowerPC 4xx family of processors do not have an FPU, so this just
  364. ### returns.
  365. ###
  366. _GLOBAL(giveup_fpu)
  367. blr
  368. ###
  369. ### extern void abort(void)
  370. ###
  371. ### At present, this routine just applies a system reset.
  372. ### 
  373. _GLOBAL(abort)
  374. mfspr r13,SPRN_DBCR
  375. oris r13,r13,DBCR_RST(DBCR_RST_SYSTEM)@h
  376. mtspr SPRN_DBCR,r13
  377. ### 
  378. ### This is where the main kernel code starts.
  379. ### 
  380. start_here:
  381. ## Establish a pointer to the current task
  382. lis r2,init_task_union@h
  383. ori r2,r2,init_task_union@l
  384. ## Clear out the BSS as per ANSI C requirements
  385. lis r7,_end@ha
  386. addi r7,r7,_end@l
  387. lis r8,__bss_start@ha
  388. addi r8,r8,__bss_start@l
  389. subf r7,r8,r7
  390. addi r7,r7,3
  391. srwi. r7,r7,2
  392. beq 2f
  393. addi r8,r8,-4
  394. mtctr r7
  395. li r0,0
  396. 3: stwu r0,4(r8)
  397. bdnz 3b
  398. ## Stack
  399. 2: addi r1,r2,TASK_UNION_SIZE
  400. li r0,0
  401. stwu r0,-STACK_FRAME_OVERHEAD(r1)
  402. ## Determine what type of platform this is.
  403. mr r3,r31
  404. mr r4,r30
  405. mr r5,r29
  406. mr r6,r28
  407. mr r7,r27
  408. bl identify_machine
  409. ## Initialize the memory management unit.
  410. bl MMU_init
  411. ## Go back to running unmapped so that we can change to our
  412. ## exception vectors.
  413. lis r4,2f@h
  414. ori r4,r4,2f@l
  415. tophys(r4,r4)
  416. li r3,MSR_KERNEL & ~(MSR_IR|MSR_DR)
  417. mtspr SPRN_SRR0,r4 # Set up the instruction pointer
  418. mtspr SPRN_SRR1,r3 # Set up the machine state register
  419. rfi
  420. ## Load up the kernel context
  421. 2: SYNC # Force all PTE updates to finish
  422. # tlbia # Clear all TLB entries
  423. # sync # Wait for tlbia to finish...
  424. ## Set up for using our exception vectors
  425. tophys(r4,r2) # Pointer to physical current thread
  426. addi r4,r4,THREAD # The init task thread
  427. mtspr SPRN_SPRG3,r4 # Save it for exceptions later
  428. li r3,0 # 
  429. mtspr SPRN_SPRG2,r3 # 0 implies r1 has kernel stack pointer
  430. ## Really turn on the MMU and jump into the kernel
  431.         lis     r4,MSR_KERNEL@h
  432.         ori     r4,r4,MSR_KERNEL@l
  433.         lis     r3,start_kernel@h
  434.         ori     r3,r3,start_kernel@l
  435.         mtspr   SPRN_SRR0,r3 # Set up the instruction pointer
  436.         mtspr   SPRN_SRR1,r4 # Set up the machine state register
  437.         rfi # Enable the MMU, jump to the kernel
  438. _GLOBAL(set_context)
  439. mtspr SPRN_PID,r3
  440. blr
  441. ###
  442. ### We put a few things here that have to be page-aligned. This stuff
  443. ### goes at the beginning of the data segment, which is page-aligned.
  444. ###
  445. .data
  446. _GLOBAL(sdata)
  447. _GLOBAL(empty_zero_page)
  448. .space 4096
  449. _GLOBAL(swapper_pg_dir)
  450. .space 4096
  451. ###
  452. ### This space gets a copy of optional info passed to us by the bootstrap
  453. ### which is used to pass parameters into the kernel like root=/dev/sda1, etc.
  454. ###
  455. _GLOBAL(cmd_line)
  456. .space 512