1/* 2 * arch/xtensa/mm/misc.S 3 * 4 * Miscellaneous assembly functions. 5 * 6 * This file is subject to the terms and conditions of the GNU General Public 7 * License. See the file "COPYING" in the main directory of this archive 8 * for more details. 9 * 10 * Copyright (C) 2001 - 2007 Tensilica Inc. 11 * 12 * Chris Zankel <chris@zankel.net> 13 */ 14 15 16#include <linux/linkage.h> 17#include <asm/page.h> 18#include <asm/pgtable.h> 19#include <asm/asmmacro.h> 20#include <asm/cacheasm.h> 21#include <asm/tlbflush.h> 22 23 24/* 25 * clear_page and clear_user_page are the same for non-cache-aliased configs. 26 * 27 * clear_page (unsigned long page) 28 * a2 29 */ 30 31ENTRY(clear_page) 32 entry a1, 16 33 34 movi a3, 0 35 __loopi a2, a7, PAGE_SIZE, 32 36 s32i a3, a2, 0 37 s32i a3, a2, 4 38 s32i a3, a2, 8 39 s32i a3, a2, 12 40 s32i a3, a2, 16 41 s32i a3, a2, 20 42 s32i a3, a2, 24 43 s32i a3, a2, 28 44 __endla a2, a7, 32 45 46 retw 47 48/* 49 * copy_page and copy_user_page are the same for non-cache-aliased configs. 50 * 51 * copy_page (void *to, void *from) 52 * a2 a3 53 */ 54 55ENTRY(copy_page) 56 entry a1, 16 57 58 __loopi a2, a4, PAGE_SIZE, 32 59 60 l32i a8, a3, 0 61 l32i a9, a3, 4 62 s32i a8, a2, 0 63 s32i a9, a2, 4 64 65 l32i a8, a3, 8 66 l32i a9, a3, 12 67 s32i a8, a2, 8 68 s32i a9, a2, 12 69 70 l32i a8, a3, 16 71 l32i a9, a3, 20 72 s32i a8, a2, 16 73 s32i a9, a2, 20 74 75 l32i a8, a3, 24 76 l32i a9, a3, 28 77 s32i a8, a2, 24 78 s32i a9, a2, 28 79 80 addi a2, a2, 32 81 addi a3, a3, 32 82 83 __endl a2, a4 84 85 retw 86 87/* 88 * If we have to deal with cache aliasing, we use temporary memory mappings 89 * to ensure that the source and destination pages have the same color as 90 * the virtual address. We use way 0 and 1 for temporary mappings in such cases. 91 * 92 * The temporary DTLB entries shouldn't be flushed by interrupts, but are 93 * flushed by preemptive task switches. Special code in the 94 * fast_second_level_miss handler re-established the temporary mapping. 95 * It requires that the PPNs for the destination and source addresses are 96 * in a6, and a7, respectively. 97 */ 98 99/* TLB miss exceptions are treated special in the following region */ 100 101ENTRY(__tlbtemp_mapping_start) 102 103#if (DCACHE_WAY_SIZE > PAGE_SIZE) 104 105/* 106 * clear_user_page (void *addr, unsigned long vaddr, struct page *page) 107 * a2 a3 a4 108 */ 109 110ENTRY(clear_user_page) 111 entry a1, 32 112 113 /* Mark page dirty and determine alias. */ 114 115 movi a7, (1 << PG_ARCH_1) 116 l32i a5, a4, PAGE_FLAGS 117 xor a6, a2, a3 118 extui a3, a3, PAGE_SHIFT, DCACHE_ALIAS_ORDER 119 extui a6, a6, PAGE_SHIFT, DCACHE_ALIAS_ORDER 120 or a5, a5, a7 121 slli a3, a3, PAGE_SHIFT 122 s32i a5, a4, PAGE_FLAGS 123 124 /* Skip setting up a temporary DTLB if not aliased. */ 125 126 beqz a6, 1f 127 128 /* Invalidate kernel page. */ 129 130 mov a10, a2 131 call8 __invalidate_dcache_page 132 133 /* Setup a temporary DTLB with the color of the VPN */ 134 135 movi a4, -PAGE_OFFSET + (PAGE_KERNEL | _PAGE_HW_WRITE) 136 movi a5, TLBTEMP_BASE_1 # virt 137 add a6, a2, a4 # ppn 138 add a2, a5, a3 # add 'color' 139 140 wdtlb a6, a2 141 dsync 142 1431: movi a3, 0 144 __loopi a2, a7, PAGE_SIZE, 32 145 s32i a3, a2, 0 146 s32i a3, a2, 4 147 s32i a3, a2, 8 148 s32i a3, a2, 12 149 s32i a3, a2, 16 150 s32i a3, a2, 20 151 s32i a3, a2, 24 152 s32i a3, a2, 28 153 __endla a2, a7, 32 154 155 bnez a6, 1f 156 retw 157 158 /* We need to invalidate the temporary idtlb entry, if any. */ 159 1601: addi a2, a2, -PAGE_SIZE 161 idtlb a2 162 dsync 163 164 retw 165 166/* 167 * copy_page_user (void *to, void *from, unsigned long vaddr, struct page *page) 168 * a2 a3 a4 a5 169 */ 170 171ENTRY(copy_user_page) 172 173 entry a1, 32 174 175 /* Mark page dirty and determine alias for destination. */ 176 177 movi a8, (1 << PG_ARCH_1) 178 l32i a9, a5, PAGE_FLAGS 179 xor a6, a2, a4 180 xor a7, a3, a4 181 extui a4, a4, PAGE_SHIFT, DCACHE_ALIAS_ORDER 182 extui a6, a6, PAGE_SHIFT, DCACHE_ALIAS_ORDER 183 extui a7, a7, PAGE_SHIFT, DCACHE_ALIAS_ORDER 184 or a9, a9, a8 185 slli a4, a4, PAGE_SHIFT 186 s32i a9, a5, PAGE_FLAGS 187 movi a5, -PAGE_OFFSET + (PAGE_KERNEL | _PAGE_HW_WRITE) 188 189 beqz a6, 1f 190 191 /* Invalidate dcache */ 192 193 mov a10, a2 194 call8 __invalidate_dcache_page 195 196 /* Setup a temporary DTLB with a matching color. */ 197 198 movi a8, TLBTEMP_BASE_1 # base 199 add a6, a2, a5 # ppn 200 add a2, a8, a4 # add 'color' 201 202 wdtlb a6, a2 203 dsync 204 205 /* Skip setting up a temporary DTLB for destination if not aliased. */ 206 2071: beqz a7, 1f 208 209 /* Setup a temporary DTLB with a matching color. */ 210 211 movi a8, TLBTEMP_BASE_2 # base 212 add a7, a3, a5 # ppn 213 add a3, a8, a4 214 addi a8, a3, 1 # way1 215 216 wdtlb a7, a8 217 dsync 218 2191: __loopi a2, a4, PAGE_SIZE, 32 220 221 l32i a8, a3, 0 222 l32i a9, a3, 4 223 s32i a8, a2, 0 224 s32i a9, a2, 4 225 226 l32i a8, a3, 8 227 l32i a9, a3, 12 228 s32i a8, a2, 8 229 s32i a9, a2, 12 230 231 l32i a8, a3, 16 232 l32i a9, a3, 20 233 s32i a8, a2, 16 234 s32i a9, a2, 20 235 236 l32i a8, a3, 24 237 l32i a9, a3, 28 238 s32i a8, a2, 24 239 s32i a9, a2, 28 240 241 addi a2, a2, 32 242 addi a3, a3, 32 243 244 __endl a2, a4 245 246 /* We need to invalidate any temporary mapping! */ 247 248 bnez a6, 1f 249 bnez a7, 2f 250 retw 251 2521: addi a2, a2, -PAGE_SIZE 253 idtlb a2 254 dsync 255 bnez a7, 2f 256 retw 257 2582: addi a3, a3, -PAGE_SIZE+1 259 idtlb a3 260 dsync 261 262 retw 263 264#endif 265 266#if (DCACHE_WAY_SIZE > PAGE_SIZE) 267 268/* 269 * void __flush_invalidate_dcache_page_alias (addr, phys) 270 * a2 a3 271 */ 272 273ENTRY(__flush_invalidate_dcache_page_alias) 274 entry sp, 16 275 276 movi a7, 0 # required for exception handler 277 addi a6, a3, (PAGE_KERNEL | _PAGE_HW_WRITE) 278 mov a4, a2 279 wdtlb a6, a2 280 dsync 281 282 ___flush_invalidate_dcache_page a2 a3 283 284 idtlb a4 285 dsync 286 287 retw 288 289#endif 290 291ENTRY(__tlbtemp_mapping_itlb) 292 293#if (ICACHE_WAY_SIZE > PAGE_SIZE) 294 295ENTRY(__invalidate_icache_page_alias) 296 entry sp, 16 297 298 addi a6, a3, (PAGE_KERNEL_EXEC | _PAGE_HW_WRITE) 299 mov a4, a2 300 witlb a6, a2 301 isync 302 303 ___invalidate_icache_page a2 a3 304 305 iitlb a4 306 isync 307 retw 308 309#endif 310 311/* End of special treatment in tlb miss exception */ 312 313ENTRY(__tlbtemp_mapping_end) 314 315/* 316 * void __invalidate_icache_page(ulong start) 317 */ 318 319ENTRY(__invalidate_icache_page) 320 entry sp, 16 321 322 ___invalidate_icache_page a2 a3 323 isync 324 325 retw 326 327/* 328 * void __invalidate_dcache_page(ulong start) 329 */ 330 331ENTRY(__invalidate_dcache_page) 332 entry sp, 16 333 334 ___invalidate_dcache_page a2 a3 335 dsync 336 337 retw 338 339/* 340 * void __flush_invalidate_dcache_page(ulong start) 341 */ 342 343ENTRY(__flush_invalidate_dcache_page) 344 entry sp, 16 345 346 ___flush_invalidate_dcache_page a2 a3 347 348 dsync 349 retw 350 351/* 352 * void __flush_dcache_page(ulong start) 353 */ 354 355ENTRY(__flush_dcache_page) 356 entry sp, 16 357 358 ___flush_dcache_page a2 a3 359 360 dsync 361 retw 362 363/* 364 * void __invalidate_icache_range(ulong start, ulong size) 365 */ 366 367ENTRY(__invalidate_icache_range) 368 entry sp, 16 369 370 ___invalidate_icache_range a2 a3 a4 371 isync 372 373 retw 374 375/* 376 * void __flush_invalidate_dcache_range(ulong start, ulong size) 377 */ 378 379ENTRY(__flush_invalidate_dcache_range) 380 entry sp, 16 381 382 ___flush_invalidate_dcache_range a2 a3 a4 383 dsync 384 385 retw 386 387/* 388 * void _flush_dcache_range(ulong start, ulong size) 389 */ 390 391ENTRY(__flush_dcache_range) 392 entry sp, 16 393 394 ___flush_dcache_range a2 a3 a4 395 dsync 396 397 retw 398 399/* 400 * void _invalidate_dcache_range(ulong start, ulong size) 401 */ 402 403ENTRY(__invalidate_dcache_range) 404 entry sp, 16 405 406 ___invalidate_dcache_range a2 a3 a4 407 408 retw 409 410/* 411 * void _invalidate_icache_all(void) 412 */ 413 414ENTRY(__invalidate_icache_all) 415 entry sp, 16 416 417 ___invalidate_icache_all a2 a3 418 isync 419 420 retw 421 422/* 423 * void _flush_invalidate_dcache_all(void) 424 */ 425 426ENTRY(__flush_invalidate_dcache_all) 427 entry sp, 16 428 429 ___flush_invalidate_dcache_all a2 a3 430 dsync 431 432 retw 433 434/* 435 * void _invalidate_dcache_all(void) 436 */ 437 438ENTRY(__invalidate_dcache_all) 439 entry sp, 16 440 441 ___invalidate_dcache_all a2 a3 442 dsync 443 444 retw 445 446