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