linux/arch/parisc/kernel/pacache.S
<<
>>
Prefs
   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        .level  2.0w
  31#else
  32        .level  2.0
  33#endif
  34
  35#include <asm/psw.h>
  36#include <asm/assembly.h>
  37#include <asm/pgtable.h>
  38#include <asm/cache.h>
  39#include <linux/linkage.h>
  40
  41        .text
  42        .align  128
  43
  44ENTRY(flush_tlb_all_local)
  45        .proc
  46        .callinfo NO_CALLS
  47        .entry
  48
  49        /*
  50         * The pitlbe and pdtlbe instructions should only be used to
  51         * flush the entire tlb. Also, there needs to be no intervening
  52         * tlb operations, e.g. tlb misses, so the operation needs
  53         * to happen in real mode with all interruptions disabled.
  54         */
  55
  56        /* pcxt_ssm_bug - relied upon translation! PA 2.0 Arch. F-4 and F-5 */
  57        rsm             PSW_SM_I, %r19          /* save I-bit state */
  58        load32          PA(1f), %r1
  59        nop
  60        nop
  61        nop
  62        nop
  63        nop
  64
  65        rsm             PSW_SM_Q, %r0           /* prep to load iia queue */
  66        mtctl           %r0, %cr17              /* Clear IIASQ tail */
  67        mtctl           %r0, %cr17              /* Clear IIASQ head */
  68        mtctl           %r1, %cr18              /* IIAOQ head */
  69        ldo             4(%r1), %r1
  70        mtctl           %r1, %cr18              /* IIAOQ tail */
  71        load32          REAL_MODE_PSW, %r1
  72        mtctl           %r1, %ipsw
  73        rfi
  74        nop
  75
  761:      load32          PA(cache_info), %r1
  77
  78        /* Flush Instruction Tlb */
  79
  80        LDREG           ITLB_SID_BASE(%r1), %r20
  81        LDREG           ITLB_SID_STRIDE(%r1), %r21
  82        LDREG           ITLB_SID_COUNT(%r1), %r22
  83        LDREG           ITLB_OFF_BASE(%r1), %arg0
  84        LDREG           ITLB_OFF_STRIDE(%r1), %arg1
  85        LDREG           ITLB_OFF_COUNT(%r1), %arg2
  86        LDREG           ITLB_LOOP(%r1), %arg3
  87
  88        addib,COND(=)           -1, %arg3, fitoneloop   /* Preadjust and test */
  89        movb,<,n        %arg3, %r31, fitdone    /* If loop < 0, skip */
  90        copy            %arg0, %r28             /* Init base addr */
  91
  92fitmanyloop:                                    /* Loop if LOOP >= 2 */
  93        mtsp            %r20, %sr1
  94        add             %r21, %r20, %r20        /* increment space */
  95        copy            %arg2, %r29             /* Init middle loop count */
  96
  97fitmanymiddle:                                  /* Loop if LOOP >= 2 */
  98        addib,COND(>)           -1, %r31, fitmanymiddle /* Adjusted inner loop decr */
  99        pitlbe          0(%sr1, %r28)
 100        pitlbe,m        %arg1(%sr1, %r28)       /* Last pitlbe and addr adjust */
 101        addib,COND(>)           -1, %r29, fitmanymiddle /* Middle loop decr */
 102        copy            %arg3, %r31             /* Re-init inner loop count */
 103
 104        movb,tr         %arg0, %r28, fitmanyloop /* Re-init base addr */
 105        addib,COND(<=),n        -1, %r22, fitdone       /* Outer loop count decr */
 106
 107fitoneloop:                                     /* Loop if LOOP = 1 */
 108        mtsp            %r20, %sr1
 109        copy            %arg0, %r28             /* init base addr */
 110        copy            %arg2, %r29             /* init middle loop count */
 111
 112fitonemiddle:                                   /* Loop if LOOP = 1 */
 113        addib,COND(>)           -1, %r29, fitonemiddle  /* Middle loop count decr */
 114        pitlbe,m        %arg1(%sr1, %r28)       /* pitlbe for one loop */
 115
 116        addib,COND(>)           -1, %r22, fitoneloop    /* Outer loop count decr */
 117        add             %r21, %r20, %r20                /* increment space */
 118
 119fitdone:
 120
 121        /* Flush Data Tlb */
 122
 123        LDREG           DTLB_SID_BASE(%r1), %r20
 124        LDREG           DTLB_SID_STRIDE(%r1), %r21
 125        LDREG           DTLB_SID_COUNT(%r1), %r22
 126        LDREG           DTLB_OFF_BASE(%r1), %arg0
 127        LDREG           DTLB_OFF_STRIDE(%r1), %arg1
 128        LDREG           DTLB_OFF_COUNT(%r1), %arg2
 129        LDREG           DTLB_LOOP(%r1), %arg3
 130
 131        addib,COND(=)           -1, %arg3, fdtoneloop   /* Preadjust and test */
 132        movb,<,n        %arg3, %r31, fdtdone    /* If loop < 0, skip */
 133        copy            %arg0, %r28             /* Init base addr */
 134
 135fdtmanyloop:                                    /* Loop if LOOP >= 2 */
 136        mtsp            %r20, %sr1
 137        add             %r21, %r20, %r20        /* increment space */
 138        copy            %arg2, %r29             /* Init middle loop count */
 139
 140fdtmanymiddle:                                  /* Loop if LOOP >= 2 */
 141        addib,COND(>)           -1, %r31, fdtmanymiddle /* Adjusted inner loop decr */
 142        pdtlbe          0(%sr1, %r28)
 143        pdtlbe,m        %arg1(%sr1, %r28)       /* Last pdtlbe and addr adjust */
 144        addib,COND(>)           -1, %r29, fdtmanymiddle /* Middle loop decr */
 145        copy            %arg3, %r31             /* Re-init inner loop count */
 146
 147        movb,tr         %arg0, %r28, fdtmanyloop /* Re-init base addr */
 148        addib,COND(<=),n        -1, %r22,fdtdone        /* Outer loop count decr */
 149
 150fdtoneloop:                                     /* Loop if LOOP = 1 */
 151        mtsp            %r20, %sr1
 152        copy            %arg0, %r28             /* init base addr */
 153        copy            %arg2, %r29             /* init middle loop count */
 154
 155fdtonemiddle:                                   /* Loop if LOOP = 1 */
 156        addib,COND(>)           -1, %r29, fdtonemiddle  /* Middle loop count decr */
 157        pdtlbe,m        %arg1(%sr1, %r28)       /* pdtlbe for one loop */
 158
 159        addib,COND(>)           -1, %r22, fdtoneloop    /* Outer loop count decr */
 160        add             %r21, %r20, %r20        /* increment space */
 161
 162
 163fdtdone:
 164        /*
 165         * Switch back to virtual mode
 166         */
 167        /* pcxt_ssm_bug */
 168        rsm             PSW_SM_I, %r0
 169        load32          2f, %r1
 170        nop
 171        nop
 172        nop
 173        nop
 174        nop
 175
 176        rsm             PSW_SM_Q, %r0           /* prep to load iia queue */
 177        mtctl           %r0, %cr17              /* Clear IIASQ tail */
 178        mtctl           %r0, %cr17              /* Clear IIASQ head */
 179        mtctl           %r1, %cr18              /* IIAOQ head */
 180        ldo             4(%r1), %r1
 181        mtctl           %r1, %cr18              /* IIAOQ tail */
 182        load32          KERNEL_PSW, %r1
 183        or              %r1, %r19, %r1  /* I-bit to state on entry */
 184        mtctl           %r1, %ipsw      /* restore I-bit (entire PSW) */
 185        rfi
 186        nop
 187
 1882:      bv              %r0(%r2)
 189        nop
 190
 191        .exit
 192        .procend
 193ENDPROC(flush_tlb_all_local)
 194
 195        .import cache_info,data
 196
 197ENTRY(flush_instruction_cache_local)
 198        .proc
 199        .callinfo NO_CALLS
 200        .entry
 201
 202        load32          cache_info, %r1
 203
 204        /* Flush Instruction Cache */
 205
 206        LDREG           ICACHE_BASE(%r1), %arg0
 207        LDREG           ICACHE_STRIDE(%r1), %arg1
 208        LDREG           ICACHE_COUNT(%r1), %arg2
 209        LDREG           ICACHE_LOOP(%r1), %arg3
 210        rsm             PSW_SM_I, %r22          /* No mmgt ops during loop*/
 211        mtsp            %r0, %sr1
 212        addib,COND(=)           -1, %arg3, fioneloop    /* Preadjust and test */
 213        movb,<,n        %arg3, %r31, fisync     /* If loop < 0, do sync */
 214
 215fimanyloop:                                     /* Loop if LOOP >= 2 */
 216        addib,COND(>)           -1, %r31, fimanyloop    /* Adjusted inner loop decr */
 217        fice            %r0(%sr1, %arg0)
 218        fice,m          %arg1(%sr1, %arg0)      /* Last fice and addr adjust */
 219        movb,tr         %arg3, %r31, fimanyloop /* Re-init inner loop count */
 220        addib,COND(<=),n        -1, %arg2, fisync       /* Outer loop decr */
 221
 222fioneloop:                                      /* Loop if LOOP = 1 */
 223        /* Some implementations may flush with a single fice instruction */
 224        cmpib,COND(>>=),n       15, %arg2, fioneloop2
 225
 226fioneloop1:
 227        fice,m          %arg1(%sr1, %arg0)
 228        fice,m          %arg1(%sr1, %arg0)
 229        fice,m          %arg1(%sr1, %arg0)
 230        fice,m          %arg1(%sr1, %arg0)
 231        fice,m          %arg1(%sr1, %arg0)
 232        fice,m          %arg1(%sr1, %arg0)
 233        fice,m          %arg1(%sr1, %arg0)
 234        fice,m          %arg1(%sr1, %arg0)
 235        fice,m          %arg1(%sr1, %arg0)
 236        fice,m          %arg1(%sr1, %arg0)
 237        fice,m          %arg1(%sr1, %arg0)
 238        fice,m          %arg1(%sr1, %arg0)
 239        fice,m          %arg1(%sr1, %arg0)
 240        fice,m          %arg1(%sr1, %arg0)
 241        fice,m          %arg1(%sr1, %arg0)
 242        addib,COND(>)   -16, %arg2, fioneloop1
 243        fice,m          %arg1(%sr1, %arg0)
 244
 245        /* Check if done */
 246        cmpb,COND(=),n  %arg2, %r0, fisync      /* Predict branch taken */
 247
 248fioneloop2:
 249        addib,COND(>)   -1, %arg2, fioneloop2   /* Outer loop count decr */
 250        fice,m          %arg1(%sr1, %arg0)      /* Fice for one loop */
 251
 252fisync:
 253        sync
 254        mtsm            %r22                    /* restore I-bit */
 255        bv              %r0(%r2)
 256        nop
 257        .exit
 258
 259        .procend
 260ENDPROC(flush_instruction_cache_local)
 261
 262
 263        .import cache_info, data
 264ENTRY(flush_data_cache_local)
 265        .proc
 266        .callinfo NO_CALLS
 267        .entry
 268
 269        load32          cache_info, %r1
 270
 271        /* Flush Data Cache */
 272
 273        LDREG           DCACHE_BASE(%r1), %arg0
 274        LDREG           DCACHE_STRIDE(%r1), %arg1
 275        LDREG           DCACHE_COUNT(%r1), %arg2
 276        LDREG           DCACHE_LOOP(%r1), %arg3
 277        rsm             PSW_SM_I, %r22          /* No mmgt ops during loop*/
 278        mtsp            %r0, %sr1
 279        addib,COND(=)           -1, %arg3, fdoneloop    /* Preadjust and test */
 280        movb,<,n        %arg3, %r31, fdsync     /* If loop < 0, do sync */
 281
 282fdmanyloop:                                     /* Loop if LOOP >= 2 */
 283        addib,COND(>)           -1, %r31, fdmanyloop    /* Adjusted inner loop decr */
 284        fdce            %r0(%sr1, %arg0)
 285        fdce,m          %arg1(%sr1, %arg0)      /* Last fdce and addr adjust */
 286        movb,tr         %arg3, %r31, fdmanyloop /* Re-init inner loop count */
 287        addib,COND(<=),n        -1, %arg2, fdsync       /* Outer loop decr */
 288
 289fdoneloop:                                      /* Loop if LOOP = 1 */
 290        /* Some implementations may flush with a single fdce instruction */
 291        cmpib,COND(>>=),n       15, %arg2, fdoneloop2
 292
 293fdoneloop1:
 294        fdce,m          %arg1(%sr1, %arg0)
 295        fdce,m          %arg1(%sr1, %arg0)
 296        fdce,m          %arg1(%sr1, %arg0)
 297        fdce,m          %arg1(%sr1, %arg0)
 298        fdce,m          %arg1(%sr1, %arg0)
 299        fdce,m          %arg1(%sr1, %arg0)
 300        fdce,m          %arg1(%sr1, %arg0)
 301        fdce,m          %arg1(%sr1, %arg0)
 302        fdce,m          %arg1(%sr1, %arg0)
 303        fdce,m          %arg1(%sr1, %arg0)
 304        fdce,m          %arg1(%sr1, %arg0)
 305        fdce,m          %arg1(%sr1, %arg0)
 306        fdce,m          %arg1(%sr1, %arg0)
 307        fdce,m          %arg1(%sr1, %arg0)
 308        fdce,m          %arg1(%sr1, %arg0)
 309        addib,COND(>)   -16, %arg2, fdoneloop1
 310        fdce,m          %arg1(%sr1, %arg0)
 311
 312        /* Check if done */
 313        cmpb,COND(=),n  %arg2, %r0, fdsync      /* Predict branch taken */
 314
 315fdoneloop2:
 316        addib,COND(>)   -1, %arg2, fdoneloop2   /* Outer loop count decr */
 317        fdce,m          %arg1(%sr1, %arg0)      /* Fdce for one loop */
 318
 319fdsync:
 320        syncdma
 321        sync
 322        mtsm            %r22                    /* restore I-bit */
 323        bv              %r0(%r2)
 324        nop
 325        .exit
 326
 327        .procend
 328ENDPROC(flush_data_cache_local)
 329
 330        .align  16
 331
 332/* Macros to serialize TLB purge operations on SMP.  */
 333
 334        .macro  tlb_lock        la,flags,tmp
 335#ifdef CONFIG_SMP
 336        ldil            L%pa_tlb_lock,%r1
 337        ldo             R%pa_tlb_lock(%r1),\la
 338        rsm             PSW_SM_I,\flags
 3391:      LDCW            0(\la),\tmp
 340        cmpib,<>,n      0,\tmp,3f
 3412:      ldw             0(\la),\tmp
 342        cmpb,<>         %r0,\tmp,1b
 343        nop
 344        b,n             2b
 3453:
 346#endif
 347        .endm
 348
 349        .macro  tlb_unlock      la,flags,tmp
 350#ifdef CONFIG_SMP
 351        ldi             1,\tmp
 352        stw             \tmp,0(\la)
 353        mtsm            \flags
 354#endif
 355        .endm
 356
 357/* Clear page using kernel mapping.  */
 358
 359ENTRY(clear_page_asm)
 360        .proc
 361        .callinfo NO_CALLS
 362        .entry
 363
 364#ifdef CONFIG_64BIT
 365
 366        /* Unroll the loop.  */
 367        ldi             (PAGE_SIZE / 128), %r1
 368
 3691:
 370        std             %r0, 0(%r26)
 371        std             %r0, 8(%r26)
 372        std             %r0, 16(%r26)
 373        std             %r0, 24(%r26)
 374        std             %r0, 32(%r26)
 375        std             %r0, 40(%r26)
 376        std             %r0, 48(%r26)
 377        std             %r0, 56(%r26)
 378        std             %r0, 64(%r26)
 379        std             %r0, 72(%r26)
 380        std             %r0, 80(%r26)
 381        std             %r0, 88(%r26)
 382        std             %r0, 96(%r26)
 383        std             %r0, 104(%r26)
 384        std             %r0, 112(%r26)
 385        std             %r0, 120(%r26)
 386
 387        /* Note reverse branch hint for addib is taken.  */
 388        addib,COND(>),n -1, %r1, 1b
 389        ldo             128(%r26), %r26
 390
 391#else
 392
 393        /*
 394         * Note that until (if) we start saving the full 64-bit register
 395         * values on interrupt, we can't use std on a 32 bit kernel.
 396         */
 397        ldi             (PAGE_SIZE / 64), %r1
 398
 3991:
 400        stw             %r0, 0(%r26)
 401        stw             %r0, 4(%r26)
 402        stw             %r0, 8(%r26)
 403        stw             %r0, 12(%r26)
 404        stw             %r0, 16(%r26)
 405        stw             %r0, 20(%r26)
 406        stw             %r0, 24(%r26)
 407        stw             %r0, 28(%r26)
 408        stw             %r0, 32(%r26)
 409        stw             %r0, 36(%r26)
 410        stw             %r0, 40(%r26)
 411        stw             %r0, 44(%r26)
 412        stw             %r0, 48(%r26)
 413        stw             %r0, 52(%r26)
 414        stw             %r0, 56(%r26)
 415        stw             %r0, 60(%r26)
 416
 417        addib,COND(>),n -1, %r1, 1b
 418        ldo             64(%r26), %r26
 419#endif
 420        bv              %r0(%r2)
 421        nop
 422        .exit
 423
 424        .procend
 425ENDPROC(clear_page_asm)
 426
 427/* Copy page using kernel mapping.  */
 428
 429ENTRY(copy_page_asm)
 430        .proc
 431        .callinfo NO_CALLS
 432        .entry
 433
 434#ifdef CONFIG_64BIT
 435        /* PA8x00 CPUs can consume 2 loads or 1 store per cycle.
 436         * Unroll the loop by hand and arrange insn appropriately.
 437         * Prefetch doesn't improve performance on rp3440.
 438         * GCC probably can do this just as well...
 439         */
 440
 441        ldi             (PAGE_SIZE / 128), %r1
 442
 4431:      ldd             0(%r25), %r19
 444        ldd             8(%r25), %r20
 445
 446        ldd             16(%r25), %r21
 447        ldd             24(%r25), %r22
 448        std             %r19, 0(%r26)
 449        std             %r20, 8(%r26)
 450
 451        ldd             32(%r25), %r19
 452        ldd             40(%r25), %r20
 453        std             %r21, 16(%r26)
 454        std             %r22, 24(%r26)
 455
 456        ldd             48(%r25), %r21
 457        ldd             56(%r25), %r22
 458        std             %r19, 32(%r26)
 459        std             %r20, 40(%r26)
 460
 461        ldd             64(%r25), %r19
 462        ldd             72(%r25), %r20
 463        std             %r21, 48(%r26)
 464        std             %r22, 56(%r26)
 465
 466        ldd             80(%r25), %r21
 467        ldd             88(%r25), %r22
 468        std             %r19, 64(%r26)
 469        std             %r20, 72(%r26)
 470
 471        ldd              96(%r25), %r19
 472        ldd             104(%r25), %r20
 473        std             %r21, 80(%r26)
 474        std             %r22, 88(%r26)
 475
 476        ldd             112(%r25), %r21
 477        ldd             120(%r25), %r22
 478        ldo             128(%r25), %r25
 479        std             %r19, 96(%r26)
 480        std             %r20, 104(%r26)
 481
 482        std             %r21, 112(%r26)
 483        std             %r22, 120(%r26)
 484
 485        /* Note reverse branch hint for addib is taken.  */
 486        addib,COND(>),n -1, %r1, 1b
 487        ldo             128(%r26), %r26
 488
 489#else
 490
 491        /*
 492         * This loop is optimized for PCXL/PCXL2 ldw/ldw and stw/stw
 493         * bundles (very restricted rules for bundling).
 494         * Note that until (if) we start saving
 495         * the full 64 bit register values on interrupt, we can't
 496         * use ldd/std on a 32 bit kernel.
 497         */
 498        ldw             0(%r25), %r19
 499        ldi             (PAGE_SIZE / 64), %r1
 500
 5011:
 502        ldw             4(%r25), %r20
 503        ldw             8(%r25), %r21
 504        ldw             12(%r25), %r22
 505        stw             %r19, 0(%r26)
 506        stw             %r20, 4(%r26)
 507        stw             %r21, 8(%r26)
 508        stw             %r22, 12(%r26)
 509        ldw             16(%r25), %r19
 510        ldw             20(%r25), %r20
 511        ldw             24(%r25), %r21
 512        ldw             28(%r25), %r22
 513        stw             %r19, 16(%r26)
 514        stw             %r20, 20(%r26)
 515        stw             %r21, 24(%r26)
 516        stw             %r22, 28(%r26)
 517        ldw             32(%r25), %r19
 518        ldw             36(%r25), %r20
 519        ldw             40(%r25), %r21
 520        ldw             44(%r25), %r22
 521        stw             %r19, 32(%r26)
 522        stw             %r20, 36(%r26)
 523        stw             %r21, 40(%r26)
 524        stw             %r22, 44(%r26)
 525        ldw             48(%r25), %r19
 526        ldw             52(%r25), %r20
 527        ldw             56(%r25), %r21
 528        ldw             60(%r25), %r22
 529        stw             %r19, 48(%r26)
 530        stw             %r20, 52(%r26)
 531        ldo             64(%r25), %r25
 532        stw             %r21, 56(%r26)
 533        stw             %r22, 60(%r26)
 534        ldo             64(%r26), %r26
 535        addib,COND(>),n -1, %r1, 1b
 536        ldw             0(%r25), %r19
 537#endif
 538        bv              %r0(%r2)
 539        nop
 540        .exit
 541
 542        .procend
 543ENDPROC(copy_page_asm)
 544
 545/*
 546 * NOTE: Code in clear_user_page has a hard coded dependency on the
 547 *       maximum alias boundary being 4 Mb. We've been assured by the
 548 *       parisc chip designers that there will not ever be a parisc
 549 *       chip with a larger alias boundary (Never say never :-) ).
 550 *
 551 *       Subtle: the dtlb miss handlers support the temp alias region by
 552 *       "knowing" that if a dtlb miss happens within the temp alias
 553 *       region it must have occurred while in clear_user_page. Since
 554 *       this routine makes use of processor local translations, we
 555 *       don't want to insert them into the kernel page table. Instead,
 556 *       we load up some general registers (they need to be registers
 557 *       which aren't shadowed) with the physical page numbers (preshifted
 558 *       for tlb insertion) needed to insert the translations. When we
 559 *       miss on the translation, the dtlb miss handler inserts the
 560 *       translation into the tlb using these values:
 561 *
 562 *          %r26 physical page (shifted for tlb insert) of "to" translation
 563 *          %r23 physical page (shifted for tlb insert) of "from" translation
 564 */
 565
 566        /* Drop prot bits and convert to page addr for iitlbt and idtlbt */
 567        #define PAGE_ADD_SHIFT  (PAGE_SHIFT-12)
 568        .macro          convert_phys_for_tlb_insert20  phys
 569        extrd,u         \phys, 56-PAGE_ADD_SHIFT, 32-PAGE_ADD_SHIFT, \phys
 570#if _PAGE_SIZE_ENCODING_DEFAULT
 571        depdi           _PAGE_SIZE_ENCODING_DEFAULT, 63, (63-58), \phys
 572#endif
 573        .endm
 574
 575        /*
 576         * We can't do this since copy_user_page is used to bring in
 577         * file data that might have instructions. Since the data would
 578         * then need to be flushed out so the i-fetch can see it, it
 579         * makes more sense to just copy through the kernel translation
 580         * and flush it.
 581         *
 582         * I'm still keeping this around because it may be possible to
 583         * use it if more information is passed into copy_user_page().
 584         * Have to do some measurements to see if it is worthwhile to
 585         * lobby for such a change.
 586         *
 587         */
 588
 589ENTRY(copy_user_page_asm)
 590        .proc
 591        .callinfo NO_CALLS
 592        .entry
 593
 594        /* Convert virtual `to' and `from' addresses to physical addresses.
 595           Move `from' physical address to non shadowed register.  */
 596        ldil            L%(__PAGE_OFFSET), %r1
 597        sub             %r26, %r1, %r26
 598        sub             %r25, %r1, %r23
 599
 600        ldil            L%(TMPALIAS_MAP_START), %r28
 601#ifdef CONFIG_64BIT
 602#if (TMPALIAS_MAP_START >= 0x80000000)
 603        depdi           0, 31,32, %r28          /* clear any sign extension */
 604#endif
 605        convert_phys_for_tlb_insert20 %r26      /* convert phys addr to tlb insert format */
 606        convert_phys_for_tlb_insert20 %r23      /* convert phys addr to tlb insert format */
 607        depd            %r24,63,22, %r28        /* Form aliased virtual address 'to' */
 608        depdi           0, 63,PAGE_SHIFT, %r28  /* Clear any offset bits */
 609        copy            %r28, %r29
 610        depdi           1, 41,1, %r29           /* Form aliased virtual address 'from' */
 611#else
 612        extrw,u         %r26, 24,25, %r26       /* convert phys addr to tlb insert format */
 613        extrw,u         %r23, 24,25, %r23       /* convert phys addr to tlb insert format */
 614        depw            %r24, 31,22, %r28       /* Form aliased virtual address 'to' */
 615        depwi           0, 31,PAGE_SHIFT, %r28  /* Clear any offset bits */
 616        copy            %r28, %r29
 617        depwi           1, 9,1, %r29            /* Form aliased virtual address 'from' */
 618#endif
 619
 620        /* Purge any old translations */
 621
 622#ifdef CONFIG_PA20
 623        pdtlb,l         0(%r28)
 624        pdtlb,l         0(%r29)
 625#else
 626        tlb_lock        %r20,%r21,%r22
 627        pdtlb           0(%r28)
 628        pdtlb           0(%r29)
 629        tlb_unlock      %r20,%r21,%r22
 630#endif
 631
 632#ifdef CONFIG_64BIT
 633        /* PA8x00 CPUs can consume 2 loads or 1 store per cycle.
 634         * Unroll the loop by hand and arrange insn appropriately.
 635         * GCC probably can do this just as well.
 636         */
 637
 638        ldd             0(%r29), %r19
 639        ldi             (PAGE_SIZE / 128), %r1
 640
 6411:      ldd             8(%r29), %r20
 642
 643        ldd             16(%r29), %r21
 644        ldd             24(%r29), %r22
 645        std             %r19, 0(%r28)
 646        std             %r20, 8(%r28)
 647
 648        ldd             32(%r29), %r19
 649        ldd             40(%r29), %r20
 650        std             %r21, 16(%r28)
 651        std             %r22, 24(%r28)
 652
 653        ldd             48(%r29), %r21
 654        ldd             56(%r29), %r22
 655        std             %r19, 32(%r28)
 656        std             %r20, 40(%r28)
 657
 658        ldd             64(%r29), %r19
 659        ldd             72(%r29), %r20
 660        std             %r21, 48(%r28)
 661        std             %r22, 56(%r28)
 662
 663        ldd             80(%r29), %r21
 664        ldd             88(%r29), %r22
 665        std             %r19, 64(%r28)
 666        std             %r20, 72(%r28)
 667
 668        ldd              96(%r29), %r19
 669        ldd             104(%r29), %r20
 670        std             %r21, 80(%r28)
 671        std             %r22, 88(%r28)
 672
 673        ldd             112(%r29), %r21
 674        ldd             120(%r29), %r22
 675        std             %r19, 96(%r28)
 676        std             %r20, 104(%r28)
 677
 678        ldo             128(%r29), %r29
 679        std             %r21, 112(%r28)
 680        std             %r22, 120(%r28)
 681        ldo             128(%r28), %r28
 682
 683        /* conditional branches nullify on forward taken branch, and on
 684         * non-taken backward branch. Note that .+4 is a backwards branch.
 685         * The ldd should only get executed if the branch is taken.
 686         */
 687        addib,COND(>),n -1, %r1, 1b             /* bundle 10 */
 688        ldd             0(%r29), %r19           /* start next loads */
 689
 690#else
 691        ldi             (PAGE_SIZE / 64), %r1
 692
 693        /*
 694         * This loop is optimized for PCXL/PCXL2 ldw/ldw and stw/stw
 695         * bundles (very restricted rules for bundling). It probably
 696         * does OK on PCXU and better, but we could do better with
 697         * ldd/std instructions. Note that until (if) we start saving
 698         * the full 64 bit register values on interrupt, we can't
 699         * use ldd/std on a 32 bit kernel.
 700         */
 701
 7021:      ldw             0(%r29), %r19
 703        ldw             4(%r29), %r20
 704        ldw             8(%r29), %r21
 705        ldw             12(%r29), %r22
 706        stw             %r19, 0(%r28)
 707        stw             %r20, 4(%r28)
 708        stw             %r21, 8(%r28)
 709        stw             %r22, 12(%r28)
 710        ldw             16(%r29), %r19
 711        ldw             20(%r29), %r20
 712        ldw             24(%r29), %r21
 713        ldw             28(%r29), %r22
 714        stw             %r19, 16(%r28)
 715        stw             %r20, 20(%r28)
 716        stw             %r21, 24(%r28)
 717        stw             %r22, 28(%r28)
 718        ldw             32(%r29), %r19
 719        ldw             36(%r29), %r20
 720        ldw             40(%r29), %r21
 721        ldw             44(%r29), %r22
 722        stw             %r19, 32(%r28)
 723        stw             %r20, 36(%r28)
 724        stw             %r21, 40(%r28)
 725        stw             %r22, 44(%r28)
 726        ldw             48(%r29), %r19
 727        ldw             52(%r29), %r20
 728        ldw             56(%r29), %r21
 729        ldw             60(%r29), %r22
 730        stw             %r19, 48(%r28)
 731        stw             %r20, 52(%r28)
 732        stw             %r21, 56(%r28)
 733        stw             %r22, 60(%r28)
 734        ldo             64(%r28), %r28
 735
 736        addib,COND(>)           -1, %r1,1b
 737        ldo             64(%r29), %r29
 738#endif
 739
 740        bv              %r0(%r2)
 741        nop
 742        .exit
 743
 744        .procend
 745ENDPROC(copy_user_page_asm)
 746
 747ENTRY(clear_user_page_asm)
 748        .proc
 749        .callinfo NO_CALLS
 750        .entry
 751
 752        tophys_r1       %r26
 753
 754        ldil            L%(TMPALIAS_MAP_START), %r28
 755#ifdef CONFIG_64BIT
 756#if (TMPALIAS_MAP_START >= 0x80000000)
 757        depdi           0, 31,32, %r28          /* clear any sign extension */
 758#endif
 759        convert_phys_for_tlb_insert20 %r26      /* convert phys addr to tlb insert format */
 760        depd            %r25, 63,22, %r28       /* Form aliased virtual address 'to' */
 761        depdi           0, 63,PAGE_SHIFT, %r28  /* Clear any offset bits */
 762#else
 763        extrw,u         %r26, 24,25, %r26       /* convert phys addr to tlb insert format */
 764        depw            %r25, 31,22, %r28       /* Form aliased virtual address 'to' */
 765        depwi           0, 31,PAGE_SHIFT, %r28  /* Clear any offset bits */
 766#endif
 767
 768        /* Purge any old translation */
 769
 770#ifdef CONFIG_PA20
 771        pdtlb,l         0(%r28)
 772#else
 773        tlb_lock        %r20,%r21,%r22
 774        pdtlb           0(%r28)
 775        tlb_unlock      %r20,%r21,%r22
 776#endif
 777
 778#ifdef CONFIG_64BIT
 779        ldi             (PAGE_SIZE / 128), %r1
 780
 781        /* PREFETCH (Write) has not (yet) been proven to help here */
 782        /* #define      PREFETCHW_OP    ldd             256(%0), %r0 */
 783
 7841:      std             %r0, 0(%r28)
 785        std             %r0, 8(%r28)
 786        std             %r0, 16(%r28)
 787        std             %r0, 24(%r28)
 788        std             %r0, 32(%r28)
 789        std             %r0, 40(%r28)
 790        std             %r0, 48(%r28)
 791        std             %r0, 56(%r28)
 792        std             %r0, 64(%r28)
 793        std             %r0, 72(%r28)
 794        std             %r0, 80(%r28)
 795        std             %r0, 88(%r28)
 796        std             %r0, 96(%r28)
 797        std             %r0, 104(%r28)
 798        std             %r0, 112(%r28)
 799        std             %r0, 120(%r28)
 800        addib,COND(>)           -1, %r1, 1b
 801        ldo             128(%r28), %r28
 802
 803#else   /* ! CONFIG_64BIT */
 804        ldi             (PAGE_SIZE / 64), %r1
 805
 8061:      stw             %r0, 0(%r28)
 807        stw             %r0, 4(%r28)
 808        stw             %r0, 8(%r28)
 809        stw             %r0, 12(%r28)
 810        stw             %r0, 16(%r28)
 811        stw             %r0, 20(%r28)
 812        stw             %r0, 24(%r28)
 813        stw             %r0, 28(%r28)
 814        stw             %r0, 32(%r28)
 815        stw             %r0, 36(%r28)
 816        stw             %r0, 40(%r28)
 817        stw             %r0, 44(%r28)
 818        stw             %r0, 48(%r28)
 819        stw             %r0, 52(%r28)
 820        stw             %r0, 56(%r28)
 821        stw             %r0, 60(%r28)
 822        addib,COND(>)           -1, %r1, 1b
 823        ldo             64(%r28), %r28
 824#endif  /* CONFIG_64BIT */
 825
 826        bv              %r0(%r2)
 827        nop
 828        .exit
 829
 830        .procend
 831ENDPROC(clear_user_page_asm)
 832
 833ENTRY(flush_dcache_page_asm)
 834        .proc
 835        .callinfo NO_CALLS
 836        .entry
 837
 838        ldil            L%(TMPALIAS_MAP_START), %r28
 839#ifdef CONFIG_64BIT
 840#if (TMPALIAS_MAP_START >= 0x80000000)
 841        depdi           0, 31,32, %r28          /* clear any sign extension */
 842#endif
 843        convert_phys_for_tlb_insert20 %r26      /* convert phys addr to tlb insert format */
 844        depd            %r25, 63,22, %r28       /* Form aliased virtual address 'to' */
 845        depdi           0, 63,PAGE_SHIFT, %r28  /* Clear any offset bits */
 846#else
 847        extrw,u         %r26, 24,25, %r26       /* convert phys addr to tlb insert format */
 848        depw            %r25, 31,22, %r28       /* Form aliased virtual address 'to' */
 849        depwi           0, 31,PAGE_SHIFT, %r28  /* Clear any offset bits */
 850#endif
 851
 852        /* Purge any old translation */
 853
 854#ifdef CONFIG_PA20
 855        pdtlb,l         0(%r28)
 856#else
 857        tlb_lock        %r20,%r21,%r22
 858        pdtlb           0(%r28)
 859        tlb_unlock      %r20,%r21,%r22
 860#endif
 861
 862        ldil            L%dcache_stride, %r1
 863        ldw             R%dcache_stride(%r1), r31
 864
 865#ifdef CONFIG_64BIT
 866        depdi,z         1, 63-PAGE_SHIFT,1, %r25
 867#else
 868        depwi,z         1, 31-PAGE_SHIFT,1, %r25
 869#endif
 870        add             %r28, %r25, %r25
 871        sub             %r25, r31, %r25
 872
 873
 8741:      fdc,m           r31(%r28)
 875        fdc,m           r31(%r28)
 876        fdc,m           r31(%r28)
 877        fdc,m           r31(%r28)
 878        fdc,m           r31(%r28)
 879        fdc,m           r31(%r28)
 880        fdc,m           r31(%r28)
 881        fdc,m           r31(%r28)
 882        fdc,m           r31(%r28)
 883        fdc,m           r31(%r28)
 884        fdc,m           r31(%r28)
 885        fdc,m           r31(%r28)
 886        fdc,m           r31(%r28)
 887        fdc,m           r31(%r28)
 888        fdc,m           r31(%r28)
 889        cmpb,COND(<<)           %r28, %r25,1b
 890        fdc,m           r31(%r28)
 891
 892        sync
 893
 894#ifdef CONFIG_PA20
 895        pdtlb,l         0(%r25)
 896#else
 897        tlb_lock        %r20,%r21,%r22
 898        pdtlb           0(%r25)
 899        tlb_unlock      %r20,%r21,%r22
 900#endif
 901
 902        bv              %r0(%r2)
 903        nop
 904        .exit
 905
 906        .procend
 907ENDPROC(flush_dcache_page_asm)
 908
 909ENTRY(flush_icache_page_asm)
 910        .proc
 911        .callinfo NO_CALLS
 912        .entry
 913
 914        ldil            L%(TMPALIAS_MAP_START), %r28
 915#ifdef CONFIG_64BIT
 916#if (TMPALIAS_MAP_START >= 0x80000000)
 917        depdi           0, 31,32, %r28          /* clear any sign extension */
 918#endif
 919        convert_phys_for_tlb_insert20 %r26      /* convert phys addr to tlb insert format */
 920        depd            %r25, 63,22, %r28       /* Form aliased virtual address 'to' */
 921        depdi           0, 63,PAGE_SHIFT, %r28  /* Clear any offset bits */
 922#else
 923        extrw,u         %r26, 24,25, %r26       /* convert phys addr to tlb insert format */
 924        depw            %r25, 31,22, %r28       /* Form aliased virtual address 'to' */
 925        depwi           0, 31,PAGE_SHIFT, %r28  /* Clear any offset bits */
 926#endif
 927
 928        /* Purge any old translation */
 929
 930#ifdef CONFIG_PA20
 931        pitlb,l         %r0(%sr4,%r28)
 932#else
 933        tlb_lock        %r20,%r21,%r22
 934        pitlb           (%sr4,%r28)
 935        tlb_unlock      %r20,%r21,%r22
 936#endif
 937
 938        ldil            L%icache_stride, %r1
 939        ldw             R%icache_stride(%r1), %r31
 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             %r28, %r25, %r25
 947        sub             %r25, %r31, %r25
 948
 949
 950        /* fic only has the type 26 form on PA1.1, requiring an
 951         * explicit space specification, so use %sr4 */
 9521:      fic,m           %r31(%sr4,%r28)
 953        fic,m           %r31(%sr4,%r28)
 954        fic,m           %r31(%sr4,%r28)
 955        fic,m           %r31(%sr4,%r28)
 956        fic,m           %r31(%sr4,%r28)
 957        fic,m           %r31(%sr4,%r28)
 958        fic,m           %r31(%sr4,%r28)
 959        fic,m           %r31(%sr4,%r28)
 960        fic,m           %r31(%sr4,%r28)
 961        fic,m           %r31(%sr4,%r28)
 962        fic,m           %r31(%sr4,%r28)
 963        fic,m           %r31(%sr4,%r28)
 964        fic,m           %r31(%sr4,%r28)
 965        fic,m           %r31(%sr4,%r28)
 966        fic,m           %r31(%sr4,%r28)
 967        cmpb,COND(<<)   %r28, %r25,1b
 968        fic,m           %r31(%sr4,%r28)
 969
 970        sync
 971
 972#ifdef CONFIG_PA20
 973        pitlb,l         %r0(%sr4,%r25)
 974#else
 975        tlb_lock        %r20,%r21,%r22
 976        pitlb           (%sr4,%r25)
 977        tlb_unlock      %r20,%r21,%r22
 978#endif
 979
 980        bv              %r0(%r2)
 981        nop
 982        .exit
 983
 984        .procend
 985ENDPROC(flush_icache_page_asm)
 986
 987ENTRY(flush_kernel_dcache_page_asm)
 988        .proc
 989        .callinfo NO_CALLS
 990        .entry
 991
 992        ldil            L%dcache_stride, %r1
 993        ldw             R%dcache_stride(%r1), %r23
 994
 995#ifdef CONFIG_64BIT
 996        depdi,z         1, 63-PAGE_SHIFT,1, %r25
 997#else
 998        depwi,z         1, 31-PAGE_SHIFT,1, %r25
 999#endif
1000        add             %r26, %r25, %r25
1001        sub             %r25, %r23, %r25
1002
1003
10041:      fdc,m           %r23(%r26)
1005        fdc,m           %r23(%r26)
1006        fdc,m           %r23(%r26)
1007        fdc,m           %r23(%r26)
1008        fdc,m           %r23(%r26)
1009        fdc,m           %r23(%r26)
1010        fdc,m           %r23(%r26)
1011        fdc,m           %r23(%r26)
1012        fdc,m           %r23(%r26)
1013        fdc,m           %r23(%r26)
1014        fdc,m           %r23(%r26)
1015        fdc,m           %r23(%r26)
1016        fdc,m           %r23(%r26)
1017        fdc,m           %r23(%r26)
1018        fdc,m           %r23(%r26)
1019        cmpb,COND(<<)           %r26, %r25,1b
1020        fdc,m           %r23(%r26)
1021
1022        sync
1023        bv              %r0(%r2)
1024        nop
1025        .exit
1026
1027        .procend
1028ENDPROC(flush_kernel_dcache_page_asm)
1029
1030ENTRY(purge_kernel_dcache_page_asm)
1031        .proc
1032        .callinfo NO_CALLS
1033        .entry
1034
1035        ldil            L%dcache_stride, %r1
1036        ldw             R%dcache_stride(%r1), %r23
1037
1038#ifdef CONFIG_64BIT
1039        depdi,z         1, 63-PAGE_SHIFT,1, %r25
1040#else
1041        depwi,z         1, 31-PAGE_SHIFT,1, %r25
1042#endif
1043        add             %r26, %r25, %r25
1044        sub             %r25, %r23, %r25
1045
10461:      pdc,m           %r23(%r26)
1047        pdc,m           %r23(%r26)
1048        pdc,m           %r23(%r26)
1049        pdc,m           %r23(%r26)
1050        pdc,m           %r23(%r26)
1051        pdc,m           %r23(%r26)
1052        pdc,m           %r23(%r26)
1053        pdc,m           %r23(%r26)
1054        pdc,m           %r23(%r26)
1055        pdc,m           %r23(%r26)
1056        pdc,m           %r23(%r26)
1057        pdc,m           %r23(%r26)
1058        pdc,m           %r23(%r26)
1059        pdc,m           %r23(%r26)
1060        pdc,m           %r23(%r26)
1061        cmpb,COND(<<)           %r26, %r25, 1b
1062        pdc,m           %r23(%r26)
1063
1064        sync
1065        bv              %r0(%r2)
1066        nop
1067        .exit
1068
1069        .procend
1070ENDPROC(purge_kernel_dcache_page_asm)
1071
1072ENTRY(flush_user_dcache_range_asm)
1073        .proc
1074        .callinfo NO_CALLS
1075        .entry
1076
1077        ldil            L%dcache_stride, %r1
1078        ldw             R%dcache_stride(%r1), %r23
1079        ldo             -1(%r23), %r21
1080        ANDCM           %r26, %r21, %r26
1081
10821:      cmpb,COND(<<),n %r26, %r25, 1b
1083        fdc,m           %r23(%sr3, %r26)
1084
1085        sync
1086        bv              %r0(%r2)
1087        nop
1088        .exit
1089
1090        .procend
1091ENDPROC(flush_user_dcache_range_asm)
1092
1093ENTRY(flush_kernel_dcache_range_asm)
1094        .proc
1095        .callinfo NO_CALLS
1096        .entry
1097
1098        ldil            L%dcache_stride, %r1
1099        ldw             R%dcache_stride(%r1), %r23
1100        ldo             -1(%r23), %r21
1101        ANDCM           %r26, %r21, %r26
1102
11031:      cmpb,COND(<<),n %r26, %r25,1b
1104        fdc,m           %r23(%r26)
1105
1106        sync
1107        syncdma
1108        bv              %r0(%r2)
1109        nop
1110        .exit
1111
1112        .procend
1113ENDPROC(flush_kernel_dcache_range_asm)
1114
1115ENTRY(flush_user_icache_range_asm)
1116        .proc
1117        .callinfo NO_CALLS
1118        .entry
1119
1120        ldil            L%icache_stride, %r1
1121        ldw             R%icache_stride(%r1), %r23
1122        ldo             -1(%r23), %r21
1123        ANDCM           %r26, %r21, %r26
1124
11251:      cmpb,COND(<<),n %r26, %r25,1b
1126        fic,m           %r23(%sr3, %r26)
1127
1128        sync
1129        bv              %r0(%r2)
1130        nop
1131        .exit
1132
1133        .procend
1134ENDPROC(flush_user_icache_range_asm)
1135
1136ENTRY(flush_kernel_icache_page)
1137        .proc
1138        .callinfo NO_CALLS
1139        .entry
1140
1141        ldil            L%icache_stride, %r1
1142        ldw             R%icache_stride(%r1), %r23
1143
1144#ifdef CONFIG_64BIT
1145        depdi,z         1, 63-PAGE_SHIFT,1, %r25
1146#else
1147        depwi,z         1, 31-PAGE_SHIFT,1, %r25
1148#endif
1149        add             %r26, %r25, %r25
1150        sub             %r25, %r23, %r25
1151
1152
11531:      fic,m           %r23(%sr4, %r26)
1154        fic,m           %r23(%sr4, %r26)
1155        fic,m           %r23(%sr4, %r26)
1156        fic,m           %r23(%sr4, %r26)
1157        fic,m           %r23(%sr4, %r26)
1158        fic,m           %r23(%sr4, %r26)
1159        fic,m           %r23(%sr4, %r26)
1160        fic,m           %r23(%sr4, %r26)
1161        fic,m           %r23(%sr4, %r26)
1162        fic,m           %r23(%sr4, %r26)
1163        fic,m           %r23(%sr4, %r26)
1164        fic,m           %r23(%sr4, %r26)
1165        fic,m           %r23(%sr4, %r26)
1166        fic,m           %r23(%sr4, %r26)
1167        fic,m           %r23(%sr4, %r26)
1168        cmpb,COND(<<)           %r26, %r25, 1b
1169        fic,m           %r23(%sr4, %r26)
1170
1171        sync
1172        bv              %r0(%r2)
1173        nop
1174        .exit
1175
1176        .procend
1177ENDPROC(flush_kernel_icache_page)
1178
1179ENTRY(flush_kernel_icache_range_asm)
1180        .proc
1181        .callinfo NO_CALLS
1182        .entry
1183
1184        ldil            L%icache_stride, %r1
1185        ldw             R%icache_stride(%r1), %r23
1186        ldo             -1(%r23), %r21
1187        ANDCM           %r26, %r21, %r26
1188
11891:      cmpb,COND(<<),n %r26, %r25, 1b
1190        fic,m           %r23(%sr4, %r26)
1191
1192        sync
1193        bv              %r0(%r2)
1194        nop
1195        .exit
1196        .procend
1197ENDPROC(flush_kernel_icache_range_asm)
1198
1199        /* align should cover use of rfi in disable_sr_hashing_asm and
1200         * srdis_done.
1201         */
1202        .align  256
1203ENTRY(disable_sr_hashing_asm)
1204        .proc
1205        .callinfo NO_CALLS
1206        .entry
1207
1208        /*
1209         * Switch to real mode
1210         */
1211        /* pcxt_ssm_bug */
1212        rsm             PSW_SM_I, %r0
1213        load32          PA(1f), %r1
1214        nop
1215        nop
1216        nop
1217        nop
1218        nop
1219
1220        rsm             PSW_SM_Q, %r0           /* prep to load iia queue */
1221        mtctl           %r0, %cr17              /* Clear IIASQ tail */
1222        mtctl           %r0, %cr17              /* Clear IIASQ head */
1223        mtctl           %r1, %cr18              /* IIAOQ head */
1224        ldo             4(%r1), %r1
1225        mtctl           %r1, %cr18              /* IIAOQ tail */
1226        load32          REAL_MODE_PSW, %r1
1227        mtctl           %r1, %ipsw
1228        rfi
1229        nop
1230
12311:      cmpib,=,n       SRHASH_PCXST, %r26,srdis_pcxs
1232        cmpib,=,n       SRHASH_PCXL, %r26,srdis_pcxl
1233        cmpib,=,n       SRHASH_PA20, %r26,srdis_pa20
1234        b,n             srdis_done
1235
1236srdis_pcxs:
1237
1238        /* Disable Space Register Hashing for PCXS,PCXT,PCXT' */
1239
1240        .word           0x141c1a00              /* mfdiag %dr0, %r28 */
1241        .word           0x141c1a00              /* must issue twice */
1242        depwi           0,18,1, %r28            /* Clear DHE (dcache hash enable) */
1243        depwi           0,20,1, %r28            /* Clear IHE (icache hash enable) */
1244        .word           0x141c1600              /* mtdiag %r28, %dr0 */
1245        .word           0x141c1600              /* must issue twice */
1246        b,n             srdis_done
1247
1248srdis_pcxl:
1249
1250        /* Disable Space Register Hashing for PCXL */
1251
1252        .word           0x141c0600              /* mfdiag %dr0, %r28 */
1253        depwi           0,28,2, %r28            /* Clear DHASH_EN & IHASH_EN */
1254        .word           0x141c0240              /* mtdiag %r28, %dr0 */
1255        b,n             srdis_done
1256
1257srdis_pa20:
1258
1259        /* Disable Space Register Hashing for PCXU,PCXU+,PCXW,PCXW+,PCXW2 */
1260
1261        .word           0x144008bc              /* mfdiag %dr2, %r28 */
1262        depdi           0, 54,1, %r28           /* clear DIAG_SPHASH_ENAB (bit 54) */
1263        .word           0x145c1840              /* mtdiag %r28, %dr2 */
1264
1265
1266srdis_done:
1267        /* Switch back to virtual mode */
1268        rsm             PSW_SM_I, %r0           /* prep to load iia queue */
1269        load32          2f, %r1
1270        nop
1271        nop
1272        nop
1273        nop
1274        nop
1275
1276        rsm             PSW_SM_Q, %r0           /* prep to load iia queue */
1277        mtctl           %r0, %cr17              /* Clear IIASQ tail */
1278        mtctl           %r0, %cr17              /* Clear IIASQ head */
1279        mtctl           %r1, %cr18              /* IIAOQ head */
1280        ldo             4(%r1), %r1
1281        mtctl           %r1, %cr18              /* IIAOQ tail */
1282        load32          KERNEL_PSW, %r1
1283        mtctl           %r1, %ipsw
1284        rfi
1285        nop
1286
12872:      bv              %r0(%r2)
1288        nop
1289        .exit
1290
1291        .procend
1292ENDPROC(disable_sr_hashing_asm)
1293
1294        .end
1295