swtch.S revision 82909
1/*- 2 * Copyright (c) 2001 Jake Burkholder. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD: head/sys/sparc64/sparc64/swtch.S 82909 2001-09-03 23:18:02Z jake $ 27 */ 28 29#include <machine/asmacros.h> 30#include <machine/asi.h> 31#include <machine/ktr.h> 32#include <machine/tstate.h> 33 34#include "assym.s" 35 36/* 37 * Save and restore FPU state. This is done at switch time. 38 * We could use FPRS_DL and FPRS_DU; however, it is accessible to non-privileged 39 * software, so it is avoided for compatabilities sake. 40 * savefp clobbers %fprs. 41 */ 42 .macro savefp state, tmp, fprs 43 or \fprs, FPRS_FEF, \tmp 44 wr \tmp, 0, %fprs 45 stx %fsr, [\state + FP_FSR] 46 rd %asi, \tmp 47 wr %g0, ASI_BLK_S, %asi 48 stda %f0, [\state + FP_FB0] %asi 49 stda %f16, [\state + FP_FB1] %asi 50 stda %f32, [\state + FP_FB2] %asi 51 stda %f48, [\state + FP_FB3] %asi 52 wr \tmp, 0, %asi 53 membar #Sync 54 .endm 55 56 .macro restrfp state, tmp 57 rd %fprs, \tmp 58 or \tmp, FPRS_FEF, \tmp 59 wr \tmp, 0, %fprs 60 rd %asi, \tmp 61 wr %g0, ASI_BLK_S, %asi 62 ldda [\state + FP_FB0] %asi, %f0 63 ldda [\state + FP_FB1] %asi, %f16 64 ldda [\state + FP_FB2] %asi, %f32 65 ldda [\state + FP_FB3] %asi, %f48 66 wr \tmp, 0, %asi 67 membar #Sync 68 ldx [\state + FP_FSR], %fsr 69 .endm 70 71ENTRY(cpu_throw) 72 save %sp, -CCFSZ, %sp 73 call chooseproc 74 ldx [PCPU(CURPROC)], %l0 75 flushw 76 b,a .Lsw1 77END(cpu_throw) 78 79ENTRY(cpu_switch) 80 /* 81 * Choose a new process. If its the same as the current one, do 82 * nothing. 83 */ 84 save %sp, -CCFSZ, %sp 85 call chooseproc 86 ldx [PCPU(CURPROC)], %l0 87#if KTR_COMPILE & KTR_CT1 88 CATR(KTR_CT1, "cpu_switch: from=%p (%s) to=%p (%s)" 89 , %g1, %g2, %g3, 7, 8, 9) 90 stx %l0, [%g1 + KTR_PARM1] 91 add %l0, P_COMM, %g2 92 stx %g2, [%g1 + KTR_PARM2] 93 stx %o0, [%g1 + KTR_PARM3] 94 add %o0, P_COMM, %g2 95 stx %g2, [%g1 + KTR_PARM4] 969: 97#endif 98 cmp %l0, %o0 99 be,pn %xcc, 3f 100 EMPTY 101 102 /* 103 * Always save %fprs and %y. Both are not used within the kernel 104 * and are therefore not saved in the trap frame. 105 * If the process was using floating point, save its context. 106 */ 107 ldx [%l0 + P_FRAME], %l1 108 ldx [PCPU(CURPCB)], %l2 109 rd %y, %l3 110 stx %l3, [%l2 + PCB_Y] 111 rd %fprs, %l3 112 stx %l3, [%l2 + PCB_FPSTATE + FP_FPRS] 113 ldx [%l1 + TF_TSTATE], %l1 114 andcc %l1, TSTATE_PEF, %l1 115 be,pt %xcc, 1f 116 nop 117 savefp %l2 + PCB_FPSTATE, %l4, %l3 118 119 /* 120 * Flush the windows out to the stack and save the current frame 121 * pointer and program counter. 122 */ 1231: flushw 124 wrpr %g0, 0, %cleanwin 125 rdpr %cwp, %l3 126 stx %l3, [%l2 + PCB_CWP] 127 stx %fp, [%l2 + PCB_FP] 128 stx %i7, [%l2 + PCB_PC] 129 130 /* 131 * Load the new process's frame pointer and program counter, and set 132 * the current process and pcb. 133 */ 134.Lsw1: ldx [%o0 + P_ADDR], %o1 135#if KTR_COMPILE & KTR_CT1 136 CATR(KTR_CT1, "cpu_switch: to=%p pc=%#lx fp=%#lx sp=%#lx cwp=%#lx" 137 , %g1, %g2, %g3, 7, 8, 9) 138 stx %o0, [%g1 + KTR_PARM1] 139 ldx [%o1 + U_PCB + PCB_PC], %g2 140 stx %g2, [%g1 + KTR_PARM2] 141 ldx [%o1 + U_PCB + PCB_FP], %g2 142 stx %g2, [%g1 + KTR_PARM3] 143 sub %g2, CCFSZ, %g2 144 stx %g2, [%g1 + KTR_PARM4] 145 ldx [%o1 + U_PCB + PCB_CWP], %g2 146 stx %g2, [%g1 + KTR_PARM5] 1479: 148#endif 149#if 1 150 mov %o0, %g4 151 mov %l0, %g5 152 ldx [%o1 + U_PCB + PCB_CWP], %o2 153 wrpr %o2, %cwp 154 mov %g4, %o0 155 mov %g5, %l0 156#endif 157 ldx [%o0 + P_ADDR], %o1 158 ldx [%o1 + U_PCB + PCB_FP], %fp 159 ldx [%o1 + U_PCB + PCB_PC], %i7 160 sub %fp, CCFSZ, %sp 161 stx %o0, [PCPU(CURPROC)] 162 stx %o1, [PCPU(CURPCB)] 163 164 /* 165 * Point to the new process's vmspace and load its vm context number. 166 * If its nucleus context we are done. 167 */ 168 ldx [%o0 + P_VMSPACE], %o2 169 lduw [%o2 + VM_PMAP + PM_CONTEXT], %o3 170#if KTR_COMPILE & KTR_CT1 171 CATR(KTR_CT1, "cpu_switch: to=%p vm=%p context=%#x" 172 , %g1, %g2, %g3, 7, 8, 9) 173 stx %o0, [%g1 + KTR_PARM1] 174 stx %o2, [%g1 + KTR_PARM2] 175 stx %o3, [%g1 + KTR_PARM3] 1769: 177#endif 178 brz,pn %o3, 3f 179 EMPTY 180 181 /* 182 * If the new process was using floating point, restore its context. 183 * Always restore %fprs and %y. 184 */ 185 ldx [%o0 + P_FRAME], %o4 186 ldx [%o4 + TF_TSTATE], %o4 187 andcc %o4, TSTATE_PEF, %o4 188 be,pt %xcc, 2f 189 nop 190 restrfp %o1 + U_PCB + PCB_FPSTATE, %o4 191 1922: ldx [%o1 + PCB_FPSTATE + FP_FPRS], %o4 193 wr %o4, 0, %fprs 194 ldx [%o1 + PCB_Y], %o4 195 wr %o4, 0, %y 196 197 /* 198 * Point to the current process's vmspace and load the hardware 199 * context number. If its the same as the new process, we are 200 * done. 201 */ 202 ldx [%l0 + P_VMSPACE], %l1 203 lduw [%l1 + VM_PMAP + PM_CONTEXT], %l3 204#if KTR_COMPILE & KTR_CT1 205 CATR(KTR_CT1, "cpu_switch: from=%p vm=%p context=%#x" 206 , %g1, %g2, %g3, 7, 8, 9) 207 stx %l0, [%g1 + KTR_PARM1] 208 stx %l1, [%g1 + KTR_PARM2] 209 stx %l3, [%g1 + KTR_PARM3] 2109: 211#endif 212 cmp %l3, %o3 213 be,pn %xcc, 3f 214 EMPTY 215 216 /* 217 * Install the new primary context. 218 */ 219 mov AA_DMMU_PCXR, %o1 220 stxa %o3, [%o1] ASI_DMMU 221 flush %o0 222 223 /* 224 * Map the primary user tsb. 225 */ 226 setx TSB_USER_MIN_ADDRESS, %o1, %o0 227 mov AA_DMMU_TAR, %o1 228 stxa %o0, [%o1] ASI_DMMU 229 mov TLB_DAR_TSB_USER_PRIMARY, %o1 230 ldx [%o2 + VM_PMAP + PM_STTE + TTE_DATA], %o3 231 stxa %o3, [%o1] ASI_DTLB_DATA_ACCESS_REG 232 membar #Sync 233 234 /* 235 * If the primary tsb page hasn't been initialized, initialize it 236 * and update the bit in the tte. 237 */ 238 andcc %o3, TD_INIT, %g0 239 bnz %xcc, 3f 240 or %o3, TD_INIT, %o3 241 stx %o3, [%o2 + VM_PMAP + PM_STTE + TTE_DATA] 242 call tsb_page_init 243 clr %o1 244 245 /* 246 * Done. Return and load the new process's window from the stack. 247 */ 2483: 249#if KTR_COMPILE & KTR_CT1 250 CATR(KTR_CT1, "cpu_switch: return p=%p (%s)" 251 , %g1, %g2, %g3, 7, 8, 9) 252 ldx [PCPU(CURPROC)], %g2 253 stx %g2, [%g1 + KTR_PARM1] 254 add %g2, P_COMM, %g3 255 stx %g3, [%g1 + KTR_PARM2] 2569: 257#endif 258 ret 259 restore 260END(cpu_switch) 261 262ENTRY(savectx) 263 save %sp, -CCFSZ, %sp 264 flushw 265 rd %y, %l0 266 stx %l0, [%i0 + PCB_Y] 267 rd %fprs, %l0 268 stx %l0, [%i0 + PCB_FPSTATE + FP_FPRS] 269 ldx [PCPU(CURPROC)], %l0 270 ldx [%l0 + P_FRAME], %l0 271 ldx [%l0 + TF_TSTATE], %l0 272 andcc %l0, TSTATE_PEF, %l0 273 be,pt %xcc, 1f 274 stx %fp, [%i0 + PCB_FP] 275 add %i0, PCB_FPSTATE, %o0 276 call savefpctx 2771: stx %i7, [%i0 + PCB_PC] 278 ret 279 restore %g0, 0, %o0 280END(savectx) 281 282/* Note: this does not save %fprs. */ 283ENTRY(savefpctx) 284 rd %fprs, %o2 285 savefp %o0, %o1, %o2 286 retl 287 wr %o2, 0, %fprs 288END(savefpctx) 289 290ENTRY(restorefpctx) 291 restrfp %o0, %o1 292 ldx [%o0 + FP_FPRS], %o1 293 retl 294 wr %o1, 0, %fprs 295END(restorefpctx) 296