Linux-2.6.12-rc2
[safe/jmp/linux-2.6] / arch / arm26 / mm / proc-funcs.S
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