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