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