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