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

