swtch.S revision 112924
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 112924 2003-04-01 04:58:50Z 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 .register %g2, #ignore 35 .register %g3, #ignore 36 37#include "assym.s" 38 39ENTRY(cpu_throw) 40 save %sp, -CCFSZ, %sp 41 call choosethread 42 ldx [PCPU(CURTHREAD)], %l0 43 flushw 44 b,a %xcc, .Lsw1 45 nop 46END(cpu_throw) 47 48ENTRY(cpu_switch) 49 /* 50 * Choose a new thread. If its the same as the current one, do 51 * nothing. 52 */ 53 save %sp, -CCFSZ, %sp 54 call choosethread 55 ldx [PCPU(CURTHREAD)], %l0 56 cmp %l0, %o0 57 be,a,pn %xcc, 4f 58 nop 59 ldx [%l0 + TD_PCB], %l1 60 61 /* 62 * If the current thread was using floating point, save its context. 63 */ 64 ldx [%l0 + TD_FRAME], %l2 65 ldx [%l2 + TF_FPRS], %l3 66 andcc %l3, FPRS_FEF, %g0 67 bz,a,pt %xcc, 1f 68 nop 69 wr %g0, FPRS_FEF, %fprs 70 wr %g0, ASI_BLK_S, %asi 71 stda %f0, [%l1 + PCB_UFP + (0 * 64)] %asi 72 stda %f16, [%l1 + PCB_UFP + (1 * 64)] %asi 73 stda %f32, [%l1 + PCB_UFP + (2 * 64)] %asi 74 stda %f48, [%l1 + PCB_UFP + (3 * 64)] %asi 75 membar #Sync 76 wr %g0, 0, %fprs 77 andn %l3, FPRS_FEF, %l3 78 stx %l3, [%l2 + TF_FPRS] 79 ldx [%l1 + PCB_FLAGS], %l3 80 or %l3, PCB_FEF, %l3 81 stx %l3, [%l1 + PCB_FLAGS] 82 83 /* 84 * Flush the windows out to the stack and save the current frame 85 * pointer and program counter. 86 */ 871: flushw 88 wrpr %g0, 0, %cleanwin 89 stx %fp, [%l1 + PCB_SP] 90 stx %i7, [%l1 + PCB_PC] 91 92 /* 93 * Load the new thread's frame pointer and program counter, and set 94 * the current thread and pcb. 95 */ 96.Lsw1: 97#if KTR_COMPILE & KTR_PROC 98 CATR(KTR_PROC, "cpu_switch: new td=%p pc=%#lx fp=%#lx" 99 , %g1, %g2, %g3, 7, 8, 9) 100 stx %o0, [%g1 + KTR_PARM1] 101 ldx [%o0 + TD_PCB], %g2 102 ldx [%g2 + PCB_PC], %g3 103 stx %g3, [%g1 + KTR_PARM2] 104 ldx [%g2 + PCB_SP], %g3 105 stx %g3, [%g1 + KTR_PARM3] 1069: 107#endif 108 ldx [%o0 + TD_PCB], %o1 109 ldx [%o1 + PCB_SP], %fp 110 ldx [%o1 + PCB_PC], %i7 111 sub %fp, CCFSZ, %sp 112 stx %o0, [PCPU(CURTHREAD)] 113 stx %o1, [PCPU(CURPCB)] 114 115 SET(sched_lock, %o3, %o2) 116 stx %o0, [%o2 + MTX_LOCK] 117 118 wrpr %g0, PSTATE_NORMAL, %pstate 119 mov %o1, PCB_REG 120 wrpr %g0, PSTATE_ALT, %pstate 121 mov %o1, PCB_REG 122 wrpr %g0, PSTATE_KERNEL, %pstate 123 124 /* 125 * Point to the vmspaces of the new process, and of the last non-kernel 126 * process to run. 127 */ 128 ldx [%o0 + TD_PROC], %o2 129 ldx [PCPU(VMSPACE)], %l2 130 ldx [%o2 + P_VMSPACE], %o2 131 132#if KTR_COMPILE & KTR_PROC 133 CATR(KTR_PROC, "cpu_switch: new vm=%p old vm=%p" 134 , %g1, %g2, %g3, 7, 8, 9) 135 stx %o2, [%g1 + KTR_PARM1] 136 stx %l2, [%g1 + KTR_PARM2] 1379: 138#endif 139 140 /* 141 * If they are the same we are done. 142 */ 143 cmp %l2, %o2 144 be,a,pn %xcc, 4f 145 nop 146 147 /* 148 * If the new process has nucleus context we are done. 149 */ 150 lduw [PCPU(CPUID)], %o3 151 sllx %o3, INT_SHIFT, %o3 152 add %o2, VM_PMAP + PM_CONTEXT, %o4 153 lduw [%o3 + %o4], %o5 154 155#if KTR_COMPILE & KTR_PROC 156 CATR(KTR_PROC, "cpu_switch: ctx=%#lx" 157 , %g1, %g2, %g3, 7, 8, 9) 158 stx %o5, [%g1 + KTR_PARM1] 1599: 160#endif 161 162 brz,a,pn %o5, 4f 163 nop 164 165 /* 166 * If there was no non-kernel vmspace, don't try to deactivate it. 167 */ 168 brz,a,pn %l2, 2f 169 nop 170 171 /* 172 * Mark the pmap of the last non-kernel vmspace to run as no longer 173 * active on this cpu. 174 */ 175 lduw [%l2 + VM_PMAP + PM_ACTIVE], %l3 176 lduw [PCPU(CPUMASK)], %l4 177 andn %l3, %l4, %l3 178 stw %l3, [%l2 + VM_PMAP + PM_ACTIVE] 179 180 /* 181 * Take away its context. 182 */ 183 lduw [PCPU(CPUID)], %l3 184 sllx %l3, INT_SHIFT, %l3 185 add %l2, VM_PMAP + PM_CONTEXT, %l4 186 mov -1, %l5 187 stw %l5, [%l3 + %l4] 188 189 /* 190 * Find the current free tlb context for this cpu and install it as 191 * the new primary context. 192 */ 1932: lduw [PCPU(TLB_CTX)], %o5 194 stw %o5, [%o3 + %o4] 195 mov AA_DMMU_PCXR, %o4 196 stxa %o5, [%o4] ASI_DMMU 197 membar #Sync 198 199 /* 200 * See if we have run out of free contexts. 201 */ 202 lduw [PCPU(TLB_CTX_MAX)], %o3 203 204#if KTR_COMPILE & KTR_PROC 205 CATR(KTR_PROC, "cpu_switch: ctx=%#lx next=%#lx max=%#lx" 206 , %g1, %g2, %g3, 7, 8, 9) 207 stx %o5, [%g1 + KTR_PARM1] 208 add %o5, 1, %g2 209 stx %g2, [%g1 + KTR_PARM2] 210 stx %o3, [%g1 + KTR_PARM3] 2119: 212#endif 213 214 add %o5, 1, %o5 215 cmp %o3, %o5 216 bne,a,pt %xcc, 3f 217 stw %o5, [PCPU(TLB_CTX)] 218 219#if KTR_COMPILE & KTR_PROC 220 CATR(KTR_PROC, "cpu_switch: context rollover" 221 , %g1, %g2, %g3, 7, 8, 9) 2229: 223#endif 224 225 /* 226 * We will start re-using contexts on the next switch. Flush all 227 * non-nucleus mappings from the tlb, and reset the next free context. 228 */ 229 call pmap_context_rollover 230 nop 231 ldx [PCPU(CURTHREAD)], %o0 232 ldx [%o0 + TD_PROC], %o2 233 ldx [%o2 + P_VMSPACE], %o2 234 235 /* 236 * Mark the pmap as active on this cpu. 237 */ 2383: lduw [%o2 + VM_PMAP + PM_ACTIVE], %o3 239 lduw [PCPU(CPUMASK)], %o4 240 or %o3, %o4, %o3 241 stw %o3, [%o2 + VM_PMAP + PM_ACTIVE] 242 243 /* 244 * Make note of the change in vmspace. 245 */ 246 stx %o2, [PCPU(VMSPACE)] 247 248 /* 249 * Load the tsb registers. 250 */ 251 ldx [%o2 + VM_PMAP + PM_TSB], %o3 252 mov AA_DMMU_TSB, %o4 253 stxa %o3, [%o4] ASI_DMMU 254 mov AA_IMMU_TSB, %o4 255 stxa %o3, [%o4] ASI_IMMU 256 membar #Sync 257 2584: 259#if KTR_COMPILE & KTR_PROC 260 CATR(KTR_PROC, "cpu_switch: return" 261 , %g1, %g2, %g3, 7, 8, 9) 2629: 263#endif 264 265 /* 266 * Done. Return and load the new process's window from the stack. 267 */ 268 ret 269 restore 270END(cpu_switch) 271 272ENTRY(savectx) 273 save %sp, -CCFSZ, %sp 274 flushw 275 call savefpctx 276 mov %i0, %o0 277 stx %fp, [%i0 + PCB_SP] 278 stx %i7, [%i0 + PCB_PC] 279 ret 280 restore %g0, 0, %o0 281END(savectx) 282 283/* 284 * void savefpctx(uint32_t *); 285 */ 286ENTRY(savefpctx) 287 wr %g0, FPRS_FEF, %fprs 288 wr %g0, ASI_BLK_S, %asi 289 stda %f0, [%o0 + (0 * 64)] %asi 290 stda %f16, [%o0 + (1 * 64)] %asi 291 stda %f32, [%o0 + (2 * 64)] %asi 292 stda %f48, [%o0 + (3 * 64)] %asi 293 membar #Sync 294 retl 295 wr %g0, 0, %fprs 296END(savefpctx) 297