swtch.S revision 89043
180709Sjake/*- 280709Sjake * Copyright (c) 2001 Jake Burkholder. 380709Sjake * All rights reserved. 480709Sjake * 580709Sjake * Redistribution and use in source and binary forms, with or without 680709Sjake * modification, are permitted provided that the following conditions 780709Sjake * are met: 880709Sjake * 1. Redistributions of source code must retain the above copyright 980709Sjake * notice, this list of conditions and the following disclaimer. 1080709Sjake * 2. Redistributions in binary form must reproduce the above copyright 1180709Sjake * notice, this list of conditions and the following disclaimer in the 1280709Sjake * documentation and/or other materials provided with the distribution. 1380709Sjake * 1481337Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1580709Sjake * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1680709Sjake * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1781337Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1880709Sjake * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1980709Sjake * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2080709Sjake * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2180709Sjake * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2280709Sjake * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2380709Sjake * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2480709Sjake * SUCH DAMAGE. 2580709Sjake * 2680709Sjake * $FreeBSD: head/sys/sparc64/sparc64/swtch.S 89043 2002-01-08 05:10:07Z jake $ 2780709Sjake */ 2880709Sjake 2980709Sjake#include <machine/asmacros.h> 3081184Sjake#include <machine/asi.h> 3182909Sjake#include <machine/ktr.h> 3282909Sjake#include <machine/tstate.h> 3380709Sjake 3480709Sjake#include "assym.s" 3580709Sjake 3682013SjakeENTRY(cpu_throw) 3782013Sjake save %sp, -CCFSZ, %sp 3883366Sjulian call choosethread 3983366Sjulian ldx [PCPU(CURTHREAD)], %l0 4082013Sjake flushw 4188645Sjake b,a %xcc, .Lsw1 4288645Sjake nop 4382013SjakeEND(cpu_throw) 4482013Sjake 4580709SjakeENTRY(cpu_switch) 4681184Sjake /* 4788645Sjake * Choose a new thread. If its the same as the current one, do 4881184Sjake * nothing. 4981184Sjake */ 5080709Sjake save %sp, -CCFSZ, %sp 5183366Sjulian call choosethread 5283366Sjulian ldx [PCPU(CURTHREAD)], %l0 5380709Sjake cmp %l0, %o0 5488645Sjake be,a,pn %xcc, 6f 5588645Sjake nop 5688645Sjake ldx [%l0 + TD_PCB], %l1 5781184Sjake 5881184Sjake /* 5988645Sjake * If the current thread was using floating point, save its context. 6081184Sjake */ 6188645Sjake ldx [%l0 + TD_FRAME], %l2 6288645Sjake ldub [%l2 + TF_FPRS], %l3 6388645Sjake andcc %l3, FPRS_FEF, %g0 6488645Sjake bz,a,pt %xcc, 1f 6582013Sjake nop 6688645Sjake wr %g0, FPRS_FEF, %fprs 6788645Sjake wr %g0, ASI_BLK_S, %asi 6888645Sjake stda %f0, [%l1 + PCB_FPSTATE + FP_FB0] %asi 6988645Sjake stda %f16, [%l1 + PCB_FPSTATE + FP_FB1] %asi 7088645Sjake stda %f32, [%l1 + PCB_FPSTATE + FP_FB2] %asi 7188645Sjake stda %f48, [%l1 + PCB_FPSTATE + FP_FB3] %asi 7288645Sjake membar #Sync 7388645Sjake wr %g0, 0, %fprs 7488645Sjake andn %l3, FPRS_FEF, %l3 7588645Sjake stb %l3, [%l2 + TF_FPRS] 7681184Sjake 7781184Sjake /* 7881184Sjake * Flush the windows out to the stack and save the current frame 7981184Sjake * pointer and program counter. 8081184Sjake */ 8180709Sjake1: flushw 8280709Sjake wrpr %g0, 0, %cleanwin 8388645Sjake stx %fp, [%l1 + PCB_FP] 8488645Sjake stx %i7, [%l1 + PCB_PC] 8581184Sjake 8681184Sjake /* 8788645Sjake * Load the new thread's frame pointer and program counter, and set 8888645Sjake * the current thread and pcb. 8981184Sjake */ 9088645Sjake.Lsw1: 9185239Sjake#if KTR_COMPILE & KTR_PROC 9288645Sjake CATR(KTR_PROC, "cpu_switch: td=%d (%s) pc=%#lx fp=%#lx" 9388645Sjake , %l3, %l4, %l5, 7, 8, 9) 9488645Sjake ldx [%o0 + TD_PROC], %l4 9588645Sjake lduw [%l4 + P_PID], %l5 9688645Sjake stx %l5, [%l3 + KTR_PARM1] 9788645Sjake add %l4, P_COMM, %l5 9888645Sjake stx %l5, [%l3 + KTR_PARM2] 9988645Sjake ldx [%o0 + TD_PCB], %l4 10088645Sjake ldx [%l4 + PCB_PC], %l5 10188645Sjake stx %l5, [%l3 + KTR_PARM3] 10288645Sjake ldx [%l4 + PCB_FP], %l5 10388645Sjake stx %l5, [%l3 + KTR_PARM4] 10482909Sjake9: 10582909Sjake#endif 10683366Sjulian ldx [%o0 + TD_PCB], %o1 10783366Sjulian ldx [%o1 + PCB_FP], %fp 10883366Sjulian ldx [%o1 + PCB_PC], %i7 10981184Sjake sub %fp, CCFSZ, %sp 11083366Sjulian stx %o0, [PCPU(CURTHREAD)] 11181184Sjake stx %o1, [PCPU(CURPCB)] 11281184Sjake 11389043Sjake wrpr %g0, PSTATE_NORMAL, %pstate 11489043Sjake mov %o1, PCB_REG 11588645Sjake wrpr %g0, PSTATE_ALT, %pstate 11688645Sjake mov %o1, PCB_REG 11788645Sjake wrpr %g0, PSTATE_KERNEL, %pstate 11888645Sjake 11981184Sjake /* 12088645Sjake * Point to the vmspaces of the new and old processes. 12181184Sjake */ 12288645Sjake2: ldx [%l0 + TD_PROC], %l2 12383366Sjulian ldx [%o0 + TD_PROC], %o2 12488645Sjake ldx [%l2 + P_VMSPACE], %l2 12583366Sjulian ldx [%o2 + P_VMSPACE], %o2 12681184Sjake 12781184Sjake /* 12888645Sjake * If they're the same we are done. 12981184Sjake */ 13088645Sjake cmp %l2, %o2 13188645Sjake be,a,pn %xcc, 6f 13281184Sjake nop 13381184Sjake 13488645Sjake /* 13588645Sjake * If the old process has nucleus context we can skip demapping the 13688645Sjake * tsb. 13788645Sjake */ 13888645Sjake lduw [%l2 + VM_PMAP + PM_CONTEXT], %l3 13988645Sjake brz,a,pn %l3, 3f 14088645Sjake nop 14182013Sjake 14281184Sjake /* 14388645Sjake * Demap the old process's tsb. 14481184Sjake */ 14588645Sjake ldx [%l2 + VM_PMAP + PM_TSB], %l3 14688645Sjake or %l3, TLB_DEMAP_NUCLEUS | TLB_DEMAP_PAGE, %l3 14788645Sjake stxa %g0, [%l3] ASI_DMMU_DEMAP 14888645Sjake membar #Sync 14981184Sjake 15081184Sjake /* 15188645Sjake * Mark the pmap no longer active on this cpu. 15288645Sjake */ 15388645Sjake lduw [%l2 + VM_PMAP + PM_ACTIVE], %l3 15488645Sjake mov 1, %l4 15588645Sjake lduw [PCPU(CPUID)], %l5 15688645Sjake sllx %l4, %l5, %l4 15788645Sjake andn %l3, %l4, %l3 15888645Sjake stw %l3, [%l2 + VM_PMAP + PM_ACTIVE] 15988645Sjake 16088645Sjake /* 16188645Sjake * If the new process has nucleus context we are done. 16288645Sjake */ 16388645Sjake3: lduw [%o2 + VM_PMAP + PM_CONTEXT], %o3 16488645Sjake brz,a,pn %o3, 6f 16588645Sjake nop 16688645Sjake 16788645Sjake /* 16888645Sjake * If the new process has had its context stolen, get one. 16988645Sjake */ 17088645Sjake cmp %o3, -1 17188645Sjake bne,a,pt %xcc, 4f 17288645Sjake nop 17388645Sjake PANIC("cpu_switch: steal context", %o4) 17488645Sjake 17588645Sjake /* 17681184Sjake * Install the new primary context. 17781184Sjake */ 17888645Sjake4: mov AA_DMMU_PCXR, %o4 17988645Sjake stxa %o3, [%o4] ASI_DMMU 18081184Sjake flush %o0 18181184Sjake 18281184Sjake /* 18388645Sjake * Mark the pmap as active on this cpu. 18481184Sjake */ 18588645Sjake lduw [%o2 + VM_PMAP + PM_ACTIVE], %o3 18688645Sjake mov 1, %o4 18788645Sjake lduw [PCPU(CPUID)], %o5 18888645Sjake sllx %o4, %o5, %o4 18988645Sjake or %o3, %o4, %o3 19088645Sjake stw %o3, [%o2 + VM_PMAP + PM_ACTIVE] 19181184Sjake 19281184Sjake /* 19388645Sjake * Load the address of the user tsb and the tte data that maps it into 19488645Sjake * kernel space and set the lock bit. 19581184Sjake */ 19688645Sjake ldx [%o2 + VM_PMAP + PM_TSB], %o3 19788645Sjake ldx [%o2 + VM_PMAP + PM_TSB_TTE], %o4 19888645Sjake ldx [%o4 + TTE_DATA], %o4 19988645Sjake or %o4, TD_L, %o4 20081184Sjake 20181184Sjake /* 20288645Sjake * Switch to mmu globals, install the preloaded tsb pointer and map 20388645Sjake * the new tsb. We also disable interrupts so that this is as atomic 20488645Sjake * as can be. 20588645Sjake */ 20688645Sjake wrpr %g0, PSTATE_MMU, %pstate 20788645Sjake mov %o3, TSB_REG 20888645Sjake or %o3, TLB_DEMAP_NUCLEUS | TLB_DEMAP_PAGE, %o5 20988645Sjake stxa %g0, [%o5] ASI_DMMU_DEMAP 21088645Sjake mov AA_DMMU_TAR, %o5 21188645Sjake stxa %o3, [%o5] ASI_DMMU 21288645Sjake stxa %o4, [%g0] ASI_DTLB_DATA_IN_REG 21388645Sjake membar #Sync 21488645Sjake wrpr %g0, PSTATE_KERNEL, %pstate 21588645Sjake 21688645Sjake /* 21781184Sjake * Done. Return and load the new process's window from the stack. 21881184Sjake */ 21988645Sjake6: ret 22080709Sjake restore 22180709SjakeEND(cpu_switch) 22280709Sjake 22380709SjakeENTRY(savectx) 22480709Sjake save %sp, -CCFSZ, %sp 22580709Sjake flushw 22681135Stmm call savefpctx 22788645Sjake mov %i0, %o0 22888645Sjake stx %fp, [%i0 + PCB_FP] 22988645Sjake stx %i7, [%i0 + PCB_PC] 23080709Sjake ret 23180709Sjake restore %g0, 0, %o0 23280709SjakeEND(savectx) 23381135Stmm 23481135StmmENTRY(savefpctx) 23588645Sjake wr %g0, FPRS_FEF, %fprs 23688645Sjake wr %g0, ASI_BLK_S, %asi 23788645Sjake stda %f0, [%o0 + PCB_FPSTATE + FP_FB0] %asi 23888645Sjake stda %f16, [%o0 + PCB_FPSTATE + FP_FB1] %asi 23988645Sjake stda %f32, [%o0 + PCB_FPSTATE + FP_FB2] %asi 24088645Sjake stda %f48, [%o0 + PCB_FPSTATE + FP_FB3] %asi 24188645Sjake membar #Sync 24281135Stmm retl 24388645Sjake wr %g0, 0, %fprs 24481135StmmEND(savefpctx) 24581135Stmm 24681135StmmENTRY(restorefpctx) 24788645Sjake wr %g0, FPRS_FEF, %fprs 24888645Sjake wr %g0, ASI_BLK_S, %asi 24988645Sjake ldda [%o0 + PCB_FPSTATE + FP_FB0] %asi, %f0 25088645Sjake ldda [%o0 + PCB_FPSTATE + FP_FB1] %asi, %f16 25188645Sjake ldda [%o0 + PCB_FPSTATE + FP_FB2] %asi, %f32 25288645Sjake ldda [%o0 + PCB_FPSTATE + FP_FB3] %asi, %f48 25388645Sjake membar #Sync 25481135Stmm retl 25588645Sjake wr %g0, 0, %fprs 25681135StmmEND(restorefpctx) 257