proc-funcs.S 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. /*
  2. * linux/arch/arm26/mm/proc-arm2,3.S
  3. *
  4. * Copyright (C) 1997-1999 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. * MMU functions for ARM2,3
  11. *
  12. * These are the low level assembler for performing cache
  13. * and memory functions on ARM2, ARM250 and ARM3 processors.
  14. */
  15. #include <linux/linkage.h>
  16. #include <asm/assembler.h>
  17. #include <asm/asm_offsets.h>
  18. #include <asm/procinfo.h>
  19. #include <asm/ptrace.h>
  20. /*
  21. * MEMC workhorse code. It's both a horse which things it's a pig.
  22. */
  23. /*
  24. * Function: cpu_memc_update_entry(pgd_t *pgd, unsigned long phys_pte, unsigned long addr)
  25. * Params : pgd Page tables/MEMC mapping
  26. * : phys_pte physical address, or PTE
  27. * : addr virtual address
  28. */
  29. ENTRY(cpu_memc_update_entry)
  30. tst r1, #PAGE_PRESENT @ is the page present
  31. orreq r1, r1, #PAGE_OLD | PAGE_CLEAN
  32. moveq r2, #0x01f00000
  33. mov r3, r1, lsr #13 @ convert to physical page nr
  34. and r3, r3, #0x3fc
  35. adr ip, memc_phys_table_32
  36. ldr r3, [ip, r3]
  37. tst r1, #PAGE_OLD | PAGE_NOT_USER
  38. biceq r3, r3, #0x200
  39. tsteq r1, #PAGE_READONLY | PAGE_CLEAN
  40. biceq r3, r3, #0x300
  41. mov r2, r2, lsr #15 @ virtual -> nr
  42. orr r3, r3, r2, lsl #15
  43. and r2, r2, #0x300
  44. orr r3, r3, r2, lsl #2
  45. and r2, r3, #255
  46. sub r0, r0, #256 * 4
  47. str r3, [r0, r2, lsl #2]
  48. strb r3, [r3]
  49. movs pc, lr
  50. /*
  51. * Params : r0 = preserved
  52. * : r1 = memc table base (preserved)
  53. * : r2 = page table entry
  54. * : r3 = preserved
  55. * : r4 = unused
  56. * : r5 = memc physical address translation table
  57. * : ip = virtual address (preserved)
  58. */
  59. update_pte:
  60. mov r4, r2, lsr #13
  61. and r4, r4, #0x3fc
  62. ldr r4, [r5, r4] @ covert to MEMC page
  63. tst r2, #PAGE_OLD | PAGE_NOT_USER @ check for MEMC read
  64. biceq r4, r4, #0x200
  65. tsteq r2, #PAGE_READONLY | PAGE_CLEAN @ check for MEMC write
  66. biceq r4, r4, #0x300
  67. orr r4, r4, ip
  68. and r2, ip, #0x01800000
  69. orr r4, r4, r2, lsr #13
  70. and r2, r4, #255
  71. str r4, [r1, r2, lsl #2]
  72. movs pc, lr
  73. /*
  74. * Params : r0 = preserved
  75. * : r1 = memc table base (preserved)
  76. * : r2 = page table base
  77. * : r3 = preserved
  78. * : r4 = unused
  79. * : r5 = memc physical address translation table
  80. * : ip = virtual address (updated)
  81. */
  82. update_pte_table:
  83. stmfd sp!, {r0, lr}
  84. bic r0, r2, #3
  85. 1: ldr r2, [r0], #4 @ get entry
  86. tst r2, #PAGE_PRESENT @ page present
  87. blne update_pte @ process pte
  88. add ip, ip, #32768 @ increment virt addr
  89. ldr r2, [r0], #4 @ get entry
  90. tst r2, #PAGE_PRESENT @ page present
  91. blne update_pte @ process pte
  92. add ip, ip, #32768 @ increment virt addr
  93. ldr r2, [r0], #4 @ get entry
  94. tst r2, #PAGE_PRESENT @ page present
  95. blne update_pte @ process pte
  96. add ip, ip, #32768 @ increment virt addr
  97. ldr r2, [r0], #4 @ get entry
  98. tst r2, #PAGE_PRESENT @ page present
  99. blne update_pte @ process pte
  100. add ip, ip, #32768 @ increment virt addr
  101. tst ip, #32768 * 31 @ finished?
  102. bne 1b
  103. ldmfd sp!, {r0, pc}^
  104. /*
  105. * Function: cpu_memc_update_all(pgd_t *pgd)
  106. * Params : pgd Page tables/MEMC mapping
  107. * Notes : this is optimised for 32k pages
  108. */
  109. ENTRY(cpu_memc_update_all)
  110. stmfd sp!, {r4, r5, lr}
  111. bl clear_tables
  112. sub r1, r0, #256 * 4 @ start of MEMC tables
  113. adr r5, memc_phys_table_32 @ Convert to logical page number
  114. mov ip, #0 @ virtual address
  115. 1: ldmia r0!, {r2, r3} @ load two pgd entries
  116. tst r2, #PAGE_PRESENT @ is pgd entry present?
  117. addeq ip, ip, #1048576 @FIXME - PAGE_PRESENT is for PTEs technically...
  118. blne update_pte_table
  119. mov r2, r3
  120. tst r2, #PAGE_PRESENT @ is pgd entry present?
  121. addeq ip, ip, #1048576
  122. blne update_pte_table
  123. teq ip, #32 * 1048576
  124. bne 1b
  125. ldmfd sp!, {r4, r5, pc}^
  126. /*
  127. * Build the table to map from physical page number to memc page number
  128. */
  129. .type memc_phys_table_32, #object
  130. memc_phys_table_32:
  131. .irp b7, 0x00, 0x80
  132. .irp b6, 0x00, 0x02
  133. .irp b5, 0x00, 0x04
  134. .irp b4, 0x00, 0x01
  135. .irp b3, 0x00, 0x40
  136. .irp b2, 0x00, 0x20
  137. .irp b1, 0x00, 0x10
  138. .irp b0, 0x00, 0x08
  139. .long 0x03800300 + \b7 + \b6 + \b5 + \b4 + \b3 + \b2 + \b1 + \b0
  140. .endr
  141. .endr
  142. .endr
  143. .endr
  144. .endr
  145. .endr
  146. .endr
  147. .endr
  148. .size memc_phys_table_32, . - memc_phys_table_32
  149. /*
  150. * helper for cpu_memc_update_all, this clears out all
  151. * mappings, setting them close to the top of memory,
  152. * and inaccessible (0x01f00000).
  153. * Params : r0 = page table pointer
  154. */
  155. clear_tables: ldr r1, _arm3_set_pgd - 4
  156. ldr r2, [r1]
  157. sub r1, r0, #256 * 4 @ start of MEMC tables
  158. add r2, r1, r2, lsl #2 @ end of tables
  159. mov r3, #0x03f00000 @ Default mapping (null mapping)
  160. orr r3, r3, #0x00000f00
  161. orr r4, r3, #1
  162. orr r5, r3, #2
  163. orr ip, r3, #3
  164. 1: stmia r1!, {r3, r4, r5, ip}
  165. add r3, r3, #4
  166. add r4, r4, #4
  167. add r5, r5, #4
  168. add ip, ip, #4
  169. stmia r1!, {r3, r4, r5, ip}
  170. add r3, r3, #4
  171. add r4, r4, #4
  172. add r5, r5, #4
  173. add ip, ip, #4
  174. teq r1, r2
  175. bne 1b
  176. mov pc, lr
  177. /*
  178. * Function: *_set_pgd(pgd_t *pgd)
  179. * Params : pgd New page tables/MEMC mapping
  180. * Purpose : update MEMC hardware with new mapping
  181. */
  182. .word page_nr @ extern - declared in mm-memc.c
  183. _arm3_set_pgd: mcr p15, 0, r1, c1, c0, 0 @ flush cache
  184. _arm2_set_pgd: stmfd sp!, {lr}
  185. ldr r1, _arm3_set_pgd - 4
  186. ldr r2, [r1]
  187. sub r0, r0, #256 * 4 @ start of MEMC tables
  188. add r1, r0, r2, lsl #2 @ end of tables
  189. 1: ldmia r0!, {r2, r3, ip, lr}
  190. strb r2, [r2]
  191. strb r3, [r3]
  192. strb ip, [ip]
  193. strb lr, [lr]
  194. ldmia r0!, {r2, r3, ip, lr}
  195. strb r2, [r2]
  196. strb r3, [r3]
  197. strb ip, [ip]
  198. strb lr, [lr]
  199. teq r0, r1
  200. bne 1b
  201. ldmfd sp!, {pc}^
  202. /*
  203. * Function: *_proc_init (void)
  204. * Purpose : Initialise the cache control registers
  205. */
  206. _arm3_proc_init:
  207. mov r0, #0x001f0000
  208. orr r0, r0, #0x0000ff00
  209. orr r0, r0, #0x000000ff
  210. mcr p15, 0, r0, c3, c0 @ ARM3 Cacheable
  211. mcr p15, 0, r0, c4, c0 @ ARM3 Updateable
  212. mov r0, #0
  213. mcr p15, 0, r0, c5, c0 @ ARM3 Disruptive
  214. mcr p15, 0, r0, c1, c0 @ ARM3 Flush
  215. mov r0, #3
  216. mcr p15, 0, r0, c2, c0 @ ARM3 Control
  217. _arm2_proc_init:
  218. movs pc, lr
  219. /*
  220. * Function: *_proc_fin (void)
  221. * Purpose : Finalise processor (disable caches)
  222. */
  223. _arm3_proc_fin: mov r0, #2
  224. mcr p15, 0, r0, c2, c0
  225. _arm2_proc_fin: orrs pc, lr, #PSR_I_BIT|PSR_F_BIT
  226. /*
  227. * Function: *_xchg_1 (int new, volatile void *ptr)
  228. * Params : new New value to store at...
  229. * : ptr pointer to byte-wide location
  230. * Purpose : Performs an exchange operation
  231. * Returns : Original byte data at 'ptr'
  232. */
  233. _arm2_xchg_1: mov r2, pc
  234. orr r2, r2, #PSR_I_BIT
  235. teqp r2, #0
  236. ldrb r2, [r1]
  237. strb r0, [r1]
  238. mov r0, r2
  239. movs pc, lr
  240. _arm3_xchg_1: swpb r0, r0, [r1]
  241. movs pc, lr
  242. /*
  243. * Function: *_xchg_4 (int new, volatile void *ptr)
  244. * Params : new New value to store at...
  245. * : ptr pointer to word-wide location
  246. * Purpose : Performs an exchange operation
  247. * Returns : Original word data at 'ptr'
  248. */
  249. _arm2_xchg_4: mov r2, pc
  250. orr r2, r2, #PSR_I_BIT
  251. teqp r2, #0
  252. ldr r2, [r1]
  253. str r0, [r1]
  254. mov r0, r2
  255. movs pc, lr
  256. _arm3_xchg_4: swp r0, r0, [r1]
  257. movs pc, lr
  258. _arm2_3_check_bugs:
  259. bics pc, lr, #PSR_F_BIT @ Clear FIQ disable bit
  260. armvlsi_name: .asciz "ARM/VLSI"
  261. _arm2_name: .asciz "ARM 2"
  262. _arm250_name: .asciz "ARM 250"
  263. _arm3_name: .asciz "ARM 3"
  264. .section ".init.text", #alloc, #execinstr
  265. /*
  266. * Purpose : Function pointers used to access above functions - all calls
  267. * come through these
  268. */
  269. .globl arm2_processor_functions
  270. arm2_processor_functions:
  271. .word _arm2_3_check_bugs
  272. .word _arm2_proc_init
  273. .word _arm2_proc_fin
  274. .word _arm2_set_pgd
  275. .word _arm2_xchg_1
  276. .word _arm2_xchg_4
  277. cpu_arm2_info:
  278. .long armvlsi_name
  279. .long _arm2_name
  280. .globl arm250_processor_functions
  281. arm250_processor_functions:
  282. .word _arm2_3_check_bugs
  283. .word _arm2_proc_init
  284. .word _arm2_proc_fin
  285. .word _arm2_set_pgd
  286. .word _arm3_xchg_1
  287. .word _arm3_xchg_4
  288. cpu_arm250_info:
  289. .long armvlsi_name
  290. .long _arm250_name
  291. .globl arm3_processor_functions
  292. arm3_processor_functions:
  293. .word _arm2_3_check_bugs
  294. .word _arm3_proc_init
  295. .word _arm3_proc_fin
  296. .word _arm3_set_pgd
  297. .word _arm3_xchg_1
  298. .word _arm3_xchg_4
  299. cpu_arm3_info:
  300. .long armvlsi_name
  301. .long _arm3_name
  302. arm2_arch_name: .asciz "armv1"
  303. arm3_arch_name: .asciz "armv2"
  304. arm2_elf_name: .asciz "v1"
  305. arm3_elf_name: .asciz "v2"
  306. .align
  307. .section ".proc.info", #alloc, #execinstr
  308. .long 0x41560200
  309. .long 0xfffffff0
  310. .long arm2_arch_name
  311. .long arm2_elf_name
  312. .long 0
  313. .long cpu_arm2_info
  314. .long arm2_processor_functions
  315. .long 0x41560250
  316. .long 0xfffffff0
  317. .long arm3_arch_name
  318. .long arm3_elf_name
  319. .long 0
  320. .long cpu_arm250_info
  321. .long arm250_processor_functions
  322. .long 0x41560300
  323. .long 0xfffffff0
  324. .long arm3_arch_name
  325. .long arm3_elf_name
  326. .long 0
  327. .long cpu_arm3_info
  328. .long arm3_processor_functions