The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/osfmk/ppc/machine_routines_asm.s

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 2000-2005 Apple Computer, Inc. All rights reserved.
    3  *
    4  * @APPLE_LICENSE_HEADER_START@
    5  * 
    6  * The contents of this file constitute Original Code as defined in and
    7  * are subject to the Apple Public Source License Version 1.1 (the
    8  * "License").  You may not use this file except in compliance with the
    9  * License.  Please obtain a copy of the License at
   10  * http://www.apple.com/publicsource and read it before using this file.
   11  * 
   12  * This Original Code and all software distributed under the License are
   13  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
   14  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
   15  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
   16  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
   17  * License for the specific language governing rights and limitations
   18  * under the License.
   19  * 
   20  * @APPLE_LICENSE_HEADER_END@
   21  */
   22 #include <ppc/asm.h>
   23 #include <ppc/proc_reg.h>
   24 #include <assym.s>
   25 #include <debug.h>
   26 #include <mach/ppc/vm_param.h>
   27 #include <ppc/exception.h>
   28         
   29     
   30 /*
   31  * ml_set_physical()                    -- turn off DR and (if 64-bit) turn SF on
   32  *                                                                 it is assumed that pf64Bit is already in cr6
   33  * ml_set_physical_get_ffs()    -- turn DR off, SF on, and get feature flags 
   34  * ml_set_physical_disabled()   -- turn DR and EE off, SF on, get feature flags
   35  * ml_set_translation_off()             -- turn DR, IR, and EE off, SF on, get feature flags
   36  *
   37  * Callable only from assembler, these return:
   38  *       r2 -- new MSR
   39  *      r11 -- old MSR
   40  *      r10 -- feature flags (pf64Bit etc, ie SPRG 2)
   41  *      cr6 -- feature flags 24-27, ie pf64Bit, pf128Byte, and pf32Byte
   42  *
   43  * Uses r0 and r2.  ml_set_translation_off also uses r3 and cr5.
   44  */
   45 
   46         .align  4
   47         .globl  EXT(ml_set_translation_off)
   48 LEXT(ml_set_translation_off)
   49         mfsprg  r10,2                                           // get feature flags
   50         li              r0,0                                            ; Clear this
   51         mtcrf   0x02,r10                                        // move pf64Bit etc to cr6
   52         ori             r0,r0,lo16(MASK(MSR_EE)+MASK(MSR_FP)+MASK(MSR_IR)+MASK(MSR_DR)) // turn off all 4
   53         mfmsr   r11                                                     // get MSR
   54                 oris    r0,r0,hi16(MASK(MSR_VEC))       // Turn off vector too
   55         mtcrf   0x04,r10                                        // move pfNoMSRir etc to cr5
   56         andc    r2,r11,r0                                       // turn off EE, IR, and DR
   57         bt++    pf64Bitb,ml_set_physical_64     // skip if 64-bit (only they take the hint)
   58         bf              pfNoMSRirb,ml_set_physical_32   // skip if we can load MSR directly
   59         li              r0,loadMSR                                      // Get the MSR setter SC
   60         mr              r3,r2                                           // copy new MSR to r2
   61         sc                                                                      // Set it
   62         blr
   63         
   64                 .align  4
   65                 .globl  EXT(ml_set_physical_disabled)
   66 
   67 LEXT(ml_set_physical_disabled)
   68                 li              r0,0                                            ; Clear
   69         mfsprg  r10,2                                           // get feature flags
   70         ori             r0,r0,lo16(MASK(MSR_EE))        // turn EE and fp off
   71         mtcrf   0x02,r10                                        // move pf64Bit etc to cr6
   72         b               ml_set_physical_join
   73 
   74                 .align  5
   75                 .globl  EXT(ml_set_physical_get_ffs)
   76 
   77 LEXT(ml_set_physical_get_ffs)
   78         mfsprg  r10,2                                           // get feature flags
   79         mtcrf   0x02,r10                                        // move pf64Bit etc to cr6
   80 
   81                 .globl  EXT(ml_set_physical)
   82 LEXT(ml_set_physical)
   83 
   84         li              r0,0                                            // do not turn off interrupts
   85 
   86 ml_set_physical_join:
   87                 oris    r0,r0,hi16(MASK(MSR_VEC))       // Always gonna turn of vectors
   88         mfmsr   r11                                                     // get MSR
   89         ori             r0,r0,lo16(MASK(MSR_DR)+MASK(MSR_FP))   // always turn off DR and FP bit
   90         andc    r2,r11,r0                                       // turn off DR and maybe EE
   91         bt++    pf64Bitb,ml_set_physical_64     // skip if 64-bit (only they take the hint)
   92 ml_set_physical_32:
   93         mtmsr   r2                                                      // turn off translation
   94         isync
   95         blr
   96         
   97 ml_set_physical_64:
   98         li              r0,1                                            // get a 1 to slam into SF
   99         rldimi  r2,r0,63,MSR_SF_BIT                     // set SF bit (bit 0)
  100         mtmsrd  r2                                                      // set 64-bit mode, turn off data relocation
  101         isync                                                           // synchronize
  102         blr
  103     
  104 
  105 /*
  106  * ml_restore(old_MSR)
  107  *
  108  * Callable only from assembler, restores the MSR in r11 saved by ml_set_physical.
  109  * We assume cr6 and r11 are as set by ml_set_physical, ie:
  110  *      cr6 - pf64Bit flag (feature flags 24-27)
  111  *      r11 - old MSR
  112  */
  113  
  114                 .align  5
  115                 .globl  EXT(ml_restore)
  116 
  117 LEXT(ml_restore)
  118         bt++    pf64Bitb,ml_restore_64          // handle 64-bit cpus (only they take the hint)
  119         mtmsr   r11                                                     // restore a 32-bit MSR
  120         isync
  121         blr
  122         
  123 ml_restore_64:
  124         mtmsrd  r11                                                     // restore a 64-bit MSR
  125         isync
  126         blr
  127 
  128     
  129 /* PCI config cycle probing
  130  *
  131  *      boolean_t ml_probe_read(vm_offset_t paddr, unsigned int *val)
  132  *
  133  *      Read the memory location at physical address paddr.
  134  *  This is a part of a device probe, so there is a good chance we will
  135  *  have a machine check here. So we have to be able to handle that.
  136  *  We assume that machine checks are enabled both in MSR and HIDs
  137  */
  138 
  139 ;                       Force a line boundry here
  140                         .align  5
  141                         .globl  EXT(ml_probe_read)
  142 
  143 LEXT(ml_probe_read)
  144 
  145                         mfsprg  r9,2                                                    ; Get feature flags
  146                         
  147                         rlwinm. r0,r9,0,pf64Bitb,pf64Bitb               ; Are we on a 64-bit machine?
  148                         rlwinm  r3,r3,0,0,31                                    ; Clean up for 64-bit machines
  149                         bne++   mpr64bit                                                ; Go do this the 64-bit way...
  150 
  151 mpr32bit:       lis             r8,hi16(MASK(MSR_VEC))                  ; Get the vector flag
  152                         mfmsr   r0                                                              ; Save the current MSR
  153                         ori             r8,r8,lo16(MASK(MSR_FP))                ; Add the FP flag
  154 
  155                         neg             r10,r3                                                  ; Number of bytes to end of page
  156                         andc    r0,r0,r8                                                ; Clear VEC and FP
  157                         rlwinm. r10,r10,0,20,31                                 ; Clear excess junk and test for page bndry
  158                         ori             r8,r8,lo16(MASK(MSR_EE)|MASK(MSR_IR)|MASK(MSR_DR))              ; Drop EE, IR, and DR
  159                         mr              r12,r3                                                  ; Save the load address
  160                         andc    r2,r0,r8                                                ; Clear VEC, FP, and EE
  161                         mtcrf   0x04,r9                                                 ; Set the features                      
  162                         cmplwi  cr1,r10,4                                               ; At least 4 bytes left in page?
  163                         beq-    mprdoit                                                 ; We are right on the boundary...
  164                         li              r3,0
  165                         bltlr-  cr1                                                             ; No, just return failure...
  166 
  167 mprdoit:
  168 
  169                         bt              pfNoMSRirb,mprNoMSR                             ; No MSR...
  170 
  171                         mtmsr   r2                                                              ; Translation and all off
  172                         isync                                                                   ; Toss prefetch
  173                         b               mprNoMSRx
  174                         
  175 mprNoMSR:       
  176                         mr              r5,r0
  177                         li              r0,loadMSR                                              ; Get the MSR setter SC
  178                         mr              r3,r2                                                   ; Get new MSR
  179                         sc                                                                              ; Set it
  180                         mr              r0,r5
  181                         li              r3,0
  182 mprNoMSRx:
  183 
  184                         mfspr           r6, hid0                                        ; Get a copy of hid0
  185                         
  186                         rlwinm.         r5, r9, 0, pfNoMuMMCKb, pfNoMuMMCKb             ; Check for NoMuMMCK
  187                         bne             mprNoMuM
  188                         
  189                         rlwinm          r5, r6, 0, ice+1, ice-1                         ; Turn off L1 I-Cache
  190                         mtspr           hid0, r5
  191                         isync                                                           ; Wait for I-Cache off
  192                         rlwinm          r5, r6, 0, mum+1, mum-1                         ; Turn off MuM w/ I-Cache on
  193                         mtspr           hid0, r5
  194 mprNoMuM:
  195 
  196 ;
  197 ;                       We need to insure that there is no more than 1 BAT register that
  198 ;                       can get a hit. There could be repercussions beyond the ken
  199 ;                       of mortal man. It is best not to tempt fate.
  200 ;
  201 
  202 ;                       Note: we will reload these from the shadow BATs later
  203 
  204                         li              r10,0                                                   ; Clear a register
  205                         
  206                         sync                                                                    ; Make sure all is well
  207 
  208                         mtdbatu 1,r10                                                   ; Invalidate DBAT 1 
  209                         mtdbatu 2,r10                                                   ; Invalidate DBAT 2 
  210                         mtdbatu 3,r10                                                   ; Invalidate DBAT 3  
  211                         
  212                         rlwinm  r10,r12,0,0,14                                  ; Round down to a 128k boundary
  213                         ori             r11,r10,0x32                                    ; Set uncached, coherent, R/W
  214                         ori             r10,r10,2                                               ; Make the upper half (128k, valid supervisor)
  215                         mtdbatl 0,r11                                                   ; Set lower BAT first
  216                         mtdbatu 0,r10                                                   ; Now the upper
  217                         sync                                                                    ; Just make sure
  218                         
  219                         dcbf    0,r12                                                   ; Make sure we kill the cache to avoid paradoxes
  220                         sync
  221                         
  222                         ori             r11,r2,lo16(MASK(MSR_DR))               ; Turn on data translation
  223                         mtmsr   r11                                                             ; Do it for real
  224                         isync                                                                   ; Make sure of it
  225                         
  226                         eieio                                                                   ; Make sure of all previous accesses
  227                         sync                                                                    ; Make sure it is all caught up
  228                         
  229                         lwz             r11,0(r12)                                              ; Get it and maybe machine check here
  230                         
  231                         eieio                                                                   ; Make sure of ordering again
  232                         sync                                                                    ; Get caught up yet again
  233                         isync                                                                   ; Do not go further till we are here
  234                         
  235                         mtmsr   r2                                                              ; Turn translation back off
  236                         isync
  237                         
  238                         lis             r10,hi16(EXT(shadow_BAT)+shdDBAT)       ; Get shadow address
  239                         ori             r10,r10,lo16(EXT(shadow_BAT)+shdDBAT)   ; Get shadow address
  240                         
  241                         lwz             r5,0(r10)                                               ; Pick up DBAT 0 high
  242                         lwz             r6,4(r10)                                               ; Pick up DBAT 0 low
  243                         lwz             r7,8(r10)                                               ; Pick up DBAT 1 high
  244                         lwz             r8,16(r10)                                              ; Pick up DBAT 2 high
  245                         lwz             r9,24(r10)                                              ; Pick up DBAT 3 high
  246                         
  247                         mtdbatu 0,r5                                                    ; Restore DBAT 0 high
  248                         mtdbatl 0,r6                                                    ; Restore DBAT 0 low
  249                         mtdbatu 1,r7                                                    ; Restore DBAT 1 high
  250                         mtdbatu 2,r8                                                    ; Restore DBAT 2 high
  251                         mtdbatu 3,r9                                                    ; Restore DBAT 3 high 
  252                         sync
  253                         
  254                         li              r3,1                                                    ; We made it
  255                         
  256                         mtmsr   r0                                                              ; Restore translation and exceptions
  257                         isync                                                                   ; Toss speculations
  258                         
  259                         stw             r11,0(r4)                                               ; Save the loaded value
  260                         blr                                                                             ; Return...
  261                         
  262 ;                       Force a line boundry here. This means we will be able to check addresses better
  263                         .align  5
  264                         .globl  EXT(ml_probe_read_mck)
  265 LEXT(ml_probe_read_mck)
  266 
  267     
  268 /* PCI config cycle probing - 64-bit
  269  *
  270  *      boolean_t ml_probe_read_64(addr64_t paddr, unsigned int *val)
  271  *
  272  *      Read the memory location at physical address paddr.
  273  *  This is a part of a device probe, so there is a good chance we will
  274  *  have a machine check here. So we have to be able to handle that.
  275  *  We assume that machine checks are enabled both in MSR and HIDs
  276  */
  277 
  278 ;                       Force a line boundry here
  279                         .align  6
  280                         .globl  EXT(ml_probe_read_64)
  281 
  282 LEXT(ml_probe_read_64)
  283 
  284                         mfsprg  r9,2                                                    ; Get feature flags
  285                         rlwinm  r3,r3,0,1,0                                             ; Copy low 32 bits to top 32
  286                         rlwinm. r0,r9,0,pf64Bitb,pf64Bitb               ; Are we on a 64-bit machine?
  287                         rlwimi  r3,r4,0,0,31                                    ; Insert low part of 64-bit address in bottom 32 bits                   
  288                         
  289                         mr              r4,r5                                                   ; Move result to common register
  290                         beq--   mpr32bit                                                ; Go do this the 32-bit way...
  291 
  292 mpr64bit:       andi.   r0,r3,3                                                 ; Check if we are on a word boundary
  293                         li              r0,0                                                    ; Clear the EE bit (and everything else for that matter)
  294                         bne--   mprFail                                                 ; Boundary not good...
  295                         mfmsr   r11                                                             ; Get the MSR
  296                         mtmsrd  r0,1                                                    ; Set the EE bit only (do not care about RI)
  297                         rlwinm  r11,r11,0,MSR_EE_BIT,MSR_EE_BIT ; Isolate just the EE bit
  298                         mfmsr   r10                                                             ; Refresh our view of the MSR (VMX/FP may have changed)
  299                         or              r12,r10,r11                                             ; Turn on EE if on before we turned it off
  300                         ori             r0,r0,lo16(MASK(MSR_IR)|MASK(MSR_DR))   ; Get the IR and DR bits
  301                         li              r2,1                                                    ; Get a 1
  302                         sldi    r2,r2,63                                                ; Get the 64-bit bit
  303                         andc    r10,r10,r0                                              ; Clear IR and DR
  304                         or              r10,r10,r2                                              ; Set 64-bit
  305                         
  306                         li              r0,1                                                    ; Get a 1
  307                         mtmsrd  r10                                                             ; Translation and EE off, 64-bit on
  308                         isync                   
  309                         
  310                         sldi    r0,r0,32+8                                              ; Get the right bit to inhibit caching
  311 
  312                         mfspr   r8,hid4                                                 ; Get HID4
  313                         or              r2,r8,r0                                                ; Set bit to make real accesses cache-inhibited
  314                         sync                                                                    ; Sync up
  315                         mtspr   hid4,r2                                                 ; Make real accesses cache-inhibited
  316                         isync                                                                   ; Toss prefetches
  317                         
  318                         lis             r7,0xE000                                               ; Get the unlikeliest ESID possible
  319                         srdi    r7,r7,1                                                 ; Make 0x7FFFFFFFF0000000
  320                         slbie   r7                                                              ; Make sure the ERAT is cleared 
  321                         
  322                         sync
  323                         isync
  324 
  325                         eieio                                                                   ; Make sure of all previous accesses
  326                         
  327                         lwz             r11,0(r3)                                               ; Get it and maybe machine check here
  328                         
  329                         eieio                                                                   ; Make sure of ordering again
  330                         sync                                                                    ; Get caught up yet again
  331                         isync                                                                   ; Do not go further till we are here
  332 
  333                         sync                                                                    ; Sync up
  334                         mtspr   hid4,r8                                                 ; Make real accesses not cache-inhibited
  335                         isync                                                                   ; Toss prefetches
  336 
  337                         lis             r7,0xE000                                               ; Get the unlikeliest ESID possible
  338                         srdi    r7,r7,1                                                 ; Make 0x7FFFFFFFF0000000
  339                         slbie   r7                                                              ; Make sure the ERAT is cleared 
  340 
  341                         mtmsrd  r12                                                             ; Restore entry MSR
  342                         isync
  343                         
  344                         stw             r11,0(r4)                                               ; Pass back the result
  345                         li              r3,1                                                    ; Indicate success
  346                         blr                                                                             ; Leave...
  347 
  348 mprFail:        li              r3,0                                                    ; Set failure
  349                         blr                                                                             ; Leave...
  350 
  351 ;                       Force a line boundry here. This means we will be able to check addresses better
  352                         .align  6
  353                         .globl  EXT(ml_probe_read_mck_64)
  354 LEXT(ml_probe_read_mck_64)
  355 
  356 
  357 /* Read physical address byte
  358  *
  359  *      unsigned int ml_phys_read_byte(vm_offset_t paddr)
  360  *      unsigned int ml_phys_read_byte_64(addr64_t paddr)
  361  *
  362  *      Read the byte at physical address paddr. Memory should not be cache inhibited.
  363  */
  364 
  365 ;                       Force a line boundry here
  366 
  367                         .align  5
  368                         .globl  EXT(ml_phys_read_byte_64)
  369 
  370 LEXT(ml_phys_read_byte_64)
  371 
  372                         rlwinm  r3,r3,0,1,0                                             ; Copy low 32 bits to top 32
  373                         rlwimi  r3,r4,0,0,31                                    ; Insert low part of 64-bit address in bottom 32 bits
  374             b           ml_phys_read_byte_join                  
  375 
  376                         .globl  EXT(ml_phys_read_byte)
  377 
  378 LEXT(ml_phys_read_byte)
  379             rlwinm   r3,r3,0,0,31                               ; truncate address to 32-bits
  380 ml_phys_read_byte_join:                                                         ; r3 = address to read (reg64_t)
  381                         mflr    r11                                                             ; Save the return
  382                         bl              rdwrpre                                                 ; Get set up, translation/interrupts off, 64-bit on, etc.
  383                         
  384                         lbz             r3,0(r3)                                                ; Get the byte
  385                         b               rdwrpost                                                ; Clean up and leave...
  386 
  387 
  388 /* Read physical address half word
  389  *
  390  *      unsigned int ml_phys_read_half(vm_offset_t paddr)
  391  *      unsigned int ml_phys_read_half_64(addr64_t paddr)
  392  *
  393  *      Read the half word at physical address paddr. Memory should not be cache inhibited.
  394  */
  395 
  396 ;                       Force a line boundry here
  397 
  398                         .align  5
  399                         .globl  EXT(ml_phys_read_half_64)
  400 
  401 LEXT(ml_phys_read_half_64)
  402 
  403                         rlwinm  r3,r3,0,1,0                                             ; Copy low 32 bits to top 32
  404                         rlwimi  r3,r4,0,0,31                                    ; Insert low part of 64-bit address in bottom 32 bits
  405             b           ml_phys_read_half_join          
  406 
  407                         .globl  EXT(ml_phys_read_half)
  408 
  409 LEXT(ml_phys_read_half)
  410             rlwinm   r3,r3,0,0,31                               ; truncate address to 32-bits
  411 ml_phys_read_half_join:                                                         ; r3 = address to read (reg64_t)
  412                         mflr    r11                                                             ; Save the return
  413                         bl              rdwrpre                                                 ; Get set up, translation/interrupts off, 64-bit on, etc.
  414                         
  415                         lhz             r3,0(r3)                                                ; Get the half word
  416                         b               rdwrpost                                                ; Clean up and leave...
  417 
  418 
  419 /* Read physical address word
  420  *
  421  *      unsigned int ml_phys_read(vm_offset_t paddr)
  422  *      unsigned int ml_phys_read_64(addr64_t paddr)
  423  *      unsigned int ml_phys_read_word(vm_offset_t paddr)
  424  *      unsigned int ml_phys_read_word_64(addr64_t paddr)
  425  *
  426  *      Read the word at physical address paddr. Memory should not be cache inhibited.
  427  */
  428 
  429 ;                       Force a line boundry here
  430 
  431                         .align  5
  432                         .globl  EXT(ml_phys_read_64)
  433                         .globl  EXT(ml_phys_read_word_64)
  434 
  435 LEXT(ml_phys_read_64)
  436 LEXT(ml_phys_read_word_64)
  437 
  438                         rlwinm  r3,r3,0,1,0                                             ; Copy low 32 bits to top 32
  439                         rlwimi  r3,r4,0,0,31                                    ; Insert low part of 64-bit address in bottom 32 bits
  440             b           ml_phys_read_word_join          
  441 
  442                         .globl  EXT(ml_phys_read)
  443                         .globl  EXT(ml_phys_read_word)
  444 
  445 LEXT(ml_phys_read)
  446 LEXT(ml_phys_read_word)
  447             rlwinm   r3,r3,0,0,31                               ; truncate address to 32-bits
  448 ml_phys_read_word_join:                                                         ; r3 = address to read (reg64_t)
  449                         mflr    r11                                                             ; Save the return
  450                         bl              rdwrpre                                                 ; Get set up, translation/interrupts off, 64-bit on, etc.
  451                         
  452                         lwz             r3,0(r3)                                                ; Get the word
  453                         b               rdwrpost                                                ; Clean up and leave...
  454 
  455 
  456 /* Read physical address double word
  457  *
  458  *      unsigned long long ml_phys_read_double(vm_offset_t paddr)
  459  *      unsigned long long ml_phys_read_double_64(addr64_t paddr)
  460  *
  461  *      Read the double word at physical address paddr. Memory should not be cache inhibited.
  462  */
  463 
  464 ;                       Force a line boundry here
  465 
  466                         .align  5
  467                         .globl  EXT(ml_phys_read_double_64)
  468 
  469 LEXT(ml_phys_read_double_64)
  470 
  471                         rlwinm  r3,r3,0,1,0                                             ; Copy low 32 bits to top 32
  472                         rlwimi  r3,r4,0,0,31                                    ; Insert low part of 64-bit address in bottom 32 bits                   
  473             b           ml_phys_read_double_join                
  474 
  475                         .globl  EXT(ml_phys_read_double)
  476 
  477 LEXT(ml_phys_read_double)
  478             rlwinm   r3,r3,0,0,31                               ; truncate address to 32-bits
  479 ml_phys_read_double_join:                                                       ; r3 = address to read (reg64_t)
  480                         mflr    r11                                                             ; Save the return
  481                         bl              rdwrpre                                                 ; Get set up, translation/interrupts off, 64-bit on, etc.
  482                         
  483                         lwz             r4,4(r3)                                                ; Get the low word
  484                         lwz             r3,0(r3)                                                ; Get the high word
  485                         b               rdwrpost                                                ; Clean up and leave...
  486 
  487 
  488 /* Write physical address byte
  489  *
  490  *      void ml_phys_write_byte(vm_offset_t paddr, unsigned int data)
  491  *      void ml_phys_write_byte_64(addr64_t paddr, unsigned int data)
  492  *
  493  *      Write the byte at physical address paddr. Memory should not be cache inhibited.
  494  */
  495 
  496                         .align  5
  497                         .globl  EXT(ml_phys_write_byte_64)
  498 
  499 LEXT(ml_phys_write_byte_64)
  500 
  501                         rlwinm  r3,r3,0,1,0                                             ; Copy low 32 bits to top 32
  502                         rlwimi  r3,r4,0,0,31                                    ; Insert low part of 64-bit address in bottom 32 bits                   
  503                         mr              r4,r5                                                   ; Copy over the data
  504             b           ml_phys_write_byte_join
  505 
  506                         .globl  EXT(ml_phys_write_byte)
  507 
  508 LEXT(ml_phys_write_byte)
  509             rlwinm   r3,r3,0,0,31                               ; truncate address to 32-bits
  510 ml_phys_write_byte_join:                                                        ; r3 = address to write (reg64_t), r4 = data
  511                         mflr    r11                                                             ; Save the return
  512                         bl              rdwrpre                                                 ; Get set up, translation/interrupts off, 64-bit on, etc.
  513                         
  514                         stb             r4,0(r3)                                                ; Set the byte
  515                         b               rdwrpost                                                ; Clean up and leave...
  516 
  517 
  518 /* Write physical address half word
  519  *
  520  *      void ml_phys_write_half(vm_offset_t paddr, unsigned int data)
  521  *      void ml_phys_write_half_64(addr64_t paddr, unsigned int data)
  522  *
  523  *      Write the half word at physical address paddr. Memory should not be cache inhibited.
  524  */
  525 
  526                         .align  5
  527                         .globl  EXT(ml_phys_write_half_64)
  528 
  529 LEXT(ml_phys_write_half_64)
  530 
  531                         rlwinm  r3,r3,0,1,0                                             ; Copy low 32 bits to top 32
  532                         rlwimi  r3,r4,0,0,31                                    ; Insert low part of 64-bit address in bottom 32 bits                   
  533                         mr              r4,r5                                                   ; Copy over the data
  534             b           ml_phys_write_half_join
  535 
  536                         .globl  EXT(ml_phys_write_half)
  537 
  538 LEXT(ml_phys_write_half)
  539             rlwinm   r3,r3,0,0,31                               ; truncate address to 32-bits
  540 ml_phys_write_half_join:                                                        ; r3 = address to write (reg64_t), r4 = data
  541                         mflr    r11                                                             ; Save the return
  542                         bl              rdwrpre                                                 ; Get set up, translation/interrupts off, 64-bit on, etc.
  543                         
  544                         sth             r4,0(r3)                                                ; Set the half word
  545                         b               rdwrpost                                                ; Clean up and leave...
  546 
  547 
  548 /* Write physical address word
  549  *
  550  *      void ml_phys_write(vm_offset_t paddr, unsigned int data)
  551  *      void ml_phys_write_64(addr64_t paddr, unsigned int data)
  552  *      void ml_phys_write_word(vm_offset_t paddr, unsigned int data)
  553  *      void ml_phys_write_word_64(addr64_t paddr, unsigned int data)
  554  *
  555  *      Write the word at physical address paddr. Memory should not be cache inhibited.
  556  */
  557 
  558                         .align  5
  559                         .globl  EXT(ml_phys_write_64)
  560                         .globl  EXT(ml_phys_write_word_64)
  561 
  562 LEXT(ml_phys_write_64)
  563 LEXT(ml_phys_write_word_64)
  564 
  565                         rlwinm  r3,r3,0,1,0                                             ; Copy low 32 bits to top 32
  566                         rlwimi  r3,r4,0,0,31                                    ; Insert low part of 64-bit address in bottom 32 bits                   
  567                         mr              r4,r5                                                   ; Copy over the data
  568             b           ml_phys_write_word_join
  569 
  570                         .globl  EXT(ml_phys_write)
  571                         .globl  EXT(ml_phys_write_word)
  572 
  573 LEXT(ml_phys_write)
  574 LEXT(ml_phys_write_word)
  575             rlwinm   r3,r3,0,0,31                               ; truncate address to 32-bits
  576 ml_phys_write_word_join:                                                        ; r3 = address to write (reg64_t), r4 = data
  577                         mflr    r11                                                             ; Save the return
  578                         bl              rdwrpre                                                 ; Get set up, translation/interrupts off, 64-bit on, etc.
  579                         
  580                         stw             r4,0(r3)                                                ; Set the word
  581                         b               rdwrpost                                                ; Clean up and leave...
  582 
  583 
  584 /* Write physical address double word
  585  *
  586  *      void ml_phys_write_double(vm_offset_t paddr, unsigned long long data)
  587  *      void ml_phys_write_double_64(addr64_t paddr, unsigned long long data)
  588  *
  589  *      Write the double word at physical address paddr. Memory should not be cache inhibited.
  590  */
  591 
  592                         .align  5
  593                         .globl  EXT(ml_phys_write_double_64)
  594 
  595 LEXT(ml_phys_write_double_64)
  596 
  597                         rlwinm  r3,r3,0,1,0                                             ; Copy low 32 bits to top 32
  598                         rlwimi  r3,r4,0,0,31                                    ; Insert low part of 64-bit address in bottom 32 bits                   
  599                         mr              r4,r5                                                   ; Copy over the high data
  600                         mr              r5,r6                                                   ; Copy over the low data
  601             b           ml_phys_write_double_join
  602 
  603                         .globl  EXT(ml_phys_write_double)
  604 
  605 LEXT(ml_phys_write_double)
  606             rlwinm   r3,r3,0,0,31                               ; truncate address to 32-bits
  607 ml_phys_write_double_join:                                                      ; r3 = address to write (reg64_t), r4,r5 = data (long long)
  608                         mflr    r11                                                             ; Save the return
  609                         bl              rdwrpre                                                 ; Get set up, translation/interrupts off, 64-bit on, etc.
  610                         
  611                         stw             r4,0(r3)                                                ; Set the high word
  612                         stw             r5,4(r3)                                                ; Set the low word
  613                         b               rdwrpost                                                ; Clean up and leave...
  614 
  615 
  616                         .align  5
  617 
  618 rdwrpre:        mfsprg  r12,2                                                   ; Get feature flags 
  619                         lis             r8,hi16(MASK(MSR_VEC))                  ; Get the vector flag
  620                         mfmsr   r10                                                             ; Save the MSR 
  621                         ori             r8,r8,lo16(MASK(MSR_FP))                ; Add the FP flag
  622                         mtcrf   0x02,r12                                                ; move pf64Bit
  623                         andc    r10,r10,r8                                              ; Clear VEC and FP
  624                         ori             r9,r8,lo16(MASK(MSR_EE)|MASK(MSR_IR)|MASK(MSR_DR))              ; Drop EE, DR, and IR
  625                         li              r2,1                                                    ; Prepare for 64 bit
  626                         andc    r9,r10,r9                                               ; Clear VEC, FP, DR, and EE
  627                         bf--    pf64Bitb,rdwrpre32                              ; Join 32-bit code...
  628                         
  629                         srdi    r7,r3,31                                                ; Get a 1 if address is in I/O memory
  630                         rldimi  r9,r2,63,MSR_SF_BIT                             ; set SF bit (bit 0)
  631                         cmpldi  cr7,r7,1                                                ; Is source in I/O memory?
  632                         mtmsrd  r9                                                              ; set 64-bit mode, turn off EE, DR, and IR
  633                         isync                                                                   ; synchronize
  634 
  635                         sldi    r0,r2,32+8                                              ; Get the right bit to turn off caching
  636                         
  637                         bnelr++ cr7                                                             ; We are not in the I/O area, all ready...
  638                         
  639                         mfspr   r8,hid4                                                 ; Get HID4
  640                         or              r2,r8,r0                                                ; Set bit to make real accesses cache-inhibited
  641                         sync                                                                    ; Sync up
  642                         mtspr   hid4,r2                                                 ; Make real accesses cache-inhibited
  643                         isync                                                                   ; Toss prefetches
  644                         
  645                         lis             r7,0xE000                                               ; Get the unlikeliest ESID possible
  646                         srdi    r7,r7,1                                                 ; Make 0x7FFFFFFFF0000000
  647                         slbie   r7                                                              ; Make sure the ERAT is cleared 
  648                         
  649                         sync
  650                         isync
  651                         blr                                                                             ; Finally,  all ready...
  652         
  653                         .align  5
  654                         
  655 rdwrpre32:      rlwimi  r9,r10,0,MSR_IR_BIT,MSR_IR_BIT  ; Leave the IR bit unchanged
  656                         mtmsr   r9                                                              ; Drop EE, DR, and leave IR unchanged
  657                         isync
  658                         blr                                                                             ; All set up, leave...
  659                         
  660                         .align  5
  661                         
  662 rdwrpost:       mtlr    r11                                                             ; Restore the return
  663                         bt++    pf64Bitb,rdwrpost64                             ; Join 64-bit code...
  664                         
  665                         mtmsr   r10                                                             ; Restore entry MSR (sans FP and VEC)
  666                         isync
  667                         blr                                                                             ; Leave...
  668                         
  669 rdwrpost64:     bne++   cr7,rdwrpcok                                    ; Skip enabling real mode caching if we did not change it...
  670 
  671                         sync                                                                    ; Sync up
  672                         mtspr   hid4,r8                                                 ; Make real accesses not cache-inhibited
  673                         isync                                                                   ; Toss prefetches
  674 
  675                         lis             r7,0xE000                                               ; Get the unlikeliest ESID possible
  676                         srdi    r7,r7,1                                                 ; Make 0x7FFFFFFFF0000000
  677                         slbie   r7                                                              ; Make sure the ERAT is cleared 
  678 
  679 rdwrpcok:       mtmsrd  r10                                                             ; Restore entry MSR (sans FP and VEC)
  680                         isync
  681                         blr                                                                             ; Leave...
  682 
  683 
  684 /* set interrupts enabled or disabled
  685  *
  686  *      boolean_t set_interrupts_enabled(boolean_t enable)
  687  *
  688  *      Set EE bit to "enable" and return old value as boolean
  689  */
  690 
  691 ;                       Force a line boundry here
  692                         .align  5
  693                         .globl  EXT(ml_set_interrupts_enabled)
  694  
  695 LEXT(ml_set_interrupts_enabled)
  696 
  697                         andi.   r4,r3,1                                                 ; Are we turning interruptions on?
  698                         lis             r0,hi16(MASK(MSR_VEC))                  ; Get vector enable
  699                         mfmsr   r5                                                              ; Get the current MSR
  700                         ori             r0,r0,lo16(MASK(MSR_EE)|MASK(MSR_FP))   ; Get float enable and EE enable
  701                         rlwinm  r3,r5,17,31,31                                  ; Set return value
  702                         andc    r5,r5,r0                                                ; Force VEC and FP off
  703                         bne         CheckPreemption                                     ; Interrupts going on, check ASTs...
  704 
  705                         mtmsr   r5                              ; Slam diable (always going disabled here)
  706                         isync                                                                   ; Need this because FP/Vec might go off
  707                         blr
  708 
  709                         .align  5
  710 
  711 CheckPreemption:
  712                         mfsprg  r9,1                                                    ; Get current activation
  713                         lwz             r7,ACT_PER_PROC(r9)                             ; Get the per_proc block
  714                         ori             r5,r5,lo16(MASK(MSR_EE))                ; Turn on the enable
  715                         lwz             r8,PP_PENDING_AST(r7)                   ; Get pending AST mask
  716                         li              r6,AST_URGENT                                   ; Get the type we will preempt for 
  717                         lwz             r7,ACT_PREEMPT_CNT(r9)                  ; Get preemption count
  718                         lis             r0,hi16(DoPreemptCall)                  ; High part of Preempt FW call
  719                         cmpwi   cr1,r7,0                                                ; Are preemptions masked off?
  720                         and.    r8,r8,r6                                                ; Are we urgent?
  721                         crorc   cr1_eq,cr0_eq,cr1_eq                    ; Remember if preemptions are masked or not urgent
  722                         ori             r0,r0,lo16(DoPreemptCall)       ; Bottome of FW call
  723 
  724                         mtmsr   r5                                                              ; Restore the MSR now, before we can preempt
  725                         isync                                                                   ; Need this because FP/Vec might go off
  726 
  727                         beqlr++ cr1                                                             ; Return if no premption...
  728                         sc                                                                              ; Preempt
  729                         blr
  730 
  731 ;                       Force a line boundry here
  732                         .align  5
  733                         .globl  EXT(timer_update)
  734  
  735 LEXT(timer_update)
  736                         stw             r4,TIMER_HIGHCHK(r3)
  737                         eieio
  738                         stw             r5,TIMER_LOW(r3)
  739                         eieio
  740                         stw             r4,TIMER_HIGH(r3)
  741                         blr
  742 
  743 ;                       Force a line boundry here
  744                         .align  5
  745                         .globl  EXT(timer_grab)
  746  
  747 LEXT(timer_grab)
  748 0:                      lwz             r11,TIMER_HIGH(r3)
  749                         lwz             r4,TIMER_LOW(r3)
  750                         isync
  751                         lwz             r9,TIMER_HIGHCHK(r3)
  752                         cmpw    r11,r9
  753                         bne--   0b
  754                         mr              r3,r11
  755                         blr
  756 
  757 ;                       Force a line boundry here
  758                         .align  5
  759                         .globl  EXT(timer_event)
  760  
  761 LEXT(timer_event)
  762                         mfsprg  r10,1                                                   ; Get the current activation
  763                         lwz             r10,ACT_PER_PROC(r10)                   ; Get the per_proc block
  764                         addi    r10,r10,PP_PROCESSOR
  765                         lwz             r11,CURRENT_TIMER(r10)
  766 
  767                         lwz             r9,TIMER_LOW(r11)
  768                         lwz             r2,TIMER_TSTAMP(r11)
  769                         add             r0,r9,r3
  770                         subf    r5,r2,r0
  771                         cmplw   r5,r9
  772                         bge++   0f
  773 
  774                         lwz             r6,TIMER_HIGH(r11)
  775                         addi    r6,r6,1
  776                         stw             r6,TIMER_HIGHCHK(r11)
  777                         eieio
  778                         stw             r5,TIMER_LOW(r11)
  779                         eieio
  780                         stw             r6,TIMER_HIGH(r11)
  781                         b               1f
  782 
  783 0:                      stw             r5,TIMER_LOW(r11)
  784 
  785 1:                      stw             r4,CURRENT_TIMER(r10)
  786                         stw             r3,TIMER_TSTAMP(r4)
  787                         blr
  788 
  789 /*  Set machine into idle power-saving mode. 
  790  *
  791  *      void machine_idle(void)
  792  *
  793  *      We will use the PPC NAP or DOZE for this. 
  794  *      This call always returns.  Must be called with spllo (i.e., interruptions
  795  *      enabled).
  796  *
  797  */
  798 
  799 ;                       Force a line boundry here
  800                         .align  5
  801                         .globl  EXT(machine_idle)
  802 
  803 LEXT(machine_idle)
  804 
  805                         mfsprg  r12,1                                                   ; Get the current activation
  806                         lwz             r12,ACT_PER_PROC(r12)                   ; Get the per_proc block
  807                         lhz             r10,PP_CPU_FLAGS(r12)                   ; Get the flags
  808                         lwz             r11,PP_INTS_ENABLED(r12)                ; Get interrupt enabled state
  809                         andi.   r10,r10,SignalReady                             ; Are Signal ready?
  810                         cmpwi   cr1,r11,0                                               ; Are interrupt disabled?
  811                         cror    cr0_eq, cr1_eq, cr0_eq                  ; Interrupt disabled or Signal not ready?
  812                         mfmsr   r3                                                              ; Save the MSR 
  813                         
  814                         beq--   nonap                                                   ; Yes, return after re-enabling interrupts
  815                         lis             r0,hi16(MASK(MSR_VEC))                  ; Get the vector flag
  816                         ori             r0,r0,lo16(MASK(MSR_FP))                ; Add the FP flag
  817                         andc    r3,r3,r0                                                ; Clear VEC and FP
  818                         ori             r0,r0,lo16(MASK(MSR_EE))                ; Drop EE also
  819                         andc    r5,r3,r0                                                ; Clear VEC, FP, DR, and EE
  820 
  821                         mtmsr   r5                                                              ; Hold up interruptions for now
  822                         isync                                                                   ; May have messed with fp/vec
  823                         mfsprg  r11,2                                                   ; Get CPU specific features
  824                         mfspr   r6,hid0                                                 ; Get the current power-saving mode
  825                         mtcrf   0xC7,r11                                                ; Get the facility flags
  826 
  827                         lis             r4,hi16(napm)                                   ; Assume we can nap
  828                         bt              pfWillNapb,yesnap                               ; Yeah, nap is ok...
  829                         
  830                         lis             r4,hi16(dozem)                                  ; Assume we can doze
  831                         bt              pfCanDozeb,yesnap                               ; We can sleep or doze one this machine...
  832 
  833 nonap:          ori             r3,r3,lo16(MASK(MSR_EE))                ; Flip on EE
  834                         
  835                         mtmsr   r3                                                              ; Turn interruptions back on
  836                         blr                                                                             ; Leave...
  837 
  838 yesnap:         mftbu   r9                                                              ; Get the upper timebase
  839                         mftb    r7                                                              ; Get the lower timebase
  840                         mftbu   r8                                                              ; Get the upper one again
  841                         cmplw   r9,r8                                                   ; Did the top tick?
  842                         bne--   yesnap                                                  ; Yeah, need to get it again...
  843                         stw             r8,napStamp(r12)                                ; Set high order time stamp
  844                         stw             r7,napStamp+4(r12)                              ; Set low order nap stamp
  845 
  846                         rlwinm. r0,r11,0,pfAltivecb,pfAltivecb  ; Do we have altivec?
  847                         beq--   minovec                                                 ; No...
  848                         dssall                                                                  ; Stop the streams before we nap/doze
  849                         sync
  850                         lwz             r8,napStamp(r12)                                ; Reload high order time stamp
  851 clearpipe:
  852                         cmplw   r8,r8
  853                         bne-    clearpipe
  854                         isync
  855 
  856 minovec:        rlwinm. r7,r11,0,pfNoL2PFNapb,pfNoL2PFNapb      ; Turn off L2 Prefetch before nap?
  857                         beq++   miL2PFok
  858 
  859                         mfspr   r7,msscr0                                               ; Get currect MSSCR0 value
  860                         rlwinm  r7,r7,0,0,l2pfes-1                              ; Disable L2 Prefetch
  861                         mtspr   msscr0,r7                                               ; Updates MSSCR0 value
  862                         sync
  863                         isync
  864 
  865 miL2PFok:
  866                         rlwinm. r7,r11,0,pfSlowNapb,pfSlowNapb  ; Should nap at slow speed?
  867                         beq     minoslownap
  868 
  869                         mfspr   r7,hid1                                                 ; Get current HID1 value
  870                         oris    r7,r7,hi16(hid1psm)                             ; Select PLL1
  871                         mtspr   hid1,r7                                                 ; Update HID1 value
  872 
  873 
  874 ;
  875 ;                       We have to open up interruptions here because book 4 says that we should
  876 ;                       turn on only the POW bit and that we should have interrupts enabled.
  877 ;                       The interrupt handler will detect that nap or doze is set if an interrupt
  878 ;                       is taken and set everything up to return directly to machine_idle_ret.
  879 ;                       So, make sure everything we need there is already set up...
  880 ;
  881 
  882 minoslownap:
  883                         lis             r10,hi16(dozem|napm|sleepm)             ; Mask of power management bits
  884                 
  885                         bf--    pf64Bitb,mipNSF1                                ; skip if 32-bit...
  886                         
  887                         sldi    r4,r4,32                                                ; Position the flags
  888                         sldi    r10,r10,32                                              ; Position the masks
  889 
  890 mipNSF1:        li              r2,lo16(MASK(MSR_DR)|MASK(MSR_IR))      ; Get the translation mask
  891                         andc    r6,r6,r10                                               ; Clean up the old power bits           
  892                         ori             r7,r5,lo16(MASK(MSR_EE))                ; Flip on EE to make exit msr
  893                         andc    r5,r5,r2                                                ; Clear IR and DR from current MSR
  894                         or              r6,r6,r4                                                ; Set nap or doze
  895                         ori             r5,r5,lo16(MASK(MSR_EE))                ; Flip on EE to make nap msr
  896                         oris    r2,r5,hi16(MASK(MSR_POW))               ; Turn on power management in next MSR
  897                         
  898                         sync
  899                         mtspr   hid0,r6                                                 ; Set up the HID for nap/doze
  900                         mfspr   r6,hid0                                                 ; Yes, this is silly, keep it here
  901                         mfspr   r6,hid0                                                 ; Yes, this is a duplicate, keep it here
  902                         mfspr   r6,hid0                                                 ; Yes, this is a duplicate, keep it here
  903                         mfspr   r6,hid0                                                 ; Yes, this is a duplicate, keep it here
  904                         mfspr   r6,hid0                                                 ; Yes, this is a duplicate, keep it here
  905                         mfspr   r6,hid0                                                 ; Yes, this is a duplicate, keep it here
  906                         isync                                                                   ; Make sure it is set
  907 
  908 
  909 ;
  910 ;                       Turn translation off to nap
  911 ;
  912 
  913                         bt              pfNoMSRirb,miNoMSR                              ; Jump if we need to use SC for this...
  914                         mtmsr   r5                                                              ; Turn translation off, interrupts on
  915                         isync                                                                   ; Wait for it
  916                         b               miNoMSRx                                                ; Jump back in line...
  917                         
  918 miNoMSR:        mr              r3,r5                                                   ; Pass in the new MSR value 
  919                         li              r0,loadMSR                                              ; MSR setter ultrafast
  920                         sc                                                                              ; Do it to it like you never done before...
  921 
  922 miNoMSRx:       bf--    pf64Bitb,mipowloop                              ; skip if 32-bit...
  923                         
  924                         li              r3,0x10                                                 ; Fancy nap threshold is 0x10 ticks
  925                         mftb    r8                                                              ; Get the low half of the time base
  926                         mfdec   r4                                                              ; Get the decrementer ticks
  927                         cmplw   r4,r3                                                   ; Less than threshold?
  928                         blt             mipowloop
  929                         
  930                         mtdec   r3                                                              ; Load decrementer with threshold
  931                         isync                                                                   ; and make sure,
  932                         mfdec   r3                                                              ; really sure, it gets there
  933                         
  934                         rlwinm  r6,r2,0,MSR_EE_BIT+1,MSR_EE_BIT-1       ; Clear out the EE bit
  935                         sync                                                                    ; Make sure queues are clear
  936                         mtmsr   r6                                                              ; Set MSR with EE off but POW on
  937                         isync                                                                   ; Make sure this takes before we proceed
  938                         
  939                         mftb    r9                                                              ; Get the low half of the time base
  940                         sub             r9,r9,r8                                                ; Get the number of ticks spent waiting
  941                         sub             r4,r4,r9                                                ; Adjust the decrementer value
  942                         
  943                         mtdec   r4                                                              ; Load decrementer with the rest of the timeout
  944                         isync                                                                   ; and make sure,
  945                         mfdec   r4                                                              ; really sure, it gets there
  946                         
  947 mipowloop:
  948                         sync                                                                    ; Make sure queues are clear
  949                         mtmsr   r2                                                              ; Nap or doze, MSR with POW, EE set, translation off
  950                         isync                                                                   ; Make sure this takes before we proceed
  951                         b               mipowloop                                               ; loop if POW does not take
  952 
  953 ;
  954 ;                       Note that the interrupt handler will turn off the nap/doze bits in the hid.
  955 ;                       Also remember that the interrupt handler will force return to here whenever
  956 ;                       the nap/doze bits are set.
  957 ;
  958                         .globl  EXT(machine_idle_ret)
  959 LEXT(machine_idle_ret)
  960                         mtmsr   r7                                                              ; Make sure the MSR is what we want
  961                         isync                                                                   ; In case we turn on translation
  962 ;
  963 ;                       Protect against a lost decrementer trap if the current decrementer value is negative
  964 ;                       by more than 10 ticks, re-arm it since it is unlikely to fire at this point...
  965 ;                       A hardware interrupt got us out of machine_idle and may also be contributing to this state
  966 ; 
  967                         mfdec   r6                                                              ; Get decrementer
  968                         cmpwi   cr0,r6,-10                                              ; Compare decrementer with -10
  969                         bgelr++                                                                 ; Return if greater
  970                         li              r0,1                                                    ; Load 1
  971                         mtdec   r0                                                              ; Set decrementer to 1
  972                         blr                                                                             ; Return...
  973 
  974 /*  Put machine to sleep. 
  975  *      This call never returns. We always exit sleep via a soft reset.
  976  *      All external interruptions must be drained at this point and disabled.
  977  *
  978  *      void ml_ppc_do_sleep(void)
  979  *
  980  *      We will use the PPC SLEEP for this. 
  981  *
  982  *      There is one bit of hackery in here: we need to enable for
  983  *      interruptions when we go to sleep and there may be a pending
  984  *      decrimenter rupt.  So we make the decrimenter 0x7FFFFFFF and enable for
  985  *      interruptions. The decrimenter rupt vector recognizes this and returns
  986  *      directly back here.
  987  *
  988  */
  989 
  990 ;                       Force a line boundry here
  991                         .align  5
  992                         .globl  EXT(ml_ppc_do_sleep)
  993 
  994 LEXT(ml_ppc_do_sleep)
  995 
  996 #if 0
  997                         mfmsr   r5                                                              ; Hack to spin instead of sleep 
  998                         rlwinm  r5,r5,0,MSR_DR_BIT+1,MSR_IR_BIT-1       ; Turn off translation  
  999                         rlwinm  r5,r5,0,MSR_EE_BIT+1,MSR_EE_BIT-1       ; Turn off interruptions
 1000                         mtmsr   r5                                                              ; No talking
 1001                         isync
 1002                         
 1003 deadsleep:      addi    r3,r3,1                                                 ; Make analyzer happy
 1004                         addi    r3,r3,1
 1005                         addi    r3,r3,1
 1006                         b               deadsleep                                               ; Die the death of 1000 joys...
 1007 #endif  
 1008                         
 1009                         mfsprg  r12,1                                                   ; Get the current activation
 1010                         lwz             r12,ACT_PER_PROC(r12)                   ; Get the per_proc block
 1011                         mfsprg  r11,2                                                   ; Get CPU specific features
 1012                         eqv             r10,r10,r10                                             ; Get all foxes
 1013                         mtcrf   0x04,r11                                                ; move pfNoMSRirb to cr5
 1014                         mfspr   r4,hid0                                                 ; Get the current power-saving mode
 1015                         mtcrf   0x02,r11                                                ; move pf64Bit to cr6
 1016 
 1017                         rlwinm. r5,r11,0,pfNoL2PFNapb,pfNoL2PFNapb      ; Turn off L2 Prefetch before sleep?
 1018                         beq     mpsL2PFok
 1019 
 1020                         mfspr   r5,msscr0                                               ; Get currect MSSCR0 value
 1021                         rlwinm  r5,r5,0,0,l2pfes-1                              ; Disable L2 Prefetch
 1022                         mtspr   msscr0,r5                                               ; Updates MSSCR0 value
 1023                         sync
 1024                         isync
 1025 
 1026 mpsL2PFok:
 1027                         bt++    pf64Bitb,mpsPF64bit                             ; PM bits are shifted on 64bit systems.
 1028 
 1029                         rlwinm  r4,r4,0,sleep+1,doze-1                  ; Clear all possible power-saving modes (not DPM though)
 1030                         oris    r4,r4,hi16(sleepm)                              ; Set sleep
 1031                         b               mpsClearDEC
 1032 
 1033 mpsPF64bit:
 1034                         lis             r5, hi16(dozem|napm|sleepm)             ; Clear all possible power-saving modes (not DPM though)
 1035                         sldi    r5, r5, 32
 1036                         andc    r4, r4, r5
 1037                         lis             r5, hi16(napm)                                  ; Set sleep
 1038                         sldi    r5, r5, 32
 1039                         or              r4, r4, r5
 1040 
 1041 mpsClearDEC:
 1042                         mfmsr   r5                                                              ; Get the current MSR
 1043                         rlwinm  r10,r10,0,1,31                                  ; Make 0x7FFFFFFF
 1044                         mtdec   r10                                                             ; Load decrimenter with 0x7FFFFFFF
 1045                         isync                                                                   ; and make sure,
 1046                         mfdec   r9                                                              ; really sure, it gets there
 1047                         
 1048                         li              r2,1                                                    ; Prepare for 64 bit
 1049                         rlwinm  r5,r5,0,MSR_DR_BIT+1,MSR_IR_BIT-1       ; Turn off translation          
 1050 ;
 1051 ;                       Note that we need translation off before we set the HID to sleep.  Otherwise
 1052 ;                       we will ignore any PTE misses that occur and cause an infinite loop.
 1053 ;
 1054                         bf++    pf64Bitb,mpsCheckMSR                    ; check 64-bit processor
 1055                         rldimi  r5,r2,63,MSR_SF_BIT                             ; set SF bit (bit 0)
 1056                         mtmsrd  r5                                                              ; set 64-bit mode, turn off EE, DR, and IR
 1057                         isync                                                                   ; Toss prefetch                           
 1058                         b               mpsNoMSRx
 1059 
 1060 mpsCheckMSR:
 1061                         bt              pfNoMSRirb,mpsNoMSR                             ; No MSR...
 1062 
 1063                         mtmsr   r5                                                              ; Translation off
 1064                         isync                                                                   ; Toss prefetch
 1065                         b               mpsNoMSRx
 1066                         
 1067 mpsNoMSR:       
 1068                         li              r0,loadMSR                                              ; Get the MSR setter SC
 1069                         mr              r3,r5                                                   ; Get new MSR
 1070                         sc                                                                              ; Set it
 1071 mpsNoMSRx:
 1072 
 1073                         ori             r3,r5,lo16(MASK(MSR_EE))                ; Flip on EE
 1074                         sync
 1075                         mtspr   hid0,r4                                                 ; Set up the HID to sleep
 1076                         mfspr   r4,hid0                                                 ; Yes, this is silly, keep it here
 1077                         mfspr   r4,hid0                                                 ; Yes, this is a duplicate, keep it here
 1078                         mfspr   r4,hid0                                                 ; Yes, this is a duplicate, keep it here
 1079                         mfspr   r4,hid0                                                 ; Yes, this is a duplicate, keep it here
 1080                         mfspr   r4,hid0                                                 ; Yes, this is a duplicate, keep it here
 1081                         mfspr   r4,hid0                                                 ; Yes, this is a duplicate, keep it here
 1082 
 1083                         mtmsr   r3                                                              ; Enable for interrupts to drain decrimenter
 1084                                 
 1085                         add             r6,r4,r5                                                ; Just waste time
 1086                         add             r6,r6,r4                                                ; A bit more
 1087                         add             r6,r6,r5                                                ; A bit more
 1088 
 1089                         mtmsr   r5                                                              ; Interruptions back off
 1090                         isync                                                                   ; Toss prefetch
 1091 
 1092 ;
 1093 ;                       We are here with translation off, interrupts off, all possible
 1094 ;                       interruptions drained off, and a decrimenter that will not pop.
 1095 ;
 1096 
 1097                         bl              EXT(cacheInit)                                  ; Clear out the caches.  This will leave them on
 1098                         bl              EXT(cacheDisable)                               ; Turn off all caches
 1099                         
 1100                         mfmsr   r5                                                              ; Get the current MSR
 1101                         oris    r5,r5,hi16(MASK(MSR_POW))               ; Turn on power management in next MSR
 1102                                                                                                         ; Leave EE off because power goes off shortly
 1103                         mfsprg  r12,0                                                   ; Get the per_proc_info
 1104                         li              r10,PP_CPU_FLAGS
 1105                         lhz             r11,PP_CPU_FLAGS(r12)                   ; Get the flags
 1106                         ori             r11,r11,SleepState                              ; Marked SleepState
 1107                         sth             r11,PP_CPU_FLAGS(r12)                   ; Set the flags
 1108                         dcbf    r10,r12
 1109                         
 1110                         mfsprg  r11,2                                                   ; Get CPU specific features
 1111                         rlwinm. r0,r11,0,pf64Bitb,pf64Bitb              ; Test for 64 bit processor
 1112                         eqv             r4,r4,r4                                                ; Get all foxes
 1113                         rlwinm  r4,r4,0,1,31                                    ; Make 0x7FFFFFFF
 1114                         beq             slSleepNow                                              ; skip if 32-bit...
 1115                         li              r3, 0x4000                                              ; Cause decrimenter to roll over soon
 1116                         mtdec   r3                                                              ; Load decrimenter with 0x00004000
 1117                         isync                                                                   ; and make sure,
 1118                         mfdec   r3                                                              ; really sure, it gets there
 1119                         
 1120 slSleepNow:
 1121                         sync                                                                    ; Sync it all up
 1122                         mtmsr   r5                                                              ; Do sleep with interruptions enabled
 1123                         isync                                                                   ; Take a pill
 1124                         mtdec   r4                                                              ; Load decrimenter with 0x7FFFFFFF
 1125                         isync                                                                   ; and make sure,
 1126                         mfdec   r3                                                              ; really sure, it gets there
 1127                         b               slSleepNow                                              ; Go back to sleep if we wake up...
 1128                         
 1129 
 1130 
 1131 /*  Initialize all caches including the TLBs
 1132  *
 1133  *      void cacheInit(void)
 1134  *
 1135  *      This is used to force the caches to an initial clean state.  First, we 
 1136  *      check if the cache is on, if so, we need to flush the contents to memory.
 1137  *      Then we invalidate the L1. Next, we configure and invalidate the L2 etc.
 1138  *      Finally we turn on all of the caches
 1139  *
 1140  *      Note that if translation is not disabled when this is called, the TLB will not
 1141  *      be completely clear after return.
 1142  *
 1143  */
 1144 
 1145 ;                       Force a line boundry here
 1146                         .align  5
 1147                         .globl  EXT(cacheInit)
 1148 
 1149 LEXT(cacheInit)
 1150 
 1151                         mfsprg  r12,0                                                   ; Get the per_proc_info
 1152                         mfspr   r9,hid0                                                 ; Get the current power-saving mode
 1153                         
 1154                         mfsprg  r11,2                                                   ; Get CPU specific features
 1155                         mfmsr   r7                                                              ; Get the current MSR
 1156                         rlwinm  r7,r7,0,MSR_FP_BIT+1,MSR_FP_BIT-1       ; Force floating point off
 1157                         rlwinm  r7,r7,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1     ; Force vectors off
 1158                         rlwimi  r11,r11,pfLClckb+1,31,31                ; Move pfLClck to another position (to keep from using non-volatile CRs)
 1159                         rlwinm  r5,r7,0,MSR_DR_BIT+1,MSR_IR_BIT-1       ; Turn off translation          
 1160                         rlwinm  r5,r5,0,MSR_EE_BIT+1,MSR_EE_BIT-1       ; Turn off interruptions
 1161                         mtcrf   0x87,r11                                                ; Get the feature flags
 1162                         lis             r10,hi16(dozem|napm|sleepm|dpmm)        ; Mask of power management bits
 1163                         bf--    pf64Bitb,cIniNSF1                               ; Skip if 32-bit...
 1164                         
 1165                         sldi    r10,r10,32                                              ; Position the masks
 1166 
 1167 cIniNSF1:       andc    r4,r9,r10                                               ; Clean up the old power bits           
 1168                         mtspr   hid0,r4                                                 ; Set up the HID
 1169                         mfspr   r4,hid0                                                 ; Yes, this is silly, keep it here
 1170                         mfspr   r4,hid0                                                 ; Yes, this is a duplicate, keep it here
 1171                         mfspr   r4,hid0                                                 ; Yes, this is a duplicate, keep it here
 1172                         mfspr   r4,hid0                                                 ; Yes, this is a duplicate, keep it here
 1173                         mfspr   r4,hid0                                                 ; Yes, this is a duplicate, keep it here
 1174                         mfspr   r4,hid0                                                 ; Yes, this is a duplicate, keep it here
 1175 
 1176                         bt              pfNoMSRirb,ciNoMSR                              ; No MSR...
 1177 
 1178                         mtmsr   r5                                                              ; Translation and all off
 1179                         isync                                                                   ; Toss prefetch
 1180                         b               ciNoMSRx
 1181                         
 1182 ciNoMSR:        
 1183                         li              r0,loadMSR                                              ; Get the MSR setter SC
 1184                         mr              r3,r5                                                   ; Get new MSR
 1185                         sc                                                                              ; Set it
 1186 ciNoMSRx:
 1187                         
 1188                         bf              pfAltivecb,cinoDSS                              ; No Altivec here...
 1189                         
 1190                         dssall                                                                  ; Stop streams
 1191                         sync
 1192 
 1193 cinoDSS:        li              r5,tlbieLock                                    ; Get the TLBIE lock
 1194                         li              r0,128                                                  ; Get number of TLB entries
 1195                         
 1196                         li              r6,0                                                    ; Start at 0
 1197                         bf--    pf64Bitb,citlbhang                              ; Skip if 32-bit...
 1198                         li              r0,1024                                                 ; Get the number of TLB entries
 1199 
 1200 citlbhang:      lwarx   r2,0,r5                                                 ; Get the TLBIE lock
 1201                         mr.             r2,r2                                                   ; Is it locked?
 1202                         bne-    citlbhang                                               ; It is locked, go wait...
 1203                         stwcx.  r0,0,r5                                                 ; Try to get it
 1204                         bne-    citlbhang                                               ; We was beat...
 1205 
 1206                         mtctr   r0                                                              ; Set the CTR
 1207                         
 1208 cipurgeTLB:     tlbie   r6                                                              ; Purge this entry
 1209                         addi    r6,r6,4096                                              ; Next page
 1210                         bdnz    cipurgeTLB                                              ; Do them all...
 1211                         
 1212                         mtcrf   0x80,r11                                                ; Set SMP capability
 1213                         sync                                                                    ; Make sure all TLB purges are done
 1214                         eieio                                                                   ; Order, order in the court
 1215                         
 1216                         bf              pfSMPcapb,cinoSMP                               ; SMP incapable...
 1217                         
 1218                         tlbsync                                                                 ; Sync all TLBs
 1219                         sync
 1220                         isync
 1221                         
 1222                         bf--    pf64Bitb,cinoSMP                                ; Skip if 32-bit...
 1223                         ptesync                                                                 ; Wait for quiet again
 1224                         sync
 1225                         
 1226 cinoSMP:        stw             r2,tlbieLock(0)                                 ; Unlock TLBIE lock
 1227 
 1228                         bt++    pf64Bitb,cin64                                  ; Skip if 64-bit...
 1229 
 1230                         rlwinm. r0,r9,0,ice,dce                                 ; Were either of the level 1s on?
 1231                         beq-    cinoL1                                                  ; No, no need to flush...
 1232                         
 1233             rlwinm.     r0,r11,0,pfL1fab,pfL1fab                ; do we have L1 flush assist?
 1234                         beq             ciswdl1                                                 ; If no hw flush assist, go do by software...
 1235                         
 1236                         mfspr   r8,msscr0                                               ; Get the memory system control register
 1237                         oris    r8,r8,hi16(dl1hwfm)                             ; Turn on the hardware flush request
 1238                         
 1239                         mtspr   msscr0,r8                                               ; Start the flush operation
 1240                         
 1241 ciwdl1f:        mfspr   r8,msscr0                                               ; Get the control register again
 1242                         
 1243                         rlwinm. r8,r8,0,dl1hwf,dl1hwf                   ; Has the flush request been reset yet?
 1244                         bne             ciwdl1f                                                 ; No, flush is still in progress...
 1245                         b               ciinvdl1                                                ; Go invalidate l1...
 1246                         
 1247 ;
 1248 ;                       We need to either make this very complicated or to use ROM for
 1249 ;                       the flush.  The problem is that if during the following sequence a
 1250 ;                       snoop occurs that invalidates one of the lines in the cache, the
 1251 ;                       PLRU sequence will be altered making it possible to miss lines
 1252 ;                       during the flush.  So, we either need to dedicate an area of RAM
 1253 ;                       to each processor, lock use of a RAM area, or use ROM.  ROM is
 1254 ;                       by far the easiest. Note that this is not an issue for machines
 1255 ;                       that have harware flush assists.
 1256 ;
 1257 
 1258 ciswdl1:        lwz             r0,pfl1dSize(r12)                               ; Get the level 1 cache size
 1259                                         
 1260                         bf              31,cisnlck                                              ; Skip if pfLClck not set...
 1261                         
 1262                         mfspr   r4,msscr0                                               ; ?
 1263                         rlwinm  r6,r4,0,0,l2pfes-1                              ; ?
 1264                         mtspr   msscr0,r6                                               ; Set it
 1265                         sync
 1266                         isync
 1267                         
 1268                         mfspr   r8,ldstcr                                               ; Save the LDSTCR
 1269                         li              r2,1                                                    ; Get a mask of 0x01
 1270                         lis             r3,0xFFF0                                               ; Point to ROM
 1271                         rlwinm  r11,r0,29,3,31                                  ; Get the amount of memory to handle all indexes
 1272 
 1273                         li              r6,0                                                    ; Start here
 1274                         
 1275 cisiniflsh:     dcbf    r6,r3                                                   ; Flush each line of the range we use
 1276                         addi    r6,r6,32                                                ; Bump to the next
 1277                         cmplw   r6,r0                                                   ; Have we reached the end?
 1278                         blt+    cisiniflsh                                              ; Nope, continue initial flush...
 1279                         
 1280                         sync                                                                    ; Make sure it is done
 1281         
 1282                         addi    r11,r11,-1                                              ; Get mask for index wrap       
 1283                         li              r6,0                                                    ; Get starting offset
 1284                                                 
 1285 cislckit:       not             r5,r2                                                   ; Lock all but 1 way
 1286                         rlwimi  r5,r8,0,0,23                                    ; Build LDSTCR
 1287                         mtspr   ldstcr,r5                                               ; Lock a way
 1288                         sync                                                                    ; Clear out memory accesses
 1289                         isync                                                                   ; Wait for all
 1290                         
 1291                         
 1292 cistouch:       lwzx    r10,r3,r6                                               ; Pick up some trash
 1293                         addi    r6,r6,32                                                ; Go to the next index
 1294                         and.    r0,r6,r11                                               ; See if we are about to do next index
 1295                         bne+    cistouch                                                ; Nope, do more...
 1296                         
 1297                         sync                                                                    ; Make sure it is all done
 1298                         isync                                                                   
 1299                         
 1300                         sub             r6,r6,r11                                               ; Back up to start + 1
 1301                         addi    r6,r6,-1                                                ; Get it right
 1302                         
 1303 cisflush:       dcbf    r3,r6                                                   ; Flush everything out
 1304                         addi    r6,r6,32                                                ; Go to the next index
 1305                         and.    r0,r6,r11                                               ; See if we are about to do next index
 1306                         bne+    cisflush                                                ; Nope, do more...
 1307 
 1308                         sync                                                                    ; Make sure it is all done
 1309                         isync                                                                   
 1310                         
 1311                         
 1312                         rlwinm. r2,r2,1,24,31                                   ; Shift to next way
 1313                         bne+    cislckit                                                ; Do this for all ways...
 1314 
 1315                         mtspr   ldstcr,r8                                               ; Slam back to original
 1316                         sync
 1317                         isync
 1318                         
 1319                         mtspr   msscr0,r4                                               ; ?
 1320                         sync
 1321                         isync
 1322 
 1323                         b               cinoL1                                                  ; Go on to level 2...
 1324                         
 1325 
 1326 cisnlck:        rlwinm  r2,r0,0,1,30                                    ; Double cache size
 1327                         add             r0,r0,r2                                                ; Get 3 times cache size
 1328                         rlwinm  r0,r0,26,6,31                                   ; Get 3/2 number of cache lines
 1329                         lis             r3,0xFFF0                                               ; Dead recon ROM address for now
 1330                         mtctr   r0                                                              ; Number of lines to flush
 1331 
 1332 ciswfldl1a:     lwz             r2,0(r3)                                                ; Flush anything else
 1333                         addi    r3,r3,32                                                ; Next line
 1334                         bdnz    ciswfldl1a                                              ; Flush the lot...
 1335                         
 1336 ciinvdl1:       sync                                                                    ; Make sure all flushes have been committed
 1337 
 1338                         mfspr   r8,hid0                                                 ; Get the HID0 bits
 1339                         rlwinm  r8,r8,0,dce+1,ice-1                             ; Clear cache enables
 1340                         mtspr   hid0,r8                                                 ; and turn off L1 cache
 1341                         sync                                                                    ; Make sure all is done
 1342                         isync
 1343 
 1344                         ori             r8,r8,lo16(icem|dcem|icfim|dcfim)       ; Set the HID0 bits for enable, and invalidate
 1345                         sync
 1346                         isync                                                                           
 1347                         
 1348                         mtspr   hid0,r8                                                 ; Start the invalidate and turn on cache        
 1349                         rlwinm  r8,r8,0,dcfi+1,icfi-1                   ; Turn off the invalidate bits
 1350                         mtspr   hid0,r8                                                 ; Turn off the invalidate (needed for some older machines)
 1351                         sync
 1352 
 1353                         
 1354 cinoL1:
 1355 ;
 1356 ;                       Flush and disable the level 2
 1357 ;
 1358             mfsprg      r10,2                                                   ; need to check 2 features we did not put in CR
 1359             rlwinm.     r0,r10,0,pfL2b,pfL2b                    ; do we have L2?
 1360                         beq             cinol2                                                  ; No level 2 cache to flush
 1361 
 1362                         mfspr   r8,l2cr                                                 ; Get the L2CR
 1363                         lwz             r3,pfl2cr(r12)                                  ; Get the L2CR value
 1364                         rlwinm.         r0,r8,0,l2e,l2e                                 ; Was the L2 enabled?
 1365                         bne             ciflushl2                                       ; Yes, force flush
 1366                         cmplwi          r8, 0                                           ; Was the L2 all the way off?
 1367                         beq             ciinvdl2                                        ; Yes, force invalidate
 1368                         lis             r0,hi16(l2sizm|l2clkm|l2ramm|l2ohm)     ; Get confiuration bits
 1369                         xor             r2,r8,r3                                                ; Get changing bits?
 1370                         ori             r0,r0,lo16(l2slm|l2dfm|l2bypm)  ; More config bits
 1371                         and.    r0,r0,r2                                                ; Did any change?
 1372                         bne-    ciinvdl2                                                ; Yes, just invalidate and get PLL synced...            
 1373                         
 1374 ciflushl2:
 1375             rlwinm.     r0,r10,0,pfL2fab,pfL2fab                ; hardware-assisted L2 flush?
 1376                         beq             ciswfl2                                                 ; Flush not in hardware...
 1377                         
 1378                         mr              r10,r8                                                  ; Take a copy now
 1379                         
 1380                         bf              31,cinol2lck                                    ; Skip if pfLClck not set...
 1381                         
 1382                         oris    r10,r10,hi16(l2ionlym|l2donlym) ; Set both instruction- and data-only
 1383                         sync
 1384                         mtspr   l2cr,r10                                                ; Lock out the cache
 1385                         sync
 1386                         isync
 1387                         
 1388 cinol2lck:      ori             r10,r10,lo16(l2hwfm)                    ; Request flush
 1389                         sync                                                                    ; Make sure everything is done
 1390                         
 1391                         mtspr   l2cr,r10                                                ; Request flush
 1392                         
 1393 cihwfl2:        mfspr   r10,l2cr                                                ; Get back the L2CR
 1394                         rlwinm. r10,r10,0,l2hwf,l2hwf                   ; Is the flush over?
 1395                         bne+    cihwfl2                                                 ; Nope, keep going...
 1396                         b               ciinvdl2                                                ; Flush done, go invalidate L2...
 1397                         
 1398 ciswfl2:
 1399                         lwz             r0,pfl2Size(r12)                                ; Get the L2 size
 1400                         oris    r2,r8,hi16(l2dom)                               ; Set L2 to data only mode
 1401 
 1402                         b               ciswfl2doa                                      ; Branch to next line...
 1403 
 1404                         .align  5
 1405 ciswfl2doc:
 1406                         mtspr   l2cr,r2                                                 ; Disable L2
 1407                         sync
 1408                         isync
 1409                         b               ciswfl2dod                                      ; It is off, go invalidate it...
 1410 
 1411 ciswfl2doa:
 1412                         b               ciswfl2dob                                      ; Branch to next...
 1413 
 1414 ciswfl2dob:
 1415                         sync                                                            ; Finish memory stuff
 1416                         isync                                                           ; Stop speculation
 1417                         b               ciswfl2doc                                      ; Jump back up and turn on data only...
 1418 ciswfl2dod:
 1419                         rlwinm  r0,r0,27,5,31                                   ; Get the number of lines
 1420                         lis             r10,0xFFF0                                              ; Dead recon ROM for now
 1421                         mtctr   r0                                                              ; Set the number of lines
 1422                         
 1423 ciswfldl2a:     lwz             r0,0(r10)                                               ; Load something to flush something
 1424                         addi    r10,r10,32                                              ; Next line
 1425                         bdnz    ciswfldl2a                                              ; Do the lot...
 1426                         
 1427 ciinvdl2:       rlwinm  r8,r3,0,l2e+1,31                                ; Clear the enable bit
 1428                         b               cinla                                                   ; Branch to next line...
 1429 
 1430                         .align  5
 1431 cinlc:          mtspr   l2cr,r8                                                 ; Disable L2
 1432                         sync
 1433                         isync
 1434                         b               ciinvl2                                                 ; It is off, go invalidate it...
 1435                         
 1436 cinla:          b               cinlb                                                   ; Branch to next...
 1437 
 1438 cinlb:          sync                                                                    ; Finish memory stuff
 1439                         isync                                                                   ; Stop speculation
 1440                         b               cinlc                                                   ; Jump back up and turn off cache...
 1441                         
 1442 ciinvl2:        sync
 1443                         isync
 1444 
 1445                         cmplwi  r3, 0                                                   ; Should the L2 be all the way off?
 1446                         beq     cinol2                                                  ; Yes, done with L2
 1447 
 1448                         oris    r2,r8,hi16(l2im)                                ; Get the invalidate flag set
 1449                         
 1450                         mtspr   l2cr,r2                                                 ; Start the invalidate
 1451                         sync
 1452                         isync
 1453 ciinvdl2a:      mfspr   r2,l2cr                                                 ; Get the L2CR
 1454             mfsprg      r0,2                                                    ; need to check a feature in "non-volatile" set
 1455             rlwinm.     r0,r0,0,pfL2ib,pfL2ib                   ; flush in HW?
 1456                         beq             ciinvdl2b                                               ; Flush not in hardware...
 1457                         rlwinm. r2,r2,0,l2i,l2i                                 ; Is the invalidate still going?
 1458                         bne+    ciinvdl2a                                               ; Assume so, this will take a looong time...
 1459                         sync
 1460                         b               cinol2                                                  ; No level 2 cache to flush
 1461 ciinvdl2b:
 1462                         rlwinm. r2,r2,0,l2ip,l2ip                               ; Is the invalidate still going?
 1463                         bne+    ciinvdl2a                                               ; Assume so, this will take a looong time...
 1464                         sync
 1465                         mtspr   l2cr,r8                                                 ; Turn off the invalidate request
 1466                         
 1467 cinol2:
 1468                         
 1469 ;
 1470 ;                       Flush and enable the level 3
 1471 ;
 1472                         bf              pfL3b,cinol3                                    ; No level 3 cache to flush
 1473 
 1474                         mfspr   r8,l3cr                                                 ; Get the L3CR
 1475                         lwz             r3,pfl3cr(r12)                                  ; Get the L3CR value
 1476                         rlwinm.         r0,r8,0,l3e,l3e                                 ; Was the L3 enabled?
 1477                         bne             ciflushl3                                       ; Yes, force flush
 1478                         cmplwi          r8, 0                                           ; Was the L3 all the way off?
 1479                         beq             ciinvdl3                                        ; Yes, force invalidate
 1480                         lis             r0,hi16(l3pem|l3sizm|l3dxm|l3clkm|l3spom|l3ckspm)       ; Get configuration bits
 1481                         xor             r2,r8,r3                                                ; Get changing bits?
 1482                         ori             r0,r0,lo16(l3pspm|l3repm|l3rtm|l3cyam|l3dmemm|l3dmsizm) ; More config bits
 1483                         and.    r0,r0,r2                                                ; Did any change?
 1484                         bne-    ciinvdl3                                                ; Yes, just invalidate and get PLL synced...
 1485                         
 1486 ciflushl3:
 1487                         sync                                                                    ; 7450 book says do this even though not needed
 1488                         mr              r10,r8                                                  ; Take a copy now
 1489                         
 1490                         bf              31,cinol3lck                                    ; Skip if pfL23lck not set...
 1491                         
 1492                         oris    r10,r10,hi16(l3iom)                             ; Set instruction-only
 1493                         ori             r10,r10,lo16(l3donlym)                  ; Set data-only
 1494                         sync
 1495                         mtspr   l3cr,r10                                                ; Lock out the cache
 1496                         sync
 1497                         isync
 1498                         
 1499 cinol3lck:      ori             r10,r10,lo16(l3hwfm)                    ; Request flush
 1500                         sync                                                                    ; Make sure everything is done
 1501                         
 1502                         mtspr   l3cr,r10                                                ; Request flush
 1503                         
 1504 cihwfl3:        mfspr   r10,l3cr                                                ; Get back the L3CR
 1505                         rlwinm. r10,r10,0,l3hwf,l3hwf                   ; Is the flush over?
 1506                         bne+    cihwfl3                                                 ; Nope, keep going...
 1507 
 1508 ciinvdl3:       rlwinm  r8,r3,0,l3e+1,31                                ; Clear the enable bit
 1509                         sync                                                                    ; Make sure of life, liberty, and justice
 1510                         mtspr   l3cr,r8                                                 ; Disable L3
 1511                         sync
 1512 
 1513                         cmplwi  r3, 0                                                   ; Should the L3 be all the way off?
 1514                         beq     cinol3                                                  ; Yes, done with L3
 1515 
 1516                         ori             r8,r8,lo16(l3im)                                ; Get the invalidate flag set
 1517 
 1518                         mtspr   l3cr,r8                                                 ; Start the invalidate
 1519 
 1520 ciinvdl3b:      mfspr   r8,l3cr                                                 ; Get the L3CR
 1521                         rlwinm. r8,r8,0,l3i,l3i                                 ; Is the invalidate still going?
 1522                         bne+    ciinvdl3b                                               ; Assume so...
 1523                         sync
 1524 
 1525                         lwz     r10, pfBootConfig(r12)                                  ; ?
 1526                         rlwinm. r10, r10, 24, 28, 31                                    ; ?
 1527                         beq     ciinvdl3nopdet                                          ; ?
 1528                         
 1529                         mfspr   r8,l3pdet                                               ; ?
 1530                         srw     r2, r8, r10                                             ; ?
 1531                         rlwimi  r2, r8, 0, 24, 31                                       ; ?
 1532                         subfic  r10, r10, 32                                            ; ?
 1533                         li      r8, -1                                                  ; ?
 1534                         ori     r2, r2, 0x0080                                          ; ?
 1535                         slw     r8, r8, r10                                             ; ?
 1536                         or      r8, r2, r8                                              ; ?
 1537                         mtspr   l3pdet, r8                                              ; ?
 1538                         isync
 1539 
 1540 ciinvdl3nopdet:
 1541                         mfspr   r8,l3cr                                                 ; Get the L3CR
 1542                         rlwinm  r8,r8,0,l3clken+1,l3clken-1             ; Clear the clock enable bit
 1543                         mtspr   l3cr,r8                                                 ; Disable the clock
 1544 
 1545                         li              r2,128                                                  ; ?
 1546 ciinvdl3c:      addi    r2,r2,-1                                                ; ?
 1547                         cmplwi  r2,0                                                    ; ?
 1548                         bne+    ciinvdl3c
 1549 
 1550                         mfspr   r10,msssr0                                              ; ?
 1551                         rlwinm  r10,r10,0,vgL3TAG+1,vgL3TAG-1   ; ?
 1552                         mtspr   msssr0,r10                                              ; ?
 1553                         sync
 1554 
 1555                         mtspr   l3cr,r3                                                 ; Enable it as desired
 1556                         sync
 1557 cinol3:
 1558             mfsprg      r0,2                                                    ; need to check a feature in "non-volatile" set
 1559             rlwinm.     r0,r0,0,pfL2b,pfL2b                             ; is there an L2 cache?
 1560                         beq             cinol2a                                                 ; No level 2 cache to enable
 1561 
 1562                         lwz             r3,pfl2cr(r12)                                  ; Get the L2CR value
 1563                         cmplwi          r3, 0                                           ; Should the L2 be all the way off?
 1564                         beq             cinol2a                                                 : Yes, done with L2
 1565                         mtspr   l2cr,r3                                                 ; Enable it as desired
 1566                         sync
 1567 
 1568 ;
 1569 ;                       Invalidate and turn on L1s
 1570 ;
 1571 
 1572 cinol2a:        
 1573                         bt              31,cinoexit                                             ; Skip if pfLClck set...
 1574 
 1575                         rlwinm  r8,r9,0,dce+1,ice-1                             ; Clear the I- and D- cache enables
 1576                         mtspr   hid0,r8                                                 ; Turn off dem caches
 1577                         sync
 1578                         
 1579                         ori             r8,r9,lo16(icem|dcem|icfim|dcfim)       ; Set the HID0 bits for enable, and invalidate
 1580                         rlwinm  r9,r8,0,dcfi+1,icfi-1                   ; Turn off the invalidate bits
 1581                         sync
 1582                         isync                                                                                   
 1583 
 1584                         mtspr   hid0,r8                                                 ; Start the invalidate and turn on L1 cache     
 1585 
 1586 cinoexit:       mtspr   hid0,r9                                                 ; Turn off the invalidate (needed for some older machines) and restore entry conditions
 1587                         sync
 1588                         mtmsr   r7                                                              ; Restore MSR to entry
 1589                         isync
 1590                         blr                                                                             ; Return...
 1591 
 1592 
 1593 ;
 1594 ;                       Handle 64-bit architecture
 1595 ;                       This processor can not run without caches, so we just push everything out
 1596 ;                       and flush.  It will be relativily clean afterwards
 1597 ;
 1598                         
 1599                         .align  5
 1600                         
 1601 cin64:          
 1602                         mfspr   r10,hid1                                                ; Save hid1
 1603                         mfspr   r4,hid4                                                 ; Save hid4
 1604                         mr              r12,r10                                                 ; Really save hid1
 1605                         mr              r11,r4                                                  ; Get a working copy of hid4
 1606 
 1607                         li              r0,0                                                    ; Get a 0
 1608                         eqv             r2,r2,r2                                                ; Get all foxes
 1609                         
 1610                         rldimi  r10,r0,55,7                                             ; Clear I$ prefetch bits (7:8)
 1611                         
 1612                         isync
 1613                         mtspr   hid1,r10                                                ; Stick it
 1614                         mtspr   hid1,r10                                                ; Stick it again
 1615                         isync
 1616 
 1617                         rldimi  r11,r2,38,25                                    ; Disable D$ prefetch (25:25)
 1618                         
 1619                         sync
 1620                         mtspr   hid4,r11                                                ; Stick it
 1621                         isync
 1622 
 1623                         li              r3,8                                                    ; Set bit 28+32
 1624                         sldi    r3,r3,32                                                ; Make it bit 28
 1625                         or              r3,r3,r11                                               ; Turn on the flash invalidate L1D$
 1626                         
 1627                         oris    r5,r11,0x0600                                   ; Set disable L1D$ bits         
 1628                         sync
 1629                         mtspr   hid4,r3                                                 ; Invalidate
 1630                         isync
 1631         
 1632                         mtspr   hid4,r5                                                 ; Un-invalidate and disable L1D$
 1633                         isync
 1634                         
 1635                         lis             r8,GUSModeReg                                   ; Get the GUS mode ring address
 1636                         mfsprg  r0,2                                                    ; Get the feature flags
 1637                         ori             r8,r8,0x8000                                    ; Set to read data
 1638                         rlwinm. r0,r0,pfSCOMFixUpb+1,31,31              ; Set shift if we need a fix me up
 1639 
 1640                         sync
 1641 
 1642                         mtspr   scomc,r8                                                ; Request the GUS mode
 1643                         mfspr   r11,scomd                                               ; Get the GUS mode
 1644                         mfspr   r8,scomc                                                ; Get back the status (we just ignore it)
 1645                         sync
 1646                         isync                                                   
 1647 
 1648                         sld             r11,r11,r0                                              ; Fix up if needed
 1649 
 1650                         ori             r6,r11,lo16(GUSMdmapen)                 ; Set the bit that means direct L2 cache address
 1651                         lis             r8,GUSModeReg                                   ; Get GUS mode register address
 1652                                 
 1653                         sync
 1654 
 1655                         mtspr   scomd,r6                                                ; Set that we want direct L2 mode
 1656                         mtspr   scomc,r8                                                ; Tell GUS we want direct L2 mode
 1657                         mfspr   r3,scomc                                                ; Get back the status
 1658                         sync
 1659                         isync                                                   
 1660 
 1661                         li              r3,0                                                    ; Clear start point
 1662                 
 1663 cflushlp:       lis             r6,0x0040                                               ; Pick 4MB line as our target
 1664                         or              r6,r6,r3                                                ; Put in the line offset
 1665                         lwz             r5,0(r6)                                                ; Load a line
 1666                         addis   r6,r6,8                                                 ; Roll bit 42:44
 1667                         lwz             r5,0(r6)                                                ; Load a line
 1668                         addis   r6,r6,8                                                 ; Roll bit 42:44
 1669                         lwz             r5,0(r6)                                                ; Load a line
 1670                         addis   r6,r6,8                                                 ; Roll bit 42:44
 1671                         lwz             r5,0(r6)                                                ; Load a line
 1672                         addis   r6,r6,8                                                 ; Roll bit 42:44
 1673                         lwz             r5,0(r6)                                                ; Load a line
 1674                         addis   r6,r6,8                                                 ; Roll bit 42:44
 1675                         lwz             r5,0(r6)                                                ; Load a line
 1676                         addis   r6,r6,8                                                 ; Roll bit 42:44
 1677                         lwz             r5,0(r6)                                                ; Load a line
 1678                         addis   r6,r6,8                                                 ; Roll bit 42:44
 1679                         lwz             r5,0(r6)                                                ; Load a line
 1680 
 1681                         addi    r3,r3,128                                               ; Next line
 1682                         andis.  r5,r3,8                                                 ; Have we done enough?
 1683                         beq++   cflushlp                                                ; Not yet...
 1684                         
 1685                         sync
 1686 
 1687                         lis             r6,0x0040                                               ; Pick 4MB line as our target
 1688 
 1689 cflushx:        dcbf    0,r6                                                    ; Flush line and invalidate
 1690                         addi    r6,r6,128                                               ; Next line
 1691                         andis.  r5,r6,0x0080                                    ; Have we done enough?
 1692                         beq++   cflushx                                                 ; Keep on flushing...
 1693 
 1694                         mr              r3,r10                                                  ; Copy current hid1
 1695                         rldimi  r3,r2,54,9                                              ; Set force icbi match mode
 1696                         
 1697                         li              r6,0                                                    ; Set start if ICBI range
 1698                         isync
 1699                         mtspr   hid1,r3                                                 ; Stick it
 1700                         mtspr   hid1,r3                                                 ; Stick it again
 1701                         isync
 1702 
 1703 cflicbi:        icbi    0,r6                                                    ; Kill I$
 1704                         addi    r6,r6,128                                               ; Next line
 1705                         andis.  r5,r6,1                                                 ; Have we done them all?
 1706                         beq++   cflicbi                                                 ; Not yet...
 1707 
 1708                         lis             r8,GUSModeReg                                   ; Get GUS mode register address
 1709                                 
 1710                         sync
 1711 
 1712                         mtspr   scomd,r11                                               ; Set that we do not want direct mode
 1713                         mtspr   scomc,r8                                                ; Tell GUS we do not want direct mode
 1714                         mfspr   r3,scomc                                                ; Get back the status
 1715                         sync
 1716                         isync                                                   
 1717 
 1718                         isync
 1719                         mtspr   hid0,r9                                                 ; Restore entry hid0
 1720                         mfspr   r9,hid0                                                 ; Yes, this is silly, keep it here
 1721                         mfspr   r9,hid0                                                 ; Yes, this is a duplicate, keep it here
 1722                         mfspr   r9,hid0                                                 ; Yes, this is a duplicate, keep it here
 1723                         mfspr   r9,hid0                                                 ; Yes, this is a duplicate, keep it here
 1724                         mfspr   r9,hid0                                                 ; Yes, this is a duplicate, keep it here
 1725                         mfspr   r9,hid0                                                 ; Yes, this is a duplicate, keep it here
 1726                         isync
 1727 
 1728                         isync
 1729                         mtspr   hid1,r12                                                ; Restore entry hid1
 1730                         mtspr   hid1,r12                                                ; Stick it again
 1731                         isync
 1732                 
 1733                         sync
 1734                         mtspr   hid4,r4                                                 ; Restore entry hid4
 1735                         isync
 1736 
 1737                         sync
 1738                         mtmsr   r7                                                              ; Restore MSR to entry
 1739                         isync
 1740                         blr                                                                             ; Return...
 1741                         
 1742                         
 1743 
 1744 /*  Disables all caches
 1745  *
 1746  *      void cacheDisable(void)
 1747  *
 1748  *      Turns off all caches on the processor. They are not flushed.
 1749  *
 1750  */
 1751 
 1752 ;                       Force a line boundry here
 1753                         .align  5
 1754                         .globl  EXT(cacheDisable)
 1755 
 1756 LEXT(cacheDisable)
 1757 
 1758                         mfsprg  r11,2                                                   ; Get CPU specific features
 1759                         mtcrf   0x83,r11                                                ; Set feature flags
 1760                         
 1761                         bf              pfAltivecb,cdNoAlt                              ; No vectors...
 1762                         
 1763                         dssall                                                                  ; Stop streams
 1764                         
 1765 cdNoAlt:        sync
 1766                         
 1767                         btlr    pf64Bitb                                                ; No way to disable a 64-bit machine...
 1768                         
 1769                         mfspr   r5,hid0                                                 ; Get the hid
 1770                         rlwinm  r5,r5,0,dce+1,ice-1                             ; Clear the I- and D- cache enables
 1771                         mtspr   hid0,r5                                                 ; Turn off dem caches
 1772                         sync
 1773 
 1774             rlwinm.     r0,r11,0,pfL2b,pfL2b                    ; is there an L2?
 1775                         beq             cdNoL2                                                  ; Skip if no L2...
 1776 
 1777                         mfspr   r5,l2cr                                                 ; Get the L2
 1778                         rlwinm  r5,r5,0,l2e+1,31                                ; Turn off enable bit
 1779 
 1780                         b               cinlaa                                                  ; Branch to next line...
 1781 
 1782                         .align  5
 1783 cinlcc:         mtspr   l2cr,r5                                                 ; Disable L2
 1784                         sync
 1785                         isync
 1786                         b               cdNoL2                                                  ; It is off, we are done...
 1787                         
 1788 cinlaa:         b               cinlbb                                                  ; Branch to next...
 1789 
 1790 cinlbb:         sync                                                                    ; Finish memory stuff
 1791                         isync                                                                   ; Stop speculation
 1792                         b               cinlcc                                                  ; Jump back up and turn off cache...
 1793 
 1794 cdNoL2:
 1795 
 1796                         bf              pfL3b,cdNoL3                                    ; Skip down if no L3...
 1797                         
 1798                         mfspr   r5,l3cr                                                 ; Get the L3
 1799                         rlwinm  r5,r5,0,l3e+1,31                                ; Turn off enable bit
 1800                         rlwinm  r5,r5,0,l3clken+1,l3clken-1             ; Turn off cache enable bit
 1801                         mtspr   l3cr,r5                                                 ; Disable the caches
 1802                         sync
 1803                         
 1804 cdNoL3:
 1805                         blr                                                                             ; Leave...
 1806 
 1807 
 1808 /*  Initialize processor thermal monitoring  
 1809  *      void ml_thrm_init(void)
 1810  *
 1811  *      Obsolete, deprecated and will be removed.
 1812  */
 1813 
 1814 ;                       Force a line boundry here
 1815                         .align  5
 1816                         .globl  EXT(ml_thrm_init)
 1817 
 1818 LEXT(ml_thrm_init)
 1819                         blr
 1820 
 1821 /*  Set thermal monitor bounds 
 1822  *      void ml_thrm_set(unsigned int low, unsigned int high)
 1823  *
 1824  *      Obsolete, deprecated and will be removed.
 1825  */
 1826 
 1827 ;                       Force a line boundry here
 1828                         .align  5
 1829                         .globl  EXT(ml_thrm_set)
 1830 
 1831 LEXT(ml_thrm_set)
 1832                         blr
 1833 
 1834 /*  Read processor temprature  
 1835  *      unsigned int ml_read_temp(void)
 1836  *
 1837  *      Obsolete, deprecated and will be removed.
 1838  */
 1839 
 1840 ;                       Force a line boundry here
 1841                         .align  5
 1842                         .globl  EXT(ml_read_temp)
 1843 
 1844 LEXT(ml_read_temp)
 1845                         li              r3,-1
 1846                         blr
 1847 
 1848 /*  Throttle processor speed up or down
 1849  *      unsigned int ml_throttle(unsigned int step)
 1850  *
 1851  *      Returns old speed and sets new.  Both step and return are values from 0 to
 1852  *      255 that define number of throttle steps, 0 being off and "ictcfim" is max * 2.
 1853  *
 1854  *      Obsolete, deprecated and will be removed.
 1855  */
 1856 
 1857 ;                       Force a line boundry here
 1858                         .align  5
 1859                         .globl  EXT(ml_throttle)
 1860 
 1861 LEXT(ml_throttle)
 1862                         li              r3,0
 1863                         blr
 1864 
 1865 /*
 1866 **      ml_get_timebase()
 1867 **
 1868 **      Entry   - R3 contains pointer to 64 bit structure.
 1869 **
 1870 **      Exit    - 64 bit structure filled in.
 1871 **
 1872 */
 1873 ;                       Force a line boundry here
 1874                         .align  5
 1875                         .globl  EXT(ml_get_timebase)
 1876 
 1877 LEXT(ml_get_timebase)
 1878 
 1879 loop:
 1880                         mftbu   r4
 1881                         mftb    r5
 1882                         mftbu   r6
 1883                         cmpw    r6, r4
 1884                         bne-    loop
 1885                         
 1886                         stw     r4, 0(r3)
 1887                         stw     r5, 4(r3)
 1888                         
 1889                         blr
 1890 
 1891 /*
 1892  *              unsigned int cpu_number(void)
 1893  *
 1894  *                      Returns the current cpu number. 
 1895  */
 1896 
 1897                         .align  5
 1898                         .globl  EXT(cpu_number)
 1899 
 1900 LEXT(cpu_number)
 1901                         mfsprg  r4,1                                                    ; Get the current activation
 1902                         lwz             r4,ACT_PER_PROC(r4)                             ; Get the per_proc block
 1903                         lhz             r3,PP_CPU_NUMBER(r4)                    ; Get CPU number 
 1904                         blr                                                                             ; Return...
 1905 
 1906 /*
 1907  *              processor_t current_processor(void)
 1908  *
 1909  *                      Returns the current processor. 
 1910  */
 1911 
 1912                         .align  5
 1913                         .globl  EXT(current_processor)
 1914 
 1915 LEXT(current_processor)
 1916                         mfsprg  r3,1                                                    ; Get the current activation
 1917                         lwz             r3,ACT_PER_PROC(r3)                             ; Get the per_proc block
 1918                         addi    r3,r3,PP_PROCESSOR
 1919                         blr
 1920 
 1921 #if     PROCESSOR_SIZE > PP_PROCESSOR_SIZE
 1922 #error processor overflows per_proc
 1923 #endif
 1924 
 1925 /*
 1926  *              ast_t   *ast_pending(void)
 1927  *
 1928  *              Returns the address of the pending AST mask for the current processor.
 1929  */
 1930 
 1931                         .align  5
 1932                         .globl  EXT(ast_pending)
 1933 
 1934 LEXT(ast_pending)
 1935                         mfsprg  r3,1                                                    ; Get the current activation
 1936                         lwz             r3,ACT_PER_PROC(r3)                             ; Get the per_proc block
 1937                         addi    r3,r3,PP_PENDING_AST
 1938                         blr                                                                             ; Return...
 1939 
 1940 /*
 1941  *              void machine_set_current_thread(thread_t)
 1942  *
 1943  *                      Set the current thread
 1944  */
 1945                         .align  5
 1946                         .globl  EXT(machine_set_current_thread)
 1947 
 1948 LEXT(machine_set_current_thread)
 1949 
 1950                         mfsprg  r4,1                                                    ; Get spr1
 1951                         lwz             r5,ACT_PER_PROC(r4)                             ; Get the PerProc from the previous active thread
 1952                         stw             r5,ACT_PER_PROC(r3)                             ; Set the PerProc in the active thread
 1953                         mtsprg  1,r3                                                    ; Set spr1 with the active thread
 1954                         blr                                                                             ; Return...
 1955 
 1956 /*
 1957  *              thread_t current_thread(void)
 1958  *              thread_t current_act(void)
 1959  *
 1960  *
 1961  *                      Return the current thread for outside components.
 1962  */
 1963                         .align  5
 1964                         .globl  EXT(current_thread)
 1965                         .globl  EXT(current_act)
 1966 
 1967 LEXT(current_thread)
 1968 LEXT(current_act)
 1969 
 1970                         mfsprg  r3,1
 1971                         blr
 1972 
 1973                         .align  5
 1974                         .globl  EXT(clock_get_uptime)
 1975 LEXT(clock_get_uptime)
 1976 1:                      mftbu   r9
 1977                         mftb    r0
 1978                         mftbu   r11
 1979                         cmpw    r11,r9
 1980                         bne--   1b
 1981                         stw             r0,4(r3)
 1982                         stw             r9,0(r3)
 1983                         blr
 1984 
 1985                 
 1986                         .align  5
 1987                         .globl  EXT(mach_absolute_time)
 1988 LEXT(mach_absolute_time)
 1989 1:                      mftbu   r3
 1990                         mftb    r4
 1991                         mftbu   r0
 1992                         cmpw    r0,r3
 1993                         bne--   1b  
 1994                         blr
 1995 
 1996 /*
 1997 **      ml_sense_nmi()
 1998 **
 1999 */
 2000 ;                       Force a line boundry here
 2001                         .align  5
 2002                         .globl  EXT(ml_sense_nmi)
 2003 
 2004 LEXT(ml_sense_nmi)
 2005 
 2006                         blr                                                                             ; Leave...
 2007 
 2008 /*
 2009 **      ml_set_processor_speed_powertune()
 2010 **
 2011 */
 2012 ;                       Force a line boundry here
 2013                         .align  5
 2014                         .globl  EXT(ml_set_processor_speed_powertune)
 2015 
 2016 LEXT(ml_set_processor_speed_powertune)
 2017                         mflr    r0                                                                              ; Save the link register
 2018                         stwu    r1, -(FM_ALIGN(4*4)+FM_SIZE)(r1)                ; Make some space on the stack
 2019                         stw             r28, FM_ARG0+0x00(r1)                                   ; Save a register
 2020                         stw             r29, FM_ARG0+0x04(r1)                                   ; Save a register
 2021                         stw             r30, FM_ARG0+0x08(r1)                                   ; Save a register
 2022                         stw             r31, FM_ARG0+0x0C(r1)                                   ; Save a register
 2023                         stw             r0, (FM_ALIGN(4*4)+FM_SIZE+FM_LR_SAVE)(r1)      ; Save the return
 2024 
 2025                         mfsprg  r31,1                                                                   ; Get the current activation
 2026                         lwz             r31,ACT_PER_PROC(r31)                                   ; Get the per_proc block
 2027 
 2028                         rlwinm  r28, r3, 31-dnap, dnap, dnap                    ; Shift the 1 bit to the dnap+32 bit
 2029                         rlwinm  r3, r3, 2, 29, 29                                               ; Shift the 1 to a 4 and mask
 2030                         addi    r3, r3, pfPowerTune0                                    ; Add in the pfPowerTune0 offset
 2031                         lwzx    r29, r31, r3                                                    ; Load the PowerTune number 0 or 1
 2032 
 2033                         sldi    r28, r28, 32                                                    ; Shift to the top half
 2034                         ld              r3, pfHID0(r31)                                                 ; Load the saved hid0 value
 2035                         and             r28, r28, r3                                                    ; Save the dnap bit
 2036                         lis             r4, hi16(dnapm)                                                 ; Make a mask for the dnap bit
 2037                         sldi    r4, r4, 32                                                              ; Shift to the top half
 2038                         andc    r3, r3, r4                                                              ; Clear the dnap bit
 2039                         or              r28, r28, r3                                                    ; Insert the dnap bit as needed for later
 2040 
 2041                         sync
 2042                         mtspr   hid0, r3                                                                ; Turn off dnap in hid0
 2043                         mfspr   r3, hid0                                                                ; Yes, this is silly, keep it here
 2044                         mfspr   r3, hid0                                                                ; Yes, this is a duplicate, keep it here
 2045                         mfspr   r3, hid0                                                                ; Yes, this is a duplicate, keep it here
 2046                         mfspr   r3, hid0                                                                ; Yes, this is a duplicate, keep it here
 2047                         mfspr   r3, hid0                                                                ; Yes, this is a duplicate, keep it here
 2048                         mfspr   r3, hid0                                                                ; Yes, this is a duplicate, keep it here
 2049                         isync                                                                                   ; Make sure it is set
 2050 
 2051                         lis             r3, hi16(PowerTuneControlReg)                   ; Write zero to the PCR
 2052                         ori             r3, r3, lo16(PowerTuneControlReg)
 2053                         li              r4, 0
 2054                         li              r5, 0
 2055                         bl              _ml_scom_write
 2056 
 2057                         lis             r3, hi16(PowerTuneControlReg)                   ; Write the PowerTune value to the PCR
 2058                         ori             r3, r3, lo16(PowerTuneControlReg)
 2059                         li              r4, 0
 2060                         mr              r5, r29
 2061                         bl              _ml_scom_write
 2062 
 2063                         rlwinm  r29, r29, 13-6, 6, 7                                    ; Move to PSR speed location and isolate the requested speed
 2064 spsPowerTuneLoop:
 2065                         lis             r3, hi16(PowerTuneStatusReg)                    ; Read the status from the PSR
 2066                         ori             r3, r3, lo16(PowerTuneStatusReg)
 2067                         li              r4, 0
 2068                         bl              _ml_scom_read
 2069                         srdi    r5, r5, 32
 2070                         rlwinm  r0, r5, 0, 6, 7                                                 ; Isolate the current speed
 2071                         rlwimi  r0, r5, 0, 2, 2                                                 ; Copy in the change in progress bit
 2072                         cmpw    r0, r29                                                                 ; Compare the requested and current speeds
 2073                         beq             spsPowerTuneDone
 2074                         rlwinm. r0, r5, 0, 3, 3
 2075                         beq             spsPowerTuneLoop
 2076 
 2077 spsPowerTuneDone:
 2078                         sync
 2079                         mtspr   hid0, r28                                                               ; Turn on dnap in hid0 if needed
 2080                         mfspr   r28, hid0                                                               ; Yes, this is silly, keep it here
 2081                         mfspr   r28, hid0                                                               ; Yes, this is a duplicate, keep it here
 2082                         mfspr   r28, hid0                                                               ; Yes, this is a duplicate, keep it here
 2083                         mfspr   r28, hid0                                                               ; Yes, this is a duplicate, keep it here
 2084                         mfspr   r28, hid0                                                               ; Yes, this is a duplicate, keep it here
 2085                         mfspr   r28, hid0                                                               ; Yes, this is a duplicate, keep it here
 2086                         isync                                                                                   ; Make sure it is set
 2087 
 2088                         lwz             r0, (FM_ALIGN(4*4)+FM_SIZE+FM_LR_SAVE)(r1)      ; Get the return
 2089                         lwz             r28, FM_ARG0+0x00(r1)                                   ; Restore a register
 2090                         lwz             r29, FM_ARG0+0x04(r1)                                   ; Restore a register
 2091                         lwz             r30, FM_ARG0+0x08(r1)                                   ; Restore a register
 2092                         lwz             r31, FM_ARG0+0x0C(r1)                                   ; Restore a register
 2093                         lwz             r1, FM_BACKPTR(r1)                                              ; Pop the stack
 2094                         mtlr    r0
 2095                         blr
 2096 
 2097 /*
 2098 **      ml_set_processor_speed_dpll()
 2099 **
 2100 */
 2101 ;                       Force a line boundry here
 2102                         .align  5
 2103                         .globl  EXT(ml_set_processor_speed_dpll)
 2104 
 2105 LEXT(ml_set_processor_speed_dpll)
 2106                         mfsprg  r5,1                                                                    ; Get the current activation
 2107                         lwz             r5,ACT_PER_PROC(r5)                                             ; Get the per_proc block
 2108                         
 2109                         cmplwi  r3, 0                                                                   ; Turn off BTIC before low speed
 2110                         beq             spsDPLL1
 2111                         mfspr   r4, hid0                                                                ; Get the current hid0 value
 2112                         rlwinm  r4, r4, 0, btic+1, btic-1                               ; Clear the BTIC bit
 2113                         sync
 2114                         mtspr   hid0, r4                                                                ; Set the new hid0 value
 2115                         isync
 2116                         sync
 2117 
 2118 spsDPLL1:
 2119                         mfspr   r4, hid1                                                                ; Get the current PLL settings
 2120                         rlwimi  r4, r3, 31-hid1ps, hid1ps, hid1ps               ; Copy the PLL Select bit
 2121                         stw             r4, pfHID1(r5)                                                  ; Save the new hid1 value
 2122                         mtspr   hid1, r4                                                                ; Select desired PLL
 2123 
 2124                         cmplwi  r3, 0                                                                   ; Restore BTIC after high speed
 2125                         bne             spsDPLL2
 2126                         lwz             r4, pfHID0(r5)                                                  ; Load the hid0 value
 2127                         sync
 2128                         mtspr   hid0, r4                                                                ; Set the hid0 value
 2129                         isync
 2130                         sync
 2131 spsDPLL2:
 2132                         blr
 2133 
 2134 
 2135 /*
 2136 **      ml_set_processor_speed_dfs(divideby)
 2137 **                      divideby == 0 then divide by 1 (full speed)
 2138 **                      divideby == 1 then divide by 2 (half speed)
 2139 **                      divideby == 2 then divide by 4 (quarter speed)
 2140 **                      divideby == 3 then divide by 4 (quarter speed) - preferred
 2141 **
 2142 */
 2143 ;                       Force a line boundry here
 2144                         .align  5
 2145                         .globl  EXT(ml_set_processor_speed_dfs)
 2146 
 2147 LEXT(ml_set_processor_speed_dfs)
 2148 
 2149                         mfspr   r4,hid1                                                                 ; Get the current HID1
 2150                         mfsprg  r5,0                                                                    ; Get the per_proc_info
 2151                         rlwimi  r4,r3,31-hid1dfs1,hid1dfs0,hid1dfs1             ; Stick the new divider bits in
 2152                         stw             r4,pfHID1(r5)                                                   ; Save the new hid1 value
 2153                         sync
 2154                         mtspr   hid1,r4                                                                 ; Set the new HID1
 2155                         sync
 2156                         isync
 2157                         blr
 2158 
 2159 
 2160 /*
 2161 **      ml_set_processor_voltage()
 2162 **
 2163 */
 2164 ;                       Force a line boundry here
 2165                         .align  5
 2166                         .globl  EXT(ml_set_processor_voltage)
 2167 
 2168 LEXT(ml_set_processor_voltage)
 2169                         mfsprg  r5,1                                                                    ; Get the current activation
 2170                         lwz             r5,ACT_PER_PROC(r5)                                             ; Get the per_proc block
 2171 
 2172                         lwz             r6, pfPowerModes(r5)                                    ; Get the supported power modes
 2173 
 2174                         rlwinm. r0, r6, 0, pmDPLLVminb, pmDPLLVminb             ; Is DPLL Vmin supported
 2175                         beq             spvDone
 2176 
 2177                         mfspr   r4, hid2                                                                ; Get HID2 value
 2178                         rlwimi  r4, r3, 31-hid2vmin, hid2vmin, hid2vmin ; Insert the voltage mode bit
 2179                         mtspr   hid2, r4                                                                ; Set the voltage mode
 2180                         sync                                                                                    ; Make sure it is done
 2181 
 2182 spvDone:
 2183                         blr
 2184 
 2185 
 2186 ;
 2187 ;                       unsigned int ml_scom_write(unsigned int reg, unsigned long long data)
 2188 ;                       64-bit machines only
 2189 ;                       returns status
 2190 ;
 2191 
 2192                         .align  5
 2193                         .globl  EXT(ml_scom_write)
 2194 
 2195 LEXT(ml_scom_write)
 2196 
 2197                         rldicr  r3,r3,8,47                                                      ; Align register it correctly
 2198                         rldimi  r5,r4,32,0                                                      ; Merge the high part of data
 2199                         sync                                                                            ; Clean up everything
 2200                         
 2201                         mtspr   scomd,r5                                                        ; Stick in the data
 2202                         mtspr   scomc,r3                                                        ; Set write to register
 2203                         sync
 2204                         isync                                   
 2205 
 2206                         mfspr   r3,scomc                                                        ; Read back status
 2207                         blr                                                                                     ; leave....                                                     
 2208 
 2209 ;
 2210 ;                       unsigned int ml_read_scom(unsigned int reg, unsigned long long *data)
 2211 ;                       64-bit machines only
 2212 ;                       returns status
 2213 ;                       ASM Callers: data (r4) can be zero and the 64 bit data will be returned in r5
 2214 ;
 2215 
 2216                         .align  5
 2217                         .globl  EXT(ml_scom_read)
 2218 
 2219 LEXT(ml_scom_read)
 2220 
 2221                         mfsprg  r0,2                                                            ; Get the feature flags
 2222                         rldicr  r3,r3,8,47                                                      ; Align register it correctly
 2223                         rlwinm  r0,r0,pfSCOMFixUpb+1,31,31                      ; Set shift if we need a fix me up
 2224                         
 2225                         ori             r3,r3,0x8000                                            ; Set to read data
 2226                         sync
 2227 
 2228                         mtspr   scomc,r3                                                        ; Request the register
 2229                         mfspr   r5,scomd                                                        ; Get the register contents
 2230                         mfspr   r3,scomc                                                        ; Get back the status
 2231                         sync
 2232                         isync                                                   
 2233 
 2234                         sld             r5,r5,r0                                                        ; Fix up if needed
 2235 
 2236                         cmplwi  r4, 0                                                           ; If data pointer is null, just return
 2237                         beqlr                                                                           ; the received data in r5
 2238                         std             r5,0(r4)                                                        ; Pass back the received data                   
 2239                         blr                                                                                     ; Leave...
 2240 
 2241 ;
 2242 ;                       Calculates the hdec to dec ratio
 2243 ;
 2244 
 2245                         .align  5
 2246                         .globl  EXT(ml_hdec_ratio)
 2247 
 2248 LEXT(ml_hdec_ratio)
 2249 
 2250                         li              r0,0                                                            ; Clear the EE bit (and everything else for that matter)
 2251                         mfmsr   r11                                                                     ; Get the MSR
 2252                         mtmsrd  r0,1                                                            ; Set the EE bit only (do not care about RI)
 2253                         rlwinm  r11,r11,0,MSR_EE_BIT,MSR_EE_BIT         ; Isolate just the EE bit
 2254                         mfmsr   r10                                                                     ; Refresh our view of the MSR (VMX/FP may have changed)
 2255                         or              r12,r10,r11                                                     ; Turn on EE if on before we turned it off
 2256 
 2257                         mftb    r9                                                                      ; Get time now
 2258                         mfspr   r2,hdec                                                         ; Save hdec
 2259 
 2260 mhrcalc:        mftb    r8                                                                      ; Get time now
 2261                         sub             r8,r8,r9                                                        ; How many ticks?
 2262                         cmplwi  r8,10000                                                        ; 10000 yet?
 2263                         blt             mhrcalc                                                         ; Nope...
 2264 
 2265                         mfspr   r9,hdec                                                         ; Get hdec now
 2266                         sub             r3,r2,r9                                                        ; How many ticks?
 2267                         mtmsrd  r12,1                                                           ; Flip EE on if needed
 2268                         blr                                                                                     ; Leave...
 2269 
 2270 
 2271 ;
 2272 ;                       int setPop(time)
 2273 ;       
 2274 ;                       Calculates the number of ticks to the supplied event and
 2275 ;                       sets the decrementer.  Never set the time for less that the
 2276 ;                       minimum, which is 10, nor more than maxDec, which is usually 0x7FFFFFFF
 2277 ;                       and never more than that but can be set by root.
 2278 ;
 2279 ;
 2280 
 2281                         .align  7
 2282                         .globl  EXT(setPop)
 2283 
 2284 #define kMin    10
 2285 
 2286 LEXT(setPop)
 2287 
 2288 spOver:         mftbu   r8                                                                      ; Get upper time
 2289                         addic   r2,r4,-kMin                                                     ; Subtract minimum from target
 2290                         mftb    r9                                                                      ; Get lower
 2291                         addme   r11,r3                                                          ; Do you have any bits I could borrow?
 2292                         mftbu   r10                                                                     ; Get upper again
 2293                         subfe   r0,r0,r0                                                        ; Get -1 if we went negative 0 otherwise
 2294                         subc    r7,r2,r9                                                        ; Subtract bottom and get carry
 2295                         cmplw   r8,r10                                                          ; Did timebase upper tick?
 2296                         subfe   r6,r8,r11                                                       ; Get the upper difference accounting for borrow
 2297                         lwz             r12,maxDec(0)                                           ; Get the maximum decrementer size 
 2298                         addme   r0,r0                                                           ; Get -1 or -2 if anything negative, 0 otherwise
 2299                         addic   r2,r6,-1                                                        ; Set carry if diff < 2**32
 2300                         srawi   r0,r0,1                                                         ; Make all foxes
 2301                         subi    r10,r12,kMin                                            ; Adjust maximum for minimum adjust
 2302                         andc    r7,r7,r0                                                        ; Pin time at 0 if under minimum
 2303                         subfe   r2,r2,r2                                                        ; 0 if diff > 2**32, -1 otherwise               
 2304                         sub             r7,r7,r10                                                       ; Negative if duration is less than (max - min)
 2305                         or              r2,r2,r0                                                        ; If the duration is negative, it isn't too big
 2306                         srawi   r0,r7,31                                                        ; -1 if duration is too small
 2307                         and             r7,r7,r2                                                        ; Clear duration if high part too big
 2308                         and             r7,r7,r0                                                        ; Clear duration if low part too big
 2309                         bne--   spOver                                                          ; Timer ticked...
 2310                         add             r3,r7,r12                                                       ; Add back the max for total                            
 2311                         mtdec   r3                                                                      ; Set the decrementer
 2312                         blr                                                                                     ; Leave...
 2313 
 2314 

Cache object: 755e26c83e21e4c1dae3c7158389646e


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.