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