1*5d9d9091SRichard Lowe/* 2*5d9d9091SRichard Lowe * CDDL HEADER START 3*5d9d9091SRichard Lowe * 4*5d9d9091SRichard Lowe * The contents of this file are subject to the terms of the 5*5d9d9091SRichard Lowe * Common Development and Distribution License (the "License"). 6*5d9d9091SRichard Lowe * You may not use this file except in compliance with the License. 7*5d9d9091SRichard Lowe * 8*5d9d9091SRichard Lowe * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*5d9d9091SRichard Lowe * or http://www.opensolaris.org/os/licensing. 10*5d9d9091SRichard Lowe * See the License for the specific language governing permissions 11*5d9d9091SRichard Lowe * and limitations under the License. 12*5d9d9091SRichard Lowe * 13*5d9d9091SRichard Lowe * When distributing Covered Code, include this CDDL HEADER in each 14*5d9d9091SRichard Lowe * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*5d9d9091SRichard Lowe * If applicable, add the following below this CDDL HEADER, with the 16*5d9d9091SRichard Lowe * fields enclosed by brackets "[]" replaced with your own identifying 17*5d9d9091SRichard Lowe * information: Portions Copyright [yyyy] [name of copyright owner] 18*5d9d9091SRichard Lowe * 19*5d9d9091SRichard Lowe * CDDL HEADER END 20*5d9d9091SRichard Lowe */ 21*5d9d9091SRichard Lowe/* 22*5d9d9091SRichard Lowe * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23*5d9d9091SRichard Lowe * Use is subject to license terms. 24*5d9d9091SRichard Lowe */ 25*5d9d9091SRichard Lowe 26*5d9d9091SRichard Lowe#include "assym.h" 27*5d9d9091SRichard Lowe 28*5d9d9091SRichard Lowe#include <sys/asm_linkage.h> 29*5d9d9091SRichard Lowe#include <sys/machthread.h> 30*5d9d9091SRichard Lowe#include <sys/machcpuvar.h> 31*5d9d9091SRichard Lowe#include <sys/mmu.h> 32*5d9d9091SRichard Lowe#include <sys/intreg.h> 33*5d9d9091SRichard Lowe#include <sys/dmv.h> 34*5d9d9091SRichard Lowe 35*5d9d9091SRichard Lowe#ifdef TRAPTRACE 36*5d9d9091SRichard Lowe#include <sys/traptrace.h> 37*5d9d9091SRichard Lowe#endif /* TRAPTRACE */ 38*5d9d9091SRichard Lowe 39*5d9d9091SRichard Lowe 40*5d9d9091SRichard Lowevec_uiii_irdr_tab: 41*5d9d9091SRichard Lowe .byte UIII_IRDR_0, UIII_IRDR_1, UIII_IRDR_2, UIII_IRDR_3 42*5d9d9091SRichard Lowe .byte UIII_IRDR_4, UIII_IRDR_5, UIII_IRDR_6, UIII_IRDR_7 43*5d9d9091SRichard Lowe 44*5d9d9091SRichard Lowe/* 45*5d9d9091SRichard Lowe * (TT 0x60, TL>0) Interrupt Vector Handler 46*5d9d9091SRichard Lowe * Globals are the Interrupt Globals. 47*5d9d9091SRichard Lowe */ 48*5d9d9091SRichard Lowe ENTRY_NP(vec_interrupt) 49*5d9d9091SRichard Lowe ! 50*5d9d9091SRichard Lowe ! Load the interrupt receive data register 0. 51*5d9d9091SRichard Lowe ! It could be a fast trap handler address (pc > KERNELBASE) at TL>0 52*5d9d9091SRichard Lowe ! or an interrupt number. 53*5d9d9091SRichard Lowe ! 54*5d9d9091SRichard Lowe mov IRDR_0, %g2 55*5d9d9091SRichard Lowe ldxa [%g2]ASI_INTR_RECEIVE, %g5 ! %g5 = PC or Interrupt Number 56*5d9d9091SRichard Lowe 57*5d9d9091SRichard Lowe ! If the high bit of IRDR_0 is set, then this is a 58*5d9d9091SRichard Lowe ! data bearing mondo vector. 59*5d9d9091SRichard Lowe brlz,pt %g5, dmv_vector 60*5d9d9091SRichard Lowe .empty 61*5d9d9091SRichard Lowe 62*5d9d9091SRichard Lowe 63*5d9d9091SRichard Lowevec_interrupt_resume: 64*5d9d9091SRichard Lowe set KERNELBASE, %g4 65*5d9d9091SRichard Lowe cmp %g5, %g4 66*5d9d9091SRichard Lowe bl,a,pt %xcc, 0f ! an interrupt number found 67*5d9d9091SRichard Lowe nop 68*5d9d9091SRichard Lowe ! 69*5d9d9091SRichard Lowe ! intercept OBP xcalls and set PCONTEXT=0 70*5d9d9091SRichard Lowe ! 71*5d9d9091SRichard Lowe set _end, %g4 ! _end is highest kernel address 72*5d9d9091SRichard Lowe cmp %g5, %g4 73*5d9d9091SRichard Lowe bl,a,pt %xcc, 7f 74*5d9d9091SRichard Lowe nop 75*5d9d9091SRichard Lowe 76*5d9d9091SRichard Lowe#ifndef _OPL 77*5d9d9091SRichard Lowe mov MMU_PCONTEXT, %g1 78*5d9d9091SRichard Lowe ldxa [%g1]ASI_DMMU, %g1 79*5d9d9091SRichard Lowe srlx %g1, CTXREG_NEXT_SHIFT, %g3 80*5d9d9091SRichard Lowe brz,pt %g3, 7f ! nucleus pgsz is 0, no problem 81*5d9d9091SRichard Lowe sllx %g3, CTXREG_NEXT_SHIFT, %g3 82*5d9d9091SRichard Lowe set CTXREG_CTX_MASK, %g4 ! check Pcontext 83*5d9d9091SRichard Lowe btst %g4, %g1 84*5d9d9091SRichard Lowe bz,a,pt %xcc, 6f 85*5d9d9091SRichard Lowe clr %g3 ! kernel: PCONTEXT=0 86*5d9d9091SRichard Lowe xor %g3, %g1, %g3 ! user: clr N_pgsz0/1 bits 87*5d9d9091SRichard Lowe6: 88*5d9d9091SRichard Lowe set DEMAP_ALL_TYPE, %g1 89*5d9d9091SRichard Lowe stxa %g0, [%g1]ASI_DTLB_DEMAP 90*5d9d9091SRichard Lowe stxa %g0, [%g1]ASI_ITLB_DEMAP 91*5d9d9091SRichard Lowe mov MMU_PCONTEXT, %g1 92*5d9d9091SRichard Lowe stxa %g3, [%g1]ASI_DMMU 93*5d9d9091SRichard Lowe membar #Sync 94*5d9d9091SRichard Lowe sethi %hi(FLUSH_ADDR), %g1 95*5d9d9091SRichard Lowe flush %g1 ! flush required by immu 96*5d9d9091SRichard Lowe#endif /* _OPL */ 97*5d9d9091SRichard Lowe 98*5d9d9091SRichard Lowe7: 99*5d9d9091SRichard Lowe ! 100*5d9d9091SRichard Lowe ! Cross-trap request case 101*5d9d9091SRichard Lowe ! 102*5d9d9091SRichard Lowe ! Load interrupt receive data registers 1 and 2 to fetch 103*5d9d9091SRichard Lowe ! the arguments for the fast trap handler. 104*5d9d9091SRichard Lowe ! 105*5d9d9091SRichard Lowe ! Register usage: 106*5d9d9091SRichard Lowe ! g5: TL>0 handler 107*5d9d9091SRichard Lowe ! g1: arg1 108*5d9d9091SRichard Lowe ! g2: arg2 109*5d9d9091SRichard Lowe ! g3: arg3 110*5d9d9091SRichard Lowe ! g4: arg4 111*5d9d9091SRichard Lowe ! 112*5d9d9091SRichard Lowe mov IRDR_1, %g2 113*5d9d9091SRichard Lowe ldxa [%g2]ASI_INTR_RECEIVE, %g1 114*5d9d9091SRichard Lowe mov IRDR_2, %g2 115*5d9d9091SRichard Lowe ldxa [%g2]ASI_INTR_RECEIVE, %g2 116*5d9d9091SRichard Lowe#ifdef TRAPTRACE 117*5d9d9091SRichard Lowe TRACE_PTR(%g4, %g6) 118*5d9d9091SRichard Lowe GET_TRACE_TICK(%g6, %g3) 119*5d9d9091SRichard Lowe stxa %g6, [%g4 + TRAP_ENT_TICK]%asi 120*5d9d9091SRichard Lowe rdpr %tl, %g6 121*5d9d9091SRichard Lowe stha %g6, [%g4 + TRAP_ENT_TL]%asi 122*5d9d9091SRichard Lowe rdpr %tt, %g6 123*5d9d9091SRichard Lowe stha %g6, [%g4 + TRAP_ENT_TT]%asi 124*5d9d9091SRichard Lowe rdpr %tpc, %g6 125*5d9d9091SRichard Lowe stna %g6, [%g4 + TRAP_ENT_TPC]%asi 126*5d9d9091SRichard Lowe rdpr %tstate, %g6 127*5d9d9091SRichard Lowe stxa %g6, [%g4 + TRAP_ENT_TSTATE]%asi 128*5d9d9091SRichard Lowe stna %sp, [%g4 + TRAP_ENT_SP]%asi 129*5d9d9091SRichard Lowe stna %g5, [%g4 + TRAP_ENT_TR]%asi ! pc of the TL>0 handler 130*5d9d9091SRichard Lowe stxa %g1, [%g4 + TRAP_ENT_F1]%asi 131*5d9d9091SRichard Lowe stxa %g2, [%g4 + TRAP_ENT_F3]%asi 132*5d9d9091SRichard Lowe stxa %g0, [%g4 + TRAP_ENT_F2]%asi 133*5d9d9091SRichard Lowe stxa %g0, [%g4 + TRAP_ENT_F4]%asi 134*5d9d9091SRichard Lowe TRACE_NEXT(%g4, %g6, %g3) 135*5d9d9091SRichard Lowe#endif /* TRAPTRACE */ 136*5d9d9091SRichard Lowe stxa %g0, [%g0]ASI_INTR_RECEIVE_STATUS ! clear the BUSY bit 137*5d9d9091SRichard Lowe membar #Sync 138*5d9d9091SRichard Lowe#ifdef SF_ERRATA_51 139*5d9d9091SRichard Lowe ba,pt %icc, 1f 140*5d9d9091SRichard Lowe nop 141*5d9d9091SRichard Lowe .align 32 142*5d9d9091SRichard Lowe1: jmp %g5 ! call the fast trap handler 143*5d9d9091SRichard Lowe nop 144*5d9d9091SRichard Lowe#else 145*5d9d9091SRichard Lowe jmp %g5 146*5d9d9091SRichard Lowe nop 147*5d9d9091SRichard Lowe#endif /* SF_ERRATA_51 */ 148*5d9d9091SRichard Lowe /* Never Reached */ 149*5d9d9091SRichard Lowe 150*5d9d9091SRichard Lowe0: 151*5d9d9091SRichard Lowe ! We have an interrupt number. 152*5d9d9091SRichard Lowe ! 153*5d9d9091SRichard Lowe ! Register usage: 154*5d9d9091SRichard Lowe ! %g5 - inum 155*5d9d9091SRichard Lowe ! %g1 - temp 156*5d9d9091SRichard Lowe ! 157*5d9d9091SRichard Lowe ! We don't bother to verify that the received inum is valid (it should 158*5d9d9091SRichard Lowe ! be < MAXIVNUM) since setvecint_tl1 will do that for us. 159*5d9d9091SRichard Lowe ! 160*5d9d9091SRichard Lowe ! clear BUSY bit 161*5d9d9091SRichard Lowe ! 162*5d9d9091SRichard Lowe stxa %g0, [%g0]ASI_INTR_RECEIVE_STATUS 163*5d9d9091SRichard Lowe membar #Sync 164*5d9d9091SRichard Lowe 165*5d9d9091SRichard Lowe ! setvecint_tl1 will do all the work, and finish with a retry 166*5d9d9091SRichard Lowe ! 167*5d9d9091SRichard Lowe ba,pt %xcc, setvecint_tl1 168*5d9d9091SRichard Lowe mov %g5, %g1 ! setvecint_tl1 expects inum in %g1 169*5d9d9091SRichard Lowe 170*5d9d9091SRichard Lowe /* Never Reached */ 171*5d9d9091SRichard Lowe SET_SIZE(vec_interrupt) 172*5d9d9091SRichard Lowe 173*5d9d9091SRichard Lowe 174*5d9d9091SRichard Lowe! 175*5d9d9091SRichard Lowe! See usr/src/uts/sun4u/sys/dmv.h for the Databearing Mondo Vector 176*5d9d9091SRichard Lowe! interrupt format 177*5d9d9091SRichard Lowe! 178*5d9d9091SRichard Lowe! Inputs: 179*5d9d9091SRichard Lowe! g1: value of ASI_INTR_RECEIVE_STATUS 180*5d9d9091SRichard Lowe! g5: word 0 of the interrupt data 181*5d9d9091SRichard Lowe! Register use: 182*5d9d9091SRichard Lowe! g2: dmv inum 183*5d9d9091SRichard Lowe! g3: scratch 184*5d9d9091SRichard Lowe! g4: pointer to dmv_dispatch_table 185*5d9d9091SRichard Lowe! g6: handler pointer from dispatch table 186*5d9d9091SRichard Lowe 187*5d9d9091SRichard Lowe 188*5d9d9091SRichard Lowe DGDEF(dmv_spurious_cnt) 189*5d9d9091SRichard Lowe .word 0 190*5d9d9091SRichard Lowe 191*5d9d9091SRichard Lowe ENTRY_NP(dmv_vector) 192*5d9d9091SRichard Lowe srlx %g5, DMV_INUM_SHIFT, %g2 193*5d9d9091SRichard Lowe set DMV_INUM_MASK, %g3 194*5d9d9091SRichard Lowe and %g2, %g3, %g2 ! %g2 = inum 195*5d9d9091SRichard Lowe 196*5d9d9091SRichard Lowe set dmv_totalints, %g3 197*5d9d9091SRichard Lowe ld [%g3], %g3 198*5d9d9091SRichard Lowe cmp %g2, %g3 199*5d9d9091SRichard Lowe bge,pn %xcc, 2f ! inum >= dmv_totalints 200*5d9d9091SRichard Lowe nop 201*5d9d9091SRichard Lowe 202*5d9d9091SRichard Lowe set dmv_dispatch_table, %g3 203*5d9d9091SRichard Lowe ldn [%g3], %g4 204*5d9d9091SRichard Lowe brz,pn %g4, 2f 205*5d9d9091SRichard Lowe sll %g2, DMV_DISP_SHIFT, %g3 ! %g3 = inum*sizeof(struct dmv_disp) 206*5d9d9091SRichard Lowe 207*5d9d9091SRichard Lowe add %g4, %g3, %g4 ! %g4 = &dmv_dispatch_table[inum] 208*5d9d9091SRichard Lowe#if (DMV_FUNC != 0) || (DMV_ARG != 8) 209*5d9d9091SRichard Lowe#error "DMV_FUNC or DMV_SIZE has changed" 210*5d9d9091SRichard Lowe#endif 211*5d9d9091SRichard Lowe ldda [%g4]ASI_NQUAD_LD, %g2 ! %g2=handler %g3=argument 212*5d9d9091SRichard Lowe mov %g3, %g1 213*5d9d9091SRichard Lowe brz,pn %g2, 2f 214*5d9d9091SRichard Lowe nop 215*5d9d9091SRichard Lowe 216*5d9d9091SRichard Lowe ! we have a handler, so call it 217*5d9d9091SRichard Lowe ! On entry to the handler, the %g registers are set as follows: 218*5d9d9091SRichard Lowe ! 219*5d9d9091SRichard Lowe ! %g1 The argument (arg) passed to dmv_add_intr(). 220*5d9d9091SRichard Lowe ! %g2 Word 0 of the incoming mondo vector. 221*5d9d9091SRichard Lowe ! 222*5d9d9091SRichard Lowe jmp %g2 223*5d9d9091SRichard Lowe mov %g5, %g2 224*5d9d9091SRichard Lowe 225*5d9d9091SRichard Lowe ! No handler was listed in the table, so just record it 226*5d9d9091SRichard Lowe ! as an error condition and continue. There is a race 227*5d9d9091SRichard Lowe ! window here updating the counter, but that's ok since 228*5d9d9091SRichard Lowe ! just knowing that spurious interrupts happened is enough, 229*5d9d9091SRichard Lowe ! we probably won't need to know exactly how many. 230*5d9d9091SRichard Lowe2: 231*5d9d9091SRichard Lowe set dmv_spurious_cnt, %g1 232*5d9d9091SRichard Lowe ld [%g1], %g2 233*5d9d9091SRichard Lowe inc %g2 234*5d9d9091SRichard Lowe ba,pt %xcc,3f 235*5d9d9091SRichard Lowe st %g2, [%g1] 236*5d9d9091SRichard Lowe 237*5d9d9091SRichard Lowe ! When the handler's processing (which should be as quick as 238*5d9d9091SRichard Lowe ! possible) is complete, the handler must exit by jumping to 239*5d9d9091SRichard Lowe ! the label dmv_finish_intr. The contents of %g1 at this time 240*5d9d9091SRichard Lowe ! determine whether a software interrupt will be issued, as 241*5d9d9091SRichard Lowe ! follows: 242*5d9d9091SRichard Lowe ! 243*5d9d9091SRichard Lowe ! If %g1 is less than zero, no interrupt will be queued. 244*5d9d9091SRichard Lowe ! Otherwise, %g1 will be used as the interrupt number 245*5d9d9091SRichard Lowe ! to simulate; this means that the behavior of the 246*5d9d9091SRichard Lowe ! interrupt system will be exactly that which would have 247*5d9d9091SRichard Lowe ! occurred if the first word of the incoming interrupt 248*5d9d9091SRichard Lowe ! vector had contained the contents of %g1. 249*5d9d9091SRichard Lowe 250*5d9d9091SRichard Lowe ENTRY_NP(dmv_finish_intr) 251*5d9d9091SRichard Lowe brlz,pn %g1,3f 252*5d9d9091SRichard Lowe nop 253*5d9d9091SRichard Lowe ! generate an interrupt based on the contents of %g1 254*5d9d9091SRichard Lowe ba,pt %xcc,vec_interrupt_resume 255*5d9d9091SRichard Lowe mov %g1, %g5 256*5d9d9091SRichard Lowe ! We are done 257*5d9d9091SRichard Lowe3: 258*5d9d9091SRichard Lowe stxa %g0, [%g0]ASI_INTR_RECEIVE_STATUS ! clear the busy bit 259*5d9d9091SRichard Lowe retry 260*5d9d9091SRichard Lowe SET_SIZE(dmv_vector) 261*5d9d9091SRichard Lowe 262*5d9d9091SRichard Lowe DGDEF(vec_spurious_cnt) 263*5d9d9091SRichard Lowe .word 0 264*5d9d9091SRichard Lowe 265*5d9d9091SRichard Lowe ENTRY_NP(vec_intr_spurious) 266*5d9d9091SRichard Lowe sethi %hi(vec_spurious_cnt), %g2 267*5d9d9091SRichard Lowe ld [%g2 + %lo(vec_spurious_cnt)], %g2 268*5d9d9091SRichard Lowe#ifdef TRAPTRACE 269*5d9d9091SRichard Lowe TRACE_PTR(%g4, %g6) 270*5d9d9091SRichard Lowe GET_TRACE_TICK(%g6, %g3) 271*5d9d9091SRichard Lowe stxa %g6, [%g4 + TRAP_ENT_TICK]%asi 272*5d9d9091SRichard Lowe rdpr %tl, %g6 273*5d9d9091SRichard Lowe stha %g6, [%g4 + TRAP_ENT_TL]%asi 274*5d9d9091SRichard Lowe rdpr %tt, %g6 275*5d9d9091SRichard Lowe or %g6, TT_SPURIOUS_INT, %g6 276*5d9d9091SRichard Lowe stha %g6, [%g4 + TRAP_ENT_TT]%asi 277*5d9d9091SRichard Lowe rdpr %tpc, %g6 278*5d9d9091SRichard Lowe stna %g6, [%g4 + TRAP_ENT_TPC]%asi 279*5d9d9091SRichard Lowe rdpr %tstate, %g6 280*5d9d9091SRichard Lowe stxa %g6, [%g4 + TRAP_ENT_TSTATE]%asi 281*5d9d9091SRichard Lowe stna %sp, [%g4 + TRAP_ENT_SP]%asi 282*5d9d9091SRichard Lowe stna %g1, [%g4 + TRAP_ENT_TR]%asi ! irsr 283*5d9d9091SRichard Lowe stna %g2, [%g4 + TRAP_ENT_F1]%asi 284*5d9d9091SRichard Lowe ldxa [%g0]ASI_INTR_RECEIVE_STATUS, %g5 285*5d9d9091SRichard Lowe stxa %g5, [%g4 + TRAP_ENT_F2]%asi 286*5d9d9091SRichard Lowe stxa %g0, [%g4 + TRAP_ENT_F4]%asi 287*5d9d9091SRichard Lowe TRACE_NEXT(%g4, %g6, %g3) 288*5d9d9091SRichard Lowe#endif /* TRAPTRACE */ 289*5d9d9091SRichard Lowe cmp %g2, 16 290*5d9d9091SRichard Lowe bl,a,pt %xcc, 1f 291*5d9d9091SRichard Lowe inc %g2 292*5d9d9091SRichard Lowe ! 293*5d9d9091SRichard Lowe ! prepare for sys_trap() 294*5d9d9091SRichard Lowe ! %g1 - sys_tl1_panic 295*5d9d9091SRichard Lowe ! %g2 - panic message 296*5d9d9091SRichard Lowe ! %g4 - current pil 297*5d9d9091SRichard Lowe ! 298*5d9d9091SRichard Lowe#ifdef CLEAR_INTR_BUSYBIT_ON_SPURIOUS 299*5d9d9091SRichard Lowe /* 300*5d9d9091SRichard Lowe * Certain processors (OPL) need to explicitly 301*5d9d9091SRichard Lowe * clear the intr busy bit even though it is 302*5d9d9091SRichard Lowe * not visibly set (spurious intrs) 303*5d9d9091SRichard Lowe */ 304*5d9d9091SRichard Lowe stxa %g0, [%g0]ASI_INTR_RECEIVE_STATUS ! clear the BUSY bit 305*5d9d9091SRichard Lowe membar #Sync 306*5d9d9091SRichard Lowe#endif /* CLEAR_INTR_BUSYBIT_ON_SPURIOUS */ 307*5d9d9091SRichard Lowe sub %g0, 1, %g4 308*5d9d9091SRichard Lowe set _not_ready, %g2 309*5d9d9091SRichard Lowe sethi %hi(sys_tl1_panic), %g1 310*5d9d9091SRichard Lowe ba,pt %xcc, sys_trap 311*5d9d9091SRichard Lowe or %g1, %lo(sys_tl1_panic), %g1 312*5d9d9091SRichard Lowe ! 313*5d9d9091SRichard Lowe1: sethi %hi(vec_spurious_cnt), %g1 314*5d9d9091SRichard Lowe st %g2, [%g1 + %lo(vec_spurious_cnt)] 315*5d9d9091SRichard Lowe retry 316*5d9d9091SRichard Lowe SET_SIZE(vec_intr_spurious) 317*5d9d9091SRichard Lowe 318*5d9d9091SRichard Lowe_not_ready: .asciz "Interrupt Vector Receive Register not READY" 319*5d9d9091SRichard Lowe 320