]> git.saurik.com Git - apple/xnu.git/blame - osfmk/ppc/vmachmon_asm.s
xnu-344.23.tar.gz
[apple/xnu.git] / osfmk / ppc / vmachmon_asm.s
CommitLineData
1c79356b
A
1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
de355530
A
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.
1c79356b 11 *
de355530
A
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
1c79356b
A
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
de355530
A
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.
1c79356b
A
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22#include <assym.s>
23#include <debug.h>
24#include <ppc/asm.h>
25#include <ppc/proc_reg.h>
26#include <ppc/exception.h>
27
28/*
29 * This file contains implementations for the Virtual Machine Monitor
30 * facility.
31 */
32
33
34/*
35 * int vmm_dispatch(savearea, act);
36
37 * vmm_dispatch is a PPC only system call. It is used with a selector (first
38 * parameter) to determine what function to enter. This is treated as an extension
39 * of hw_exceptions.
40 *
41 * Inputs:
42 * R4 = current activation
43 * R16 = current thread
44 * R30 = current savearea
45 */
46
de355530 47 .align 5 /* Line up on cache line */
1c79356b
A
48 .globl EXT(vmm_dispatch_table)
49
50LEXT(vmm_dispatch_table)
51
52 /* Don't change the order of these routines in the table. It's */
53 /* OK to add new routines, but they must be added at the bottom. */
54
55 .long EXT(vmm_get_version_sel) ; Get the version of the VMM interface
d7e50217 56 .long 0 ; Not valid in Fam
1c79356b 57 .long EXT(vmm_get_features_sel) ; Get the features of the VMM interface
d7e50217 58 .long 0 ; Not valid in Fam
1c79356b 59 .long EXT(vmm_init_context_sel) ; Initializes a new VMM context
d7e50217 60 .long 0 ; Not valid in Fam
1c79356b 61 .long EXT(vmm_tear_down_context) ; Tears down a previously-allocated VMM context
d7e50217 62 .long 0 ; Not valid in Fam
1c79356b 63 .long EXT(vmm_tear_down_all) ; Tears down all VMMs
d7e50217 64 .long 0 ; Not valid in Fam
de355530 65 .long EXT(vmm_map_page) ; Maps a page from the main address space into the VM space
d7e50217 66 .long 1 ; Valid in Fam
de355530 67 .long EXT(vmm_get_page_mapping) ; Returns client va associated with VM va
d7e50217 68 .long 1 ; Valid in Fam
de355530 69 .long EXT(vmm_unmap_page) ; Unmaps a page from the VM space
d7e50217 70 .long 1 ; Valid in Fam
de355530 71 .long EXT(vmm_unmap_all_pages) ; Unmaps all pages from the VM space
d7e50217 72 .long 1 ; Valid in Fam
de355530 73 .long EXT(vmm_get_page_dirty_flag) ; Gets the change bit for a page and optionally clears it
d7e50217 74 .long 1 ; Valid in Fam
1c79356b 75 .long EXT(vmm_get_float_state) ; Gets current floating point state
d7e50217 76 .long 0 ; not valid in Fam
1c79356b 77 .long EXT(vmm_get_vector_state) ; Gets current vector state
d7e50217 78 .long 0 ; Not valid in Fam
1c79356b 79 .long EXT(vmm_set_timer) ; Sets a timer value
d7e50217 80 .long 1 ; Valid in Fam
1c79356b 81 .long EXT(vmm_get_timer) ; Gets a timer value
d7e50217 82 .long 1 ; Valid in Fam
1c79356b 83 .long EXT(switchIntoVM) ; Switches to the VM context
d7e50217 84 .long 1 ; Valid in Fam
de355530 85 .long EXT(vmm_protect_page) ; Sets protection values for a page
d7e50217 86 .long 1 ; Valid in Fam
de355530 87 .long EXT(vmm_map_execute) ; Maps a page an launches VM
d7e50217 88 .long 1 ; Not valid in Fam
de355530 89 .long EXT(vmm_protect_execute) ; Sets protection values for a page and launches VM
d7e50217 90 .long 1 ; Valid in Fam
de355530 91 .long EXT(vmm_map_list) ; Maps a list of pages
d7e50217 92 .long 1 ; Valid in Fam
de355530 93 .long EXT(vmm_unmap_list) ; Unmaps a list of pages
d7e50217
A
94 .long 1 ; Valid in Fam
95 .long EXT(vmm_fam_reserved) ; exit from Fam to host
96 .long 1 ; Valid in Fam
97 .long EXT(vmm_fam_reserved) ; resume guest from Fam
98 .long 1 ; Valid in Fam
99 .long EXT(vmm_fam_reserved) ; get guest register from Fam
100 .long 1 ; Valid in Fam
101 .long EXT(vmm_fam_reserved) ; Set guest register from Fam
102 .long 1 ; Valid in Fam
d7e50217
A
103
104 .set vmm_count,(.-EXT(vmm_dispatch_table))/8 ; Get the top number
1c79356b
A
105
106
107 .align 5
108 .globl EXT(vmm_dispatch)
109
110LEXT(vmm_dispatch)
111
de355530 112 lwz r11,saver3(r30) ; Get the selector
1c79356b
A
113 mr r3,r4 ; All of our functions want the activation as the first parm
114 lis r10,hi16(EXT(vmm_dispatch_table)) ; Get top half of table
115 cmplwi r11,kVmmExecuteVM ; Should we switch to the VM now?
116 cmplwi cr1,r11,vmm_count ; See if we have a valid selector
117 ori r10,r10,lo16(EXT(vmm_dispatch_table)) ; Get low half of table
de355530 118 lwz r4,saver4(r30) ; Get 1st parameter after selector
1c79356b 119 beq+ EXT(switchIntoVM) ; Yes, go switch to it....
d7e50217 120 rlwinm r11,r11,3,0,28 ; Index into table
de355530 121 bgt- cr1,vmmBogus ; It is a bogus entry
d7e50217
A
122 add r12,r10,r11 ; Get the vmm dispatch syscall entry
123 mfsprg r10,0 ; Get the per_proc
124 lwz r13,0(r12) ; Get address of routine
125 lwz r12,4(r12) ; Get validity flag
126 lwz r5,spcFlags(r10) ; Get per_proc special flags
127 cmpwi cr1,r12,0 ; Check Fam valid
128 rlwinm. r5,r5,0,FamVMmodebit,FamVMmodebit ; Test FamVMmodebit
129 crand cr0_eq,cr1_eq,cr0_gt ; In Fam and Invalid syscall
130 beq vmmBogus ; Intercept to host
de355530
A
131 lwz r5,saver5(r30) ; Get 2nd parameter after selector
132 lwz r6,saver6(r30) ; Get 3rd parameter after selector
d7e50217 133 mtlr r13 ; Set the routine address
de355530 134 lwz r7,saver7(r30) ; Get 4th parameter after selector
d7e50217 135;
de355530
A
136; NOTE: currently the most paramters for any call is 4. We will support at most 8 because we
137; do not want to get into any stack based parms. However, here is where we need to add
138; code for the 5th - 8th parms if we need them.
1c79356b
A
139;
140
141 blrl ; Call function
de355530
A
142
143 stw r3,saver3(r30) ; Pass back the return code
1c79356b
A
144 li r3,1 ; Set normal return with check for AST
145 b EXT(ppcscret) ; Go back to handler...
146
d7e50217
A
147vmmBogus:
148 mfsprg r10,0 ; Get the per_proc
149 mfsprg r3,1 ; Load current activation
150 lwz r5,spcFlags(r10) ; Get per_proc special flags
151 rlwinm. r5,r5,0,FamVMmodebit,FamVMmodebit ; Test FamVMmodebit
152 bne vmmexitcall ; Do it to it
153 li r3,0 ; Bogus selector, treat like a bogus system call
1c79356b
A
154 b EXT(ppcscret) ; Go back to handler...
155
156
157 .align 5
158 .globl EXT(vmm_get_version_sel)
159
160LEXT(vmm_get_version_sel) ; Selector based version of get version
161
162 lis r3,hi16(EXT(vmm_get_version))
163 ori r3,r3,lo16(EXT(vmm_get_version))
164 b selcomm
165
166
167 .align 5
168 .globl EXT(vmm_get_features_sel)
169
170LEXT(vmm_get_features_sel) ; Selector based version of get features
171
0b4e3aa0
A
172 lis r3,hi16(EXT(vmm_get_features))
173 ori r3,r3,lo16(EXT(vmm_get_features))
1c79356b
A
174 b selcomm
175
176
177 .align 5
178 .globl EXT(vmm_init_context_sel)
179
180LEXT(vmm_init_context_sel) ; Selector based version of init context
181
de355530
A
182 lwz r4,saver4(r30) ; Get the passed in version
183 lwz r5,saver5(r30) ; Get the passed in comm area
0b4e3aa0 184 lis r3,hi16(EXT(vmm_init_context))
de355530 185 stw r4,saver3(r30) ; Cheat and move this parameter over
0b4e3aa0 186 ori r3,r3,lo16(EXT(vmm_init_context))
de355530 187 stw r5,saver4(r30) ; Cheat and move this parameter over
1c79356b
A
188
189selcomm: mtlr r3 ; Set the real routine address
190 mr r3,r30 ; Pass in the savearea
191 blrl ; Call the function
192 b EXT(ppcscret) ; Go back to handler...
193
194/*
195 * Here is where we transition to the virtual machine.
196 *
197 * We will swap the register context in the savearea with that which is saved in our shared
198 * context area. We will validity check a bit and clear any nasty bits in the MSR and force
199 * the manditory ones on.
200 *
201 * Then we will setup the new address space to run with, and anything else that is normally part
202 * of a context switch.
203 *
0b4e3aa0
A
204 * The vmm_execute_vm entry point is for the fused vmm_map_execute and vmm_protect_execute
205 * calls. This is called, but never returned from. We always go directly back to the
206 * user from here.
207 *
de355530
A
208 * Still need to figure out final floats and vectors. For now, we will go brute
209 * force and when we go into the VM, we will force save any normal floats and
210 * vectors. Then we will hide them and swap the VM copy (if any) into the normal
211 * chain. When we exit VM we will do the opposite. This is not as fast as I would
212 * like it to be.
213 *
1c79356b
A
214 *
215 */
216
0b4e3aa0
A
217
218 .align 5
219 .globl EXT(vmm_execute_vm)
220
221LEXT(vmm_execute_vm)
0b4e3aa0
A
222 lwz r30,ACT_MACT_PCB(r3) ; Restore the savearea pointer because it could be trash here
223 b EXT(switchIntoVM) ; Join common...
224
225
1c79356b
A
226 .align 5
227 .globl EXT(switchIntoVM)
228
229LEXT(switchIntoVM)
d7e50217 230 mfsprg r10,0 ; Get the per_proc
de355530
A
231 lwz r15,spcFlags(r10) ; Get per_proc special flags
232 rlwinm. r0,r15,0,FamVMmodebit,FamVMmodebit ; Test FamVMmodebit
233 bne vmmFamGuestResume
234 lwz r5,vmmControl(r3) ; Pick up the control table address
1c79356b 235 subi r4,r4,1 ; Switch to zero offset
de355530 236 rlwinm. r2,r5,0,0,30 ; Is there a context there? (Note: we will ignore bit 31 so that we
1c79356b 237 ; do not try this while we are transitioning off to on
de355530 238 cmplwi cr1,r4,kVmmMaxContextsPerThread ; Is the index valid?
1c79356b
A
239 beq- vmmBogus ; Not started, treat like a bogus system call
240 mulli r2,r4,vmmCEntrySize ; Get displacement from index
de355530
A
241 bgt- cr1,swvmmBogus ; Index is bogus...
242 add r2,r2,r5 ; Point to the entry
243
1c79356b
A
244 lwz r4,vmmFlags(r2) ; Get the flags for the selected entry
245 lwz r5,vmmContextKern(r2) ; Get the context area address
246 rlwinm. r26,r4,0,vmmInUseb,vmmInUseb ; See if the slot is in use
de355530
A
247 bne+ swvmChkIntcpt ; We are so cool. Go do check for immediate intercepts...
248
249swvmmBogus: li r2,kVmmBogusContext ; Set bogus index return
250 li r3,1 ; Set normal return with check for AST
251 stw r2,saver3(r30) ; Pass back the return code
252 b EXT(ppcscret) ; Go back to handler...
253
1c79356b
A
254;
255; Here we check for any immediate intercepts. So far, the only
0b4e3aa0
A
256; two of these are a timer pop and and external stop. We will not dispatch if
257; either is true. They need to either reset the timer (i.e. set timer
258; to 0) or to set a future time, or if it is external stop, set the vmmXStopRst flag.
1c79356b
A
259;
260
de355530 261swvmChkIntcpt:
0b4e3aa0
A
262 lwz r6,vmmCntrl(r5) ; Get the control field
263 rlwinm. r7,r6,0,vmmXStartb,vmmXStartb ; Clear all but start bit
264 beq+ swvmChkStop ; Do not reset stop
265 andc r6,r6,r7 ; Clear it
266 li r8,vmmFlags ; Point to the flags
267 stw r6,vmmCntrl(r5) ; Set the control field
268
269swvmtryx: lwarx r4,r8,r2 ; Pick up the flags
270 rlwinm r4,r4,0,vmmXStopb+1,vmmXStopb-1 ; Clear the stop bit
271 stwcx. r4,r8,r2 ; Save the updated field
272 bne- swvmtryx ; Try again...
273
274swvmChkStop:
275 rlwinm. r26,r4,0,vmmXStopb,vmmXStopb ; Is this VM stopped?
de355530
A
276 beq+ swvmNoStop ; Nope...
277
278 li r2,kVmmStopped ; Set stopped return
279 li r3,1 ; Set normal return with check for AST
280 stw r2,saver3(r30) ; Pass back the return code
281 stw r2,return_code(r5) ; Save the exit code
282 b EXT(ppcscret) ; Go back to handler...
0b4e3aa0 283
de355530 284swvmNoStop:
9bccf70c 285 rlwinm. r26,r4,0,vmmTimerPopb,vmmTimerPopb ; Did the timer go pop?
de355530
A
286 beq+ swvmDoSwitch ; No...
287
288 li r2,kVmmReturnNull ; Set null return
289 li r3,1 ; Set normal return with check for AST
290 stw r2,saver3(r30) ; Pass back the return code
291 stw r2,return_code(r5) ; Save the exit code
292 b EXT(ppcscret) ; Go back to handler...
1c79356b
A
293
294;
295; Here is where we actually swap into the VM (alternate) context.
296; We will bulk do a wholesale swap of the registers in the context area (the VMs)
297; with the ones in the savearea (our main code). During the copy, we will fix up the
298; MSR, forcing on a few bits and turning off a few others. Then we will deal with the
299; PMAP and other per_proc stuff. Finally, we will exit back through the main exception
300; handler to deal with unstacking saveareas and ASTs, etc.
301;
302
303swvmDoSwitch:
304
305;
306; First, we save the volatile registers we care about. Remember, all register
307; handling here is pretty funky anyway, so we just pick the ones that are ok.
308;
309 mr r26,r3 ; Save the activation pointer
1c79356b 310
9bccf70c
A
311 la r11,vmmFacCtx(r2) ; Point to the virtual machine facility context
312 mr r27,r2 ; Save the context entry
313 stw r11,deferctx(r3) ; Start using the virtual machine facility context when we exit
1c79356b
A
314
315 lwz r11,ACT_MACT_SPF(r26) ; Get the special flags
de355530 316 lwz r3,vmmPmap(r27) ; Get the pointer to the PMAP
1c79356b
A
317 oris r15,r11,hi16(runningVM) ; ; Show that we are swapped to the VM right now
318 bl EXT(hw_set_user_space_dis) ; Swap the address spaces
319 lwz r17,vmmFlags(r27) ; Get the status flags
d7e50217
A
320 lwz r20,vmmContextKern(r27) ; Get the state page kernel addr
321 lwz r21,vmmCntrl(r20) ; Get vmmCntrl
322 rlwinm. r22,r21,0,vmmFamEnab,vmmFamEnab ; Is vmmFamEnab set?
d7e50217 323 beq swvmNoFam ; No Fam intercept
d7e50217
A
324 rlwimi r15,r21,32+vmmFamSetb-FamVMmodebit,FamVMmodebit,FamVMmodebit ; Set FamVMmode bit
325 rlwinm r21,r21,0,vmmFamSetb+1,vmmFamSetb-1 ; Clear FamSet bit
d7e50217 326 lwz r22,famintercepts(r20) ; Load intercept bit field
d7e50217
A
327 stw r21,vmmCntrl(r20) ; Update vmmCntrl
328 lwz r19,vmmContextPhys(r27) ; Get vmmFAMarea address
329 stw r22,vmmFAMintercept(r27) ; Get vmmFAMintercept
330 stw r22,FAMintercept(r10) ; Store vmmFAMintercept in per_proc FAMintercept
de355530 331 stw r19,vmmContextPhys(r27) ; Store vmmContextPhys
d7e50217
A
332 stw r19,VMMareaPhys(r10) ; Store VMMareaPhys
333 oris r15,r15,hi16(FamVMena) ; Set FamVMenabit
334swvmNoFam:
de355530 335 rlwinm. r0,r17,0,vmmMapDoneb,vmmMapDoneb ; Did we just do a map function?
1c79356b 336 stw r27,vmmCEntry(r26) ; Remember what context we are running
de355530
A
337 andc r17,r17,r0 ; Turn off map flag
338 beq+ swvmNoMap ; No mapping done...
1c79356b
A
339
340;
341; This little bit of hoopala here (triggered by vmmMapDone) is
342; a performance enhancement. This will change the returning savearea
343; to look like we had a DSI rather than a system call. Then, setting
344; the redrive bit, the exception handler will redrive the exception as
345; a DSI, entering the last mapped address into the hash table. This keeps
346; double faults from happening. Note that there is only a gain if the VM
347; takes a fault, then the emulator resolves it only, and then begins
348; the VM execution again. It seems like this should be the normal case.
349;
350
351 lwz r3,SAVflags(r30) ; Pick up the savearea flags
de355530 352 lwz r2,vmmLastMap(r27) ; Get the last mapped address
1c79356b
A
353 li r20,T_DATA_ACCESS ; Change to DSI fault
354 oris r3,r3,hi16(SAVredrive) ; Set exception redrive
355 stw r2,savedar(r30) ; Set the DAR to the last thing we mapped
356 stw r3,SAVflags(r30) ; Turn on the redrive request
357 lis r2,hi16(MASK(DSISR_HASH)) ; Set PTE/DBAT miss
358 stw r20,saveexception(r30) ; Say we need to emulate a DSI
359 stw r2,savedsisr(r30) ; Pretend we have a PTE miss
360
0b4e3aa0
A
361swvmNoMap: lwz r20,vmmContextKern(r27) ; Get the comm area
362 rlwimi r15,r17,32-(floatCngbit-vmmFloatCngdb),floatCngbit,vectorCngbit ; Shift and insert changed bits
363 lwz r20,vmmCntrl(r20) ; Get the control flags
1c79356b 364 rlwimi r17,r11,8,24,31 ; Save the old spf flags
0b4e3aa0 365 rlwimi r15,r20,32+vmmKeyb-userProtKeybit,userProtKeybit,userProtKeybit ; Set the protection key
1c79356b
A
366 stw r15,spcFlags(r10) ; Set per_proc copy of the special flags
367 stw r15,ACT_MACT_SPF(r26) ; Get the special flags
368
369 stw r17,vmmFlags(r27) ; Set the status flags
370
371 bl swapCtxt ; First, swap the general register state
372
0b4e3aa0 373 lwz r17,vmmContextKern(r27) ; Get the comm area back
9bccf70c 374 la r25,vmmFacCtx(r27) ; Point to the facility context
0b4e3aa0 375 lwz r15,vmmCntrl(r17) ; Get the control flags again
9bccf70c 376 mfsprg r29,0 ; Get the per_proc
1c79356b 377
9bccf70c
A
378;
379; Check if there is new floating point context to load
380;
381
1c79356b 382 rlwinm. r0,r15,0,vmmFloatLoadb,vmmFloatLoadb ; Are there new floating point values?
9bccf70c 383 lhz r29,PP_CPU_NUMBER(r29) ; Get our cpu number
1c79356b
A
384 li r14,vmmppcFPRs ; Get displacement to the new values
385 andc r15,r15,r0 ; Clear the bit
386 beq+ swvmNoNewFloats ; Nope, good...
387
9bccf70c
A
388 lwz r19,FPUcpu(r25) ; Get the last CPU we ran on
389
390 stw r29,FPUcpu(r25) ; Claim the context for ourselves
391
392 eieio ; Make sure this stays in order
393
394 lis r18,hi16(EXT(per_proc_info)) ; Set base per_proc
395 mulli r19,r19,ppSize ; Find offset to the owner per_proc
396 ori r18,r18,lo16(EXT(per_proc_info)) ; Set base per_proc
397 li r16,FPUowner ; Displacement to float owner
398 add r19,r18,r19 ; Point to the owner per_proc
de355530 399 li r0,0 ; Clear this out
9bccf70c
A
400
401swvminvfpu: lwarx r18,r16,r19 ; Get the owner
de355530
A
402 cmplw r18,r25 ; Does he still have this context?
403 bne swvminvfpv ; Nope...
404 stwcx. r0,r16,r19 ; Try to invalidate it
405 bne- swvminvfpu ; Try again if there was a collision...
406
407swvminvfpv: lwz r3,FPUsave(r25) ; Get the FPU savearea
9bccf70c 408 dcbt r14,r17 ; Touch in first line of new stuff
1c79356b
A
409 mr. r3,r3 ; Is there one?
410 bne+ swvmGotFloat ; Yes...
411
412 bl EXT(save_get) ; Get a savearea
413
9bccf70c
A
414 li r7,SAVfloat ; Get floating point flag
415 stw r26,SAVact(r3) ; Save our activation
416 li r0,0 ; Get a zero
417 stb r7,SAVflags+2(r3) ; Set that this is floating point
de355530 418 stw r0,SAVprev(r3) ; Clear the back chain
9bccf70c
A
419 stw r0,SAVlevel(r3) ; We are always at level 0 (user state)
420
421 stw r3,FPUsave(r25) ; Chain us to context
1c79356b
A
422
423swvmGotFloat:
1c79356b
A
424 la r4,savefp0(r3) ; Point to the destination
425 mr r21,r3 ; Save the save area
426 la r3,vmmppcFPRs(r17) ; Point to the source
9bccf70c 427 li r5,32*8 ; Get the size (32 FPRs at 8 bytes each)
1c79356b
A
428
429 bl EXT(bcopy) ; Copy the new values
9bccf70c 430
de355530
A
431 lwz r14,vmmppcFPSCRshadow(r17) ; Get the fpscr pad
432 lwz r10,vmmppcFPSCRshadow+4(r17) ; Get the fpscr
433 stw r14,savefpscrpad(r30) ; Save the new fpscr pad
434 stw r10,savefpscr(r30) ; Save the new fpscr
435
1c79356b
A
436 lwz r11,ACT_MACT_SPF(r26) ; Get the special flags
437 stw r15,vmmCntrl(r17) ; Save the control flags sans vmmFloatLoad
438 rlwinm r11,r11,0,floatCngbit+1,floatCngbit-1 ; Clear the changed bit here
439 lwz r14,vmmStat(r17) ; Get the status flags
440 mfsprg r10,0 ; Get the per_proc
441 stw r11,ACT_MACT_SPF(r26) ; Get the special flags
442 rlwinm r14,r14,0,vmmFloatCngdb+1,vmmFloatCngdb-1 ; Clear the changed flag
443 stw r11,spcFlags(r10) ; Set per_proc copy of the special flags
444 stw r14,vmmStat(r17) ; Set the status flags sans vmmFloatCngd
1c79356b 445
9bccf70c
A
446;
447; Check if there is new vector context to load
448;
449
1c79356b
A
450swvmNoNewFloats:
451 rlwinm. r0,r15,0,vmmVectLoadb,vmmVectLoadb ; Are there new vector values?
452 li r14,vmmppcVRs ; Get displacement to the new values
453 andc r15,r15,r0 ; Clear the bit
454 beq+ swvmNoNewVects ; Nope, good...
455
9bccf70c
A
456 lwz r19,VMXcpu(r25) ; Get the last CPU we ran on
457
458 stw r29,VMXcpu(r25) ; Claim the context for ourselves
459
460 eieio ; Make sure this stays in order
461
462 lis r18,hi16(EXT(per_proc_info)) ; Set base per_proc
463 mulli r19,r19,ppSize ; Find offset to the owner per_proc
464 ori r18,r18,lo16(EXT(per_proc_info)) ; Set base per_proc
465 li r16,VMXowner ; Displacement to vector owner
466 add r19,r18,r19 ; Point to the owner per_proc
de355530 467 li r0,0 ; Clear this out
9bccf70c
A
468
469swvminvvec: lwarx r18,r16,r19 ; Get the owner
de355530
A
470 cmplw r18,r25 ; Does he still have this context?
471 bne swvminvved ; Nope...
472 stwcx. r0,r16,r19 ; Try to invalidate it
473 bne- swvminvvec ; Try again if there was a collision...
9bccf70c
A
474
475swvminvved: lwz r3,VMXsave(r25) ; Get the vector savearea
476 dcbt r14,r17 ; Touch in first line of new stuff
1c79356b
A
477 mr. r3,r3 ; Is there one?
478 bne+ swvmGotVect ; Yes...
479
480 bl EXT(save_get) ; Get a savearea
481
9bccf70c
A
482 li r7,SAVvector ; Get the vector type flag
483 stw r26,SAVact(r3) ; Save our activation
484 li r0,0 ; Get a zero
485 stb r7,SAVflags+2(r3) ; Set that this is vector
de355530 486 stw r0,SAVprev(r3) ; Clear the back chain
9bccf70c
A
487 stw r0,SAVlevel(r3) ; We are always at level 0 (user state)
488
489 stw r3,VMXsave(r25) ; Chain us to context
1c79356b
A
490
491swvmGotVect:
1c79356b
A
492 mr r21,r3 ; Save the pointer to the savearea
493 la r4,savevr0(r3) ; Point to the destination
494 la r3,vmmppcVRs(r17) ; Point to the source
9bccf70c 495 li r5,32*16 ; Get the size (32 vectors at 16 bytes each)
1c79356b
A
496
497 bl EXT(bcopy) ; Copy the new values
498
de355530
A
499 lwz r11,vmmppcVSCRshadow+0(r17) ; Get the VSCR
500 lwz r14,vmmppcVSCRshadow+4(r17) ; Get the VSCR
501 lwz r10,vmmppcVSCRshadow+8(r17) ; Get the VSCR
502 lwz r9,vmmppcVSCRshadow+12(r17) ; Get the VSCR
9bccf70c
A
503 lwz r8,savevrsave(r30) ; Get the current VRSave
504
de355530
A
505 stw r11,savevscr+0(r30) ; Set the VSCR
506 stw r14,savevscr+4(r30) ; Set the VSCR
507 stw r10,savevscr+8(r30) ; Set the VSCR
508 stw r9,savevscr+12(r30) ; Set the VSCR
509 stw r8,savevrvalid(r21) ; Set the current VRSave as valid saved
510
1c79356b
A
511 lwz r11,ACT_MACT_SPF(r26) ; Get the special flags
512 stw r15,vmmCntrl(r17) ; Save the control flags sans vmmVectLoad
513 rlwinm r11,r11,0,vectorCngbit+1,vectorCngbit-1 ; Clear the changed bit here
514 lwz r14,vmmStat(r17) ; Get the status flags
515 mfsprg r10,0 ; Get the per_proc
516 stw r11,ACT_MACT_SPF(r26) ; Get the special flags
517 rlwinm r14,r14,0,vmmVectCngdb+1,vmmVectCngdb-1 ; Clear the changed flag
1c79356b
A
518 stw r11,spcFlags(r10) ; Set per_proc copy of the special flags
519 stw r14,vmmStat(r17) ; Set the status flags sans vmmVectCngd
1c79356b
A
520
521swvmNoNewVects:
522 li r3,1 ; Show normal exit with check for AST
9bccf70c 523 lwz r16,ACT_THREAD(r26) ; Restore the thread pointer
1c79356b
A
524 b EXT(ppcscret) ; Go back to handler...
525
d7e50217
A
526
527;
528; These syscalls are invalid, FAM syscall fast path
529;
530
531 .align 5
532 .globl EXT(vmm_fam_reserved)
533
534LEXT(vmm_fam_reserved)
535 li r3,0 ; Force exception
536 b EXT(ppcscret) ; Go back to handler...
1c79356b 537
1c79356b
A
538;
539; Here is where we exit from vmm mode. We do this on any kind of exception.
540; Interruptions (decrementer, external, etc.) are another story though.
541; These we just pass through. We also switch back explicity when requested.
542; This will happen in response to a timer pop and some kinds of ASTs.
543;
544; Inputs:
545; R3 = activation
546; R4 = savearea
547;
548
549 .align 5
550 .globl EXT(vmm_exit)
551
552LEXT(vmm_exit)
553
d7e50217 554vmmexitcall:
1c79356b
A
555 lwz r2,vmmCEntry(r3) ; Get the context that is active
556 lwz r12,ACT_VMMAP(r3) ; Get the VM_MAP for this guy
557 lwz r11,ACT_MACT_SPF(r3) ; Get the special flags
558 lwz r19,vmmFlags(r2) ; Get the status flags
559 mr r16,r3 ; R16 is safe to use for the activation address
560
561 rlwimi r19,r11,floatCngbit-vmmFloatCngdb,vmmFloatCngdb,vmmVectCngdb ; Shift and insert changed bits
562 li r0,0 ; Get a zero
563 rlwimi r11,r19,vmmSpfSaveb,floatCngbit,vectorCngbit ; Restore the saved part of the spf
564 lwz r3,VMMAP_PMAP(r12) ; Get the pmap for the activation
565 rlwinm r11,r11,0,runningVMbit+1,runningVMbit-1 ; Clear the "in VM" flag
566 stw r0,vmmCEntry(r16) ; Clear pointer to active context
567 stw r19,vmmFlags(r2) ; Set the status flags
0b4e3aa0 568 rlwinm r11,r11,0,userProtKeybit+1,userProtKeybit-1 ; Set back to normal protection key
1c79356b 569 mfsprg r10,0 ; Get the per_proc block
d7e50217
A
570 rlwinm r11,r11,0,FamVMenabit+1,FamVMenabit-1 ; Clear FamVMEnable
571 lwz r18,spcFlags(r10) ; Get per_proc copy of the special flags
572 lwz r5,vmmContextKern(r2) ; Get the state page kernel addr
573 rlwinm r11,r11,0,FamVMmodebit+1,FamVMmodebit-1 ; Clear FamVMMode
574 lwz r6,vmmCntrl(r5) ; Get the control field
575 rlwimi r19,r18,FamVMmodebit-vmmFAMmodeb,vmmFAMmodeb,vmmFAMmodeb ; Shift and insert changed bits
576 rlwimi r6,r18,FamVMmodebit-vmmFamSetb,vmmFamSetb,vmmFamSetb ; Shift and insert changed bits
577 rlwimi r6,r18,userProtKeybit-vmmKeyb,vmmKeyb,vmmKeyb ; Shift and insert changed bits
1c79356b 578 stw r11,ACT_MACT_SPF(r16) ; Get the special flags
d7e50217 579 stw r6,vmmCntrl(r5) ; Store the control field
1c79356b
A
580 stw r11,spcFlags(r10) ; Set per_proc copy of the special flags
581
582 mr r26,r16 ; Save the activation pointer
583 mr r27,r2 ; Save the context entry
584
585 bl EXT(hw_set_user_space_dis) ; Swap the address spaces back to the emulator
586
9bccf70c 587 la r5,facctx(r16) ; Point to the main facility context
1c79356b 588 mr r2,r27 ; Restore
9bccf70c
A
589 stw r5,deferctx(r16) ; Start using the main facility context on the way out
590 lwz r5,vmmContextKern(r27) ; Get the context area address
1c79356b
A
591 mr r3,r16 ; Restore activation address
592 stw r19,vmmStat(r5) ; Save the changed and popped flags
593 bl swapCtxt ; Exchange the VM context for the emulator one
de355530 594 stw r8,saver3(r30) ; Set the return code as the return value also
1c79356b
A
595 b EXT(retFromVM) ; Go back to handler...
596
597
598;
599; Here is where we force exit from vmm mode. We do this when as
600; part of termination and is used to insure that we are not executing
601; in an alternate context. Because this is called from C we need to save
602; all non-volatile registers.
603;
604; Inputs:
605; R3 = activation
606; R4 = user savearea
607; Interruptions disabled
608;
609
610 .align 5
611 .globl EXT(vmm_force_exit)
612
613LEXT(vmm_force_exit)
614
615 stwu r1,-(FM_ALIGN(20*4)+FM_SIZE)(r1) ; Get enough space for the registers
616 mflr r0 ; Save the return
617 stmw r13,FM_ARG0(r1) ; Save all non-volatile registers
618 stw r0,(FM_ALIGN(20*4)+FM_SIZE+FM_LR_SAVE)(r1) ; Save the return
619
620 lwz r2,vmmCEntry(r3) ; Get the context that is active
621 lwz r11,ACT_MACT_SPF(r3) ; Get the special flags
622 lwz r19,vmmFlags(r2) ; Get the status flags
623 lwz r12,ACT_VMMAP(r3) ; Get the VM_MAP for this guy
624
625 rlwimi r19,r11,floatCngbit-vmmFloatCngdb,vmmFloatCngdb,vmmVectCngdb ; Shift and insert changed bits
626 mr r26,r3 ; Save the activation pointer
627 rlwimi r11,r19,vmmSpfSaveb,floatCngbit,vectorCngbit ; Restore the saved part of the spf
628 li r0,0 ; Get a zero
629 rlwinm r9,r11,0,runningVMbit+1,runningVMbit-1 ; Clear the "in VM" flag
630 cmplw r9,r11 ; Check if we were in a vm
631 lwz r3,VMMAP_PMAP(r12) ; Get the pmap for the activation
632 beq- vfeNotRun ; We were not in a vm....
0b4e3aa0 633 rlwinm r9,r9,0,userProtKeybit+1,userProtKeybit-1 ; Set back to normal protection key
1c79356b
A
634 stw r0,vmmCEntry(r26) ; Clear pointer to active context
635 mfsprg r10,0 ; Get the per_proc block
d7e50217
A
636 lwz r18,spcFlags(r10) ; Get per_proc copy of the special flags
637 rlwinm r9,r9,0,FamVMenabit+1,FamVMenabit-1 ; Clear Fam Enable
638 rlwinm r9,r9,0,FamVMmodebit+1,FamVMmodebit-1 ; Clear Fam Enable
639 lwz r5,vmmContextKern(r2) ; Get the context area address
640 lwz r6,vmmCntrl(r5) ; Get the control field
641 rlwimi r19,r18,FamVMmodebit-vmmFAMmodeb,vmmFAMmodeb,vmmFAMmodeb ; Shift and insert changed bits
642 rlwimi r6,r18,FamVMmodebit-vmmFamSetb,vmmFamSetb,vmmFamSetb ; Shift and insert changed bits
643 rlwimi r6,r18,userProtKeybit-vmmKeyb,vmmKeyb,vmmKeyb ; Shift and insert changed bits
644 stw r6,vmmCntrl(r5) ; Store the control field
1c79356b
A
645 stw r9,ACT_MACT_SPF(r26) ; Get the special flags
646 stw r9,spcFlags(r10) ; Set per_proc copy of the special flags
647
648 mr r27,r2 ; Save the context entry
649 mr r30,r4 ; Save the savearea
650
651 bl EXT(hw_set_user_space_dis) ; Swap the address spaces back to the emulator
652
9bccf70c 653 la r7,facctx(r26) ; Point to the main facility context
1c79356b
A
654
655 lwz r5,vmmContextKern(r27) ; Get the context area address
656 stw r19,vmmStat(r5) ; Save the changed and popped flags
9bccf70c
A
657 stw r7,deferctx(r26) ; Tell context launcher to switch facility context
658
1c79356b
A
659 bl swapCtxt ; Exchange the VM context for the emulator one
660
0b4e3aa0 661 lwz r8,saveexception(r30) ; Pick up the exception code
9bccf70c
A
662 lwz r7,SAVflags(r30) ; Pick up the savearea flags
663 lis r9,hi16(SAVredrive) ; Get exception redrive bit
0b4e3aa0 664 rlwinm r8,r8,30,24,31 ; Convert exception to return code
9bccf70c 665 andc r7,r7,r9 ; Make sure redrive is off because we are intercepting
de355530 666 stw r8,saver3(r30) ; Set the return code as the return value also
9bccf70c 667 stw r7,SAVflags(r30) ; Set the savearea flags
1c79356b
A
668
669
670vfeNotRun: lmw r13,FM_ARG0(r1) ; Restore all non-volatile registers
671 lwz r1,0(r1) ; Pop the stack
672 lwz r0,FM_LR_SAVE(r1) ; Get the return address
673 mtlr r0 ; Set return
674 blr
675
676;
677; Note: we will not do any DCBTs to the savearea. It was just stored to a few cycles ago and should
9bccf70c 678; still be in the cache.
1c79356b 679;
1c79356b 680; NOTE NOTE: R16 is important to save!!!!
9bccf70c 681;
1c79356b
A
682 .align 5
683
de355530 684swapCtxt: la r6,vmmppcpc(r5) ; Point to the first line
1c79356b
A
685
686 lwz r14,saveexception(r30) ; Get the exception code
9bccf70c 687 dcbt 0,r6 ; Touch in the first line of the context area
de355530
A
688 lwz r7,savesrr0(r30) ; Start moving context
689 lwz r8,savesrr1(r30)
690 lwz r9,saver0(r30)
1c79356b 691 cmplwi cr1,r14,T_SYSTEM_CALL ; Are we switching because of a system call?
de355530
A
692 lwz r10,saver1(r30)
693 lwz r11,saver2(r30)
694 lwz r12,saver3(r30)
695 lwz r13,saver4(r30)
9bccf70c 696 la r6,vmmppcr6(r5) ; Point to second line
de355530 697 lwz r14,saver5(r30)
1c79356b 698
9bccf70c 699 dcbt 0,r6 ; Touch second line of context area
1c79356b 700
9bccf70c 701 lwz r15,vmmppcpc(r5) ; First line of context
1c79356b 702 lis r22,hi16(MSR_IMPORT_BITS) ; Get the MSR bits that are controllable by user
9bccf70c 703 lwz r23,vmmppcmsr(r5)
d7e50217 704 ori r22,r22,lo16(MSR_IMPORT_BITS) ; Get the rest of the MSR bits that are controllable by user
9bccf70c
A
705 lwz r17,vmmppcr0(r5)
706 lwz r18,vmmppcr1(r5)
1c79356b 707 and r23,r23,r22 ; Keep only the controllable bits
9bccf70c 708 lwz r19,vmmppcr2(r5)
1c79356b 709 oris r23,r23,hi16(MSR_EXPORT_MASK_SET) ; Force on the required bits
9bccf70c 710 lwz r20,vmmppcr3(r5)
1c79356b 711 ori r23,r23,lo16(MSR_EXPORT_MASK_SET) ; Force on the other required bits
9bccf70c
A
712 lwz r21,vmmppcr4(r5)
713 lwz r22,vmmppcr5(r5)
1c79356b 714
9bccf70c 715 dcbt 0,r6 ; Touch third line of context area
1c79356b 716
9bccf70c
A
717 stw r7,vmmppcpc(r5) ; Save emulator context into the context area
718 stw r8,vmmppcmsr(r5)
719 stw r9,vmmppcr0(r5)
720 stw r10,vmmppcr1(r5)
721 stw r11,vmmppcr2(r5)
722 stw r12,vmmppcr3(r5)
723 stw r13,vmmppcr4(r5)
724 stw r14,vmmppcr5(r5)
1c79356b
A
725
726;
727; Save the first 3 parameters if we are an SC (we will take care of the last later)
728;
729 bne+ cr1,swapnotsc ; Skip next if not an SC exception...
730 stw r12,return_params+0(r5) ; Save the first return
731 stw r13,return_params+4(r5) ; Save the second return
732 stw r14,return_params+8(r5) ; Save the third return
733
de355530
A
734swapnotsc: stw r15,savesrr0(r30) ; Save vm context into the savearea
735 stw r23,savesrr1(r30)
736 stw r17,saver0(r30)
737 stw r18,saver1(r30)
738 stw r19,saver2(r30)
739 stw r20,saver3(r30)
740 stw r21,saver4(r30)
9bccf70c 741 la r6,vmmppcr14(r5) ; Point to fourth line
de355530 742 stw r22,saver5(r30)
9bccf70c
A
743
744 dcbt 0,r6 ; Touch fourth line
745
746; Swap 8 registers
747
de355530
A
748 lwz r7,saver6(r30) ; Read savearea
749 lwz r8,saver7(r30)
750 lwz r9,saver8(r30)
751 lwz r10,saver9(r30)
752 lwz r11,saver10(r30)
753 lwz r12,saver11(r30)
754 lwz r13,saver12(r30)
755 lwz r14,saver13(r30)
9bccf70c
A
756
757 lwz r15,vmmppcr6(r5) ; Read vm context
758 lwz r24,vmmppcr7(r5)
759 lwz r17,vmmppcr8(r5)
760 lwz r18,vmmppcr9(r5)
761 lwz r19,vmmppcr10(r5)
762 lwz r20,vmmppcr11(r5)
763 lwz r21,vmmppcr12(r5)
764 lwz r22,vmmppcr13(r5)
765
766 stw r7,vmmppcr6(r5) ; Write context
767 stw r8,vmmppcr7(r5)
768 stw r9,vmmppcr8(r5)
769 stw r10,vmmppcr9(r5)
770 stw r11,vmmppcr10(r5)
771 stw r12,vmmppcr11(r5)
772 stw r13,vmmppcr12(r5)
773 la r6,vmmppcr22(r5) ; Point to fifth line
774 stw r14,vmmppcr13(r5)
775
776 dcbt 0,r6 ; Touch fifth line
777
de355530
A
778 stw r15,saver6(r30) ; Write vm context
779 stw r24,saver7(r30)
780 stw r17,saver8(r30)
781 stw r18,saver9(r30)
782 stw r19,saver10(r30)
783 stw r20,saver11(r30)
784 stw r21,saver12(r30)
785 stw r22,saver13(r30)
9bccf70c
A
786
787; Swap 8 registers
788
de355530
A
789 lwz r7,saver14(r30) ; Read savearea
790 lwz r8,saver15(r30)
791 lwz r9,saver16(r30)
792 lwz r10,saver17(r30)
793 lwz r11,saver18(r30)
794 lwz r12,saver19(r30)
795 lwz r13,saver20(r30)
796 lwz r14,saver21(r30)
9bccf70c
A
797
798 lwz r15,vmmppcr14(r5) ; Read vm context
799 lwz r24,vmmppcr15(r5)
800 lwz r17,vmmppcr16(r5)
801 lwz r18,vmmppcr17(r5)
802 lwz r19,vmmppcr18(r5)
803 lwz r20,vmmppcr19(r5)
804 lwz r21,vmmppcr20(r5)
805 lwz r22,vmmppcr21(r5)
806
807 stw r7,vmmppcr14(r5) ; Write context
808 stw r8,vmmppcr15(r5)
809 stw r9,vmmppcr16(r5)
810 stw r10,vmmppcr17(r5)
811 stw r11,vmmppcr18(r5)
812 stw r12,vmmppcr19(r5)
813 stw r13,vmmppcr20(r5)
814 la r6,vmmppcr30(r5) ; Point to sixth line
815 stw r14,vmmppcr21(r5)
816
817 dcbt 0,r6 ; Touch sixth line
818
de355530
A
819 stw r15,saver14(r30) ; Write vm context
820 stw r24,saver15(r30)
821 stw r17,saver16(r30)
822 stw r18,saver17(r30)
823 stw r19,saver18(r30)
824 stw r20,saver19(r30)
825 stw r21,saver20(r30)
826 stw r22,saver21(r30)
9bccf70c
A
827
828; Swap 8 registers
829
de355530
A
830 lwz r7,saver22(r30) ; Read savearea
831 lwz r8,saver23(r30)
832 lwz r9,saver24(r30)
833 lwz r10,saver25(r30)
834 lwz r11,saver26(r30)
835 lwz r12,saver27(r30)
836 lwz r13,saver28(r30)
837 lwz r14,saver29(r30)
9bccf70c
A
838
839 lwz r15,vmmppcr22(r5) ; Read vm context
840 lwz r24,vmmppcr23(r5)
841 lwz r17,vmmppcr24(r5)
842 lwz r18,vmmppcr25(r5)
843 lwz r19,vmmppcr26(r5)
844 lwz r20,vmmppcr27(r5)
845 lwz r21,vmmppcr28(r5)
846 lwz r22,vmmppcr29(r5)
847
848 stw r7,vmmppcr22(r5) ; Write context
849 stw r8,vmmppcr23(r5)
850 stw r9,vmmppcr24(r5)
851 stw r10,vmmppcr25(r5)
852 stw r11,vmmppcr26(r5)
853 stw r12,vmmppcr27(r5)
854 stw r13,vmmppcr28(r5)
855 la r6,vmmppcvscr(r5) ; Point to seventh line
856 stw r14,vmmppcr29(r5)
857
858 dcbt 0,r6 ; Touch seventh line
859
de355530
A
860 stw r15,saver22(r30) ; Write vm context
861 stw r24,saver23(r30)
862 stw r17,saver24(r30)
863 stw r18,saver25(r30)
864 stw r19,saver26(r30)
865 stw r20,saver27(r30)
866 stw r21,saver28(r30)
867 stw r22,saver29(r30)
9bccf70c
A
868
869; Swap 8 registers
870
de355530
A
871 lwz r7,saver30(r30) ; Read savearea
872 lwz r8,saver31(r30)
9bccf70c 873 lwz r9,savecr(r30)
de355530
A
874 lwz r10,savexer(r30)
875 lwz r11,savelr(r30)
876 lwz r12,savectr(r30)
9bccf70c
A
877 lwz r14,savevrsave(r30)
878
879 lwz r15,vmmppcr30(r5) ; Read vm context
880 lwz r24,vmmppcr31(r5)
881 lwz r17,vmmppccr(r5)
882 lwz r18,vmmppcxer(r5)
883 lwz r19,vmmppclr(r5)
884 lwz r20,vmmppcctr(r5)
885 lwz r22,vmmppcvrsave(r5)
886
887 stw r7,vmmppcr30(r5) ; Write context
888 stw r8,vmmppcr31(r5)
889 stw r9,vmmppccr(r5)
890 stw r10,vmmppcxer(r5)
891 stw r11,vmmppclr(r5)
892 stw r12,vmmppcctr(r5)
893 stw r14,vmmppcvrsave(r5)
894
de355530
A
895 stw r15,saver30(r30) ; Write vm context
896 stw r24,saver31(r30)
9bccf70c 897 stw r17,savecr(r30)
de355530
A
898 stw r18,savexer(r30)
899 stw r19,savelr(r30)
900 stw r20,savectr(r30)
9bccf70c
A
901 stw r22,savevrsave(r30)
902
903; Swap 8 registers
904
905 lwz r7,savevscr+0(r30) ; Read savearea
906 lwz r8,savevscr+4(r30)
907 lwz r9,savevscr+8(r30)
908 lwz r10,savevscr+12(r30)
909 lwz r11,savefpscrpad(r30)
910 lwz r12,savefpscr(r30)
911
912 lwz r15,vmmppcvscr+0(r5) ; Read vm context
913 lwz r24,vmmppcvscr+4(r5)
914 lwz r17,vmmppcvscr+8(r5)
915 lwz r18,vmmppcvscr+12(r5)
916 lwz r19,vmmppcfpscrpad(r5)
917 lwz r20,vmmppcfpscr(r5)
918
919 stw r7,vmmppcvscr+0(r5) ; Write context
920 stw r8,vmmppcvscr+4(r5)
921 stw r9,vmmppcvscr+8(r5)
922 stw r10,vmmppcvscr+12(r5)
923 stw r11,vmmppcfpscrpad(r5)
924 stw r12,vmmppcfpscr(r5)
925
926 stw r15,savevscr+0(r30) ; Write vm context
927 stw r24,savevscr+4(r30)
928 stw r17,savevscr+8(r30)
929 stw r18,savevscr+12(r30)
930 stw r19,savefpscrpad(r30)
931 stw r20,savefpscr(r30)
932
1c79356b
A
933
934;
935; Cobble up the exception return code and save any specific return values
936;
937
938 lwz r7,saveexception(r30) ; Pick up the exception code
939 rlwinm r8,r7,30,24,31 ; Convert exception to return code
940 cmplwi r7,T_DATA_ACCESS ; Was this a DSI?
941 stw r8,return_code(r5) ; Save the exit code
942 cmplwi cr1,r7,T_INSTRUCTION_ACCESS ; Exiting because of an ISI?
943 beq+ swapDSI ; Yeah...
944 cmplwi r7,T_ALIGNMENT ; Alignment exception?
945 beq+ cr1,swapISI ; We had an ISI...
946 cmplwi cr1,r7,T_SYSTEM_CALL ; Exiting because of an system call?
947 beq+ swapDSI ; An alignment exception looks like a DSI...
948 beq+ cr1,swapSC ; We had a system call...
949
950 blr ; Return...
951
952;
953; Set exit returns for a DSI or alignment exception
954;
955
de355530 956swapDSI: lwz r10,savedar(r30) ; Get the DAR
1c79356b
A
957 lwz r7,savedsisr(r30) ; and the DSISR
958 stw r10,return_params+0(r5) ; Save DAR as first return parm
959 stw r7,return_params+4(r5) ; Save DSISR as second return parm
960 blr ; Return...
961
962;
963; Set exit returns for a ISI
964;
965
9bccf70c
A
966swapISI: lwz r7,vmmppcmsr(r5) ; Get the SRR1 value
967 lwz r10,vmmppcpc(r5) ; Get the PC as failing address
1c79356b
A
968 rlwinm r7,r7,0,1,4 ; Save the bits that match the DSISR
969 stw r10,return_params+0(r5) ; Save PC as first return parm
970 stw r7,return_params+4(r5) ; Save the pseudo-DSISR as second return parm
971 blr ; Return...
972
973;
974; Set exit returns for a system call (note: we did the first 3 earlier)
975; Do we really need to pass parameters back here????
976;
977
9bccf70c 978swapSC: lwz r10,vmmppcr6(r5) ; Get the fourth paramter
1c79356b
A
979 stw r10,return_params+12(r5) ; Save it
980 blr ; Return...
981
d7e50217
A
982;
983; vmmFamGuestResume:
984; Restore Guest context from Fam mode.
985;
986
987vmmFamGuestResume:
988 mfsprg r10,0 ; Get the per_proc
989 lwz r27,vmmCEntry(r3) ; Get the context that is active
d7e50217
A
990 lwz r15,spcFlags(r10) ; Get per_proc special flags
991 mr r26,r3 ; Save the activation pointer
de355530 992 lwz r17,vmmFlags(r27) ; Get the status flags
d7e50217
A
993 lwz r20,vmmContextKern(r27) ; Get the comm area
994 rlwinm r15,r15,0,FamVMmodebit+1,FamVMmodebit-1 ; Clear FamVMmodebit
995 stw r15,spcFlags(r10) ; Update the special flags
de355530 996 rlwinm. r0,r17,0,vmmMapDoneb,vmmMapDoneb ; Did we just do a map function?
d7e50217 997 lwz r7,famguestpc(r20) ; Load famguest ctx pc
de355530
A
998 andc r17,r17,r0 ; Turn off map flag
999 stw r17,vmmFlags(r27) ; Update vmmFlags
1000 beq+ vmmFamRetNoMap ; No mapping done...
d7e50217 1001 lwz r3,SAVflags(r30) ; Pick up the savearea flags
de355530 1002 lwz r2,vmmLastMap(r27) ; Get the last mapped address
d7e50217
A
1003 li r4,T_DATA_ACCESS ; Change to DSI fault
1004 oris r3,r3,hi16(SAVredrive) ; Set exception redrive
1005 stw r2,savedar(r30) ; Set the DAR to the last thing we mapped
d7e50217
A
1006 stw r3,SAVflags(r30) ; Turn on the redrive request
1007 lis r2,hi16(MASK(DSISR_HASH)) ; Set PTE/DBAT miss
1008 stw r4,saveexception(r30) ; Say we need to emulate a DSI
d7e50217 1009 stw r2,savedsisr(r30) ; Pretend we have a PTE miss
de355530
A
1010vmmFamRetNoMap:
1011 mfsrr1 r4 ; Get the current MSR value
1012 stw r7,savesrr0(r30) ; Set savearea pc
d7e50217
A
1013 lwz r5,famguestmsr(r20) ; Load famguest ctx msr
1014 lis r6,hi16(MSR_IMPORT_BITS) ; Get the MSR bits that are controllable by user
1015 ori r6,r6,lo16(MSR_IMPORT_BITS) ; Get the rest of the MSR bits that are controllable by user
1016 and r5,r5,r6 ; Keep only the controllable bits
1017 oris r5,r5,hi16(MSR_EXPORT_MASK_SET) ; Force on the required bits
1018 ori r5,r5,lo16(MSR_EXPORT_MASK_SET) ; Force on the other required bits
1019 rlwimi r5,r4,0,MSR_FP_BIT,MSR_FP_BIT ; Propagate guest FP
1020 rlwimi r5,r4,0,MSR_VEC_BIT,MSR_VEC_BIT ; Propagate guest Vector
de355530 1021 stw r5,savesrr1(r30) ; Set savearea srr1
d7e50217
A
1022 lwz r4,famguestr0(r20) ; Load famguest ctx r0
1023 lwz r5,famguestr1(r20) ; Load famguest ctx r1
1024 lwz r6,famguestr2(r20) ; Load famguest ctx r2
1025 lwz r7,famguestr3(r20) ; Load famguest ctx r3
de355530
A
1026 stw r4,saver0(r30) ; Set savearea r0
1027 stw r5,saver1(r30) ; Set savearea r1
1028 stw r6,saver2(r30) ; Set savearea r2
1029 stw r7,saver3(r30) ; Set savearea r3
d7e50217
A
1030 lwz r4,famguestr4(r20) ; Load famguest ctx r4
1031 lwz r5,famguestr5(r20) ; Load famguest ctx r5
1032 lwz r6,famguestr6(r20) ; Load famguest ctx r6
1033 lwz r7,famguestr7(r20) ; Load famguest ctx r7
de355530
A
1034 stw r4,saver4(r30) ; Set savearea r4
1035 stw r5,saver5(r30) ; Set savearea r5
1036 stw r6,saver6(r30) ; Set savearea r6
1037 stw r7,saver7(r30) ; Set savearea r7
1038
d7e50217
A
1039 li r3,1 ; Show normal exit with check for AST
1040 lwz r16,ACT_THREAD(r26) ; Restore the thread pointer
1041 b EXT(ppcscret) ; Go back to handler...
1042
1043;
de355530 1044; FAM Intercept handler
d7e50217
A
1045;
1046
1047 .align 5
de355530
A
1048 .globl EXT(vmm_fam_handler)
1049
1050LEXT(vmm_fam_handler)
1051 lwz r4,saver4(r13) ; Load savearea r0
d7e50217
A
1052 cmplwi r11,T_ALIGNMENT ; Alignment exception?
1053 lwz r3,VMMareaPhys(r2) ; Load phys state page addr
d7e50217 1054 cmplwi cr1,r11,T_PROGRAM ; Exiting because of an PRG?
d7e50217
A
1055 stw r4,famguestr4(r3) ; Save r4 in famguest ctx
1056 stw r5,famguestr5(r3) ; Save r5 in famguest ctx
1057 stw r6,famguestr6(r3) ; Save r6 in famguest ctx
1058 stw r7,famguestr7(r3) ; Save r7 in famguest ctx
de355530
A
1059 lwz r4,saver0(r13) ; Load savearea r0
1060 lwz r5,saver1(r13) ; Load savearea r1
1061 lwz r6,saver2(r13) ; Load savearea r2
1062 lwz r7,saver3(r13) ; Load savearea r3
d7e50217
A
1063 stw r4,famguestr0(r3) ; Save r0 in famguest ctx
1064 stw r5,famguestr1(r3) ; Save r1 in famguest ctx
1065 stw r6,famguestr2(r3) ; Save r2 in famguest ctx
1066 stw r7,famguestr3(r3) ; Save r3 in famguest ctx
1067 lwz r4,spcFlags(r2) ; Load per_proc spcFlags
1068 oris r4,r4,hi16(FamVMmode) ; Set FAM mode
1069 stw r4,spcFlags(r2) ; Update per_proc spcFlags
1070 mfsrr0 r2 ; Get the interrupt srr0
1071 mfsrr1 r4 ; Get the interrupt srr1
1072 stw r2,famguestpc(r3) ; Save srr0 in famguest ctx
1073 stw r4,famguestmsr(r3) ; Save srr1 in famguest ctx
1074 li r6,lo16(MASK(MSR_FE0)|MASK(MSR_SE)|MASK(MSR_BE)|MASK(MSR_FE1))
1075 andc r6,r4,r6 ; Clear SE BE FE0 FE1
1076 mtsrr1 r6 ; Set srr1
1077 mr r6,r3 ; Set r6 with phys state page addr
1078 rlwinm r7,r11,30,24,31 ; Convert exception to return code
de355530
A
1079 beq+ cr1,famPRG ; We had a program exception...
1080 bne+ famRet
d7e50217
A
1081 ; We had an Alignment...
1082 mfdar r3 ; Load dar
1083 mfdsisr r4 ; Load dsisr
1084 stw r3,famparam+0x4(r6) ; Set famparam 1 with dar
1085 stw r4,famparam+0x8(r6) ; Set famparam 2 with dsir
de355530
A
1086 b famRet ;
1087famPRG:
d7e50217
A
1088 stw r4,famparam+0x4(r6) ; Set famparam 1 with srr1
1089 mr r3,r4 ; Set r3 with dsisr
1090 lwz r4,famguestr4(r6) ; Load r4 from famguest context
de355530 1091famRet:
d7e50217
A
1092 lwz r5,famguestr5(r6) ; Load r5 from famguest context
1093 lwz r13,famhandler(r6) ; Load user address to resume
1094 stw r2,famparam(r6) ; Set famparam 0 with srr0
1095 stw r7,famdispcode(r6) ; Save the exit code
1096 lwz r1,famrefcon(r6) ; load refcon
d7e50217
A
1097 mtcr r0 ; Restore cr
1098 mtsrr0 r13 ; Load srr0
1099 mr r0,r7 ; Set dispatch code
1100 lwz r7,famguestr7(r6) ; Load r7 from famguest context
1101 lwz r6,famguestr6(r6) ; Load r6 from famguest context
1102 mfsprg r13,2 ; Restore r13
1103 mfsprg r11,3 ; Restore r11
1104 rfi
d7e50217
A
1105
1106;
1107; FAM Intercept DSI ISI fault handler
1108;
1109
1110 .align 5
de355530 1111 .globl EXT(vmm_fam_pf_handler)
d7e50217 1112
de355530 1113LEXT(vmm_fam_pf_handler)
d7e50217 1114 lwz r3,VMMareaPhys(r2) ; Load phys state page addr
de355530
A
1115 lwz r4,saver0(r13) ; Load savearea r0
1116 lwz r5,saver1(r13) ; Load savearea r1
1117 lwz r6,saver2(r13) ; Load savearea r2
1118 lwz r7,saver3(r13) ; Load savearea r3
d7e50217
A
1119 stw r4,famguestr0(r3) ; Save r0 in famguest
1120 stw r5,famguestr1(r3) ; Save r1 in famguest
1121 stw r6,famguestr2(r3) ; Save r2 in famguest
1122 stw r7,famguestr3(r3) ; Save r3 in famguest
de355530
A
1123 lwz r4,saver4(r13) ; Load savearea r0
1124 lwz r5,saver5(r13) ; Load savearea r1
1125 lwz r6,saver6(r13) ; Load savearea r2
1126 lwz r7,saver7(r13) ; Load savearea r3
d7e50217
A
1127 stw r4,famguestr4(r3) ; Save r4 in famguest
1128 lwz r4,spcFlags(r2) ; Load spcFlags
1129 stw r5,famguestr5(r3) ; Save r5 in famguest
de355530 1130 lwz r5,savesrr0(r13) ; Get the interrupt srr0
d7e50217 1131 stw r6,famguestr6(r3) ; Save r6 in famguest
de355530 1132 lwz r6,savesrr1(r13) ; Load srr1
d7e50217
A
1133 oris r4,r4,hi16(FamVMmode) ; Set FAM mode
1134 stw r7,famguestr7(r3) ; Save r7 in famguest
1135 stw r4,spcFlags(r2) ; Update spcFlags
1136 lwz r1,famrefcon(r3) ; Load refcon
1137 lwz r2,famhandler(r3) ; Load famhandler to resume
1138 stw r5,famguestpc(r3) ; Save srr0
de355530 1139 stw r5,saver2(r13) ; Store srr0 in savearea r2
d7e50217
A
1140 stw r5,famparam(r3) ; Store srr0 in fam param 0
1141 stw r6,famguestmsr(r3) ; Save srr1 in famguestmsr
1142 cmplwi cr1,r11,T_INSTRUCTION_ACCESS ; Was this a ISI?
1143 rlwinm r7,r11,30,24,31 ; Convert exception to return code
de355530
A
1144 beq+ cr1,FamPfISI ; We had an ISI...
1145; FamPfDSI
1146 lwz r6,savedar(r13) ; Load dar from savearea
d7e50217
A
1147 lwz r4,savedsisr(r13) ; Load dsisr from savearea
1148 stw r6,famparam+0x4(r3) ; Store dar in fam param 1
de355530 1149 stw r6,saver3(r13) ; Store dar in savearea r3
d7e50217 1150 stw r4,famparam+0x8(r3) ; Store dsisr in fam param 2
de355530
A
1151 stw r4,saver4(r13) ; Store dsisr in savearea r4
1152 b FamPfRet
1153FamPfISI:
d7e50217
A
1154 rlwinm r6,r6,0,1,4 ; Save the bits that match the DSISR
1155 stw r6,famparam+0x4(r3) ; Store srr1 in fam param 1
de355530
A
1156 stw r6,saver3(r13) ; Store srr1 in savearea r3
1157FamPfRet:
1158 stw r7,saver0(r13) ; Set dispatch code
d7e50217 1159 stw r7,famdispcode(r3) ; Set dispatch code
de355530
A
1160 stw r1,saver1(r13) ; Store refcon in savearea r1
1161 stw r2,savesrr0(r13) ; Store famhandler in srr0
d7e50217
A
1162 blr
1163
1164;
1165; Ultra Fast Path FAM syscalls
1166;
1167
1168 .align 5
1169 .globl EXT(vmm_ufp)
1170
1171LEXT(vmm_ufp)
1172 mfsprg r3,0 ; Get the per_proc area
de355530
A
1173 bt cr5_eq,ResumeGuest ; if kvmmResumeGuest, branch to ResumeGuest
1174 lwz r3,VMMareaPhys(r3) ; Load fast assist area
d7e50217
A
1175 cmpwi cr7,r4,0 ; Compare first arg with 0
1176 cmpwi cr5,r4,7 ; Compare first arg with 7
1177 cror cr1_eq,cr7_lt,cr5_gt ; Is it in 0 to 7 range
1178 beq cr1,ufpVMret ; Return if not in the range
1179 slwi r4,r4,2 ; multiply index by 4
de355530
A
1180 la r3,famguestr0(r3) ; Load the base address
1181 bt cr6_eq,SetGuestReg ; Set/get selector
1182; GetGuestReg
d7e50217
A
1183 lwzx r3,r4,r3 ; Load the guest register
1184 b ufpVMret ; Return
de355530 1185SetGuestReg:
d7e50217
A
1186 stwx r5,r4,r3 ; Update the guest register
1187 li r3,0 ; Set return value
1188 b ufpVMret ; Return
de355530 1189ResumeGuest:
d7e50217 1190 lwz r7,spcFlags(r3) ; Pick up the special flags
de355530 1191 lwz r13,VMMareaPhys(r3) ; Load fast assist area
d7e50217
A
1192 mtsrr0 r4 ; Set srr0
1193 rlwinm. r6,r6,0,vmmKeyb,vmmKeyb ; Check vmmKeyb in maskCntrl
1194 rlwinm r7,r7,0,FamVMmodebit+1,FamVMmodebit-1 ; Clear FamVMmodebit
de355530 1195 beq ResumeGuest_nokey ; Branch if not key switch
d7e50217
A
1196 mr r2,r7 ; Save r7
1197 rlwimi r7,r5,32+vmmKeyb-userProtKeybit,userProtKeybit,userProtKeybit ; Set the protection key
1198 cmpw cr0,r7,r2 ; Is userProtKeybit changed?
de355530
A
1199 beq ResumeGuest_nokey ; No, go to ResumeGuest_nokey
1200 lwz r2,PP_USERPMAP(r3) ; Get user pmap phys addr
1201 rlwinm r6,r7,userProtKeybit-2,2,2 ; Extract and shift the key bit
1202 lwz r5,PMAP_SPACE(r2) ; Load the space id
1203 oris r5,r5,hi16(SEG_REG_PROT) ; Set the protection
1204 xor r5,r5,r6 ; Flip to proper segment register key
1205 addis r4,r5,0x0000 ; Get SR0 value
1206 mtsr sr0,r4 ; Load up the SR
1207 addis r4,r5,0x0010 ; Get SR1 value
1208 mtsr sr1,r4 ; Load up the SR
1209 addis r4,r5,0x0020 ; Get SR2 value
1210 mtsr sr2,r4 ; Load up the SR
1211 addis r4,r5,0x0030 ; Get SR3 value
1212 mtsr sr3,r4 ; Load up the SR
1213 addis r4,r5,0x0040 ; Get SR4 value
1214 mtsr sr4,r4 ; Load up the SR
1215 addis r4,r5,0x0050 ; Get SR5 value
1216 mtsr sr5,r4 ; Load up the SR
1217 addis r4,r5,0x0060 ; Get SR6 value
1218 mtsr sr6,r4 ; Load up the SR
1219 addis r4,r5,0x0070 ; Get SR7 value
1220 mtsr sr7,r4 ; Load up the SR
1221 addis r4,r5,0x0080 ; Get SR8 value
1222 mtsr sr8,r4 ; Load up the SR
1223 addis r4,r5,0x0090 ; Get SR9 value
1224 mtsr sr9,r4 ; Load up the SR
1225 addis r4,r5,0x00a0 ; Get SR10 value
1226 mtsr sr10,r4 ; Load up the SR
1227 addis r4,r5,0x00b0 ; Get SR11 value
1228 mtsr sr11,r4 ; Load up the SR
1229 addis r4,r5,0x00c0 ; Get SR12 value
1230 mtsr sr12,r4 ; Load up the SR
1231 addis r4,r5,0x00d0 ; Get SR13 value
1232 mtsr sr13,r4 ; Load up the SR
1233 addis r4,r5,0x00e0 ; Get SR14 value
1234 mtsr sr14,r4 ; Load up the SR
1235 addis r4,r5,0x00f0 ; Get SR15 value
1236 mtsr sr15,r4 ; Load up the SR
1237ResumeGuest_nokey:
1238 mfsrr1 r6 ; Get the current MSR value
d7e50217
A
1239 lwz r0,famguestr0(r13) ; Load r0
1240 lwz r1,famguestr1(r13) ; Load r1
de355530
A
1241 lwz r4,famguestmsr(r13) ; Load guest srr1
1242 stw r7,spcFlags(r3) ; Update the special flags
1243 lis r5,hi16(MSR_IMPORT_BITS) ; Get the MSR bits that are controllable by user
d7e50217
A
1244 lwz r2,famguestr2(r13) ; Load r2
1245 lwz r3,famguestr3(r13) ; Load r3
de355530
A
1246 ori r5,r5,lo16(MSR_IMPORT_BITS) ; Get the rest of the MSR bits that are controllable by user
1247 and r7,r4,r5 ; Keep only the controllable bits
d7e50217 1248 lwz r4,famguestr4(r13) ; Load r4
de355530 1249 oris r7,r7,hi16(MSR_EXPORT_MASK_SET) ; Force on the required bits
d7e50217 1250 lwz r5,famguestr5(r13) ; Load r5
de355530
A
1251 ori r7,r7,lo16(MSR_EXPORT_MASK_SET) ; Force on the other required bits
1252 rlwimi r7,r6,0,MSR_FP_BIT,MSR_FP_BIT ; Propagate guest FP
1253 rlwimi r7,r6,0,MSR_VEC_BIT,MSR_VEC_BIT ; Propagate guest Vector
1254 mtsrr1 r7 ; Set srr1
d7e50217
A
1255 lwz r6,famguestr6(r13) ; Load r6
1256 lwz r7,famguestr7(r13) ; Load r7
1257ufpVMret:
d7e50217
A
1258 mtcrf 0xFF,r11 ; Restore CR
1259 mfsprg r11,3 ; Restore R11
d7e50217 1260 mfsprg r13,2 ; Restore R13
de355530 1261 rfi ; All done, go back...