head_4xx.S
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:16k
源码类别:

Linux/Unix编程

开发平台:

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