darwin-xnu/osfmk/ppc/savearea_asm.s
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2000 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
  23#define FPVECDBG 0
  24
  25#include <assym.s>
  26#include <debug.h>
  27#include <db_machine_commands.h>
  28#include <mach_rt.h>
  29        
  30#include <mach_debug.h>
  31#include <ppc/asm.h>
  32#include <ppc/proc_reg.h>
  33#include <ppc/exception.h>
  34#include <ppc/Performance.h>
  35#include <ppc/exception.h>
  36#include <ppc/savearea.h>
  37#include <mach/ppc/vm_param.h>
  38        
  39                        .text
  40
  41/* Register usage conventions in this code:
  42 *      r9 = return address
  43 * r10 = per-proc ptr
  44 * r11 = MSR at entry
  45 * cr6 = feature flags (ie, pf64Bit)
  46 *
  47 * Because much of this code deals with physical addresses,
  48 * there are parallel paths for 32- and 64-bit machines.
  49 */
  50 
  51
  52/*
  53 * *****************************
  54 * * s a v e _ s n a p s h o t *
  55 * *****************************
  56 *
  57 *      void save_snapshot();
  58 *
  59 *                      Link the current free list & processor local list on an independent list.
  60 */
  61                        .align  5
  62                        .globl  EXT(save_snapshot)
  63
  64LEXT(save_snapshot)
  65            mflr        r9                                                      ; get return address
  66            bl          saveSetup                                       ; turn translation off, 64-bit on, load many regs
  67            bf--        pf64Bitb,save_snapshot32        ; skip if 32-bit processor
  68
  69            ; Handle 64-bit processor.
  70
  71save_snapshot64:
  72
  73                        ld              r8,next_savearea(r10)           ; Start with the current savearea
  74                        std             r8,SVsavefreesnapshot(0)        ; Make it the restore list anchor
  75                        ld              r5,SVfree(0)                            ; Get free save area list anchor 
  76
  77save_snapshot64nextfree:
  78            mr          r7,r5
  79                        std             r7,savemisc1(r8)                        ; Link this one
  80                        ld              r5,SAVprev(r7)                          ; Get the next 
  81            mr          r8,r7
  82            mr.         r0,r5
  83            bne         save_snapshot64nextfree
  84
  85                        lwz             r6,SVinuse(0)                           ; Get inuse count
  86                        ld              r5,lclfree(r10)                         ; Get the local savearea list
  87            subi        r6,r6,1                                         ; Count the first as free
  88
  89save_snapshot64nextlocalfree:
  90            subi        r6,r6,1                                         ; Count as free
  91            mr          r7,r5
  92                        std             r7,savemisc1(r8)                        ; Link this one
  93                        ld              r5,SAVprev(r7)                          ; Get the next 
  94            mr          r8,r7
  95            mr.         r0,r5
  96            bne         save_snapshot64nextlocalfree
  97
  98                        std             r5,savemisc1(r8)                        ; End the list
  99                        stw             r6,SVsaveinusesnapshot(0)       ; Save the new number of inuse saveareas
 100
 101                        mtlr    r9                                                      ; Restore the return
 102            b           saveRestore64                           ; Restore interrupts and translation
 103
 104            ; Handle 32-bit processor.
 105
 106save_snapshot32:
 107                        lwz             r8,next_savearea+4(r10)         ; Start with the current savearea
 108                        stw             r8,SVsavefreesnapshot+4(0)      ; Make it the restore list anchor
 109                        lwz             r5,SVfree+4(0)                          ; Get free save area list anchor 
 110
 111save_snapshot32nextfree:
 112            mr          r7,r5
 113                        stw             r7,savemisc1+4(r8)              ; Link this one
 114                        lwz             r5,SAVprev+4(r7)                        ; Get the next 
 115            mr          r8,r7
 116            mr.         r0,r5
 117            bne         save_snapshot32nextfree
 118
 119                        lwz             r6,SVinuse(0)                           ; Get inuse count
 120                        lwz             r5,lclfree+4(r10)                       ; Get the local savearea list
 121            subi        r6,r6,1                                         ; Count the first as free
 122
 123save_snapshot32nextlocalfree:
 124            subi        r6,r6,1                                         ; Count as free
 125            mr          r7,r5
 126                        stw             r7,savemisc1+4(r8)                      ; Link this one
 127                        lwz             r5,SAVprev+4(r7)                        ; Get the next 
 128            mr          r8,r7
 129            mr.         r0,r5
 130            bne         save_snapshot32nextlocalfree
 131
 132                        stw             r5,savemisc1+4(r8)                      ; End the list
 133                        stw             r6,SVsaveinusesnapshot(0)       ; Save the new number of inuse saveareas
 134
 135                        mtlr    r9                                                      ; Restore the return
 136            b           saveRestore32                           ; Restore interrupts and translation
 137
 138/*
 139 * *********************************************
 140 * * s a v e _ s n a p s h o t _ r e s t o r e *
 141 * *********************************************
 142 *
 143 *      void save_snapshot_restore();
 144 *
 145 *                      Restore the free list from the snapshot list, and reset the processors next savearea.
 146 */
 147                        .align  5
 148                        .globl  EXT(save_snapshot_restore)
 149
 150LEXT(save_snapshot_restore)
 151            mflr        r9                                                      ; get return address
 152            bl          saveSetup                                       ; turn translation off, 64-bit on, load many regs
 153            bf--        pf64Bitb,save_snapshot_restore32        ; skip if 32-bit processor
 154
 155            ; Handle 64-bit processor.
 156
 157save_snapshot_restore64:
 158                        lwz             r7,SVsaveinusesnapshot(0)
 159                        stw             r7,SVinuse(0)                           ; Set the new inuse count
 160
 161            li          r6,0
 162            stw         r6,lclfreecnt(r10)                      ; None local now
 163                        std             r6,lclfree(r10)                         ; None local now
 164
 165                        ld              r8,SVsavefreesnapshot(0)        ; Get the restore list anchor 
 166                        std             r8,SVfree(0)                            ; Make it the free list anchor
 167                        li              r5,SAVempty                                     ; Get marker for free savearea
 168
 169save_snapshot_restore64nextfree:
 170            addi        r6,r6,1                                         ; Count as free
 171                        stb             r5,SAVflags+2(r8)                       ; Mark savearea free
 172                        ld              r7,savemisc1(r8)                        ; Get the next 
 173                        std             r7,SAVprev(r8)                          ; Set the next in free list
 174            mr.         r8,r7
 175            bne         save_snapshot_restore64nextfree
 176
 177            stw         r6,SVfreecnt(0)                         ; Set the new free count
 178
 179            bl          saveGet64
 180            std         r3,next_savearea(r10)           ; Get the next savearea 
 181
 182                        mtlr    r9                                                      ; Restore the return
 183            b           saveRestore64                           ; Restore interrupts and translation
 184
 185            ; Handle 32-bit processor.
 186
 187save_snapshot_restore32:
 188                        lwz             r7,SVsaveinusesnapshot(0)
 189                        stw             r7,SVinuse(0)                           ; Set the new inuse count
 190
 191            li          r6,0
 192            stw         r6,lclfreecnt(r10)                      ; None local now
 193                        stw             r6,lclfree+4(r10)                       ; None local now
 194
 195                        lwz             r8,SVsavefreesnapshot+4(0)      ; Get the restore list anchor 
 196                        stw             r8,SVfree+4(0)                          ; Make it the free list anchor
 197                        li              r5,SAVempty                                     ; Get marker for free savearea
 198
 199save_snapshot_restore32nextfree:
 200            addi        r6,r6,1                                         ; Count as free
 201                        stb             r5,SAVflags+2(r8)                       ; Mark savearea free
 202                        lwz             r7,savemisc1+4(r8)                      ; Get the next 
 203                        stw             r7,SAVprev+4(r8)                        ; Set the next in free list
 204            mr.         r8,r7
 205            bne         save_snapshot_restore32nextfree
 206
 207            stw         r6,SVfreecnt(0)                         ; Set the new free count
 208
 209            bl          saveGet32
 210            stw         r3,next_savearea+4(r10)         ; Get the next savearea 
 211
 212                        mtlr    r9                                                      ; Restore the return
 213            b           saveRestore32                           ; Restore interrupts and translation
 214
 215/*
 216 * ***********************
 217 * * s a v e _ q u e u e *
 218 * ***********************
 219 *
 220 *      void save_queue(ppnum_t pagenum);
 221 *
 222 *                      This routine will add a savearea block to the free list.
 223 *                      We also queue the block to the free pool list.  This is a
 224 *                      circular double linked list. Because this block has no free entries,
 225 *                      it gets queued to the end of the list
 226 */
 227                        .align  5
 228                        .globl  EXT(save_queue)
 229
 230LEXT(save_queue)
 231            mflr        r9                                                      ; get return address
 232            mr          r8,r3                                           ; move pagenum out of the way
 233            bl          saveSetup                                       ; turn translation off, 64-bit on, load many regs
 234            bf--        pf64Bitb,saveQueue32            ; skip if 32-bit processor
 235            
 236            sldi        r2,r8,12                                        ; r2 <-- phys address of page
 237                        li              r8,sac_cnt                                      ; Get the number of saveareas per page
 238                        mr              r4,r2                                           ; Point to start of chain
 239                        li              r0,SAVempty                                     ; Get empty marker
 240
 241saveQueue64a:   
 242            addic.      r8,r8,-1                                        ; Keep track of how many we did
 243                        stb             r0,SAVflags+2(r4)                       ; Set empty
 244                        addi    r7,r4,SAVsize                           ; Point to the next slot
 245                        ble-    saveQueue64b                            ; We are done with the chain
 246                        std             r7,SAVprev(r4)                          ; Set this chain
 247                        mr              r4,r7                                           ; Step to the next
 248                        b               saveQueue64a                            ; Fill the whole block...
 249
 250saveQueue64b:
 251                        bl              savelock                                        ; Go lock the save anchor 
 252
 253                        ld              r7,SVfree(0)                            ; Get the free save area list anchor 
 254                        lwz             r6,SVfreecnt(0)                         ; Get the number of free saveareas
 255
 256                        std             r2,SVfree(0)                            ; Queue in the new one 
 257                        addi    r6,r6,sac_cnt                           ; Count the ones we are linking in 
 258                        std             r7,SAVprev(r4)                          ; Queue the old first one off of us
 259                        stw             r6,SVfreecnt(0)                         ; Save the new count
 260                        b               saveQueueExit
 261
 262            ; Handle 32-bit processor.
 263            
 264saveQueue32:            
 265            slwi        r2,r8,12                                        ; r2 <-- phys address of page
 266                        li              r8,sac_cnt                                      ; Get the number of saveareas per page
 267                        mr              r4,r2                                           ; Point to start of chain
 268                        li              r0,SAVempty                                     ; Get empty marker
 269
 270saveQueue32a:   
 271            addic.      r8,r8,-1                                        ; Keep track of how many we did
 272                        stb             r0,SAVflags+2(r4)                       ; Set empty
 273                        addi    r7,r4,SAVsize                           ; Point to the next slot
 274                        ble-    saveQueue32b                            ; We are done with the chain
 275                        stw             r7,SAVprev+4(r4)                        ; Set this chain
 276                        mr              r4,r7                                           ; Step to the next
 277                        b               saveQueue32a                            ; Fill the whole block...
 278
 279saveQueue32b:
 280                        bl              savelock                                        ; Go lock the save anchor 
 281
 282                        lwz             r7,SVfree+4(0)                          ; Get the free save area list anchor 
 283                        lwz             r6,SVfreecnt(0)                         ; Get the number of free saveareas
 284
 285                        stw             r2,SVfree+4(0)                          ; Queue in the new one 
 286                        addi    r6,r6,sac_cnt                           ; Count the ones we are linking in 
 287                        stw             r7,SAVprev+4(r4)                        ; Queue the old first one off of us
 288                        stw             r6,SVfreecnt(0)                         ; Save the new count
 289
 290saveQueueExit:                                                                  ; join here from 64-bit path            
 291                        bl              saveunlock                                      ; Unlock the list and set the adjust count
 292                        mtlr    r9                                                      ; Restore the return
 293
 294#if FPVECDBG
 295                        mfsprg  r2,1                                            ; (TEST/DEBUG)
 296                        mr.             r2,r2                                           ; (TEST/DEBUG)
 297                        beq--   saveRestore                                     ; (TEST/DEBUG)
 298                        lis             r0,hi16(CutTrace)                       ; (TEST/DEBUG)
 299                        li              r2,0x2201                                       ; (TEST/DEBUG)
 300                        oris    r0,r0,lo16(CutTrace)            ; (TEST/DEBUG)
 301                        sc                                                                      ; (TEST/DEBUG)
 302#endif
 303            b           saveRestore                                     ; Restore interrupts and translation
 304
 305/*
 306 * *****************************
 307 * * s a v e _ g e t _ i n i t *
 308 * *****************************
 309 *
 310 *      addr64_t  save_get_init(void);
 311 *
 312 *                      Note that save_get_init is used in initial processor startup only.  It
 313 *                      is used because translation is on, but no tables exist yet and we have
 314 *                      no V=R BAT registers that cover the entire physical memory.
 315 */
 316                        .align  5
 317                        .globl  EXT(save_get_init)
 318
 319LEXT(save_get_init)
 320            mflr        r9                                                      ; get return address
 321            bl          saveSetup                                       ; turn translation off, 64-bit on, load many regs
 322            bfl--       pf64Bitb,saveGet32                      ; Get r3 <- savearea, r5 <- page address (with SAC)
 323            btl++       pf64Bitb,saveGet64                      ; get one on a 64-bit machine
 324            bl          saveRestore                                     ; restore translation etc
 325            mtlr        r9
 326            
 327            ; unpack the physaddr in r3 into a long long in (r3,r4)
 328            
 329            mr          r4,r3                                           ; copy low word of phys address to r4
 330            li          r3,0                                            ; assume upper word was 0
 331            bflr--      pf64Bitb                                        ; if 32-bit processor, return
 332            srdi        r3,r4,32                                        ; unpack reg64_t to addr64_t on 64-bit machine
 333            rlwinm      r4,r4,0,0,31
 334            blr
 335            
 336
 337/*
 338 * *******************
 339 * * s a v e _ g e t *
 340 * *******************
 341 *
 342 *      savearea *save_get(void);
 343 *
 344 *                      Allocate a savearea, returning a virtual address.  NOTE: we must preserve
 345 *                      r0, r2, and r12.  Our callers in cswtch.s depend on this.
 346 */
 347                        .align  5
 348                        .globl  EXT(save_get)
 349
 350LEXT(save_get)
 351            mflr        r9                                                      ; get return address
 352            mr          r5,r0                                           ; copy regs before saveSetup nails them
 353            bl          saveSetup                                       ; turn translation off, 64-bit on, load many regs
 354            bf--        pf64Bitb,svgt1                          ; skip if 32-bit processor
 355            
 356            std         r5,tempr0(r10)                          ; save r0 in per-proc across call to saveGet64
 357            std         r2,tempr2(r10)                          ; and r2
 358            std         r12,tempr4(r10)                         ; and r12
 359            bl          saveGet64                                       ; get r3 <- savearea, r5 <- page address (with SAC)
 360            ld          r0,tempr0(r10)                          ; restore callers regs
 361            ld          r2,tempr2(r10)
 362            ld          r12,tempr4(r10)
 363            b           svgt2
 364            
 365svgt1:                                                                                  ; handle 32-bit processor
 366            stw         r5,tempr0+4(r10)                        ; save r0 in per-proc across call to saveGet32
 367            stw         r2,tempr2+4(r10)                        ; and r2
 368            stw         r12,tempr4+4(r10)                       ; and r12
 369            bl          saveGet32                                       ; get r3 <- savearea, r5 <- page address (with SAC)
 370            lwz         r0,tempr0+4(r10)                        ; restore callers regs
 371            lwz         r2,tempr2+4(r10)
 372            lwz         r12,tempr4+4(r10)
 373            
 374svgt2:
 375                        lwz             r5,SACvrswap+4(r5)                      ; Get the virtual to real translation (only need low word)
 376            mtlr        r9                                                      ; restore return address
 377            xor         r3,r3,r5                                        ; convert physaddr to virtual
 378            rlwinm      r3,r3,0,0,31                            ; 0 upper word if a 64-bit machine
 379
 380#if FPVECDBG
 381            mr          r6,r0                                           ; (TEST/DEBUG)
 382            mr          r7,r2                                           ; (TEST/DEBUG)
 383                        mfsprg  r2,1                                            ; (TEST/DEBUG)
 384                        mr.             r2,r2                                           ; (TEST/DEBUG)
 385                        beq--   svgDBBypass                                     ; (TEST/DEBUG)
 386                        lis             r0,HIGH_ADDR(CutTrace)          ; (TEST/DEBUG)
 387                        li              r2,0x2203                                       ; (TEST/DEBUG)
 388                        oris    r0,r0,LOW_ADDR(CutTrace)        ; (TEST/DEBUG)
 389                        sc                                                                      ; (TEST/DEBUG) 
 390svgDBBypass:                                                                    ; (TEST/DEBUG)
 391            mr          r0,r6                                           ; (TEST/DEBUG)
 392            mr          r2,r7                                           ; (TEST/DEBUG) 
 393#endif                  
 394            b           saveRestore                                     ; restore MSR and return to our caller
 395            
 396            
 397/*
 398 * ***********************************
 399 * * s a v e _ g e t _ p h y s _ 3 2 *
 400 * ***********************************
 401 *
 402 *      reg64_t save_get_phys(void);
 403 *
 404 *                      This is the entry normally called from lowmem_vectors.s with
 405 *                      translation and interrupts already off.
 406 *                      MUST NOT TOUCH CR7
 407 */
 408                        .align  5
 409                        .globl  EXT(save_get_phys_32)
 410
 411LEXT(save_get_phys_32)
 412            mfsprg      r10,0                                           ; get the per-proc ptr
 413                        b               saveGet32                                       ; Get r3 <- savearea, r5 <- page address (with SAC)
 414
 415
 416/*
 417 * ***********************************
 418 * * s a v e _ g e t _ p h y s _ 6 4 *
 419 * ***********************************
 420 *
 421 *      reg64_t save_get_phys_64(void);
 422 *
 423 *                      This is the entry normally called from lowmem_vectors.s with
 424 *                      translation and interrupts already off, and in 64-bit mode.
 425 *                      MUST NOT TOUCH CR7
 426 */
 427                        .align  5
 428                        .globl  EXT(save_get_phys_64)
 429
 430LEXT(save_get_phys_64)
 431            mfsprg      r10,0                                           ; get the per-proc ptr
 432                        b               saveGet64                                       ; Get r3 <- savearea, r5 <- page address (with SAC)
 433            
 434
 435/*
 436 * *********************
 437 * * s a v e G e t 6 4 *
 438 * *********************
 439 *
 440 *                      This is the internal routine to allocate a savearea on a 64-bit processor.  
 441 *                      Note that we must not take any exceptions of any kind, including PTE misses, as that
 442 *                      would deadlock trying to reenter this routine.  We pass back the 64-bit physical address.
 443 *                      First we try the local list.  If that is below a threshold, we try the global free list,
 444 *                      which requires taking a lock, and replenish.  If there are no saveareas in either list,
 445 *                      we will install the  backpocket and choke.  This routine assumes that the caller has
 446 *                      turned translation off, masked interrupts,  turned on 64-bit mode, and set up:
 447 *                              r10 = per-proc ptr
 448 *
 449 *                      We return:
 450 *                              r3 = 64-bit physical address of the savearea
 451 *                              r5 = 64-bit physical address of the page the savearea is in, with SAC
 452 *
 453 *                      We destroy:
 454 *                              r2-r8.
 455 *              
 456 *                      MUST NOT TOUCH CR7
 457 */
 458
 459saveGet64:            
 460                        lwz             r8,lclfreecnt(r10)                      ; Get the count
 461                        ld              r3,lclfree(r10)                         ; Get the start of local savearea list
 462                        cmplwi  r8,LocalSaveMin                         ; Are we too low?
 463                        ble--   saveGet64GetGlobal                      ; We are too low and need to grow list...
 464
 465            ; Get it from the per-processor local list.
 466            
 467saveGet64GetLocal:
 468            li          r2,0x5555                                       ; get r2 <-- 0x55555555 55555555, our bugbug constant
 469                        ld              r4,SAVprev(r3)                          ; Chain to the next one
 470                        oris    r2,r2,0x5555
 471                        subi    r8,r8,1                                         ; Back down count
 472            rldimi      r2,r2,32,0
 473
 474                        std             r2,SAVprev(r3)                          ; bug next ptr
 475                        stw             r2,SAVlevel(r3)                         ; bug context ID
 476            li          r6,0
 477                        std             r4,lclfree(r10)                         ; Unchain first savearea
 478                        stw             r2,SAVact(r3)                           ; bug activation ptr
 479                        rldicr  r5,r3,0,51                                      ; r5 <-- page ptr, where SAC is kept
 480                        stw             r8,lclfreecnt(r10)                      ; Set new count
 481                        stw             r6,SAVflags(r3)                         ; clear the flags
 482
 483            blr
 484
 485            ; Local list was low so replenish from global list.
 486            ;    r7 = return address to caller of saveGet64
 487            ;    r8 = lclfreecnt
 488            ;   r10 = per-proc ptr
 489            
 490saveGet64GetGlobal:
 491            mflr        r7                                                      ; save return adress
 492                        subfic  r5,r8,LocalSaveTarget           ; Get the number of saveareas we need to grab to get to target
 493                        bl              savelock                                        ; Go lock up the anchor
 494                        
 495                        lwz             r2,SVfreecnt(0)                         ; Get the number on this list
 496                        ld              r8,SVfree(0)                            ; Get the head of the save area list 
 497                        
 498                        sub             r3,r2,r5                                        ; Get number left after we swipe enough for local list
 499                        sradi   r3,r3,63                                        ; Get 0 if enough or -1 if not
 500                        andc    r4,r5,r3                                        ; Get number to get if there are enough, 0 otherwise
 501                        and             r5,r2,r3                                        ; Get 0 if there are enough, number on list otherwise
 502                        or.             r5,r4,r5                                        ; r5 <- number we will move from global to local list
 503                        beq--   saveGet64NoFree                         ; There are none to get...
 504                        
 505                        mtctr   r5                                                      ; Get loop count
 506                        mr              r6,r8                                           ; Remember the first in the list
 507
 508saveGet64c:
 509            bdz         saveGet64d                                      ; Count down and branch when we hit 0...
 510                        ld              r8,SAVprev(r8)                          ; Get the next
 511                        b               saveGet64c                                      ; Keep going...
 512
 513saveGet64d:                     
 514            ld          r3,SAVprev(r8)                          ; Get the next one
 515                        lwz             r4,SVinuse(0)                           ; Get the in use count
 516                        sub             r2,r2,r5                                        ; Count down what we stole
 517                        std             r3,SVfree(0)                            ; Set the new first in list
 518                        add             r4,r4,r5                                        ; Count the ones we just put in the local list as "in use"
 519                        stw             r2,SVfreecnt(0)                         ; Set the new count
 520                        stw             r4,SVinuse(0)                           ; Set the new in use count
 521                        
 522                        ld              r4,lclfree(r10)                         ; Get the old head of list
 523                        lwz             r3,lclfreecnt(r10)                      ; Get the old count
 524                        std             r6,lclfree(r10)                         ; Set the new head of the list
 525                        add             r3,r3,r5                                        ; Get the new count
 526                        std             r4,SAVprev(r8)                          ; Point to the old head
 527                        stw             r3,lclfreecnt(r10)                      ; Set the new count
 528
 529                        bl              saveunlock                                      ; Update the adjust field and unlock
 530            mtlr        r7                                                      ; restore return address
 531                        b               saveGet64                                       ; Start over and finally allocate the savearea...
 532                        
 533            ; The local list is below the repopulate threshold and the global list is empty.
 534            ; First we check if there are any left in the local list and if so, we allow
 535            ; them to be allocated.  If not, we release the backpocket list and choke.  
 536            ; There is nothing more that we can do at this point.  Hopefully we stay alive
 537            ; long enough to grab some much-needed panic information.
 538            ;    r7 = return address to caller of saveGet64 
 539            ;   r10 = per-proc ptr
 540
 541saveGet64NoFree:                        
 542                        lwz             r8,lclfreecnt(r10)                      ; Get the count
 543                        mr.             r8,r8                                           ; Are there any reserve to get?
 544                        beq--   saveGet64Choke                          ; No, go choke and die...
 545                        bl              saveunlock                                      ; Update the adjust field and unlock
 546                        ld              r3,lclfree(r10)                         ; Get the start of local savearea list
 547                        lwz             r8,lclfreecnt(r10)                      ; Get the count
 548            mtlr        r7                                                      ; restore return address
 549                        b               saveGet64GetLocal                       ; We have some left, dip on in...
 550                        
 551;                       We who are about to die salute you.  The savearea chain is messed up or
 552;                       empty.  Add in a few so we have enough to take down the system.
 553
 554saveGet64Choke:
 555            lis         r9,hi16(EXT(backpocket))        ; Get high order of back pocket
 556                        ori             r9,r9,lo16(EXT(backpocket))     ; and low part
 557                        
 558                        lwz             r8,SVfreecnt-saveanchor(r9)     ; Get the new number of free elements
 559                        ld              r7,SVfree-saveanchor(r9)        ; Get the head of the chain
 560                        lwz             r6,SVinuse(0)                           ; Get total in the old list
 561
 562                        stw             r8,SVfreecnt(0)                         ; Set the new number of free elements
 563                        add             r6,r6,r8                                        ; Add in the new ones
 564                        std             r7,SVfree(0)                            ; Set the new head of the chain
 565                        stw             r6,SVinuse(0)                           ; Set total in the new list
 566
 567saveGetChokeJoin:                                                               ; join in the fun from 32-bit mode
 568                        lis             r0,hi16(Choke)                          ; Set choke firmware call
 569                        li              r7,0                                            ; Get a clear register to unlock
 570                        ori             r0,r0,lo16(Choke)                       ; Set the rest of the choke call
 571                        li              r3,failNoSavearea                       ; Set failure code
 572
 573                        eieio                                                           ; Make sure all is committed
 574                        stw             r7,SVlock(0)                            ; Unlock the free list
 575                        sc                                                                      ; System ABEND
 576
 577
 578/*
 579 * *********************
 580 * * s a v e G e t 3 2 *
 581 * *********************
 582 *
 583 *                      This is the internal routine to allocate a savearea on a 32-bit processor.  
 584 *                      Note that we must not take any exceptions of any kind, including PTE misses, as that
 585 *                      would deadlock trying to reenter this routine.  We pass back the 32-bit physical address.
 586 *                      First we try the local list.  If that is below a threshold, we try the global free list,
 587 *                      which requires taking a lock, and replenish.  If there are no saveareas in either list,
 588 *                      we will install the  backpocket and choke.  This routine assumes that the caller has
 589 *                      turned translation off, masked interrupts, and set up:
 590 *                              r10 = per-proc ptr
 591 *
 592 *                      We return:
 593 *                              r3 = 32-bit physical address of the savearea
 594 *                              r5 = 32-bit physical address of the page the savearea is in, with SAC
 595 *
 596 *                      We destroy:
 597 *                              r2-r8.
 598 */
 599
 600saveGet32:            
 601                        lwz             r8,lclfreecnt(r10)                      ; Get the count
 602                        lwz             r3,lclfree+4(r10)                       ; Get the start of local savearea list
 603                        cmplwi  r8,LocalSaveMin                         ; Are we too low?
 604                        ble-    saveGet32GetGlobal                      ; We are too low and need to grow list...
 605
 606            ; Get savearea from per-processor local list.
 607            
 608saveGet32GetLocal:
 609            li          r2,0x5555                                       ; get r2 <-- 0x55555555, our bugbug constant
 610                        lwz             r4,SAVprev+4(r3)                        ; Chain to the next one
 611                        oris    r2,r2,0x5555
 612                        subi    r8,r8,1                                         ; Back down count
 613
 614                        stw             r2,SAVprev+4(r3)                        ; bug next ptr
 615                        stw             r2,SAVlevel(r3)                         ; bug context ID
 616            li          r6,0
 617                        stw             r4,lclfree+4(r10)                       ; Unchain first savearea
 618                        stw             r2,SAVact(r3)                           ; bug activation ptr
 619                        rlwinm  r5,r3,0,0,19                            ; r5 <-- page ptr, where SAC is kept
 620                        stw             r8,lclfreecnt(r10)                      ; Set new count
 621                        stw             r6,SAVflags(r3)                         ; clear the flags
 622
 623            blr
 624
 625            ; Local list was low so replenish from global list.
 626            ;    r7 = return address to caller of saveGet32
 627            ;    r8 = lclfreecnt
 628            ;   r10 = per-proc ptr
 629            
 630saveGet32GetGlobal:
 631            mflr        r7                                                      ; save return adress
 632                        subfic  r5,r8,LocalSaveTarget           ; Get the number of saveareas we need to grab to get to target
 633                        bl              savelock                                        ; Go lock up the anchor
 634                        
 635                        lwz             r2,SVfreecnt(0)                         ; Get the number on this list
 636                        lwz             r8,SVfree+4(0)                          ; Get the head of the save area list 
 637                        
 638                        sub             r3,r2,r5                                        ; Get number left after we swipe enough for local list
 639                        srawi   r3,r3,31                                        ; Get 0 if enough or -1 if not
 640                        andc    r4,r5,r3                                        ; Get number to get if there are enough, 0 otherwise
 641                        and             r5,r2,r3                                        ; Get 0 if there are enough, number on list otherwise
 642                        or.             r5,r4,r5                                        ; r5 <- number we will move from global to local list
 643                        beq-    saveGet32NoFree                         ; There are none to get...
 644                        
 645                        mtctr   r5                                                      ; Get loop count
 646                        mr              r6,r8                                           ; Remember the first in the list
 647
 648saveGet32c:
 649            bdz         saveGet32d                                      ; Count down and branch when we hit 0...
 650                        lwz             r8,SAVprev+4(r8)                        ; Get the next
 651                        b               saveGet32c                                      ; Keep going...
 652
 653saveGet32d:                     
 654            lwz         r3,SAVprev+4(r8)                        ; Get the next one
 655                        lwz             r4,SVinuse(0)                           ; Get the in use count
 656                        sub             r2,r2,r5                                        ; Count down what we stole
 657                        stw             r3,SVfree+4(0)                          ; Set the new first in list
 658                        add             r4,r4,r5                                        ; Count the ones we just put in the local list as "in use"
 659                        stw             r2,SVfreecnt(0)                         ; Set the new count
 660                        stw             r4,SVinuse(0)                           ; Set the new in use count
 661                        
 662                        lwz             r4,lclfree+4(r10)                       ; Get the old head of list
 663                        lwz             r3,lclfreecnt(r10)                      ; Get the old count
 664                        stw             r6,lclfree+4(r10)                       ; Set the new head of the list
 665                        add             r3,r3,r5                                        ; Get the new count
 666                        stw             r4,SAVprev+4(r8)                        ; Point to the old head
 667                        stw             r3,lclfreecnt(r10)                      ; Set the new count
 668
 669                        bl              saveunlock                                      ; Update the adjust field and unlock
 670            mtlr        r7                                                      ; restore return address
 671                        b               saveGet32                                       ; Start over and finally allocate the savearea...
 672                        
 673            ; The local list is below the repopulate threshold and the global list is empty.
 674            ; First we check if there are any left in the local list and if so, we allow
 675            ; them to be allocated.  If not, we release the backpocket list and choke.  
 676            ; There is nothing more that we can do at this point.  Hopefully we stay alive
 677            ; long enough to grab some much-needed panic information.
 678            ;    r7 = return address to caller of saveGet32
 679            ;   r10 = per-proc ptr
 680
 681saveGet32NoFree:                        
 682                        lwz             r8,lclfreecnt(r10)                      ; Get the count
 683                        mr.             r8,r8                                           ; Are there any reserve to get?
 684                        beq-    saveGet32Choke                          ; No, go choke and die...
 685                        bl              saveunlock                                      ; Update the adjust field and unlock
 686                        lwz             r3,lclfree+4(r10)                       ; Get the start of local savearea list
 687                        lwz             r8,lclfreecnt(r10)                      ; Get the count
 688            mtlr        r7                                                      ; restore return address
 689                        b               saveGet32GetLocal                       ; We have some left, dip on in...
 690                        
 691;                       We who are about to die salute you.  The savearea chain is messed up or
 692;                       empty.  Add in a few so we have enough to take down the system.
 693
 694saveGet32Choke:
 695            lis         r9,hi16(EXT(backpocket))        ; Get high order of back pocket
 696                        ori             r9,r9,lo16(EXT(backpocket))     ; and low part
 697                        
 698                        lwz             r8,SVfreecnt-saveanchor(r9)     ; Get the new number of free elements
 699                        lwz             r7,SVfree+4-saveanchor(r9)      ; Get the head of the chain
 700                        lwz             r6,SVinuse(0)                           ; Get total in the old list
 701
 702                        stw             r8,SVfreecnt(0)                         ; Set the new number of free elements
 703                        add             r6,r6,r8                                        ; Add in the new ones (why?)
 704                        stw             r7,SVfree+4(0)                          ; Set the new head of the chain
 705                        stw             r6,SVinuse(0)                           ; Set total in the new list
 706            
 707            b           saveGetChokeJoin
 708
 709
 710/*
 711 * *******************
 712 * * s a v e _ r e t *
 713 * *******************
 714 *
 715 *      void    save_ret(struct savearea *);                            // normal call
 716 *      void    save_ret_wMSR(struct savearea *,reg64_t);       // passes MSR to restore as 2nd arg
 717 *
 718 *                      Return a savearea passed by virtual address to the free list.
 719 *                      Note really well: we can take NO exceptions of any kind,
 720 *                      including a PTE miss once the savearea lock is held. That's
 721 *                      a guaranteed deadlock.  That means we must disable for interrutions
 722 *                      and turn all translation off.
 723 */
 724            .globl      EXT(save_ret_wMSR)                      ; alternate entry pt w MSR to restore in r4
 725            
 726LEXT(save_ret_wMSR)
 727            crset       31                                                      ; set flag for save_ret_wMSR
 728            b           svrt1                                           ; join common code
 729            
 730            .align      5
 731            .globl      EXT(save_ret)
 732            
 733LEXT(save_ret)
 734            crclr       31                                                      ; clear flag for save_ret_wMSR
 735svrt1:                                                                                  ; join from save_ret_wMSR
 736            mflr        r9                                                      ; get return address
 737            rlwinm      r7,r3,0,0,19                            ; get virtual address of SAC area at start of page
 738            mr          r8,r3                                           ; save virtual address
 739            lwz         r5,SACvrswap+0(r7)                      ; get 64-bit converter from V to R
 740            lwz         r6,SACvrswap+4(r7)                      ; both halves, though only bottom used on 32-bit machine
 741#if FPVECDBG
 742                        lis             r0,HIGH_ADDR(CutTrace)          ; (TEST/DEBUG)
 743                        li              r2,0x2204                                       ; (TEST/DEBUG)
 744                        oris    r0,r0,LOW_ADDR(CutTrace)        ; (TEST/DEBUG) 
 745                        sc                                                                      ; (TEST/DEBUG) 
 746#endif
 747            bl          saveSetup                                       ; turn translation off, 64-bit on, load many regs
 748            bf++        31,svrt3                                        ; skip if not save_ret_wMSR
 749            mr          r11,r4                                          ; was save_ret_wMSR, so overwrite saved MSR
 750svrt3:
 751            bf--        pf64Bitb,svrt4                          ; skip if a 32-bit processor
 752            
 753            ; Handle 64-bit processor.
 754            
 755            rldimi      r6,r5,32,0                                      ; merge upper and lower halves of SACvrswap together
 756            xor         r3,r8,r6                                        ; get r3 <- 64-bit physical address of this savearea
 757            bl          saveRet64                                       ; return it
 758            mtlr        r9                                                      ; restore return address
 759            b           saveRestore64                           ; restore MSR
 760            
 761            ; Handle 32-bit processor.
 762            
 763svrt4:
 764            xor         r3,r8,r6                                        ; get r3 <- 32-bit physical address of this savearea
 765            bl          saveRet32                                       ; return it
 766            mtlr        r9                                                      ; restore return address
 767            b           saveRestore32                           ; restore MSR
 768 
 769
 770/*
 771 * *****************************
 772 * * s a v e _ r e t _ p h y s *
 773 * *****************************
 774 *
 775 *      void    save_ret_phys(reg64_t);
 776 *
 777 *                      Called from lowmem vectors to return (ie, free) a savearea by physical address.
 778 *                      Translation and interrupts are already off, and 64-bit mode is set if defined.
 779 *                      We can take _no_ exceptions of any kind in this code, including PTE miss, since
 780 *                      that would result in a deadlock.  We expect:
 781 *                              r3 = phys addr of savearea
 782 *                         msr = IR, DR, and EE off, SF on
 783 *             cr6 = pf64Bit flag
 784 *                      We destroy:
 785 *                              r0,r2-r10.
 786 */
 787                        .align  5
 788                        .globl  EXT(save_ret_phys)
 789
 790LEXT(save_ret_phys)
 791            mfsprg      r10,0                                           ; get the per-proc ptr
 792            bf--        pf64Bitb,saveRet32                      ; handle 32-bit machine
 793            b           saveRet64                                       ; handle 64-bit machine
 794            
 795
 796/*
 797 * *********************
 798 * * s a v e R e t 6 4 *
 799 * *********************
 800 *
 801 *                      This is the internal routine to free a savearea, passed by 64-bit physical
 802 *                      address.  We assume that IR, DR, and EE are all off, that SF is on, and:
 803 *                              r3 = phys address of the savearea
 804 *                         r10 = per-proc ptr
 805 *                      We destroy:
 806 *                              r0,r2-r8.
 807 */
 808            .align      5
 809 saveRet64:
 810                        li              r0,SAVempty                                     ; Get marker for free savearea
 811                        lwz             r7,lclfreecnt(r10)                      ; Get the local count
 812                        ld              r6,lclfree(r10)                         ; Get the old local header
 813                        addi    r7,r7,1                                         ; Pop up the free count
 814                        std             r6,SAVprev(r3)                          ; Plant free chain pointer
 815                        cmplwi  r7,LocalSaveMax                         ; Has the list gotten too long?
 816                        stb             r0,SAVflags+2(r3)                       ; Mark savearea free
 817                        std             r3,lclfree(r10)                         ; Chain us on in
 818                        stw             r7,lclfreecnt(r10)                      ; Bump up the count
 819                        bltlr++                                                         ; List not too long, so done
 820                        
 821/*                      The local savearea chain has gotten too long.  Trim it down to the target.
 822 *                      Here's a tricky bit, and important:
 823 *
 824 *                      When we trim the list, we NEVER trim the very first one.  This is because that is
 825 *                      the very last one released and the exception exit code will release the savearea
 826 *                      BEFORE it is done using it. Wouldn't be too good if another processor started
 827 *                      using it, eh?  So for this case, we are safe so long as the savearea stays on
 828 *                      the local list.  (Note: the exit routine needs to do this because it is in the 
 829 *                      process of restoring all context and it needs to keep it until the last second.)
 830 */
 831
 832            mflr        r0                                                      ; save return to caller of saveRet64
 833                        mr              r2,r3                                           ; r2 <- 1st one on local list, which must not be trimmed
 834                        ld              r3,SAVprev(r3)                          ; Skip over the first
 835                        subi    r7,r7,LocalSaveTarget           ; Figure out how much to trim   
 836                        mr              r6,r3                                           ; r6 <- first one to trim
 837                        mr              r5,r7                                           ; Save the number we are trimming
 838                        
 839saveRet64a:
 840            addic.      r7,r7,-1                                        ; Any left to do?
 841                        ble--   saveRet64b                                      ; Nope...
 842                        ld              r3,SAVprev(r3)                          ; Skip to the next one
 843                        b               saveRet64a                                      ; Keep going...
 844                        
 845saveRet64b:                                                                             ; r3 <- last one to trim
 846                        ld              r7,SAVprev(r3)                          ; Point to the first one not to trim
 847                        li              r4,LocalSaveTarget                      ; Set the target count
 848                        std             r7,SAVprev(r2)                          ; Trim stuff leaving the one just released as first
 849                        stw             r4,lclfreecnt(r10)                      ; Set the current count
 850                        
 851                        bl              savelock                                        ; Lock up the anchor
 852                        
 853                        ld              r8,SVfree(0)                            ; Get the old head of the free list
 854                        lwz             r4,SVfreecnt(0)                         ; Get the number of free ones
 855                        lwz             r7,SVinuse(0)                           ; Get the number that are in use
 856                        std             r6,SVfree(0)                            ; Point to the first trimmed savearea
 857                        add             r4,r4,r5                                        ; Add number trimmed to free count
 858                        std             r8,SAVprev(r3)                          ; Chain the old head to the tail of the trimmed guys
 859                        sub             r7,r7,r5                                        ; Remove the trims from the in use count
 860                        stw             r4,SVfreecnt(0)                         ; Set new free count
 861                        stw             r7,SVinuse(0)                           ; Set new in use count
 862
 863                        mtlr    r0                                                      ; Restore the return to our caller
 864                        b               saveunlock                                      ; Set adjust count, unlock the saveanchor, and return
 865            
 866
 867/*
 868 * *********************
 869 * * s a v e R e t 3 2 *
 870 * *********************
 871 *
 872 *                      This is the internal routine to free a savearea, passed by 32-bit physical
 873 *                      address.  We assume that IR, DR, and EE are all off, and:
 874 *                              r3 = phys address of the savearea
 875 *                         r10 = per-proc ptr
 876 *                      We destroy:
 877 *                              r0,r2-r8.
 878 */
 879            .align      5
 880 saveRet32:
 881                        li              r0,SAVempty                                     ; Get marker for free savearea
 882                        lwz             r7,lclfreecnt(r10)                      ; Get the local count
 883                        lwz             r6,lclfree+4(r10)                       ; Get the old local header
 884                        addi    r7,r7,1                                         ; Pop up the free count
 885                        stw             r6,SAVprev+4(r3)                        ; Plant free chain pointer
 886                        cmplwi  r7,LocalSaveMax                         ; Has the list gotten too long?
 887                        stb             r0,SAVflags+2(r3)                       ; Mark savearea free
 888                        stw             r3,lclfree+4(r10)                       ; Chain us on in
 889                        stw             r7,lclfreecnt(r10)                      ; Bump up the count
 890                        bltlr+                                                          ; List not too long, so done
 891                        
 892/*                      The local savearea chain has gotten too long.  Trim it down to the target.
 893 *                      Here's a tricky bit, and important:
 894 *
 895 *                      When we trim the list, we NEVER trim the very first one.  This is because that is
 896 *                      the very last one released and the exception exit code will release the savearea
 897 *                      BEFORE it is done using it. Wouldn't be too good if another processor started
 898 *                      using it, eh?  So for this case, we are safe so long as the savearea stays on
 899 *                      the local list.  (Note: the exit routine needs to do this because it is in the 
 900 *                      process of restoring all context and it needs to keep it until the last second.)
 901 */
 902
 903            mflr        r0                                                      ; save return to caller of saveRet32
 904                        mr              r2,r3                                           ; r2 <- 1st one on local list, which must not be trimmed
 905                        lwz             r3,SAVprev+4(r3)                        ; Skip over the first
 906                        subi    r7,r7,LocalSaveTarget           ; Figure out how much to trim   
 907                        mr              r6,r3                                           ; r6 <- first one to trim
 908                        mr              r5,r7                                           ; Save the number we are trimming
 909                        
 910saveRet32a:
 911            addic.      r7,r7,-1                                        ; Any left to do?
 912                        ble-    saveRet32b                                      ; Nope...
 913                        lwz             r3,SAVprev+4(r3)                        ; Skip to the next one
 914                        b               saveRet32a                                      ; Keep going...
 915                        
 916saveRet32b:                                                                             ; r3 <- last one to trim
 917                        lwz             r7,SAVprev+4(r3)                        ; Point to the first one not to trim
 918                        li              r4,LocalSaveTarget                      ; Set the target count
 919                        stw             r7,SAVprev+4(r2)                        ; Trim stuff leaving the one just released as first
 920                        stw             r4,lclfreecnt(r10)                      ; Set the current count
 921                        
 922                        bl              savelock                                        ; Lock up the anchor
 923                        
 924                        lwz             r8,SVfree+4(0)                          ; Get the old head of the free list
 925                        lwz             r4,SVfreecnt(0)                         ; Get the number of free ones
 926                        lwz             r7,SVinuse(0)                           ; Get the number that are in use
 927                        stw             r6,SVfree+4(0)                          ; Point to the first trimmed savearea
 928                        add             r4,r4,r5                                        ; Add number trimmed to free count
 929                        stw             r8,SAVprev+4(r3)                        ; Chain the old head to the tail of the trimmed guys
 930                        sub             r7,r7,r5                                        ; Remove the trims from the in use count
 931                        stw             r4,SVfreecnt(0)                         ; Set new free count
 932                        stw             r7,SVinuse(0)                           ; Set new in use count
 933
 934                        mtlr    r0                                                      ; Restore the return to our caller
 935                        b               saveunlock                                      ; Set adjust count, unlock the saveanchor, and return
 936
 937
 938/*
 939 * *******************************
 940 * * s a v e _ t r i m _ f r e e *
 941 * *******************************
 942 *
 943 *      struct savearea_comm    *save_trim_free(void);
 944 *
 945 *                      Trim the free list down to the target count, ie by -(SVadjust) save areas.
 946 *                      It trims the list and, if a pool page was fully allocated, puts that page on 
 947 *                      the start of the pool list.
 948 *
 949 *                      If the savearea being released is the last on a pool page (i.e., all entries
 950 *                      are released), the page is dequeued from the pool and queued to any other 
 951 *                      found during this scan.  Note that this queue is maintained virtually.
 952 *
 953 *                      When the scan is done, the saveanchor lock is released and the list of
 954 *                      freed pool pages is returned to our caller.
 955 *
 956 *                      For latency sake we may want to revisit this code. If we are trimming a
 957 *                      large number of saveareas, we could be disabled and holding the savearea lock
 958 *                      for quite a while.  It may be that we want to break the trim down into parts.
 959 *                      Possibly trimming the free list, then individually pushing them into the free pool.
 960 *
 961 *                      This function expects to be called with translation on and a valid stack.
 962 *                      It uses the standard ABI, ie we destroy r2 and r3-r11, and return the ptr in r3.
 963 */
 964                        .align  5
 965                        .globl  EXT(save_trim_free)
 966
 967LEXT(save_trim_free)
 968
 969                        subi    r1,r1,(FM_ALIGN(16)+FM_SIZE)    ; Make space for 4 registers on stack
 970            mflr        r9                                                      ; save our return address
 971                        stw             r28,FM_SIZE+0(r1)                       ; Save R28
 972                        stw             r29,FM_SIZE+4(r1)                       ; Save R29
 973                        stw             r30,FM_SIZE+8(r1)                       ; Save R30
 974                        stw             r31,FM_SIZE+12(r1)                      ; Save R31
 975
 976            bl          saveSetup                                       ; turn off translation and interrupts, load many regs
 977            bl          savelock                                        ; Go lock up the anchor
 978
 979                        lwz             r8,SVadjust(0)                          ; How many do we need to clear out?
 980                        li              r3,0                                            ; Get a 0
 981                        neg.    r8,r8                                           ; Get the actual we need to toss (adjust is neg if too many)
 982            ble-        save_trim_free1                         ; skip if no trimming needed anymore
 983            bf--        pf64Bitb,saveTrim32                     ; handle 32-bit processors
 984            b           saveTrim64                                      ; handle 64-bit processors
 985
 986save_trim_free1:                                                                ; by the time we were called, no need to trim anymore                   
 987                        stw             r3,SVlock(0)                            ; Quick unlock (no need for sync or to set adjust, nothing changed)
 988                        mtlr    r9                                                      ; Restore return
 989        
 990#if FPVECDBG
 991                        lis             r0,HIGH_ADDR(CutTrace)          ; (TEST/DEBUG)
 992                        li              r2,0x2206                                       ; (TEST/DEBUG)
 993                        oris    r0,r0,LOW_ADDR(CutTrace)        ; (TEST/DEBUG) 
 994                        sc                                                                      ; (TEST/DEBUG) 
 995#endif
 996                        addi    r1,r1,(FM_ALIGN(16)+FM_SIZE); Pop stack - have not trashed register so no need to reload
 997                        b               saveRestore                                     ; restore translation and EE, turn SF off, return to our caller
 998
 999
1000/*
1001 * ***********************
1002 * * s a v e T r i m 3 2 *
1003 * ***********************
1004 *
1005 *      Handle "save_trim_free" on 32-bit processors.  At this point, translation and interrupts
1006 *  are off, the savearea anchor is locked, and:
1007 *               r8 = #pages to trim (>0)
1008 *           r9 = return address
1009 *              r10 = per-proc ptr
1010 *              r11 = MSR at entry
1011 */
1012
1013saveTrim32:     
1014                        lwz             r7,SVfree+4(0)                          ; Get the first on the free list
1015            mr          r6,r7                                           ; Save the first one 
1016                        mr              r5,r8                                           ; Save the number we are trimming
1017                        
1018sttrimming:     addic.  r5,r5,-1                                        ; Any left to do?
1019                        ble-    sttrimmed                                       ; Nope...
1020                        lwz             r7,SAVprev+4(r7)                        ; Skip to the next one
1021                        b               sttrimming                                      ; Keep going...
1022
1023sttrimmed:      lwz             r5,SAVprev+4(r7)                        ; Get the next one (for new head of free list)
1024                        lwz             r4,SVfreecnt(0)                         ; Get the free count
1025                        stw             r5,SVfree+4(0)                          ; Set new head
1026                        sub             r4,r4,r8                                        ; Calculate the new free count
1027                        li              r31,0                                           ; Show we have no free pool blocks yet
1028                        crclr   cr1_eq                                          ; dont exit loop before 1st iteration
1029                        stw             r4,SVfreecnt(0)                         ; Set new free count
1030                        lis             r30,hi16(sac_empty)                     ; Get what empty looks like
1031                        
1032;                       NOTE: The savearea size must be 640 (0x280).  We are doing a divide by shifts and stuff
1033;                       here.
1034;
1035#if SAVsize != 640
1036#error Savearea size is not 640!!!!!!!!!!!!
1037#endif
1038
1039            ; Loop over each savearea we are trimming.
1040            ;    r6 = next savearea to trim
1041            ;    r7 = last savearea to trim
1042            ;    r8 = #pages to trim (>0)
1043            ;    r9 = return address
1044            ;   r10 = per-proc ptr
1045            ;   r11 = MSR at entry
1046            ;   r30 = what SACalloc looks like when all saveareas are free
1047            ;   r31 = free pool block list
1048            ;   cr1 = beq set if we just trimmed the last, ie if we are done
1049
1050sttoss:         beq+    cr1,stdone                                      ; All done now...
1051
1052                        cmplw   cr1,r6,r7                                       ; Have we finished the loop?
1053
1054                        lis             r0,0x0044                                       ; Get top of table      
1055                        rlwinm  r2,r6,0,0,19                            ; Back down to the savearea control stuff
1056                        ori             r0,r0,0x2200                            ; Finish shift table
1057                        rlwinm  r4,r6,25,27,30                          ; Get (addr >> 7) & 0x1E (same as twice high nybble)
1058                        lwz             r5,SACalloc(r2)                         ; Get the allocation bits
1059                        addi    r4,r4,1                                         ; Shift 1 extra
1060                        rlwinm  r3,r6,25,31,31                          ; Get (addr >> 7) & 1
1061                        rlwnm   r0,r0,r4,29,31                          ; Get partial index
1062                        lis             r4,lo16(0x8000)                         ; Get the bit mask
1063                        add             r0,r0,r3                                        ; Make the real index
1064                        srw             r4,r4,r0                                        ; Get the allocation mask
1065                        or              r5,r5,r4                                        ; Free this entry
1066                        cmplw   r5,r4                                           ; Is this the only free entry?
1067                        lwz             r6,SAVprev+4(r6)                        ; Chain to the next trimmed savearea
1068                        cmplw   cr7,r30,r5                                      ; Does this look empty?
1069                        stw             r5,SACalloc(r2)                         ; Save back the allocation bits
1070                        beq-    stputpool                                       ; First free entry, go put it into the pool...
1071                        bne+    cr7,sttoss                                      ; Not an empty block
1072                        
1073;
1074;                       We have an empty block.  Remove it from the pool list.
1075;
1076                        
1077                        lwz             r29,SACflags(r2)                        ; Get the flags
1078                        cmplwi  cr5,r31,0                                       ; Is this guy on the release list?
1079                        lwz             r28,SACnext+4(r2)                       ; Get the forward chain
1080
1081                        rlwinm. r0,r29,0,sac_permb,sac_permb    ; Is this a permanently allocated area? (also sets 0 needed below)
1082                        bne-    sttoss                                          ; This is permanent entry, do not try to release...
1083
1084                        lwz             r29,SACprev+4(r2)                       ; and the previous
1085                        beq-    cr5,stnot1st                            ; Not first
1086                        lwz             r0,SACvrswap+4(r31)                     ; Load the previous pool page vr conversion
1087                        
1088stnot1st:       stw             r28,SACnext+4(r29)                      ; Previous guy points to my next
1089                        xor             r0,r0,r31                                       ; Make the last guy virtual
1090                        stw             r29,SACprev+4(r28)                      ; Next guy points back to my previous                   
1091                        stw             r0,SAVprev+4(r2)                        ; Store the old top virtual as my back chain
1092                        mr              r31,r2                                          ; My physical is now the head of the chain
1093                        b               sttoss                                          ; Get the next one...
1094                        
1095;
1096;                       A pool block that had no free entries now has one.  Stick it on the pool list.
1097;
1098                        
1099stputpool:      lwz             r28,SVpoolfwd+4(0)                      ; Get the first guy on the list
1100                        li              r0,saveanchor                           ; Point to the saveanchor
1101                        stw             r2,SVpoolfwd+4(0)                       ; Put us on the top of the list
1102                        stw             r28,SACnext+4(r2)                       ; We point to the old top
1103                        stw             r2,SACprev+4(r28)                       ; Old top guy points back to us
1104                        stw             r0,SACprev+4(r2)                        ; Our back points to the anchor
1105                        b               sttoss                                          ; Go on to the next one...
1106
1107
1108/*
1109 * ***********************
1110 * * s a v e T r i m 6 4 *
1111 * ***********************
1112 *
1113 *      Handle "save_trim_free" on 64-bit processors.  At this point, translation and interrupts
1114 *  are off, SF is on, the savearea anchor is locked, and:
1115 *               r8 = #pages to trim (>0)
1116 *           r9 = return address
1117 *              r10 = per-proc ptr
1118 *              r11 = MSR at entry
1119 */
1120
1121saveTrim64:     
1122                        ld              r7,SVfree(0)                            ; Get the first on the free list
1123            mr          r6,r7                                           ; Save the first one 
1124                        mr              r5,r8                                           ; Save the number we are trimming
1125                        
1126sttrimming64:   
1127            addic.      r5,r5,-1                                        ; Any left to do?
1128                        ble--   sttrimmed64                                     ; Nope...
1129                        ld              r7,SAVprev(r7)                          ; Skip to the next one
1130                        b               sttrimming64                            ; Keep going...
1131
1132sttrimmed64:
1133            ld          r5,SAVprev(r7)                          ; Get the next one (for new head of free list)
1134                        lwz             r4,SVfreecnt(0)                         ; Get the free count
1135                        std             r5,SVfree(0)                            ; Set new head
1136                        sub             r4,r4,r8                                        ; Calculate the new free count
1137                        li              r31,0                                           ; Show we have no free pool blocks yet
1138                        crclr   cr1_eq                                          ; dont exit loop before 1st iteration
1139                        stw             r4,SVfreecnt(0)                         ; Set new free count
1140                        lis             r30,hi16(sac_empty)                     ; Get what empty looks like
1141                        
1142
1143            ; Loop over each savearea we are trimming.
1144            ;    r6 = next savearea to trim
1145            ;    r7 = last savearea to trim
1146            ;    r8 = #pages to trim (>0)
1147            ;    r9 = return address
1148            ;   r10 = per-proc ptr
1149            ;   r11 = MSR at entry
1150            ;   r30 = what SACalloc looks like when all saveareas are free
1151            ;   r31 = free pool block list
1152            ;   cr1 = beq set if we just trimmed the last, ie if we are done
1153            ;
1154            ; WARNING: as in the 32-bit path, this code is doing a divide by 640 (SAVsize).
1155
1156sttoss64:
1157            beq++       cr1,stdone                                      ; All done now...
1158
1159                        cmpld   cr1,r6,r7                                       ; Have we finished the loop?
1160
1161                        lis             r0,0x0044                                       ; Get top of table      
1162                        rldicr  r2,r6,0,51                                      ; r2 <- phys addr of savearea block (with control area)
1163                        ori             r0,r0,0x2200                            ; Finish shift table
1164                        rlwinm  r4,r6,25,27,30                          ; Get (addr >> 7) & 0x1E (same as twice high nybble)
1165                        lwz             r5,SACalloc(r2)                         ; Get the allocation bits
1166                        addi    r4,r4,1                                         ; Shift 1 extra
1167                        rlwinm  r3,r6,25,31,31                          ; Get (addr >> 7) & 1
1168                        rlwnm   r0,r0,r4,29,31                          ; Get partial index
1169                        lis             r4,lo16(0x8000)                         ; Get the bit mask
1170                        add             r0,r0,r3                                        ; Make the real index
1171                        srw             r4,r4,r0                                        ; Get the allocation mask
1172                        or              r5,r5,r4                                        ; Free this entry
1173                        cmplw   r5,r4                                           ; Is this the only free entry?
1174                        ld              r6,SAVprev(r6)                          ; Chain to the next trimmed savearea
1175                        cmplw   cr7,r30,r5                                      ; Does this look empty?
1176                        stw             r5,SACalloc(r2)                         ; Save back the allocation bits
1177                        beq--   stputpool64                                     ; First free entry, go put it into the pool...
1178                        bne++   cr7,sttoss64                            ; Not an empty block
1179                        
1180;                       We have an empty block.  Remove it from the pool list.
1181                        
1182                        lwz             r29,SACflags(r2)                        ; Get the flags
1183                        cmpldi  cr5,r31,0                                       ; Is this guy on the release list?
1184                        ld              r28,SACnext(r2)                         ; Get the forward chain
1185
1186                        rlwinm. r0,r29,0,sac_permb,sac_permb    ; Is this a permanently allocated area? (also sets 0 needed below)
1187                        bne--   sttoss64                                        ; This is permanent entry, do not try to release...
1188
1189                        ld              r29,SACprev(r2)                         ; and the previous
1190                        beq--   cr5,stnot1st64                          ; Not first
1191                        ld              r0,SACvrswap(r31)                       ; Load the previous pool page vr conversion
1192                        
1193stnot1st64:     
1194            std         r28,SACnext(r29)                        ; Previous guy points to my next
1195                        xor             r0,r0,r31                                       ; Make the last guy virtual
1196                        std             r29,SACprev(r28)                        ; Next guy points back to my previous                   
1197                        std             r0,SAVprev(r2)                          ; Store the old top virtual as my back chain
1198                        mr              r31,r2                                          ; My physical is now the head of the chain
1199                        b               sttoss64                                        ; Get the next one...
1200                        
1201;                       A pool block that had no free entries now has one.  Stick it on the pool list.
1202                        
1203stputpool64:
1204            ld          r28,SVpoolfwd(0)                        ; Get the first guy on the list
1205                        li              r0,saveanchor                           ; Point to the saveanchor
1206                        std             r2,SVpoolfwd(0)                         ; Put us on the top of the list
1207                        std             r28,SACnext(r2)                         ; We point to the old top
1208                        std             r2,SACprev(r28)                         ; Old top guy points back to us
1209                        std             r0,SACprev(r2)                          ; Our back points to the anchor
1210                        b               sttoss64                                        ; Go on to the next one...
1211                        
1212
1213;                       We are all done.  Relocate pool release head, restore all, and go.  This code
1214;                       is used both by the 32 and 64-bit paths.
1215;                                r9 = return address
1216;                               r10 = per-proc ptr
1217;                               r11 = MSR at entry
1218;                               r31 = free pool block list
1219
1220stdone:         bl              saveunlock                                      ; Unlock the saveanchor and set adjust field
1221
1222                        mr.             r3,r31                                          ; Move release chain and see if there are any
1223                        li              r5,0                                            ; Assume either V=R or no release chain
1224                        beq-    stnorel                                         ; Nothing to release...
1225                        lwz             r5,SACvrswap+4(r31)                     ; Get the vr conversion (only need low half if 64-bit)
1226
1227stnorel:        
1228            bl          saveRestore                                     ; restore translation and exceptions, turn off SF
1229                        mtlr    r9                                                      ; Restore the return
1230                        
1231                        lwz             r28,FM_SIZE+0(r1)                       ; Restore R28
1232                        lwz             r29,FM_SIZE+4(r1)                       ; Restore R29
1233                        lwz             r30,FM_SIZE+8(r1)                       ; Restore R30
1234                        lwz             r31,FM_SIZE+12(r1)                      ; Restore R31
1235                        addi    r1,r1,(FM_ALIGN(16)+FM_SIZE)    ; Pop the stack
1236                        xor             r3,r3,r5                                        ; Convert release chain address to virtual
1237            rlwinm      r3,r3,0,0,31                            ; if 64-bit, clear upper half of virtual address
1238                                                        
1239#if FPVECDBG
1240                        lis             r0,HIGH_ADDR(CutTrace)          ; (TEST/DEBUG)
1241                        li              r2,0x2207                                       ; (TEST/DEBUG)
1242                        oris    r0,r0,LOW_ADDR(CutTrace)        ; (TEST/DEBUG) 
1243                        sc                                                                      ; (TEST/DEBUG) 
1244#endif
1245                        blr                                                                     ; Return...
1246            
1247            
1248/*
1249 * ***************************
1250 * * s a v e _ r e c o v e r *
1251 * ***************************
1252 *
1253 *      int save_recover(void);
1254 *
1255 *      Returns nonzero if we can get enough saveareas to hit the target.  We scan the free
1256 *      pool.  If we empty a pool block, we remove it from the pool list.
1257 */                     
1258                        
1259                        .align  5
1260                        .globl  EXT(save_recover)
1261
1262LEXT(save_recover)
1263            mflr        r9                                                      ; save return address
1264            bl          saveSetup                                       ; turn translation and interrupts off, SF on, load many regs
1265            bl          savelock                                        ; lock the savearea anchor
1266
1267                        lwz             r8,SVadjust(0)                          ; How many do we need to clear get?
1268                        li              r3,0                                            ; Get a 0
1269                        mr.             r8,r8                                           ; Do we need any?
1270            ble--       save_recover1                           ; not any more
1271            bf--        pf64Bitb,saveRecover32          ; handle 32-bit processor
1272            b           saveRecover64                           ; handle 64-bit processor
1273            
1274save_recover1:                                                                  ; by the time we locked the anchor, no longer short
1275                        mtlr    r9                                                      ; Restore return
1276                        stw             r3,SVlock(0)                            ; Quick unlock (no need for sync or to set adjust, nothing changed)
1277#if FPVECDBG
1278                        lis             r0,HIGH_ADDR(CutTrace)          ; (TEST/DEBUG)
1279                        li              r2,0x2208                                       ; (TEST/DEBUG)
1280                        oris    r0,r0,LOW_ADDR(CutTrace)        ; (TEST/DEBUG) 
1281                        sc                                                                      ; (TEST/DEBUG) 
1282#endif
1283                        b               saveRestore                                     ; turn translation etc back on, return to our caller
1284
1285
1286/*
1287 * *****************************
1288 * * s a v e R e c o v e r 3 2 *
1289 * *****************************
1290 *
1291 *      Handle "save_recover" on 32-bit processors.  At this point, translation and interrupts
1292 *  are off, the savearea anchor is locked, and:
1293 *               r8 = #pages to recover
1294 *           r9 = return address
1295 *              r10 = per-proc ptr
1296 *              r11 = MSR at entry
1297 */
1298
1299saveRecover32:
1300                        li              r6,saveanchor                           ; Start at pool anchor
1301                        crclr   cr1_eq                                          ; initialize the loop test                                      
1302                        lwz             r7,SVfreecnt(0)                         ; Get the current free count
1303
1304
1305; Loop over next block in free pool.  r6 is the ptr to the last block we looked at.
1306
1307srcnpool:       lwz             r6,SACnext+4(r6)                        ; Point to the next one
1308                        cmplwi  r6,saveanchor                           ; Have we wrapped?
1309                        beq-    srcdone                                         ; Yes, did not have enough...
1310                        
1311                        lwz             r5,SACalloc(r6)                         ; Pick up the allocation for this pool block
1312                        
1313;
1314;                       NOTE: The savearea size must be 640 (0x280).  We are doing a multiply by shifts and add.
1315;                       offset = (index << 9) + (index << 7)
1316;
1317#if SAVsize != 640
1318#error Savearea size is not 640!!!!!!!!!!!!
1319#endif
1320
1321; Loop over free savearea in current block.
1322;                r5 = bitmap of free saveareas in block at r6 (ie, SACalloc)
1323;                r6 = ptr to current free pool block
1324;                r7 = free count
1325;                r8 = #pages more we still need to recover
1326;            r9 = return address
1327;               r10 = per-proc ptr
1328;               r11 = MSR at entry
1329;               cr1 = beq if (r8==0)
1330
1331srcnext:        beq-    cr1,srcdone                                     ; We have no more to get...
1332
1333                        lis             r3,0x8000                                       ; Get the top bit on
1334                        cntlzw  r4,r5                                           ; Find a free slot
1335                        addi    r7,r7,1                                         ; Bump up the free count
1336                        srw             r3,r3,r4                                        ; Make a mask
1337                        slwi    r0,r4,7                                         ; First multiply by 128
1338                        subi    r8,r8,1                                         ; Decrement the need count
1339                        slwi    r2,r4,9                                         ; Then multiply by 512
1340                        andc.   r5,r5,r3                                        ; Clear out the "free" bit
1341                        add             r2,r2,r0                                        ; Sum to multiply by 640        
1342                        
1343                        stw             r5,SACalloc(r6)                         ; Set new allocation bits
1344                        
1345                        add             r2,r2,r6                                        ; Get the actual address of the savearea
1346                        lwz             r3,SVfree+4(0)                          ; Get the head of the chain
1347                        cmplwi  cr1,r8,0                                        ; Do we actually need any more?
1348                        stw             r2,SVfree+4(0)                          ; Push ourselves in the front
1349                        stw             r3,SAVprev+4(r2)                        ; Chain the rest of the list behind 
1350                        
1351                        bne+    srcnext                                         ; The pool block is not empty yet, try for another...
1352                        
1353                        lwz             r2,SACnext+4(r6)                        ; Get the next pointer
1354                        lwz             r3,SACprev+4(r6)                        ; Get the previous pointer
1355                        stw             r3,SACprev+4(r2)                        ; The previous of my next points to my previous
1356                        stw             r2,SACnext+4(r3)                        ; The next of my previous points to my next
1357                        bne+    cr1,srcnpool                            ; We still have more to do...
1358
1359
1360; Join here from 64-bit path when we have recovered all the saveareas we need to.
1361
1362srcdone:        stw             r7,SVfreecnt(0)                         ; Set the new free count
1363                        bl              saveunlock                                      ; Unlock the save and set adjust field
1364
1365                        mtlr    r9                                                      ; Restore the return
1366#if FPVECDBG
1367                        lis             r0,HIGH_ADDR(CutTrace)          ; (TEST/DEBUG)
1368                        li              r2,0x2209                                       ; (TEST/DEBUG)
1369                        oris    r0,r0,LOW_ADDR(CutTrace)        ; (TEST/DEBUG) 
1370                        sc                                                                      ; (TEST/DEBUG) 
1371#endif
1372                        b               saveRestore                                     ; turn xlate and EE back on, SF off, and return to our caller
1373
1374
1375/*
1376 * *****************************
1377 * * s a v e R e c o v e r 6 4 *
1378 * *****************************
1379 *
1380 *      Handle "save_recover" on 64-bit processors.  At this point, translation and interrupts
1381 *  are off, the savearea anchor is locked, and:
1382 *               r8 = #pages to recover
1383 *           r9 = return address
1384 *              r10 = per-proc ptr
1385 *              r11 = MSR at entry
1386 */
1387
1388saveRecover64:
1389                        li              r6,saveanchor                           ; Start at pool anchor
1390                        crclr   cr1_eq                                          ; initialize the loop test                                      
1391                        lwz             r7,SVfreecnt(0)                         ; Get the current free count
1392
1393
1394; Loop over next block in free pool.  r6 is the ptr to the last block we looked at.
1395
1396srcnpool64:     
1397            ld          r6,SACnext(r6)                          ; Point to the next one
1398                        cmpldi  r6,saveanchor                           ; Have we wrapped?
1399                        beq--   srcdone                                         ; Yes, did not have enough...
1400                        
1401                        lwz             r5,SACalloc(r6)                         ; Pick up the allocation for this pool block
1402                        
1403
1404; Loop over free savearea in current block.
1405;                r5 = bitmap of free saveareas in block at r6 (ie, SACalloc)
1406;                r6 = ptr to current free pool block
1407;                r7 = free count
1408;                r8 = #pages more we still need to recover
1409;            r9 = return address
1410;               r10 = per-proc ptr
1411;               r11 = MSR at entry
1412;               cr1 = beq if (r8==0)
1413;
1414; WARNING: as in the 32-bit path, we depend on (SAVsize==640)
1415
1416srcnext64:      
1417            beq--       cr1,srcdone                                     ; We have no more to get...
1418
1419                        lis             r3,0x8000                                       ; Get the top bit on
1420                        cntlzw  r4,r5                                           ; Find a free slot
1421                        addi    r7,r7,1                                         ; Bump up the free count
1422                        srw             r3,r3,r4                                        ; Make a mask
1423                        slwi    r0,r4,7                                         ; First multiply by 128
1424                        subi    r8,r8,1                                         ; Decrement the need count
1425                        slwi    r2,r4,9                                         ; Then multiply by 512
1426                        andc.   r5,r5,r3                                        ; Clear out the "free" bit
1427                        add             r2,r2,r0                                        ; Sum to multiply by 640        
1428                        
1429                        stw             r5,SACalloc(r6)                         ; Set new allocation bits
1430                        
1431                        add             r2,r2,r6                                        ; Get the actual address of the savearea
1432                        ld              r3,SVfree(0)                            ; Get the head of the chain
1433                        cmplwi  cr1,r8,0                                        ; Do we actually need any more?
1434                        std             r2,SVfree(0)                            ; Push ourselves in the front
1435                        std             r3,SAVprev(r2)                          ; Chain the rest of the list behind 
1436                        
1437                        bne++   srcnext64                                       ; The pool block is not empty yet, try for another...
1438                        
1439                        ld              r2,SACnext(r6)                          ; Get the next pointer
1440                        ld              r3,SACprev(r6)                          ; Get the previous pointer
1441                        std             r3,SACprev(r2)                          ; The previous of my next points to my previous
1442                        std             r2,SACnext(r3)                          ; The next of my previous points to my next
1443                        bne++   cr1,srcnpool64                          ; We still have more to do...
1444            
1445            b           srcdone
1446
1447
1448/* 
1449 * *******************
1450 * * s a v e l o c k *
1451 * *******************
1452 *
1453 *                      Lock the savearea anchor, so we can manipulate the free list.
1454 *              msr = interrupts and translation off
1455 *                      We destroy:
1456 *                              r8, r3, r12
1457 */                     
1458                        .align  5
1459
1460savelock:       lwz             r8,SVlock(0)                            ; See if lock is held
1461            cmpwi       r8,0
1462                        li              r12,saveanchor                          ; Point to the saveanchor
1463                        bne--   savelock                                        ; loop until lock released...
1464                
1465savelock0:      lwarx   r8,0,r12                                        ; Grab the lock value 
1466                        cmpwi   r8,0                                            ; taken?
1467            li          r8,1                                            ; get nonzero to lock it with
1468                        bne--   savelock1                                       ; already locked, wait for it to clear...
1469                        stwcx.  r8,0,r12                                        ; Try to seize that there durn lock
1470            isync                                                               ; assume we got it
1471            beqlr++                                                             ; reservation not lost, so we have the lock
1472                        b               savelock0                                       ; Try again...
1473                        
1474savelock1:      li              r8,lgKillResv                           ; Point to killing field
1475                        stwcx.  r8,0,r8                                         ; Kill reservation
1476                        b               savelock                                        ; Start over....
1477                
1478
1479/*
1480 * ***********************
1481 * * s a v e u n l o c k *
1482 * ***********************
1483 *
1484 *
1485 *                      This is the common routine that sets the saveadjust field and unlocks the savearea 
1486 *                      anchor.
1487 *                              msr = interrupts and translation off
1488 *                      We destroy:
1489 *                              r2, r5, r6, r8.
1490 */
1491                        .align  5
1492saveunlock:
1493                        lwz             r6,SVfreecnt(0)                         ; and the number on the free list
1494                        lwz             r5,SVinuse(0)                           ; Pick up the in use count
1495            subic.      r8,r6,FreeListMin                       ; do we have at least the minimum?
1496                        lwz             r2,SVtarget(0)                          ; Get the target
1497            neg         r8,r8                                           ; assuming we are short, get r8 <- shortfall
1498            blt--       saveunlock1                                     ; skip if fewer than minimum on free list
1499                        
1500                        add             r6,r6,r5                                        ; Get the total number of saveareas
1501                        addi    r5,r2,-SaveLowHysteresis        ; Find low end of acceptible range
1502                        sub             r5,r6,r5                                        ; Make everything below hysteresis negative
1503                        sub             r2,r2,r6                                        ; Get the distance from the target
1504                        addi    r5,r5,-(SaveLowHysteresis + SaveHighHysteresis + 1)     ; Subtract full hysteresis range
1505                        srawi   r5,r5,31                                        ; Get 0xFFFFFFFF if outside range or 0 if inside
1506                        and             r8,r2,r5                                        ; r8 <- 0 if in range or distance to target if not
1507
1508saveunlock1:
1509                        li              r5,0                                            ; Set a clear value
1510                        stw             r8,SVadjust(0)                          ; Set the adjustment value                      
1511                        eieio                                                           ; Make sure everything is done
1512                        stw             r5,SVlock(0)                            ; Unlock the savearea chain 
1513                        blr
1514
1515
1516/*
1517 * *******************
1518 * * s a v e _ c p v *
1519 * *******************
1520 *
1521 *      struct savearea *save_cpv(addr64_t saveAreaPhysAddr);
1522 *
1523 *          Converts a physical savearea address to virtual.  Called with translation on
1524 *                      and in 32-bit mode.  Note that the argument is passed as a long long in (r3,r4).
1525 */
1526
1527                        .align  5
1528                        .globl  EXT(save_cpv)
1529
1530LEXT(save_cpv)
1531            mflr        r9                                                      ; save return address
1532            mr          r8,r3                                           ; save upper half of phys address here
1533            bl          saveSetup                                       ; turn off translation and interrupts, turn SF on
1534                        rlwinm  r5,r4,0,0,19                            ; Round back to the start of the physical savearea block
1535            bf--        pf64Bitb,save_cpv1                      ; skip if 32-bit processor
1536            rldimi      r5,r8,32,0                                      ; r5 <- 64-bit phys address of block
1537save_cpv1:
1538                        lwz             r6,SACvrswap+4(r5)                      ; Get the conversion to virtual (only need low half if 64-bit)
1539            mtlr        r9                                                      ; restore return address
1540            xor         r3,r4,r6                                        ; convert phys to virtual
1541            rlwinm      r3,r3,0,0,31                            ; if 64-bit, zero upper half of virtual address
1542            b           saveRestore                                     ; turn translation etc back on, SF off, and return r3
1543                                
1544                        
1545/*
1546 * *********************
1547 * * s a v e S e t u p *
1548 * *********************
1549 *
1550 * This routine is called at the start of all the save-area subroutines.
1551 * It turns off translation, disabled interrupts, turns on 64-bit mode,
1552 * and sets up cr6 with the feature flags (especially pf64Bit).
1553 * 
1554 * Note that most save-area routines cannot take _any_ interrupt (such as a
1555 * PTE miss) once the savearea anchor is locked, since that would result in
1556 * instant deadlock as we need a save-area to process any exception.
1557 * We set up:
1558 *              r10 = per-proc ptr
1559 *              r11 = old MSR
1560 *              cr5 = pfNoMSRir feature flag
1561 *              cr6 = pf64Bit   feature flag
1562 *
1563 * We use r0, r3, r10, and r11.
1564 */
1565 
1566saveSetup:
1567            mfmsr       r11                                                     ; get msr
1568                        mfsprg  r3,2                                            ; get feature flags
1569                        li              r0,0
1570            mtcrf       0x2,r3                                          ; copy pf64Bit to cr6
1571            ori         r0,r0,lo16(MASK(MSR_IR)+MASK(MSR_DR)+MASK(MSR_EE))
1572            mtcrf       0x4,r3                                          ; copy pfNoMSRir to cr5
1573            andc        r3,r11,r0                                       ; turn off IR, DR, and EE
1574            li          r0,1                                            ; get a 1 in case its a 64-bit machine
1575            bf--        pf64Bitb,saveSetup1                     ; skip if not a 64-bit machine
1576                        rldimi  r3,r0,63,MSR_SF_BIT                     ; turn SF (bit 0) on
1577            mtmsrd      r3                                                      ; turn translation and interrupts off, 64-bit mode on
1578            isync                                                               ; wait for it to happen
1579            mfsprg      r10,0                                           ; get per-proc ptr
1580            blr
1581saveSetup1:                                                                             ; here on 32-bit machines
1582            bt-         pfNoMSRirb,saveSetup2           ; skip if cannot turn off IR with a mtmsr
1583            mtmsr       r3                                                      ; turn translation and interrupts off
1584            isync                                                               ; wait for it to happen
1585            mfsprg      r10,0                                           ; get per-proc ptr
1586            blr
1587saveSetup2:                                                                             ; here if pfNoMSRir set for this machine
1588            li          r0,loadMSR                                      ; we will "mtmsr r3" via system call
1589            sc
1590            mfsprg      r10,0                                           ; get per-proc ptr
1591            blr
1592        
1593                        
1594/*
1595 * *************************
1596 * * s a v e R e s t o r e *
1597 * *************************
1598 *
1599 * Undoes the effect of calling "saveSetup", ie it turns relocation and interrupts back on,
1600 * and turns 64-bit mode back off.
1601 *              r11 = old MSR
1602 *              cr6 = pf64Bit   feature flag
1603 */
1604 
1605saveRestore:
1606            bt++        pf64Bitb,saveRestore64          ; handle a 64-bit processor
1607saveRestore32:
1608            mtmsr       r11                                                     ; restore MSR
1609            isync                                                               ; wait for translation to start up
1610            blr
1611saveRestore64:                                                                  ; 64-bit processor
1612            mtmsrd      r11                                                     ; restore MSR
1613            isync                                                               ; wait for changes to happen
1614            blr
1615
1616
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.