1/* 2 * PARISC TLB and cache flushing support 3 * Copyright (C) 2000-2001 Hewlett-Packard (John Marvin) 4 * Copyright (C) 2001 Matthew Wilcox (willy at parisc-linux.org) 5 * Copyright (C) 2002 Richard Hirst (rhirst with parisc-linux.org) 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2, or (at your option) 10 * any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 */ 21 22/* 23 * NOTE: fdc,fic, and pdc instructions that use base register modification 24 * should only use index and base registers that are not shadowed, 25 * so that the fast path emulation in the non access miss handler 26 * can be used. 27 */ 28 29#ifdef CONFIG_64BIT 30#define ADDIB addib,* 31#define CMPB cmpb,* 32#define ANDCM andcm,* 33 34 .level 2.0w 35#else 36#define ADDIB addib, 37#define CMPB cmpb, 38#define ANDCM andcm 39 40 .level 2.0 41#endif 42 43 44#include <asm/psw.h> 45#include <asm/assembly.h> 46#include <asm/pgtable.h> 47#include <asm/cache.h> 48 49 .text 50 .align 128 51 52 .export flush_tlb_all_local,code 53 54flush_tlb_all_local: 55 .proc 56 .callinfo NO_CALLS 57 .entry 58 59 /* 60 * The pitlbe and pdtlbe instructions should only be used to 61 * flush the entire tlb. Also, there needs to be no intervening 62 * tlb operations, e.g. tlb misses, so the operation needs 63 * to happen in real mode with all interruptions disabled. 64 */ 65 66 /* pcxt_ssm_bug - relied upon translation! PA 2.0 Arch. F-4 and F-5 */ 67 rsm PSW_SM_I, %r19 /* save I-bit state */ 68 load32 PA(1f), %r1 69 nop 70 nop 71 nop 72 nop 73 nop 74 75 rsm PSW_SM_Q, %r0 /* prep to load iia queue */ 76 mtctl %r0, %cr17 /* Clear IIASQ tail */ 77 mtctl %r0, %cr17 /* Clear IIASQ head */ 78 mtctl %r1, %cr18 /* IIAOQ head */ 79 ldo 4(%r1), %r1 80 mtctl %r1, %cr18 /* IIAOQ tail */ 81 load32 REAL_MODE_PSW, %r1 82 mtctl %r1, %ipsw 83 rfi 84 nop 85 861: load32 PA(cache_info), %r1 87 88 /* Flush Instruction Tlb */ 89 90 LDREG ITLB_SID_BASE(%r1), %r20 91 LDREG ITLB_SID_STRIDE(%r1), %r21 92 LDREG ITLB_SID_COUNT(%r1), %r22 93 LDREG ITLB_OFF_BASE(%r1), %arg0 94 LDREG ITLB_OFF_STRIDE(%r1), %arg1 95 LDREG ITLB_OFF_COUNT(%r1), %arg2 96 LDREG ITLB_LOOP(%r1), %arg3 97 98 ADDIB= -1, %arg3, fitoneloop /* Preadjust and test */ 99 movb,<,n %arg3, %r31, fitdone /* If loop < 0, skip */ 100 copy %arg0, %r28 /* Init base addr */ 101 102fitmanyloop: /* Loop if LOOP >= 2 */ 103 mtsp %r20, %sr1 104 add %r21, %r20, %r20 /* increment space */ 105 copy %arg2, %r29 /* Init middle loop count */ 106 107fitmanymiddle: /* Loop if LOOP >= 2 */ 108 ADDIB> -1, %r31, fitmanymiddle /* Adjusted inner loop decr */ 109 pitlbe 0(%sr1, %r28) 110 pitlbe,m %arg1(%sr1, %r28) /* Last pitlbe and addr adjust */ 111 ADDIB> -1, %r29, fitmanymiddle /* Middle loop decr */ 112 copy %arg3, %r31 /* Re-init inner loop count */ 113 114 movb,tr %arg0, %r28, fitmanyloop /* Re-init base addr */ 115 ADDIB<=,n -1, %r22, fitdone /* Outer loop count decr */ 116 117fitoneloop: /* Loop if LOOP = 1 */ 118 mtsp %r20, %sr1 119 copy %arg0, %r28 /* init base addr */ 120 copy %arg2, %r29 /* init middle loop count */ 121 122fitonemiddle: /* Loop if LOOP = 1 */ 123 ADDIB> -1, %r29, fitonemiddle /* Middle loop count decr */ 124 pitlbe,m %arg1(%sr1, %r28) /* pitlbe for one loop */ 125 126 ADDIB> -1, %r22, fitoneloop /* Outer loop count decr */ 127 add %r21, %r20, %r20 /* increment space */ 128 129fitdone: 130 131 /* Flush Data Tlb */ 132 133 LDREG DTLB_SID_BASE(%r1), %r20 134 LDREG DTLB_SID_STRIDE(%r1), %r21 135 LDREG DTLB_SID_COUNT(%r1), %r22 136 LDREG DTLB_OFF_BASE(%r1), %arg0 137 LDREG DTLB_OFF_STRIDE(%r1), %arg1 138 LDREG DTLB_OFF_COUNT(%r1), %arg2 139 LDREG DTLB_LOOP(%r1), %arg3 140 141 ADDIB= -1, %arg3, fdtoneloop /* Preadjust and test */ 142 movb,<,n %arg3, %r31, fdtdone /* If loop < 0, skip */ 143 copy %arg0, %r28 /* Init base addr */ 144 145fdtmanyloop: /* Loop if LOOP >= 2 */ 146 mtsp %r20, %sr1 147 add %r21, %r20, %r20 /* increment space */ 148 copy %arg2, %r29 /* Init middle loop count */ 149 150fdtmanymiddle: /* Loop if LOOP >= 2 */ 151 ADDIB> -1, %r31, fdtmanymiddle /* Adjusted inner loop decr */ 152 pdtlbe 0(%sr1, %r28) 153 pdtlbe,m %arg1(%sr1, %r28) /* Last pdtlbe and addr adjust */ 154 ADDIB> -1, %r29, fdtmanymiddle /* Middle loop decr */ 155 copy %arg3, %r31 /* Re-init inner loop count */ 156 157 movb,tr %arg0, %r28, fdtmanyloop /* Re-init base addr */ 158 ADDIB<=,n -1, %r22,fdtdone /* Outer loop count decr */ 159 160fdtoneloop: /* Loop if LOOP = 1 */ 161 mtsp %r20, %sr1 162 copy %arg0, %r28 /* init base addr */ 163 copy %arg2, %r29 /* init middle loop count */ 164 165fdtonemiddle: /* Loop if LOOP = 1 */ 166 ADDIB> -1, %r29, fdtonemiddle /* Middle loop count decr */ 167 pdtlbe,m %arg1(%sr1, %r28) /* pdtlbe for one loop */ 168 169 ADDIB> -1, %r22, fdtoneloop /* Outer loop count decr */ 170 add %r21, %r20, %r20 /* increment space */ 171 172 173fdtdone: 174 /* 175 * Switch back to virtual mode 176 */ 177 /* pcxt_ssm_bug */ 178 rsm PSW_SM_I, %r0 179 load32 2f, %r1 180 nop 181 nop 182 nop 183 nop 184 nop 185 186 rsm PSW_SM_Q, %r0 /* prep to load iia queue */ 187 mtctl %r0, %cr17 /* Clear IIASQ tail */ 188 mtctl %r0, %cr17 /* Clear IIASQ head */ 189 mtctl %r1, %cr18 /* IIAOQ head */ 190 ldo 4(%r1), %r1 191 mtctl %r1, %cr18 /* IIAOQ tail */ 192 load32 KERNEL_PSW, %r1 193 or %r1, %r19, %r1 /* I-bit to state on entry */ 194 mtctl %r1, %ipsw /* restore I-bit (entire PSW) */ 195 rfi 196 nop 197 1982: bv %r0(%r2) 199 nop 200 201 .exit 202 .procend 203 204 .export flush_instruction_cache_local,code 205 .import cache_info,data 206 207flush_instruction_cache_local: 208 .proc 209 .callinfo NO_CALLS 210 .entry 211 212 mtsp %r0, %sr1 213 load32 cache_info, %r1 214 215 /* Flush Instruction Cache */ 216 217 LDREG ICACHE_BASE(%r1), %arg0 218 LDREG ICACHE_STRIDE(%r1), %arg1 219 LDREG ICACHE_COUNT(%r1), %arg2 220 LDREG ICACHE_LOOP(%r1), %arg3 221 rsm PSW_SM_I, %r22 /* No mmgt ops during loop*/ 222 ADDIB= -1, %arg3, fioneloop /* Preadjust and test */ 223 movb,<,n %arg3, %r31, fisync /* If loop < 0, do sync */ 224 225fimanyloop: /* Loop if LOOP >= 2 */ 226 ADDIB> -1, %r31, fimanyloop /* Adjusted inner loop decr */ 227 fice %r0(%sr1, %arg0) 228 fice,m %arg1(%sr1, %arg0) /* Last fice and addr adjust */ 229 movb,tr %arg3, %r31, fimanyloop /* Re-init inner loop count */ 230 ADDIB<=,n -1, %arg2, fisync /* Outer loop decr */ 231 232fioneloop: /* Loop if LOOP = 1 */ 233 ADDIB> -1, %arg2, fioneloop /* Outer loop count decr */ 234 fice,m %arg1(%sr1, %arg0) /* Fice for one loop */ 235 236fisync: 237 sync 238 mtsm %r22 /* restore I-bit */ 239 bv %r0(%r2) 240 nop 241 .exit 242 243 .procend 244 245 .export flush_data_cache_local, code 246 .import cache_info, data 247 248flush_data_cache_local: 249 .proc 250 .callinfo NO_CALLS 251 .entry 252 253 mtsp %r0, %sr1 254 load32 cache_info, %r1 255 256 /* Flush Data Cache */ 257 258 LDREG DCACHE_BASE(%r1), %arg0 259 LDREG DCACHE_STRIDE(%r1), %arg1 260 LDREG DCACHE_COUNT(%r1), %arg2 261 LDREG DCACHE_LOOP(%r1), %arg3 262 rsm PSW_SM_I, %r22 263 ADDIB= -1, %arg3, fdoneloop /* Preadjust and test */ 264 movb,<,n %arg3, %r31, fdsync /* If loop < 0, do sync */ 265 266fdmanyloop: /* Loop if LOOP >= 2 */ 267 ADDIB> -1, %r31, fdmanyloop /* Adjusted inner loop decr */ 268 fdce %r0(%sr1, %arg0) 269 fdce,m %arg1(%sr1, %arg0) /* Last fdce and addr adjust */ 270 movb,tr %arg3, %r31, fdmanyloop /* Re-init inner loop count */ 271 ADDIB<=,n -1, %arg2, fdsync /* Outer loop decr */ 272 273fdoneloop: /* Loop if LOOP = 1 */ 274 ADDIB> -1, %arg2, fdoneloop /* Outer loop count decr */ 275 fdce,m %arg1(%sr1, %arg0) /* Fdce for one loop */ 276 277fdsync: 278 syncdma 279 sync 280 mtsm %r22 /* restore I-bit */ 281 bv %r0(%r2) 282 nop 283 .exit 284 285 .procend 286 287 .export copy_user_page_asm,code 288 .align 16 289 290copy_user_page_asm: 291 .proc 292 .callinfo NO_CALLS 293 .entry 294 295#ifdef CONFIG_64BIT 296 /* PA8x00 CPUs can consume 2 loads or 1 store per cycle. 297 * Unroll the loop by hand and arrange insn appropriately. 298 * GCC probably can do this just as well. 299 */ 300 301 ldd 0(%r25), %r19 302 ldi ASM_PAGE_SIZE_DIV128, %r1 303 304 ldw 64(%r25), %r0 /* prefetch 1 cacheline ahead */ 305 ldw 128(%r25), %r0 /* prefetch 2 */ 306 3071: ldd 8(%r25), %r20 308 ldw 192(%r25), %r0 /* prefetch 3 */ 309 ldw 256(%r25), %r0 /* prefetch 4 */ 310 311 ldd 16(%r25), %r21 312 ldd 24(%r25), %r22 313 std %r19, 0(%r26) 314 std %r20, 8(%r26) 315 316 ldd 32(%r25), %r19 317 ldd 40(%r25), %r20 318 std %r21, 16(%r26) 319 std %r22, 24(%r26) 320 321 ldd 48(%r25), %r21 322 ldd 56(%r25), %r22 323 std %r19, 32(%r26) 324 std %r20, 40(%r26) 325 326 ldd 64(%r25), %r19 327 ldd 72(%r25), %r20 328 std %r21, 48(%r26) 329 std %r22, 56(%r26) 330 331 ldd 80(%r25), %r21 332 ldd 88(%r25), %r22 333 std %r19, 64(%r26) 334 std %r20, 72(%r26) 335 336 ldd 96(%r25), %r19 337 ldd 104(%r25), %r20 338 std %r21, 80(%r26) 339 std %r22, 88(%r26) 340 341 ldd 112(%r25), %r21 342 ldd 120(%r25), %r22 343 std %r19, 96(%r26) 344 std %r20, 104(%r26) 345 346 ldo 128(%r25), %r25 347 std %r21, 112(%r26) 348 std %r22, 120(%r26) 349 ldo 128(%r26), %r26 350 351 /* conditional branches nullify on forward taken branch, and on 352 * non-taken backward branch. Note that .+4 is a backwards branch. 353 * The ldd should only get executed if the branch is taken. 354 */ 355 ADDIB>,n -1, %r1, 1b /* bundle 10 */ 356 ldd 0(%r25), %r19 /* start next loads */ 357 358#else 359 360 /* 361 * This loop is optimized for PCXL/PCXL2 ldw/ldw and stw/stw 362 * bundles (very restricted rules for bundling). 363 * Note that until (if) we start saving 364 * the full 64 bit register values on interrupt, we can't 365 * use ldd/std on a 32 bit kernel. 366 */ 367 ldw 0(%r25), %r19 368 ldi ASM_PAGE_SIZE_DIV64, %r1 369 3701: 371 ldw 4(%r25), %r20 372 ldw 8(%r25), %r21 373 ldw 12(%r25), %r22 374 stw %r19, 0(%r26) 375 stw %r20, 4(%r26) 376 stw %r21, 8(%r26) 377 stw %r22, 12(%r26) 378 ldw 16(%r25), %r19 379 ldw 20(%r25), %r20 380 ldw 24(%r25), %r21 381 ldw 28(%r25), %r22 382 stw %r19, 16(%r26) 383 stw %r20, 20(%r26) 384 stw %r21, 24(%r26) 385 stw %r22, 28(%r26) 386 ldw 32(%r25), %r19 387 ldw 36(%r25), %r20 388 ldw 40(%r25), %r21 389 ldw 44(%r25), %r22 390 stw %r19, 32(%r26) 391 stw %r20, 36(%r26) 392 stw %r21, 40(%r26) 393 stw %r22, 44(%r26) 394 ldw 48(%r25), %r19 395 ldw 52(%r25), %r20 396 ldw 56(%r25), %r21 397 ldw 60(%r25), %r22 398 stw %r19, 48(%r26) 399 stw %r20, 52(%r26) 400 ldo 64(%r25), %r25 401 stw %r21, 56(%r26) 402 stw %r22, 60(%r26) 403 ldo 64(%r26), %r26 404 ADDIB>,n -1, %r1, 1b 405 ldw 0(%r25), %r19 406#endif 407 bv %r0(%r2) 408 nop 409 .exit 410 411 .procend 412 413/* 414 * NOTE: Code in clear_user_page has a hard coded dependency on the 415 * maximum alias boundary being 4 Mb. We've been assured by the 416 * parisc chip designers that there will not ever be a parisc 417 * chip with a larger alias boundary (Never say never :-) ). 418 * 419 * Subtle: the dtlb miss handlers support the temp alias region by 420 * "knowing" that if a dtlb miss happens within the temp alias 421 * region it must have occurred while in clear_user_page. Since 422 * this routine makes use of processor local translations, we 423 * don't want to insert them into the kernel page table. Instead, 424 * we load up some general registers (they need to be registers 425 * which aren't shadowed) with the physical page numbers (preshifted 426 * for tlb insertion) needed to insert the translations. When we 427 * miss on the translation, the dtlb miss handler inserts the 428 * translation into the tlb using these values: 429 * 430 * %r26 physical page (shifted for tlb insert) of "to" translation 431 * %r23 physical page (shifted for tlb insert) of "from" translation 432 */ 433 434#if 0 435 436 /* 437 * We can't do this since copy_user_page is used to bring in 438 * file data that might have instructions. Since the data would 439 * then need to be flushed out so the i-fetch can see it, it 440 * makes more sense to just copy through the kernel translation 441 * and flush it. 442 * 443 * I'm still keeping this around because it may be possible to 444 * use it if more information is passed into copy_user_page(). 445 * Have to do some measurements to see if it is worthwhile to 446 * lobby for such a change. 447 */ 448 449 .export copy_user_page_asm,code 450 451copy_user_page_asm: 452 .proc 453 .callinfo NO_CALLS 454 .entry 455 456 ldil L%(__PAGE_OFFSET), %r1 457 sub %r26, %r1, %r26 458 sub %r25, %r1, %r23 /* move physical addr into non shadowed reg */ 459 460 ldil L%(TMPALIAS_MAP_START), %r28 461 /* FIXME for different page sizes != 4k */ 462#ifdef CONFIG_64BIT 463 extrd,u %r26,56,32, %r26 /* convert phys addr to tlb insert format */ 464 extrd,u %r23,56,32, %r23 /* convert phys addr to tlb insert format */ 465 depd %r24,63,22, %r28 /* Form aliased virtual address 'to' */ 466 depdi 0, 63,12, %r28 /* Clear any offset bits */ 467 copy %r28, %r29 468 depdi 1, 41,1, %r29 /* Form aliased virtual address 'from' */ 469#else 470 extrw,u %r26, 24,25, %r26 /* convert phys addr to tlb insert format */ 471 extrw,u %r23, 24,25, %r23 /* convert phys addr to tlb insert format */ 472 depw %r24, 31,22, %r28 /* Form aliased virtual address 'to' */ 473 depwi 0, 31,12, %r28 /* Clear any offset bits */ 474 copy %r28, %r29 475 depwi 1, 9,1, %r29 /* Form aliased virtual address 'from' */ 476#endif 477 478 /* Purge any old translations */ 479 480 pdtlb 0(%r28) 481 pdtlb 0(%r29) 482 483 ldi 64, %r1 484 485 /* 486 * This loop is optimized for PCXL/PCXL2 ldw/ldw and stw/stw 487 * bundles (very restricted rules for bundling). It probably 488 * does OK on PCXU and better, but we could do better with 489 * ldd/std instructions. Note that until (if) we start saving 490 * the full 64 bit register values on interrupt, we can't 491 * use ldd/std on a 32 bit kernel. 492 */ 493 494 4951: 496 ldw 0(%r29), %r19 497 ldw 4(%r29), %r20 498 ldw 8(%r29), %r21 499 ldw 12(%r29), %r22 500 stw %r19, 0(%r28) 501 stw %r20, 4(%r28) 502 stw %r21, 8(%r28) 503 stw %r22, 12(%r28) 504 ldw 16(%r29), %r19 505 ldw 20(%r29), %r20 506 ldw 24(%r29), %r21 507 ldw 28(%r29), %r22 508 stw %r19, 16(%r28) 509 stw %r20, 20(%r28) 510 stw %r21, 24(%r28) 511 stw %r22, 28(%r28) 512 ldw 32(%r29), %r19 513 ldw 36(%r29), %r20 514 ldw 40(%r29), %r21 515 ldw 44(%r29), %r22 516 stw %r19, 32(%r28) 517 stw %r20, 36(%r28) 518 stw %r21, 40(%r28) 519 stw %r22, 44(%r28) 520 ldw 48(%r29), %r19 521 ldw 52(%r29), %r20 522 ldw 56(%r29), %r21 523 ldw 60(%r29), %r22 524 stw %r19, 48(%r28) 525 stw %r20, 52(%r28) 526 stw %r21, 56(%r28) 527 stw %r22, 60(%r28) 528 ldo 64(%r28), %r28 529 ADDIB> -1, %r1,1b 530 ldo 64(%r29), %r29 531 532 bv %r0(%r2) 533 nop 534 .exit 535 536 .procend 537#endif 538 539 .export __clear_user_page_asm,code 540 541__clear_user_page_asm: 542 .proc 543 .callinfo NO_CALLS 544 .entry 545 546 tophys_r1 %r26 547 548 ldil L%(TMPALIAS_MAP_START), %r28 549#ifdef CONFIG_64BIT 550#if (TMPALIAS_MAP_START >= 0x80000000) 551 depdi 0, 31,32, %r28 /* clear any sign extension */ 552 /* FIXME: page size dependend */ 553#endif 554 extrd,u %r26, 56,32, %r26 /* convert phys addr to tlb insert format */ 555 depd %r25, 63,22, %r28 /* Form aliased virtual address 'to' */ 556 depdi 0, 63,12, %r28 /* Clear any offset bits */ 557#else 558 extrw,u %r26, 24,25, %r26 /* convert phys addr to tlb insert format */ 559 depw %r25, 31,22, %r28 /* Form aliased virtual address 'to' */ 560 depwi 0, 31,12, %r28 /* Clear any offset bits */ 561#endif 562 563 /* Purge any old translation */ 564 565 pdtlb 0(%r28) 566 567#ifdef CONFIG_64BIT 568 ldi ASM_PAGE_SIZE_DIV128, %r1 569 570 /* PREFETCH (Write) has not (yet) been proven to help here */ 571 /* #define PREFETCHW_OP ldd 256(%0), %r0 */ 572 5731: std %r0, 0(%r28) 574 std %r0, 8(%r28) 575 std %r0, 16(%r28) 576 std %r0, 24(%r28) 577 std %r0, 32(%r28) 578 std %r0, 40(%r28) 579 std %r0, 48(%r28) 580 std %r0, 56(%r28) 581 std %r0, 64(%r28) 582 std %r0, 72(%r28) 583 std %r0, 80(%r28) 584 std %r0, 88(%r28) 585 std %r0, 96(%r28) 586 std %r0, 104(%r28) 587 std %r0, 112(%r28) 588 std %r0, 120(%r28) 589 ADDIB> -1, %r1, 1b 590 ldo 128(%r28), %r28 591 592#else /* ! CONFIG_64BIT */ 593 ldi ASM_PAGE_SIZE_DIV64, %r1 594 5951: 596 stw %r0, 0(%r28) 597 stw %r0, 4(%r28) 598 stw %r0, 8(%r28) 599 stw %r0, 12(%r28) 600 stw %r0, 16(%r28) 601 stw %r0, 20(%r28) 602 stw %r0, 24(%r28) 603 stw %r0, 28(%r28) 604 stw %r0, 32(%r28) 605 stw %r0, 36(%r28) 606 stw %r0, 40(%r28) 607 stw %r0, 44(%r28) 608 stw %r0, 48(%r28) 609 stw %r0, 52(%r28) 610 stw %r0, 56(%r28) 611 stw %r0, 60(%r28) 612 ADDIB> -1, %r1, 1b 613 ldo 64(%r28), %r28 614#endif /* CONFIG_64BIT */ 615 616 bv %r0(%r2) 617 nop 618 .exit 619 620 .procend 621 622 .export flush_kernel_dcache_page_asm 623 624flush_kernel_dcache_page_asm: 625 .proc 626 .callinfo NO_CALLS 627 .entry 628 629 ldil L%dcache_stride, %r1 630 ldw R%dcache_stride(%r1), %r23 631 632#ifdef CONFIG_64BIT 633 depdi,z 1, 63-PAGE_SHIFT,1, %r25 634#else 635 depwi,z 1, 31-PAGE_SHIFT,1, %r25 636#endif 637 add %r26, %r25, %r25 638 sub %r25, %r23, %r25 639 640 6411: fdc,m %r23(%r26) 642 fdc,m %r23(%r26) 643 fdc,m %r23(%r26) 644 fdc,m %r23(%r26) 645 fdc,m %r23(%r26) 646 fdc,m %r23(%r26) 647 fdc,m %r23(%r26) 648 fdc,m %r23(%r26) 649 fdc,m %r23(%r26) 650 fdc,m %r23(%r26) 651 fdc,m %r23(%r26) 652 fdc,m %r23(%r26) 653 fdc,m %r23(%r26) 654 fdc,m %r23(%r26) 655 fdc,m %r23(%r26) 656 CMPB<< %r26, %r25,1b 657 fdc,m %r23(%r26) 658 659 sync 660 bv %r0(%r2) 661 nop 662 .exit 663 664 .procend 665 666 .export flush_user_dcache_page 667 668flush_user_dcache_page: 669 .proc 670 .callinfo NO_CALLS 671 .entry 672 673 ldil L%dcache_stride, %r1 674 ldw R%dcache_stride(%r1), %r23 675 676#ifdef CONFIG_64BIT 677 depdi,z 1,63-PAGE_SHIFT,1, %r25 678#else 679 depwi,z 1,31-PAGE_SHIFT,1, %r25 680#endif 681 add %r26, %r25, %r25 682 sub %r25, %r23, %r25 683 684 6851: fdc,m %r23(%sr3, %r26) 686 fdc,m %r23(%sr3, %r26) 687 fdc,m %r23(%sr3, %r26) 688 fdc,m %r23(%sr3, %r26) 689 fdc,m %r23(%sr3, %r26) 690 fdc,m %r23(%sr3, %r26) 691 fdc,m %r23(%sr3, %r26) 692 fdc,m %r23(%sr3, %r26) 693 fdc,m %r23(%sr3, %r26) 694 fdc,m %r23(%sr3, %r26) 695 fdc,m %r23(%sr3, %r26) 696 fdc,m %r23(%sr3, %r26) 697 fdc,m %r23(%sr3, %r26) 698 fdc,m %r23(%sr3, %r26) 699 fdc,m %r23(%sr3, %r26) 700 CMPB<< %r26, %r25,1b 701 fdc,m %r23(%sr3, %r26) 702 703 sync 704 bv %r0(%r2) 705 nop 706 .exit 707 708 .procend 709 710 .export flush_user_icache_page 711 712flush_user_icache_page: 713 .proc 714 .callinfo NO_CALLS 715 .entry 716 717 ldil L%dcache_stride, %r1 718 ldw R%dcache_stride(%r1), %r23 719 720#ifdef CONFIG_64BIT 721 depdi,z 1, 63-PAGE_SHIFT,1, %r25 722#else 723 depwi,z 1, 31-PAGE_SHIFT,1, %r25 724#endif 725 add %r26, %r25, %r25 726 sub %r25, %r23, %r25 727 728 7291: fic,m %r23(%sr3, %r26) 730 fic,m %r23(%sr3, %r26) 731 fic,m %r23(%sr3, %r26) 732 fic,m %r23(%sr3, %r26) 733 fic,m %r23(%sr3, %r26) 734 fic,m %r23(%sr3, %r26) 735 fic,m %r23(%sr3, %r26) 736 fic,m %r23(%sr3, %r26) 737 fic,m %r23(%sr3, %r26) 738 fic,m %r23(%sr3, %r26) 739 fic,m %r23(%sr3, %r26) 740 fic,m %r23(%sr3, %r26) 741 fic,m %r23(%sr3, %r26) 742 fic,m %r23(%sr3, %r26) 743 fic,m %r23(%sr3, %r26) 744 CMPB<< %r26, %r25,1b 745 fic,m %r23(%sr3, %r26) 746 747 sync 748 bv %r0(%r2) 749 nop 750 .exit 751 752 .procend 753 754 755 .export purge_kernel_dcache_page 756 757purge_kernel_dcache_page: 758 .proc 759 .callinfo NO_CALLS 760 .entry 761 762 ldil L%dcache_stride, %r1 763 ldw R%dcache_stride(%r1), %r23 764 765#ifdef CONFIG_64BIT 766 depdi,z 1, 63-PAGE_SHIFT,1, %r25 767#else 768 depwi,z 1, 31-PAGE_SHIFT,1, %r25 769#endif 770 add %r26, %r25, %r25 771 sub %r25, %r23, %r25 772 7731: pdc,m %r23(%r26) 774 pdc,m %r23(%r26) 775 pdc,m %r23(%r26) 776 pdc,m %r23(%r26) 777 pdc,m %r23(%r26) 778 pdc,m %r23(%r26) 779 pdc,m %r23(%r26) 780 pdc,m %r23(%r26) 781 pdc,m %r23(%r26) 782 pdc,m %r23(%r26) 783 pdc,m %r23(%r26) 784 pdc,m %r23(%r26) 785 pdc,m %r23(%r26) 786 pdc,m %r23(%r26) 787 pdc,m %r23(%r26) 788 CMPB<< %r26, %r25, 1b 789 pdc,m %r23(%r26) 790 791 sync 792 bv %r0(%r2) 793 nop 794 .exit 795 796 .procend 797 798#if 0 799 /* Currently not used, but it still is a possible alternate 800 * solution. 801 */ 802 803 .export flush_alias_page 804 805flush_alias_page: 806 .proc 807 .callinfo NO_CALLS 808 .entry 809 810 tophys_r1 %r26 811 812 ldil L%(TMPALIAS_MAP_START), %r28 813#ifdef CONFIG_64BIT 814 extrd,u %r26, 56,32, %r26 /* convert phys addr to tlb insert format */ 815 depd %r25, 63,22, %r28 /* Form aliased virtual address 'to' */ 816 depdi 0, 63,12, %r28 /* Clear any offset bits */ 817#else 818 extrw,u %r26, 24,25, %r26 /* convert phys addr to tlb insert format */ 819 depw %r25, 31,22, %r28 /* Form aliased virtual address 'to' */ 820 depwi 0, 31,12, %r28 /* Clear any offset bits */ 821#endif 822 823 /* Purge any old translation */ 824 825 pdtlb 0(%r28) 826 827 ldil L%dcache_stride, %r1 828 ldw R%dcache_stride(%r1), %r23 829 830#ifdef CONFIG_64BIT 831 depdi,z 1, 63-PAGE_SHIFT,1, %r29 832#else 833 depwi,z 1, 31-PAGE_SHIFT,1, %r29 834#endif 835 add %r28, %r29, %r29 836 sub %r29, %r23, %r29 837 8381: fdc,m %r23(%r28) 839 fdc,m %r23(%r28) 840 fdc,m %r23(%r28) 841 fdc,m %r23(%r28) 842 fdc,m %r23(%r28) 843 fdc,m %r23(%r28) 844 fdc,m %r23(%r28) 845 fdc,m %r23(%r28) 846 fdc,m %r23(%r28) 847 fdc,m %r23(%r28) 848 fdc,m %r23(%r28) 849 fdc,m %r23(%r28) 850 fdc,m %r23(%r28) 851 fdc,m %r23(%r28) 852 fdc,m %r23(%r28) 853 CMPB<< %r28, %r29, 1b 854 fdc,m %r23(%r28) 855 856 sync 857 bv %r0(%r2) 858 nop 859 .exit 860 861 .procend 862#endif 863 864 .export flush_user_dcache_range_asm 865 866flush_user_dcache_range_asm: 867 .proc 868 .callinfo NO_CALLS 869 .entry 870 871 ldil L%dcache_stride, %r1 872 ldw R%dcache_stride(%r1), %r23 873 ldo -1(%r23), %r21 874 ANDCM %r26, %r21, %r26 875 8761: CMPB<<,n %r26, %r25, 1b 877 fdc,m %r23(%sr3, %r26) 878 879 sync 880 bv %r0(%r2) 881 nop 882 .exit 883 884 .procend 885 886 .export flush_kernel_dcache_range_asm 887 888flush_kernel_dcache_range_asm: 889 .proc 890 .callinfo NO_CALLS 891 .entry 892 893 ldil L%dcache_stride, %r1 894 ldw R%dcache_stride(%r1), %r23 895 ldo -1(%r23), %r21 896 ANDCM %r26, %r21, %r26 897 8981: CMPB<<,n %r26, %r25,1b 899 fdc,m %r23(%r26) 900 901 sync 902 syncdma 903 bv %r0(%r2) 904 nop 905 .exit 906 907 .procend 908 909 .export flush_user_icache_range_asm 910 911flush_user_icache_range_asm: 912 .proc 913 .callinfo NO_CALLS 914 .entry 915 916 ldil L%icache_stride, %r1 917 ldw R%icache_stride(%r1), %r23 918 ldo -1(%r23), %r21 919 ANDCM %r26, %r21, %r26 920 9211: CMPB<<,n %r26, %r25,1b 922 fic,m %r23(%sr3, %r26) 923 924 sync 925 bv %r0(%r2) 926 nop 927 .exit 928 929 .procend 930 931 .export flush_kernel_icache_page 932 933flush_kernel_icache_page: 934 .proc 935 .callinfo NO_CALLS 936 .entry 937 938 ldil L%icache_stride, %r1 939 ldw R%icache_stride(%r1), %r23 940 941#ifdef CONFIG_64BIT 942 depdi,z 1, 63-PAGE_SHIFT,1, %r25 943#else 944 depwi,z 1, 31-PAGE_SHIFT,1, %r25 945#endif 946 add %r26, %r25, %r25 947 sub %r25, %r23, %r25 948 949 9501: fic,m %r23(%sr4, %r26) 951 fic,m %r23(%sr4, %r26) 952 fic,m %r23(%sr4, %r26) 953 fic,m %r23(%sr4, %r26) 954 fic,m %r23(%sr4, %r26) 955 fic,m %r23(%sr4, %r26) 956 fic,m %r23(%sr4, %r26) 957 fic,m %r23(%sr4, %r26) 958 fic,m %r23(%sr4, %r26) 959 fic,m %r23(%sr4, %r26) 960 fic,m %r23(%sr4, %r26) 961 fic,m %r23(%sr4, %r26) 962 fic,m %r23(%sr4, %r26) 963 fic,m %r23(%sr4, %r26) 964 fic,m %r23(%sr4, %r26) 965 CMPB<< %r26, %r25, 1b 966 fic,m %r23(%sr4, %r26) 967 968 sync 969 bv %r0(%r2) 970 nop 971 .exit 972 973 .procend 974 975 .export flush_kernel_icache_range_asm 976 977flush_kernel_icache_range_asm: 978 .proc 979 .callinfo NO_CALLS 980 .entry 981 982 ldil L%icache_stride, %r1 983 ldw R%icache_stride(%r1), %r23 984 ldo -1(%r23), %r21 985 ANDCM %r26, %r21, %r26 986 9871: CMPB<<,n %r26, %r25, 1b 988 fic,m %r23(%sr4, %r26) 989 990 sync 991 bv %r0(%r2) 992 nop 993 .exit 994 .procend 995 996 /* align should cover use of rfi in disable_sr_hashing_asm and 997 * srdis_done. 998 */ 999 .align 256 1000 .export disable_sr_hashing_asm,code 1001 1002disable_sr_hashing_asm: 1003 .proc 1004 .callinfo NO_CALLS 1005 .entry 1006 1007 /* 1008 * Switch to real mode 1009 */ 1010 /* pcxt_ssm_bug */ 1011 rsm PSW_SM_I, %r0 1012 load32 PA(1f), %r1 1013 nop 1014 nop 1015 nop 1016 nop 1017 nop 1018 1019 rsm PSW_SM_Q, %r0 /* prep to load iia queue */ 1020 mtctl %r0, %cr17 /* Clear IIASQ tail */ 1021 mtctl %r0, %cr17 /* Clear IIASQ head */ 1022 mtctl %r1, %cr18 /* IIAOQ head */ 1023 ldo 4(%r1), %r1 1024 mtctl %r1, %cr18 /* IIAOQ tail */ 1025 load32 REAL_MODE_PSW, %r1 1026 mtctl %r1, %ipsw 1027 rfi 1028 nop 1029 10301: cmpib,=,n SRHASH_PCXST, %r26,srdis_pcxs 1031 cmpib,=,n SRHASH_PCXL, %r26,srdis_pcxl 1032 cmpib,=,n SRHASH_PA20, %r26,srdis_pa20 1033 b,n srdis_done 1034 1035srdis_pcxs: 1036 1037 /* Disable Space Register Hashing for PCXS,PCXT,PCXT' */ 1038 1039 .word 0x141c1a00 /* mfdiag %dr0, %r28 */ 1040 .word 0x141c1a00 /* must issue twice */ 1041 depwi 0,18,1, %r28 /* Clear DHE (dcache hash enable) */ 1042 depwi 0,20,1, %r28 /* Clear IHE (icache hash enable) */ 1043 .word 0x141c1600 /* mtdiag %r28, %dr0 */ 1044 .word 0x141c1600 /* must issue twice */ 1045 b,n srdis_done 1046 1047srdis_pcxl: 1048 1049 /* Disable Space Register Hashing for PCXL */ 1050 1051 .word 0x141c0600 /* mfdiag %dr0, %r28 */ 1052 depwi 0,28,2, %r28 /* Clear DHASH_EN & IHASH_EN */ 1053 .word 0x141c0240 /* mtdiag %r28, %dr0 */ 1054 b,n srdis_done 1055 1056srdis_pa20: 1057 1058 /* Disable Space Register Hashing for PCXU,PCXU+,PCXW,PCXW+,PCXW2 */ 1059 1060 .word 0x144008bc /* mfdiag %dr2, %r28 */ 1061 depdi 0, 54,1, %r28 /* clear DIAG_SPHASH_ENAB (bit 54) */ 1062 .word 0x145c1840 /* mtdiag %r28, %dr2 */ 1063 1064 1065srdis_done: 1066 /* Switch back to virtual mode */ 1067 rsm PSW_SM_I, %r0 /* prep to load iia queue */ 1068 load32 2f, %r1 1069 nop 1070 nop 1071 nop 1072 nop 1073 nop 1074 1075 rsm PSW_SM_Q, %r0 /* prep to load iia queue */ 1076 mtctl %r0, %cr17 /* Clear IIASQ tail */ 1077 mtctl %r0, %cr17 /* Clear IIASQ head */ 1078 mtctl %r1, %cr18 /* IIAOQ head */ 1079 ldo 4(%r1), %r1 1080 mtctl %r1, %cr18 /* IIAOQ tail */ 1081 load32 KERNEL_PSW, %r1 1082 mtctl %r1, %ipsw 1083 rfi 1084 nop 1085 10862: bv %r0(%r2) 1087 nop 1088 .exit 1089 1090 .procend 1091 1092 .end 1093