1*7c478bd9Sstevel@tonic-gate/* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate/* 23*7c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate#pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate#include <sys/asm_linkage.h> 30*7c478bd9Sstevel@tonic-gate#include <sys/machthread.h> 31*7c478bd9Sstevel@tonic-gate#include <sys/privregs.h> 32*7c478bd9Sstevel@tonic-gate#include <sys/machasi.h> 33*7c478bd9Sstevel@tonic-gate#include <sys/trap.h> 34*7c478bd9Sstevel@tonic-gate#include <sys/mmu.h> 35*7c478bd9Sstevel@tonic-gate#include <sys/machparam.h> 36*7c478bd9Sstevel@tonic-gate#include <sys/machtrap.h> 37*7c478bd9Sstevel@tonic-gate#include <sys/traptrace.h> 38*7c478bd9Sstevel@tonic-gate 39*7c478bd9Sstevel@tonic-gate#if !defined(lint) 40*7c478bd9Sstevel@tonic-gate#include "assym.h" 41*7c478bd9Sstevel@tonic-gate 42*7c478bd9Sstevel@tonic-gate /* 43*7c478bd9Sstevel@tonic-gate * Spill fault handlers 44*7c478bd9Sstevel@tonic-gate * sn0 - spill normal tl 0 45*7c478bd9Sstevel@tonic-gate * sn1 - spill normal tl >0 46*7c478bd9Sstevel@tonic-gate * so0 - spill other tl 0 47*7c478bd9Sstevel@tonic-gate * so1 - spill other tl >0 48*7c478bd9Sstevel@tonic-gate */ 49*7c478bd9Sstevel@tonic-gate 50*7c478bd9Sstevel@tonic-gate ENTRY_NP(fault_32bit_sn0) 51*7c478bd9Sstevel@tonic-gate ! 52*7c478bd9Sstevel@tonic-gate FAULT_WINTRACE(%g1, %g2, %g3, TT_F32_SN0) 53*7c478bd9Sstevel@tonic-gate ! 54*7c478bd9Sstevel@tonic-gate ! Spill normal tl0 fault. 55*7c478bd9Sstevel@tonic-gate ! This happens when a user tries to spill to an unmapped or 56*7c478bd9Sstevel@tonic-gate ! misaligned stack. We handle an unmapped stack by simulating 57*7c478bd9Sstevel@tonic-gate ! a pagefault at the trap pc and a misaligned stack by generating 58*7c478bd9Sstevel@tonic-gate ! a user alignment trap. 59*7c478bd9Sstevel@tonic-gate ! 60*7c478bd9Sstevel@tonic-gate ! spill the window into wbuf slot 0 61*7c478bd9Sstevel@tonic-gate ! (we know wbuf is empty since we came from user mode) 62*7c478bd9Sstevel@tonic-gate ! 63*7c478bd9Sstevel@tonic-gate ! g5 = mmu trap type, g6 = tag access reg (g5 != T_ALIGNMENT) or 64*7c478bd9Sstevel@tonic-gate ! sfar (g5 == T_ALIGNMENT) 65*7c478bd9Sstevel@tonic-gate ! 66*7c478bd9Sstevel@tonic-gate CPU_ADDR(%g4, %g1) 67*7c478bd9Sstevel@tonic-gate ldn [%g4 + CPU_MPCB], %g1 68*7c478bd9Sstevel@tonic-gate stn %sp, [%g1 + MPCB_SPBUF] 69*7c478bd9Sstevel@tonic-gate ldn [%g1 + MPCB_WBUF], %g2 70*7c478bd9Sstevel@tonic-gate SAVE_V8WINDOW(%g2) 71*7c478bd9Sstevel@tonic-gate mov 1, %g2 72*7c478bd9Sstevel@tonic-gate st %g2, [%g1 + MPCB_WBCNT] 73*7c478bd9Sstevel@tonic-gate saved 74*7c478bd9Sstevel@tonic-gate ! 75*7c478bd9Sstevel@tonic-gate ! setup user_trap args 76*7c478bd9Sstevel@tonic-gate ! 77*7c478bd9Sstevel@tonic-gate set sfmmu_tsbmiss_exception, %g1 78*7c478bd9Sstevel@tonic-gate mov %g6, %g2 ! arg2 = tagaccess 79*7c478bd9Sstevel@tonic-gate mov T_WIN_OVERFLOW, %g3 ! arg3 = traptype 80*7c478bd9Sstevel@tonic-gate cmp %g5, T_ALIGNMENT 81*7c478bd9Sstevel@tonic-gate bne %icc, 1f 82*7c478bd9Sstevel@tonic-gate nop 83*7c478bd9Sstevel@tonic-gate set trap, %g1 84*7c478bd9Sstevel@tonic-gate mov T_ALIGNMENT, %g3 85*7c478bd9Sstevel@tonic-gate1: 86*7c478bd9Sstevel@tonic-gate sub %g0, 1, %g4 87*7c478bd9Sstevel@tonic-gate ! 88*7c478bd9Sstevel@tonic-gate ! spill traps increment %cwp by 2, 89*7c478bd9Sstevel@tonic-gate ! but user_trap wants the trap %cwp 90*7c478bd9Sstevel@tonic-gate ! 91*7c478bd9Sstevel@tonic-gate rdpr %tstate, %g5 92*7c478bd9Sstevel@tonic-gate and %g5, TSTATE_CWP, %g5 93*7c478bd9Sstevel@tonic-gate ba,pt %xcc, user_trap 94*7c478bd9Sstevel@tonic-gate wrpr %g0, %g5, %cwp 95*7c478bd9Sstevel@tonic-gate SET_SIZE(fault_32bit_sn0) 96*7c478bd9Sstevel@tonic-gate 97*7c478bd9Sstevel@tonic-gate ! 98*7c478bd9Sstevel@tonic-gate ! Spill normal tl1 fault. 99*7c478bd9Sstevel@tonic-gate ! This happens when sys_trap's save spills to an unmapped stack. 100*7c478bd9Sstevel@tonic-gate ! We handle it by spilling the window to the wbuf and trying 101*7c478bd9Sstevel@tonic-gate ! sys_trap again. 102*7c478bd9Sstevel@tonic-gate ! 103*7c478bd9Sstevel@tonic-gate ! spill the window into wbuf slot 0 104*7c478bd9Sstevel@tonic-gate ! (we know wbuf is empty since we came from user mode) 105*7c478bd9Sstevel@tonic-gate ! 106*7c478bd9Sstevel@tonic-gate ENTRY_NP(fault_32bit_sn1) 107*7c478bd9Sstevel@tonic-gate FAULT_WINTRACE(%g5, %g6, %g7, TT_F32_SN1) 108*7c478bd9Sstevel@tonic-gate CPU_PADDR(%g5, %g6) 109*7c478bd9Sstevel@tonic-gate mov ASI_MEM, %asi 110*7c478bd9Sstevel@tonic-gate ldxa [%g5 + CPU_MPCB_PA]%asi, %g6 111*7c478bd9Sstevel@tonic-gate ldxa [%g6 + MPCB_WBUF_PA]%asi, %g5 112*7c478bd9Sstevel@tonic-gate stna %sp, [%g6 + MPCB_SPBUF]%asi 113*7c478bd9Sstevel@tonic-gate SAVE_V8WINDOW_ASI(%g5) 114*7c478bd9Sstevel@tonic-gate mov 1, %g5 115*7c478bd9Sstevel@tonic-gate sta %g5, [%g6 + MPCB_WBCNT]%asi 116*7c478bd9Sstevel@tonic-gate saved 117*7c478bd9Sstevel@tonic-gate set sys_trap, %g5 118*7c478bd9Sstevel@tonic-gate wrpr %g5, %tnpc 119*7c478bd9Sstevel@tonic-gate done 120*7c478bd9Sstevel@tonic-gate SET_SIZE(fault_32bit_sn1) 121*7c478bd9Sstevel@tonic-gate 122*7c478bd9Sstevel@tonic-gate ENTRY_NP(fault_32bit_so0) 123*7c478bd9Sstevel@tonic-gate ! 124*7c478bd9Sstevel@tonic-gate FAULT_WINTRACE(%g5, %g6, %g1, TT_F32_SO0) 125*7c478bd9Sstevel@tonic-gate ! 126*7c478bd9Sstevel@tonic-gate ! Spill other tl0 fault. 127*7c478bd9Sstevel@tonic-gate ! This happens when the kernel spills a user window and that 128*7c478bd9Sstevel@tonic-gate ! user's stack has been unmapped. 129*7c478bd9Sstevel@tonic-gate ! We handle it by spilling the window into the user's wbuf. 130*7c478bd9Sstevel@tonic-gate ! 131*7c478bd9Sstevel@tonic-gate ! find lwp & increment wbcnt 132*7c478bd9Sstevel@tonic-gate ! 133*7c478bd9Sstevel@tonic-gate CPU_ADDR(%g5, %g6) 134*7c478bd9Sstevel@tonic-gate ldn [%g5 + CPU_MPCB], %g1 135*7c478bd9Sstevel@tonic-gate ld [%g1 + MPCB_WBCNT], %g2 136*7c478bd9Sstevel@tonic-gate add %g2, 1, %g3 137*7c478bd9Sstevel@tonic-gate st %g3, [%g1 + MPCB_WBCNT] 138*7c478bd9Sstevel@tonic-gate ! 139*7c478bd9Sstevel@tonic-gate ! use previous wbcnt to spill new spbuf & wbuf 140*7c478bd9Sstevel@tonic-gate ! 141*7c478bd9Sstevel@tonic-gate sll %g2, CPTRSHIFT, %g4 ! spbuf size is sizeof (caddr_t) 142*7c478bd9Sstevel@tonic-gate add %g1, MPCB_SPBUF, %g3 143*7c478bd9Sstevel@tonic-gate stn %sp, [%g3 + %g4] 144*7c478bd9Sstevel@tonic-gate sll %g2, RWIN32SHIFT, %g4 145*7c478bd9Sstevel@tonic-gate ldn [%g1 + MPCB_WBUF], %g3 146*7c478bd9Sstevel@tonic-gate add %g3, %g4, %g3 147*7c478bd9Sstevel@tonic-gate SAVE_V8WINDOW(%g3) 148*7c478bd9Sstevel@tonic-gate saved 149*7c478bd9Sstevel@tonic-gate retry 150*7c478bd9Sstevel@tonic-gate SET_SIZE(fault_32bit_so0) 151*7c478bd9Sstevel@tonic-gate 152*7c478bd9Sstevel@tonic-gate ! 153*7c478bd9Sstevel@tonic-gate ! Spill other tl1 fault. 154*7c478bd9Sstevel@tonic-gate ! This happens when priv_trap spills a user window and that 155*7c478bd9Sstevel@tonic-gate ! user's stack has been unmapped. 156*7c478bd9Sstevel@tonic-gate ! We handle it by spilling the window to the wbuf and retrying 157*7c478bd9Sstevel@tonic-gate ! the save. 158*7c478bd9Sstevel@tonic-gate ! 159*7c478bd9Sstevel@tonic-gate ENTRY_NP(fault_32bit_so1) 160*7c478bd9Sstevel@tonic-gate FAULT_WINTRACE(%g5, %g6, %g7, TT_F32_SO1) 161*7c478bd9Sstevel@tonic-gate CPU_PADDR(%g5, %g6) 162*7c478bd9Sstevel@tonic-gate ! 163*7c478bd9Sstevel@tonic-gate ! find lwp & increment wbcnt 164*7c478bd9Sstevel@tonic-gate ! 165*7c478bd9Sstevel@tonic-gate mov ASI_MEM, %asi 166*7c478bd9Sstevel@tonic-gate ldxa [%g5 + CPU_MPCB_PA]%asi, %g6 167*7c478bd9Sstevel@tonic-gate lda [%g6 + MPCB_WBCNT]%asi, %g5 168*7c478bd9Sstevel@tonic-gate add %g5, 1, %g7 169*7c478bd9Sstevel@tonic-gate sta %g7, [%g6 + MPCB_WBCNT]%asi 170*7c478bd9Sstevel@tonic-gate ! 171*7c478bd9Sstevel@tonic-gate ! use previous wbcnt to spill new spbuf & wbuf 172*7c478bd9Sstevel@tonic-gate ! 173*7c478bd9Sstevel@tonic-gate sll %g5, CPTRSHIFT, %g7 ! spbuf size is sizeof (caddr_t) 174*7c478bd9Sstevel@tonic-gate add %g6, %g7, %g7 175*7c478bd9Sstevel@tonic-gate stna %sp, [%g7 + MPCB_SPBUF]%asi 176*7c478bd9Sstevel@tonic-gate sll %g5, RWIN32SHIFT, %g7 177*7c478bd9Sstevel@tonic-gate ldxa [%g6 + MPCB_WBUF_PA]%asi, %g5 178*7c478bd9Sstevel@tonic-gate add %g5, %g7, %g7 179*7c478bd9Sstevel@tonic-gate SAVE_V8WINDOW_ASI(%g7) 180*7c478bd9Sstevel@tonic-gate saved 181*7c478bd9Sstevel@tonic-gate set sys_trap, %g5 182*7c478bd9Sstevel@tonic-gate wrpr %g5, %tnpc 183*7c478bd9Sstevel@tonic-gate done 184*7c478bd9Sstevel@tonic-gate SET_SIZE(fault_32bit_so1) 185*7c478bd9Sstevel@tonic-gate 186*7c478bd9Sstevel@tonic-gate ENTRY_NP(fault_64bit_sn0) 187*7c478bd9Sstevel@tonic-gate ! 188*7c478bd9Sstevel@tonic-gate FAULT_WINTRACE(%g1, %g2, %g3, TT_F64_SN0) 189*7c478bd9Sstevel@tonic-gate ! 190*7c478bd9Sstevel@tonic-gate ! Spill normal tl0 fault. 191*7c478bd9Sstevel@tonic-gate ! This happens when a user tries to spill to an unmapped or 192*7c478bd9Sstevel@tonic-gate ! misaligned stack. We handle an unmapped stack by simulating 193*7c478bd9Sstevel@tonic-gate ! a pagefault at the trap pc and a misaligned stack by generating 194*7c478bd9Sstevel@tonic-gate ! a user alignment trap. 195*7c478bd9Sstevel@tonic-gate ! 196*7c478bd9Sstevel@tonic-gate ! spill the window into wbuf slot 0 197*7c478bd9Sstevel@tonic-gate ! (we know wbuf is empty since we came from user mode) 198*7c478bd9Sstevel@tonic-gate ! 199*7c478bd9Sstevel@tonic-gate ! g5 = mmu trap type, g6 = tag access reg (g5 != T_ALIGNMENT) or 200*7c478bd9Sstevel@tonic-gate ! sfar (g5 == T_ALIGNMENT) 201*7c478bd9Sstevel@tonic-gate ! 202*7c478bd9Sstevel@tonic-gate CPU_ADDR(%g4, %g1) 203*7c478bd9Sstevel@tonic-gate ldn [%g4 + CPU_MPCB], %g1 204*7c478bd9Sstevel@tonic-gate stn %sp, [%g1 + MPCB_SPBUF] 205*7c478bd9Sstevel@tonic-gate ldn [%g1 + MPCB_WBUF], %g2 206*7c478bd9Sstevel@tonic-gate SAVE_V9WINDOW(%g2) 207*7c478bd9Sstevel@tonic-gate mov 1, %g2 208*7c478bd9Sstevel@tonic-gate st %g2, [%g1 + MPCB_WBCNT] 209*7c478bd9Sstevel@tonic-gate saved 210*7c478bd9Sstevel@tonic-gate ! 211*7c478bd9Sstevel@tonic-gate ! setup user_trap args 212*7c478bd9Sstevel@tonic-gate ! 213*7c478bd9Sstevel@tonic-gate set sfmmu_tsbmiss_exception, %g1 214*7c478bd9Sstevel@tonic-gate mov %g6, %g2 ! arg2 = tagaccess 215*7c478bd9Sstevel@tonic-gate mov %g5, %g3 ! arg3 = traptype 216*7c478bd9Sstevel@tonic-gate cmp %g5, T_ALIGNMENT 217*7c478bd9Sstevel@tonic-gate bne %icc, 1f 218*7c478bd9Sstevel@tonic-gate nop 219*7c478bd9Sstevel@tonic-gate set trap, %g1 220*7c478bd9Sstevel@tonic-gate mov T_ALIGNMENT, %g3 221*7c478bd9Sstevel@tonic-gate1: 222*7c478bd9Sstevel@tonic-gate sub %g0, 1, %g4 223*7c478bd9Sstevel@tonic-gate ! 224*7c478bd9Sstevel@tonic-gate ! spill traps increment %cwp by 2, 225*7c478bd9Sstevel@tonic-gate ! but user_trap wants the trap %cwp 226*7c478bd9Sstevel@tonic-gate ! 227*7c478bd9Sstevel@tonic-gate rdpr %tstate, %g5 228*7c478bd9Sstevel@tonic-gate and %g5, TSTATE_CWP, %g5 229*7c478bd9Sstevel@tonic-gate ba,pt %xcc, user_trap 230*7c478bd9Sstevel@tonic-gate wrpr %g0, %g5, %cwp 231*7c478bd9Sstevel@tonic-gate SET_SIZE(fault_64bit_sn0) 232*7c478bd9Sstevel@tonic-gate 233*7c478bd9Sstevel@tonic-gate ! 234*7c478bd9Sstevel@tonic-gate ! Spill normal tl1 fault. 235*7c478bd9Sstevel@tonic-gate ! This happens when sys_trap's save spills to an unmapped stack. 236*7c478bd9Sstevel@tonic-gate ! We handle it by spilling the window to the wbuf and trying 237*7c478bd9Sstevel@tonic-gate ! sys_trap again. 238*7c478bd9Sstevel@tonic-gate ! 239*7c478bd9Sstevel@tonic-gate ! spill the window into wbuf slot 0 240*7c478bd9Sstevel@tonic-gate ! (we know wbuf is empty since we came from user mode) 241*7c478bd9Sstevel@tonic-gate ! 242*7c478bd9Sstevel@tonic-gate ENTRY_NP(fault_64bit_sn1) 243*7c478bd9Sstevel@tonic-gate FAULT_WINTRACE(%g5, %g6, %g7, TT_F64_SN1) 244*7c478bd9Sstevel@tonic-gate CPU_PADDR(%g5, %g6) 245*7c478bd9Sstevel@tonic-gate mov ASI_MEM, %asi 246*7c478bd9Sstevel@tonic-gate ldxa [%g5 + CPU_MPCB_PA]%asi, %g6 247*7c478bd9Sstevel@tonic-gate ldxa [%g6 + MPCB_WBUF_PA]%asi, %g5 248*7c478bd9Sstevel@tonic-gate stna %sp, [%g6 + MPCB_SPBUF]%asi 249*7c478bd9Sstevel@tonic-gate SAVE_V9WINDOW_ASI(%g5) 250*7c478bd9Sstevel@tonic-gate mov 1, %g5 251*7c478bd9Sstevel@tonic-gate sta %g5, [%g6 + MPCB_WBCNT]%asi 252*7c478bd9Sstevel@tonic-gate saved 253*7c478bd9Sstevel@tonic-gate set sys_trap, %g5 254*7c478bd9Sstevel@tonic-gate wrpr %g5, %tnpc 255*7c478bd9Sstevel@tonic-gate done 256*7c478bd9Sstevel@tonic-gate SET_SIZE(fault_64bit_sn1) 257*7c478bd9Sstevel@tonic-gate 258*7c478bd9Sstevel@tonic-gate ! 259*7c478bd9Sstevel@tonic-gate ! Spill normal kernel tl1. 260*7c478bd9Sstevel@tonic-gate ! 261*7c478bd9Sstevel@tonic-gate ! spill the kernel window into kwbuf 262*7c478bd9Sstevel@tonic-gate ! 263*7c478bd9Sstevel@tonic-gate ENTRY_NP(fault_32bit_sk) 264*7c478bd9Sstevel@tonic-gate FAULT_WINTRACE(%g5, %g6, %g7, TT_F32_NT1) 265*7c478bd9Sstevel@tonic-gate CPU_PADDR(%g5, %g6) 266*7c478bd9Sstevel@tonic-gate set CPU_KWBUF_SP, %g6 267*7c478bd9Sstevel@tonic-gate add %g5, %g6, %g6 268*7c478bd9Sstevel@tonic-gate mov ASI_MEM, %asi 269*7c478bd9Sstevel@tonic-gate stna %sp, [%g6]%asi 270*7c478bd9Sstevel@tonic-gate set CPU_KWBUF, %g6 271*7c478bd9Sstevel@tonic-gate add %g5, %g6, %g6 272*7c478bd9Sstevel@tonic-gate SAVE_V8WINDOW_ASI(%g6) 273*7c478bd9Sstevel@tonic-gate mov 1, %g6 274*7c478bd9Sstevel@tonic-gate add %g5, CPU_MCPU, %g5 275*7c478bd9Sstevel@tonic-gate#ifdef DEBUG 276*7c478bd9Sstevel@tonic-gate lda [%g5 + MCPU_KWBUF_FULL]%asi, %g7 277*7c478bd9Sstevel@tonic-gate tst %g7 278*7c478bd9Sstevel@tonic-gate bnz,a,pn %icc, ptl1_panic 279*7c478bd9Sstevel@tonic-gate mov PTL1_BAD_WTRAP, %g1 280*7c478bd9Sstevel@tonic-gate#endif /* DEBUG */ 281*7c478bd9Sstevel@tonic-gate sta %g6, [%g5 + MCPU_KWBUF_FULL]%asi 282*7c478bd9Sstevel@tonic-gate saved 283*7c478bd9Sstevel@tonic-gate retry 284*7c478bd9Sstevel@tonic-gate SET_SIZE(fault_32bit_sk) 285*7c478bd9Sstevel@tonic-gate 286*7c478bd9Sstevel@tonic-gate ! 287*7c478bd9Sstevel@tonic-gate ! Spill normal kernel tl1. 288*7c478bd9Sstevel@tonic-gate ! 289*7c478bd9Sstevel@tonic-gate ! spill the kernel window into kwbuf 290*7c478bd9Sstevel@tonic-gate ! 291*7c478bd9Sstevel@tonic-gate ENTRY_NP(fault_64bit_sk) 292*7c478bd9Sstevel@tonic-gate ! 293*7c478bd9Sstevel@tonic-gate FAULT_WINTRACE(%g5, %g6, %g7, TT_F64_NT1) 294*7c478bd9Sstevel@tonic-gate CPU_PADDR(%g5, %g6) 295*7c478bd9Sstevel@tonic-gate set CPU_KWBUF_SP, %g6 296*7c478bd9Sstevel@tonic-gate add %g5, %g6, %g6 297*7c478bd9Sstevel@tonic-gate mov ASI_MEM, %asi 298*7c478bd9Sstevel@tonic-gate stna %sp, [%g6]%asi 299*7c478bd9Sstevel@tonic-gate set CPU_KWBUF, %g6 300*7c478bd9Sstevel@tonic-gate add %g5, %g6, %g6 301*7c478bd9Sstevel@tonic-gate SAVE_V9WINDOW_ASI(%g6) 302*7c478bd9Sstevel@tonic-gate mov 1, %g6 303*7c478bd9Sstevel@tonic-gate add %g5, CPU_MCPU, %g5 304*7c478bd9Sstevel@tonic-gate#ifdef DEBUG 305*7c478bd9Sstevel@tonic-gate lda [%g5 + MCPU_KWBUF_FULL]%asi, %g7 306*7c478bd9Sstevel@tonic-gate tst %g7 307*7c478bd9Sstevel@tonic-gate bnz,a,pn %icc, ptl1_panic 308*7c478bd9Sstevel@tonic-gate mov PTL1_BAD_WTRAP, %g1 309*7c478bd9Sstevel@tonic-gate#endif /* DEBUG */ 310*7c478bd9Sstevel@tonic-gate sta %g6, [%g5 + MCPU_KWBUF_FULL]%asi 311*7c478bd9Sstevel@tonic-gate saved 312*7c478bd9Sstevel@tonic-gate retry 313*7c478bd9Sstevel@tonic-gate SET_SIZE(fault_64bit_sk) 314*7c478bd9Sstevel@tonic-gate 315*7c478bd9Sstevel@tonic-gate ENTRY_NP(fault_64bit_so0) 316*7c478bd9Sstevel@tonic-gate ! 317*7c478bd9Sstevel@tonic-gate FAULT_WINTRACE(%g5, %g6, %g1, TT_F64_SO0) 318*7c478bd9Sstevel@tonic-gate ! 319*7c478bd9Sstevel@tonic-gate ! Spill other tl0 fault. 320*7c478bd9Sstevel@tonic-gate ! This happens when the kernel spills a user window and that 321*7c478bd9Sstevel@tonic-gate ! user's stack has been unmapped. 322*7c478bd9Sstevel@tonic-gate ! We handle it by spilling the window into the user's wbuf. 323*7c478bd9Sstevel@tonic-gate ! 324*7c478bd9Sstevel@tonic-gate ! find lwp & increment wbcnt 325*7c478bd9Sstevel@tonic-gate ! 326*7c478bd9Sstevel@tonic-gate CPU_ADDR(%g5, %g6) 327*7c478bd9Sstevel@tonic-gate ldn [%g5 + CPU_MPCB], %g1 328*7c478bd9Sstevel@tonic-gate ld [%g1 + MPCB_WBCNT], %g2 329*7c478bd9Sstevel@tonic-gate add %g2, 1, %g3 330*7c478bd9Sstevel@tonic-gate st %g3, [%g1 + MPCB_WBCNT] 331*7c478bd9Sstevel@tonic-gate ! 332*7c478bd9Sstevel@tonic-gate ! use previous wbcnt to spill new spbuf & wbuf 333*7c478bd9Sstevel@tonic-gate ! 334*7c478bd9Sstevel@tonic-gate sll %g2, CPTRSHIFT, %g4 ! spbuf size is sizeof (caddr_t) 335*7c478bd9Sstevel@tonic-gate add %g1, MPCB_SPBUF, %g3 336*7c478bd9Sstevel@tonic-gate stn %sp, [%g3 + %g4] 337*7c478bd9Sstevel@tonic-gate sll %g2, RWIN64SHIFT, %g4 338*7c478bd9Sstevel@tonic-gate ldn [%g1 + MPCB_WBUF], %g3 339*7c478bd9Sstevel@tonic-gate add %g3, %g4, %g3 340*7c478bd9Sstevel@tonic-gate SAVE_V9WINDOW(%g3) 341*7c478bd9Sstevel@tonic-gate saved 342*7c478bd9Sstevel@tonic-gate retry 343*7c478bd9Sstevel@tonic-gate SET_SIZE(fault_64bit_so0) 344*7c478bd9Sstevel@tonic-gate 345*7c478bd9Sstevel@tonic-gate ! 346*7c478bd9Sstevel@tonic-gate ! Spill other tl1 fault. 347*7c478bd9Sstevel@tonic-gate ! This happens when priv_trap spills a user window and that 348*7c478bd9Sstevel@tonic-gate ! user's stack has been unmapped. 349*7c478bd9Sstevel@tonic-gate ! We handle it by spilling the window to the wbuf and retrying 350*7c478bd9Sstevel@tonic-gate ! the save. 351*7c478bd9Sstevel@tonic-gate ! 352*7c478bd9Sstevel@tonic-gate ENTRY_NP(fault_64bit_so1) 353*7c478bd9Sstevel@tonic-gate FAULT_WINTRACE(%g5, %g6, %g7, TT_F64_SO1) 354*7c478bd9Sstevel@tonic-gate CPU_PADDR(%g5, %g6) 355*7c478bd9Sstevel@tonic-gate ! 356*7c478bd9Sstevel@tonic-gate ! find lwp & increment wbcnt 357*7c478bd9Sstevel@tonic-gate ! 358*7c478bd9Sstevel@tonic-gate mov ASI_MEM, %asi 359*7c478bd9Sstevel@tonic-gate ldxa [%g5 + CPU_MPCB_PA]%asi, %g6 360*7c478bd9Sstevel@tonic-gate lda [%g6 + MPCB_WBCNT]%asi, %g5 361*7c478bd9Sstevel@tonic-gate add %g5, 1, %g7 362*7c478bd9Sstevel@tonic-gate sta %g7, [%g6 + MPCB_WBCNT]%asi 363*7c478bd9Sstevel@tonic-gate ! 364*7c478bd9Sstevel@tonic-gate ! use previous wbcnt to spill new spbuf & wbuf 365*7c478bd9Sstevel@tonic-gate ! 366*7c478bd9Sstevel@tonic-gate sll %g5, CPTRSHIFT, %g7 ! spbuf size is sizeof (caddr_t) 367*7c478bd9Sstevel@tonic-gate add %g6, %g7, %g7 368*7c478bd9Sstevel@tonic-gate stna %sp, [%g7 + MPCB_SPBUF]%asi 369*7c478bd9Sstevel@tonic-gate sll %g5, RWIN64SHIFT, %g7 370*7c478bd9Sstevel@tonic-gate ldxa [%g6 + MPCB_WBUF_PA]%asi, %g5 371*7c478bd9Sstevel@tonic-gate add %g5, %g7, %g7 372*7c478bd9Sstevel@tonic-gate SAVE_V9WINDOW_ASI(%g7) 373*7c478bd9Sstevel@tonic-gate saved 374*7c478bd9Sstevel@tonic-gate set sys_trap, %g5 375*7c478bd9Sstevel@tonic-gate wrpr %g5, %tnpc 376*7c478bd9Sstevel@tonic-gate done 377*7c478bd9Sstevel@tonic-gate SET_SIZE(fault_64bit_so1) 378*7c478bd9Sstevel@tonic-gate 379*7c478bd9Sstevel@tonic-gate /* 380*7c478bd9Sstevel@tonic-gate * Fill fault handlers 381*7c478bd9Sstevel@tonic-gate * fn0 - fill normal tl 0 382*7c478bd9Sstevel@tonic-gate * fn1 - fill normal tl 1 383*7c478bd9Sstevel@tonic-gate */ 384*7c478bd9Sstevel@tonic-gate 385*7c478bd9Sstevel@tonic-gate ENTRY_NP(fault_32bit_fn0) 386*7c478bd9Sstevel@tonic-gate ! 387*7c478bd9Sstevel@tonic-gate FAULT_WINTRACE(%g1, %g2, %g3, TT_F32_FN0) 388*7c478bd9Sstevel@tonic-gate ! 389*7c478bd9Sstevel@tonic-gate.fault_fn0_common: 390*7c478bd9Sstevel@tonic-gate ! 391*7c478bd9Sstevel@tonic-gate ! Fill normal tl0 fault. 392*7c478bd9Sstevel@tonic-gate ! This happens when a user tries to fill to an unmapped or 393*7c478bd9Sstevel@tonic-gate ! misaligned stack. We handle an unmapped stack by simulating 394*7c478bd9Sstevel@tonic-gate ! a pagefault at the trap pc and a misaligned stack by generating 395*7c478bd9Sstevel@tonic-gate ! a user alignment trap. 396*7c478bd9Sstevel@tonic-gate ! 397*7c478bd9Sstevel@tonic-gate ! setup user_trap args 398*7c478bd9Sstevel@tonic-gate ! 399*7c478bd9Sstevel@tonic-gate ! g5 = mmu trap type, g6 = tag access reg (g5 != T_ALIGNMENT) or 400*7c478bd9Sstevel@tonic-gate ! sfar (g5 == T_ALIGNMENT) 401*7c478bd9Sstevel@tonic-gate ! 402*7c478bd9Sstevel@tonic-gate set sfmmu_tsbmiss_exception, %g1 403*7c478bd9Sstevel@tonic-gate mov %g6, %g2 ! arg2 = tagaccess 404*7c478bd9Sstevel@tonic-gate mov T_WIN_UNDERFLOW, %g3 405*7c478bd9Sstevel@tonic-gate cmp %g5, T_ALIGNMENT 406*7c478bd9Sstevel@tonic-gate bne %icc, 1f 407*7c478bd9Sstevel@tonic-gate nop 408*7c478bd9Sstevel@tonic-gate set trap, %g1 409*7c478bd9Sstevel@tonic-gate mov T_ALIGNMENT, %g3 410*7c478bd9Sstevel@tonic-gate1: 411*7c478bd9Sstevel@tonic-gate sub %g0, 1, %g4 412*7c478bd9Sstevel@tonic-gate ! 413*7c478bd9Sstevel@tonic-gate ! sys_trap wants %cwp to be the same as when the trap occured, 414*7c478bd9Sstevel@tonic-gate ! so set it from %tstate 415*7c478bd9Sstevel@tonic-gate ! 416*7c478bd9Sstevel@tonic-gate rdpr %tstate, %g5 417*7c478bd9Sstevel@tonic-gate and %g5, TSTATE_CWP, %g5 418*7c478bd9Sstevel@tonic-gate ba,pt %xcc, user_trap 419*7c478bd9Sstevel@tonic-gate wrpr %g0, %g5, %cwp 420*7c478bd9Sstevel@tonic-gate SET_SIZE(fault_32bit_fn0) 421*7c478bd9Sstevel@tonic-gate 422*7c478bd9Sstevel@tonic-gate ENTRY_NP(fault_32bit_fn1) 423*7c478bd9Sstevel@tonic-gate ! 424*7c478bd9Sstevel@tonic-gate FAULT_WINTRACE(%g1, %g2, %g3, TT_F32_FN1) 425*7c478bd9Sstevel@tonic-gate ! 426*7c478bd9Sstevel@tonic-gate wrpr %g0, 1, %gl 427*7c478bd9Sstevel@tonic-gate srl %sp, 0, %g7 428*7c478bd9Sstevel@tonic-gate ! 429*7c478bd9Sstevel@tonic-gate.fault_fn1_common: 430*7c478bd9Sstevel@tonic-gate ! 431*7c478bd9Sstevel@tonic-gate ! Fill normal tl1 fault. 432*7c478bd9Sstevel@tonic-gate ! This happens when user_rtt's restore fills from an unmapped or 433*7c478bd9Sstevel@tonic-gate ! misaligned stack. We handle an unmapped stack by simulating 434*7c478bd9Sstevel@tonic-gate ! a pagefault at user_rtt and a misaligned stack by generating 435*7c478bd9Sstevel@tonic-gate ! a RTT alignment trap. 436*7c478bd9Sstevel@tonic-gate ! 437*7c478bd9Sstevel@tonic-gate ! save fault addr & fix %cwp 438*7c478bd9Sstevel@tonic-gate ! 439*7c478bd9Sstevel@tonic-gate rdpr %tstate, %g1 440*7c478bd9Sstevel@tonic-gate and %g1, TSTATE_CWP, %g1 441*7c478bd9Sstevel@tonic-gate wrpr %g0, %g1, %cwp 442*7c478bd9Sstevel@tonic-gate ! 443*7c478bd9Sstevel@tonic-gate ! fake tl1 traps regs so that after pagefault runs, we 444*7c478bd9Sstevel@tonic-gate ! re-execute at user_rtt. 445*7c478bd9Sstevel@tonic-gate ! 446*7c478bd9Sstevel@tonic-gate wrpr %g0, 1, %tl 447*7c478bd9Sstevel@tonic-gate set TSTATE_KERN | TSTATE_IE, %g1 448*7c478bd9Sstevel@tonic-gate wrpr %g0, %g1, %tstate 449*7c478bd9Sstevel@tonic-gate set user_rtt, %g1 450*7c478bd9Sstevel@tonic-gate wrpr %g0, %g1, %tpc 451*7c478bd9Sstevel@tonic-gate add %g1, 4, %g1 452*7c478bd9Sstevel@tonic-gate wrpr %g0, %g1, %tnpc 453*7c478bd9Sstevel@tonic-gate ! 454*7c478bd9Sstevel@tonic-gate ! setup sys_trap args 455*7c478bd9Sstevel@tonic-gate ! 456*7c478bd9Sstevel@tonic-gate ! g5 = mmu trap type, g6 = tag access reg (g5 != T_ALIGNMENT) or 457*7c478bd9Sstevel@tonic-gate ! sfar (g5 == T_ALIGNMENT) 458*7c478bd9Sstevel@tonic-gate ! 459*7c478bd9Sstevel@tonic-gate set sfmmu_tsbmiss_exception, %g1 460*7c478bd9Sstevel@tonic-gate mov %g6, %g2 ! arg2 = tagaccess 461*7c478bd9Sstevel@tonic-gate set T_USER | T_SYS_RTT_PAGE, %g3 ! arg3 = traptype 462*7c478bd9Sstevel@tonic-gate cmp %g5, T_ALIGNMENT 463*7c478bd9Sstevel@tonic-gate bne %icc, 1f 464*7c478bd9Sstevel@tonic-gate nop 465*7c478bd9Sstevel@tonic-gate set trap, %g1 466*7c478bd9Sstevel@tonic-gate set T_USER | T_SYS_RTT_ALIGN, %g3 467*7c478bd9Sstevel@tonic-gate1: 468*7c478bd9Sstevel@tonic-gate sub %g0, 1, %g4 469*7c478bd9Sstevel@tonic-gate ! 470*7c478bd9Sstevel@tonic-gate ! setup to run kernel again by setting THREAD_REG, %wstate 471*7c478bd9Sstevel@tonic-gate ! and the mmu to their kernel values. 472*7c478bd9Sstevel@tonic-gate ! 473*7c478bd9Sstevel@tonic-gate ! sun4v cannot safely lower %gl then raise it again 474*7c478bd9Sstevel@tonic-gate ! so ktl0 must restore THREAD_REG 475*7c478bd9Sstevel@tonic-gate rdpr %wstate, %l1 476*7c478bd9Sstevel@tonic-gate sllx %l1, WSTATE_SHIFT, %l1 477*7c478bd9Sstevel@tonic-gate wrpr %l1, WSTATE_K64, %wstate 478*7c478bd9Sstevel@tonic-gate mov KCONTEXT, %g5 479*7c478bd9Sstevel@tonic-gate mov MMU_PCONTEXT, %g6 480*7c478bd9Sstevel@tonic-gate stxa %g5, [%g6]ASI_MMU_CTX 481*7c478bd9Sstevel@tonic-gate membar #Sync 482*7c478bd9Sstevel@tonic-gate 483*7c478bd9Sstevel@tonic-gate ba,pt %xcc, priv_trap 484*7c478bd9Sstevel@tonic-gate nop 485*7c478bd9Sstevel@tonic-gate SET_SIZE(fault_32bit_fn1) 486*7c478bd9Sstevel@tonic-gate 487*7c478bd9Sstevel@tonic-gate ENTRY_NP(fault_64bit_fn0) 488*7c478bd9Sstevel@tonic-gate FAULT_WINTRACE(%g1, %g2, %g3, TT_F64_FN0) 489*7c478bd9Sstevel@tonic-gate b .fault_fn0_common 490*7c478bd9Sstevel@tonic-gate nop 491*7c478bd9Sstevel@tonic-gate SET_SIZE(fault_64bit_fn0) 492*7c478bd9Sstevel@tonic-gate 493*7c478bd9Sstevel@tonic-gate ENTRY_NP(fault_64bit_fn1) 494*7c478bd9Sstevel@tonic-gate FAULT_WINTRACE(%g1, %g2, %g3, TT_F64_FN1) 495*7c478bd9Sstevel@tonic-gate wrpr %g0, 1, %gl 496*7c478bd9Sstevel@tonic-gate b .fault_fn1_common 497*7c478bd9Sstevel@tonic-gate nop 498*7c478bd9Sstevel@tonic-gate SET_SIZE(fault_64bit_fn1) 499*7c478bd9Sstevel@tonic-gate 500*7c478bd9Sstevel@tonic-gate ENTRY_NP(fault_rtt_fn1) 501*7c478bd9Sstevel@tonic-gate FAULT_WINTRACE(%g1, %g2, %g3, TT_RTT_FN1) 502*7c478bd9Sstevel@tonic-gate wrpr %g0, 1, %gl 503*7c478bd9Sstevel@tonic-gate b .fault_fn1_common 504*7c478bd9Sstevel@tonic-gate nop 505*7c478bd9Sstevel@tonic-gate SET_SIZE(fault_rtt_fn1) 506*7c478bd9Sstevel@tonic-gate 507*7c478bd9Sstevel@tonic-gate /* 508*7c478bd9Sstevel@tonic-gate * Kernel fault handlers 509*7c478bd9Sstevel@tonic-gate */ 510*7c478bd9Sstevel@tonic-gate ENTRY_NP(fault_32bit_not) 511*7c478bd9Sstevel@tonic-gate ENTRY_NP(fault_64bit_not) 512*7c478bd9Sstevel@tonic-gate ba,pt %xcc, ptl1_panic 513*7c478bd9Sstevel@tonic-gate mov PTL1_BAD_WTRAP, %g1 514*7c478bd9Sstevel@tonic-gate SET_SIZE(fault_32bit_not) 515*7c478bd9Sstevel@tonic-gate SET_SIZE(fault_64bit_not) 516*7c478bd9Sstevel@tonic-gate#endif /* !lint */ 517