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