-;
-; Set segment registers for user access. Do not call this if we are trying to get
-; supervisor state memory. We do not need this.
-;
-; Performance-wise, we will usually be setting one SR here. Most memory will be
-; allocated before the 1GB mark. Since the kernel maps the first GB, the exception
-; handler always sets the SRs before we get here. Therefore, we will usually
-; have to remap it.
-;
-; Also, we need to un-do these mapping ONLY if we take a non-standard
-; exit, e.g., emulate DSI, emulate trace exception, etc. This is because
-; translation will never be turned on until we return and at that point,
-; normal exception exit code will restore the first 4 SRs if needed.
-;
-
- .align 5
-
- .globl EXT(aaSetSegsX)
-
-LEXT(aaSetSegsX)
-
-aaSetSegs: addi r3,r25,-1 ; Point at last accessed offset in range
- lwz r7,PP_USERPMAP(r31) ; Get the current user pmap
- lis r0,0x4000 ; This is the address of the first segment outside of the kernel
- rlwinm r5,r23,6,26,29 ; Get index into pmap table
- add r4,r23,r3 ; Point to the last byte accessed
- addi r7,r7,PMAP_SEGS ; Point to the segment slot
- cmplw r23,r0 ; See if first segment register needs to be reloaded
- cmplw cr2,r4,r0 ; Do we need to set the second (if any) SR?
- xor r0,r4,r23 ; See if we are in the same segment as first
- bge aaSetS1ok ; Nope, we are in a pure user range
-
- lwzx r6,r5,r7 ; Get the user address space SR value
- mtsrin r6,r23 ; Load the corresponding SR register
-
-aaSetS1ok: rlwinm. r0,r0,0,0,3 ; Any change in segment?
- bgelr- cr2 ; We are in user only space, we do not need to mess with SR
- rlwinm r5,r4,6,26,29 ; Get index into pmap table
- beqlr+ ; No change in segment, we are done...
-
- lwzx r6,r5,r7 ; Get the user address space SR value
- mtsrin r6,r4 ; Load the corresponding SR register
- blr ; Leave...
-
-;
-; Unset segment registers for user access. Do not call unless we had a user access.
-;
-
- .align 5
-
- .globl EXT(aaUnSetSegsX)
-
-LEXT(aaUnSetSegsX)
-
-aaUnSetSegs:
- addi r3,r25,-1 ; Point at last accessed offset in range
- lis r0,0x4000 ; This is the address of the first segment outside of the kernel
- lis r5,hi16(KERNEL_SEG_REG0_VALUE) ; Get the high half of the kernel SR0 value
- add r4,r23,r3 ; Point to the last byte accessed
- cmplw r23,r0 ; See if first segment register needs to be reloaded
- rlwimi r5,r23,24,8,11 ; Make the correct kernel segment
- cmplw cr2,r4,r0 ; Do we need to set the second (if any) SR?
- xor r0,r4,r23 ; See if we are in the same segment as first
- bge aaUnSetS1ok ; Nope, we are in a pure user range
-
- mtsrin r5,r23 ; Load the corresponding SR register
-
-aaUnSetS1ok:
- rlwinm. r0,r0,0,0,3 ; Any change in segment?
- bgelr cr2 ; We are in user only space, we do not need to mess with SR
- rlwimi r5,r4,24,8,11 ; Make the correct kernel segment
- beqlr+ ; No change in segment, we are done...
-
- mtsrin r5,r4 ; Load the corresponding SR register
- blr ; Leave...
-