proc-arm6,7.S
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:13k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  *  linux/arch/arm/mm/proc-arm6,7.S
  3.  *
  4.  *  Copyright (C) 1997-2000 Russell King
  5.  *
  6.  * This program is free software; you can redistribute it and/or modify
  7.  * it under the terms of the GNU General Public License version 2 as
  8.  * published by the Free Software Foundation.
  9.  *
  10.  *  These are the low level assembler for performing cache and TLB
  11.  *  functions on the ARM610 & ARM710.
  12.  */
  13. #include <linux/linkage.h>
  14. #include <asm/assembler.h>
  15. #include <asm/constants.h>
  16. #include <asm/procinfo.h>
  17. /*
  18.  * Function: arm6_7_cache_clean_invalidate_all (void)
  19.  *    : arm6_7_cache_clean_invalidate_page (unsigned long address, int size, int flags)
  20.  *
  21.  * Params  : address Area start address
  22.  *    : size size of area
  23.  *    : flags b0 = I cache as well
  24.  *
  25.  * Purpose : Flush all cache lines
  26.  */
  27. ENTRY(cpu_arm6_cache_clean_invalidate_all)
  28. ENTRY(cpu_arm7_cache_clean_invalidate_all)
  29. ENTRY(cpu_arm6_cache_clean_invalidate_range)
  30. ENTRY(cpu_arm7_cache_clean_invalidate_range)
  31. ENTRY(cpu_arm6_icache_invalidate_range)
  32. ENTRY(cpu_arm7_icache_invalidate_range)
  33. ENTRY(cpu_arm6_icache_invalidate_page)
  34. ENTRY(cpu_arm7_icache_invalidate_page)
  35. ENTRY(cpu_arm6_dcache_clean_range)
  36. ENTRY(cpu_arm7_dcache_clean_range)
  37. ENTRY(cpu_arm6_dcache_invalidate_range)
  38. ENTRY(cpu_arm7_dcache_invalidate_range)
  39. mov r0, #0
  40. mcr p15, 0, r0, c7, c0, 0 @ flush cache
  41. ENTRY(cpu_arm6_dcache_clean_page)
  42. ENTRY(cpu_arm7_dcache_clean_page)
  43. ENTRY(cpu_arm6_dcache_clean_entry)
  44. ENTRY(cpu_arm7_dcache_clean_entry)
  45. ENTRY(cpu_arm6_flush_ram_page)
  46. ENTRY(cpu_arm7_flush_ram_page)
  47. mov pc, lr
  48. /*
  49.  * Function: arm6_7_tlb_invalidate_all (void)
  50.  *
  51.  * Purpose : flush all TLB entries in all caches
  52.  */
  53. ENTRY(cpu_arm6_tlb_invalidate_all)
  54. ENTRY(cpu_arm7_tlb_invalidate_all)
  55. mov r0, #0
  56. mcr p15, 0, r0, c5, c0, 0 @ flush TLB
  57. mov pc, lr
  58. /*
  59.  * Function: arm6_7_tlb_invalidate_page (unsigned long address, int end, int flags)
  60.  *
  61.  * Params  : address Area start address
  62.  *    : end Area end address
  63.  *    : flags b0 = I cache as well
  64.  *
  65.  * Purpose : flush a TLB entry
  66.  */
  67. ENTRY(cpu_arm6_tlb_invalidate_range)
  68. ENTRY(cpu_arm7_tlb_invalidate_range)
  69. 1: mcr p15, 0, r0, c6, c0, 0 @ flush TLB
  70. add r0, r0, #4096
  71. cmp r0, r1
  72. blt 1b
  73. mov pc, lr
  74. /*
  75.  * Function: arm6_7_tlb_invalidate_page (unsigned long address, int flags)
  76.  *
  77.  * Params  : address Address
  78.  *    : flags b0 = I-TLB as well
  79.  *
  80.  * Purpose : flush a TLB entry
  81.  */
  82. ENTRY(cpu_arm6_tlb_invalidate_page)
  83. ENTRY(cpu_arm7_tlb_invalidate_page)
  84. mcr p15, 0, r0, c6, c0, 0 @ flush TLB
  85. mov pc, lr
  86. /*
  87.  * Function: arm6_7_data_abort ()
  88.  *
  89.  * Params  : r0 = address of aborted instruction
  90.  *
  91.  * Purpose : obtain information about current aborted instruction
  92.  *
  93.  * Returns : r0 = address of abort
  94.  *    : r1 != 0 if writing
  95.  *    : r3 = FSR
  96.  *    : sp = pointer to registers
  97.  */
  98. ENTRY(cpu_arm6_data_abort)
  99. ldr r4, [r0] @ read instruction causing problem
  100. tst r4, r4, lsr #21 @ C = bit 20
  101. sbc r1, r1, r1 @ r1 = C - 1
  102. and r2, r4, #14 << 24
  103. teq r2, #8 << 24 @ was it ldm/stm
  104. bne Ldata_simple
  105. Ldata_ldmstm: tst r4, #1 << 21 @ check writeback bit
  106. beq Ldata_simple
  107. mov r7, #0x11
  108. orr r7, r7, r7, lsl #8
  109. and r0, r4, r7
  110. and r2, r4, r7, lsl #1
  111. add r0, r0, r2, lsr #1
  112. and r2, r4, r7, lsl #2
  113. add r0, r0, r2, lsr #2
  114. and r2, r4, r7, lsl #3
  115. add r0, r0, r2, lsr #3
  116. add r0, r0, r0, lsr #8
  117. add r0, r0, r0, lsr #4
  118. and r7, r0, #15 @ r7 = no. of registers to transfer.
  119. and r5, r4, #15 << 16 @ Get Rn
  120. ldr r0, [sp, r5, lsr #14] @ Get register
  121. tst r4, #1 << 23 @ U bit
  122. subne r7, r0, r7, lsl #2
  123. addeq r7, r0, r7, lsl #2 @ Do correction (signed)
  124. Ldata_saver7: str r7, [sp, r5, lsr #14] @ Put register
  125. Ldata_simple: mrc p15, 0, r0, c6, c0, 0 @ get FAR
  126. mrc p15, 0, r3, c5, c0, 0 @ get FSR
  127. and r3, r3, #255
  128. mov pc, lr
  129. ENTRY(cpu_arm7_data_abort)
  130. ldr r4, [r0] @ read instruction causing problem
  131. tst r4, r4, lsr #21 @ C = bit 20
  132. sbc r1, r1, r1 @ r1 = C - 1
  133. and r2, r4, #15 << 24
  134. add pc, pc, r2, lsr #22 @ Now branch to the relevent processing routine
  135. movs pc, lr
  136. b Ldata_unknown
  137. b Ldata_unknown
  138. b Ldata_unknown
  139. b Ldata_unknown
  140. b Ldata_lateldrpostconst @ ldr rd, [rn], #m
  141. b Ldata_lateldrpreconst @ ldr rd, [rn, #m] @ RegVal
  142. b Ldata_lateldrpostreg @ ldr rd, [rn], rm
  143. b Ldata_lateldrprereg @ ldr rd, [rn, rm]
  144. b Ldata_ldmstm @ ldm*a rn, <rlist>
  145. b Ldata_ldmstm @ ldm*b rn, <rlist>
  146. b Ldata_unknown
  147. b Ldata_unknown
  148. b Ldata_simple @ ldc rd, [rn], #m @ Same as ldr rd, [rn], #m
  149. b Ldata_simple @ ldc rd, [rn, #m]
  150. b Ldata_unknown
  151. Ldata_unknown: @ Part of jumptable
  152. mov r0, r2
  153. mov r1, r4
  154. mov r2, r3
  155. bl baddataabort
  156. b ret_from_exception
  157. Ldata_lateldrpreconst:
  158. tst r4, #1 << 21 @ check writeback bit
  159. beq Ldata_simple
  160. Ldata_lateldrpostconst:
  161. movs r2, r4, lsl #20 @ Get offset
  162. beq Ldata_simple
  163. and r5, r4, #15 << 16 @ Get Rn
  164. ldr r0, [sp, r5, lsr #14]
  165. tst r4, #1 << 23 @ U bit
  166. subne r7, r0, r2, lsr #20
  167. addeq r7, r0, r2, lsr #20
  168. b Ldata_saver7
  169. Ldata_lateldrprereg:
  170. tst r4, #1 << 21 @ check writeback bit
  171. beq Ldata_simple
  172. Ldata_lateldrpostreg:
  173. and r5, r4, #15
  174. ldr r2, [sp, r5, lsl #2] @ Get Rm
  175. mov r3, r4, lsr #7
  176. ands r3, r3, #31
  177. and r6, r4, #0x70
  178. orreq r6, r6, #8
  179. add pc, pc, r6
  180. mov r0, r0
  181. mov r2, r2, lsl r3 @ 0: LSL #!0
  182. b 1f
  183. b 1f @ 1: LSL #0
  184. mov r0, r0
  185. b 1f @ 2: MUL?
  186. mov r0, r0
  187. b 1f @ 3: MUL?
  188. mov r0, r0
  189. mov r2, r2, lsr r3 @ 4: LSR #!0
  190. b 1f
  191. mov r2, r2, lsr #32 @ 5: LSR #32
  192. b 1f
  193. b 1f @ 6: MUL?
  194. mov r0, r0
  195. b 1f @ 7: MUL?
  196. mov r0, r0
  197. mov r2, r2, asr r3 @ 8: ASR #!0
  198. b 1f
  199. mov r2, r2, asr #32 @ 9: ASR #32
  200. b 1f
  201. b 1f @ A: MUL?
  202. mov r0, r0
  203. b 1f @ B: MUL?
  204. mov r0, r0
  205. mov r2, r2, ror r3 @ C: ROR #!0
  206. b 1f
  207. mov r2, r2, rrx @ D: RRX
  208. b 1f
  209. mov r0, r0 @ E: MUL?
  210. mov r0, r0
  211. mov r0, r0 @ F: MUL?
  212. 1: and r5, r4, #15 << 16 @ Get Rn
  213. ldr r0, [sp, r5, lsr #14]
  214. tst r4, #1 << 23 @ U bit
  215. subne r7, r0, r2
  216. addeq r7, r0, r2
  217. b Ldata_saver7
  218. /*
  219.  * Function: arm6_7_check_bugs (void)
  220.  *    : arm6_7_proc_init (void)
  221.  *    : arm6_7_proc_fin (void)
  222.  *
  223.  * Notes   : This processor does not require these
  224.  */
  225. ENTRY(cpu_arm6_check_bugs)
  226. ENTRY(cpu_arm7_check_bugs)
  227. mrs ip, cpsr
  228. bic ip, ip, #F_BIT
  229. msr cpsr, ip
  230. mov pc, lr
  231. ENTRY(cpu_arm6_proc_init)
  232. ENTRY(cpu_arm7_proc_init)
  233. mov pc, lr
  234. ENTRY(cpu_arm6_proc_fin)
  235. ENTRY(cpu_arm7_proc_fin)
  236. mov r0, #F_BIT | I_BIT | SVC_MODE
  237. msr cpsr_c, r0
  238. mov r0, #0x31 @ ....S..DP...M
  239. mcr p15, 0, r0, c1, c0, 0 @ disable caches
  240. mov pc, lr
  241. ENTRY(cpu_arm6_do_idle)
  242. ENTRY(cpu_arm7_do_idle)
  243. mov r0, #-EINVAL
  244. mov pc, lr
  245. /*
  246.  * Function: arm6_7_set_pgd(unsigned long pgd_phys)
  247.  * Params  : pgd_phys Physical address of page table
  248.  * Purpose : Perform a task switch, saving the old processes state, and restoring
  249.  *      the new.
  250.  */
  251. ENTRY(cpu_arm6_set_pgd)
  252. ENTRY(cpu_arm7_set_pgd)
  253. mov r1, #0
  254. mcr p15, 0, r1, c7, c0, 0 @ flush cache
  255. mcr p15, 0, r0, c2, c0, 0 @ update page table ptr
  256. mcr p15, 0, r1, c5, c0, 0 @ flush TLBs
  257. mov pc, lr
  258. /*
  259.  * Function: arm6_set_pmd ()
  260.  *
  261.  * Params  : r0 = Address to set
  262.  *    : r1 = value to set
  263.  *
  264.  * Purpose : Set a PMD and flush it out of any WB cache
  265.  */
  266. ENTRY(cpu_arm6_set_pmd)
  267. and r2, r1, #11
  268. teq r2, #1
  269. teqne r2, #9
  270. teqne r2, #10
  271. orreq r1, r1, #16 @ Updatable = 1 if Page table/Cacheable section
  272. str r1, [r0]
  273. mov pc, lr
  274. /*
  275.  * Function: arm7_set_pmd ()
  276.  *
  277.  * Params  : r0 = Address to set
  278.  *    : r1 = value to set
  279.  *
  280.  * Purpose : Set a PMD and flush it out of any WB cache
  281.  */
  282. ENTRY(cpu_arm7_set_pmd)
  283. tst r1, #3
  284. orrne r1, r1, #16 @ Updatable bit is always set on ARM7
  285. str r1, [r0]
  286. mov pc, lr
  287. /*
  288.  * Function: arm6_7_set_pte(pte_t *ptep, pte_t pte)
  289.  * Params  : r0 = Address to set
  290.  *    : r1 = value to set
  291.  * Purpose : Set a PTE and flush it out of any WB cache
  292.  */
  293. .align 5
  294. ENTRY(cpu_arm6_set_pte)
  295. ENTRY(cpu_arm7_set_pte)
  296. str r1, [r0], #-1024 @ linux version
  297. eor r1, r1, #LPTE_PRESENT | LPTE_YOUNG | LPTE_WRITE | LPTE_DIRTY
  298. bic r2, r1, #0xff0
  299. bic r2, r2, #3
  300. orr r2, r2, #HPTE_TYPE_SMALL
  301. tst r1, #LPTE_USER | LPTE_EXEC @ User or Exec?
  302. orrne r2, r2, #HPTE_AP_READ
  303. tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty?
  304. orreq r2, r2, #HPTE_AP_WRITE
  305. tst r1, #LPTE_PRESENT | LPTE_YOUNG @ Present and Young
  306. movne r2, #0
  307. str r2, [r0] @ hardware version
  308. mov pc, lr
  309. /*
  310.  * Function: _arm6_7_reset
  311.  * Params  : r0 = address to jump to
  312.  * Notes   : This sets up everything for a reset
  313.  */
  314. ENTRY(cpu_arm6_reset)
  315. ENTRY(cpu_arm7_reset)
  316. mov r1, #0
  317. mcr p15, 0, r1, c7, c0, 0 @ flush cache
  318. mcr p15, 0, r1, c5, c0, 0 @ flush TLB
  319. mov r1, #0x30
  320. mcr p15, 0, r1, c1, c0, 0 @ turn off MMU etc
  321. mov pc, r0
  322. cpu_armvlsi_name:
  323. .asciz "ARM/VLSI"
  324. cpu_arm6_name: .asciz "ARM 6"
  325. cpu_arm610_name:
  326. .asciz "ARM 610"
  327. cpu_arm7_name: .asciz "ARM 7"
  328. cpu_arm710_name:
  329. .asciz "ARM 710"
  330. .align
  331. .section ".text.init", #alloc, #execinstr
  332. __arm6_setup: mov r0, #0
  333. mcr p15, 0, r0, c7, c0 @ flush caches on v3
  334. mcr p15, 0, r0, c5, c0 @ flush TLBs on v3
  335. mcr p15, 0, r4, c2, c0 @ load page table pointer
  336. mov r0, #0x1f @ Domains 0, 1 = client
  337. mcr p15, 0, r0, c3, c0 @ load domain access register
  338. mov r0, #0x3d @ . ..RS BLDP WCAM
  339. orr r0, r0, #0x100 @ . ..01 0011 1101
  340. mov pc, lr
  341. __arm7_setup: mov r0, #0
  342. mcr p15, 0, r0, c7, c0 @ flush caches on v3
  343. mcr p15, 0, r0, c5, c0 @ flush TLBs on v3
  344. mcr p15, 0, r4, c2, c0 @ load page table pointer
  345. mov r0, #0x1f @ Domains 0, 1 = client
  346. mcr p15, 0, r0, c3, c0 @ load domain access register
  347. mov r0, #0x7d @ . ..RS BLDP WCAM
  348. orr r0, r0, #0x100 @ . ..01 0111 1101
  349. mov pc, lr
  350. /*
  351.  * Purpose : Function pointers used to access above functions - all calls
  352.  *      come through these
  353.  */
  354. .type arm6_processor_functions, #object
  355. ENTRY(arm6_processor_functions)
  356. .word cpu_arm6_data_abort
  357. .word cpu_arm6_check_bugs
  358. .word cpu_arm6_proc_init
  359. .word cpu_arm6_proc_fin
  360. .word cpu_arm6_reset
  361. .word cpu_arm6_do_idle
  362. /* cache */
  363. .word cpu_arm6_cache_clean_invalidate_all
  364. .word cpu_arm6_cache_clean_invalidate_range
  365. .word cpu_arm6_flush_ram_page
  366. /* dcache */
  367. .word cpu_arm6_dcache_invalidate_range
  368. .word cpu_arm6_dcache_clean_range
  369. .word cpu_arm6_dcache_clean_page
  370. .word cpu_arm6_dcache_clean_entry
  371. /* icache */
  372. .word cpu_arm6_icache_invalidate_range
  373. .word cpu_arm6_icache_invalidate_page
  374. /* tlb */
  375. .word cpu_arm6_tlb_invalidate_all
  376. .word cpu_arm6_tlb_invalidate_range
  377. .word cpu_arm6_tlb_invalidate_page
  378. /* pgtable */
  379. .word cpu_arm6_set_pgd
  380. .word cpu_arm6_set_pmd
  381. .word cpu_arm6_set_pte
  382. .size arm6_processor_functions, . - arm6_processor_functions
  383. /*
  384.  * Purpose : Function pointers used to access above functions - all calls
  385.  *      come through these
  386.  */
  387. .type arm7_processor_functions, #object
  388. ENTRY(arm7_processor_functions)
  389. .word cpu_arm7_data_abort
  390. .word cpu_arm7_check_bugs
  391. .word cpu_arm7_proc_init
  392. .word cpu_arm7_proc_fin
  393. .word cpu_arm7_reset
  394. .word cpu_arm7_do_idle
  395. /* cache */
  396. .word cpu_arm7_cache_clean_invalidate_all
  397. .word cpu_arm7_cache_clean_invalidate_range
  398. .word cpu_arm7_flush_ram_page
  399. /* dcache */
  400. .word cpu_arm7_dcache_invalidate_range
  401. .word cpu_arm7_dcache_clean_range
  402. .word cpu_arm7_dcache_clean_page
  403. .word cpu_arm7_dcache_clean_entry
  404. /* icache */
  405. .word cpu_arm7_icache_invalidate_range
  406. .word cpu_arm7_icache_invalidate_page
  407. /* tlb */
  408. .word cpu_arm7_tlb_invalidate_all
  409. .word cpu_arm7_tlb_invalidate_range
  410. .word cpu_arm7_tlb_invalidate_page
  411. /* pgtable */
  412. .word cpu_arm7_set_pgd
  413. .word cpu_arm7_set_pmd
  414. .word cpu_arm7_set_pte
  415. .size arm7_processor_functions, . - arm7_processor_functions
  416. .type cpu_arm6_info, #object
  417. cpu_arm6_info:
  418. .long cpu_armvlsi_name
  419. .long cpu_arm6_name
  420. .size cpu_arm6_info, . - cpu_arm6_info
  421. .type cpu_arm610_info, #object
  422. cpu_arm610_info:
  423. .long cpu_armvlsi_name
  424. .long cpu_arm610_name
  425. .size cpu_arm610_info, . - cpu_Arm610_info
  426. .type cpu_arm7_info, #object
  427. cpu_arm7_info:
  428. .long cpu_armvlsi_name
  429. .long cpu_arm7_name
  430. .size cpu_arm7_info, . - cpu_arm7_info
  431. .type cpu_arm710_info, #object
  432. cpu_arm710_info:
  433. .long cpu_armvlsi_name
  434. .long cpu_arm710_name
  435. .size cpu_arm710_info, . - cpu_arm710_info
  436. .type cpu_arch_name, #object
  437. cpu_arch_name: .asciz "armv3"
  438. .size cpu_arch_name, . - cpu_arch_name
  439. .type cpu_elf_name, #object
  440. cpu_elf_name: .asciz "v3"
  441. .size cpu_elf_name, . - cpu_elf_name
  442. .align
  443. .section ".proc.info", #alloc, #execinstr
  444. .type __arm6_proc_info, #object
  445. __arm6_proc_info:
  446. .long 0x41560600
  447. .long 0xfffffff0
  448. .long 0x00000c1e
  449. b __arm6_setup
  450. .long cpu_arch_name
  451. .long cpu_elf_name
  452. .long HWCAP_SWP | HWCAP_26BIT
  453. .long cpu_arm6_info
  454. .long arm6_processor_functions
  455. .size __arm6_proc_info, . - __arm6_proc_info
  456. .type __arm610_proc_info, #object
  457. __arm610_proc_info:
  458. .long 0x41560610
  459. .long 0xfffffff0
  460. .long 0x00000c1e
  461. b __arm6_setup
  462. .long cpu_arch_name
  463. .long cpu_elf_name
  464. .long HWCAP_SWP | HWCAP_26BIT
  465. .long cpu_arm610_info
  466. .long arm6_processor_functions
  467. .size __arm610_proc_info, . - __arm610_proc_info
  468. .type __arm7_proc_info, #object
  469. __arm7_proc_info:
  470. .long 0x41007000
  471. .long 0xffffff00
  472. .long 0x00000c1e
  473. b __arm7_setup
  474. .long cpu_arch_name
  475. .long cpu_elf_name
  476. .long HWCAP_SWP | HWCAP_26BIT
  477. .long cpu_arm7_info
  478. .long arm7_processor_functions
  479. .size __arm7_proc_info, . - __arm7_proc_info
  480. .type __arm710_proc_info, #object
  481. __arm710_proc_info:
  482. .long 0x41007100
  483. .long 0xfff8ff00
  484. .long 0x00000c1e
  485. b __arm7_setup
  486. .long cpu_arch_name
  487. .long cpu_elf_name
  488. .long HWCAP_SWP | HWCAP_26BIT
  489. .long cpu_arm710_info
  490. .long arm7_processor_functions
  491. .size __arm710_proc_info, . - __arm710_proc_info