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 */ 30ENTRY(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 */ 60update_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 */ 87update_pte_table: 88 stmfd sp!, {r0, lr} 89 bic r0, r2, #3 901: 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 */ 115ENTRY(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 1211: 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 137memc_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 */ 165clear_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 1741: 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 2001: 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 279armvlsi_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 290arm2_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 298cpu_arm2_info: 299 .long armvlsi_name 300 .long _arm2_name 301 302 .globl arm250_processor_functions 303arm250_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 311cpu_arm250_info: 312 .long armvlsi_name 313 .long _arm250_name 314 315 .globl arm3_processor_functions 316arm3_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 324cpu_arm3_info: 325 .long armvlsi_name 326 .long _arm3_name 327 328arm2_arch_name: .asciz "armv1" 329arm3_arch_name: .asciz "armv2" 330arm2_elf_name: .asciz "v1" 331arm3_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