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 2006 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 mov MMU_PCONTEXT, %g1 91 ldxa [%g1]ASI_DMMU, %g1 92 srlx %g1, CTXREG_NEXT_SHIFT, %g3 93 brz,pt %g3, 7f ! nucleus pgsz is 0, no problem 94 sllx %g3, CTXREG_NEXT_SHIFT, %g3 95 set CTXREG_CTX_MASK, %g4 ! check Pcontext 96 btst %g4, %g1 97 bz,a,pt %xcc, 6f 98 clr %g3 ! kernel: PCONTEXT=0 99 xor %g3, %g1, %g3 ! user: clr N_pgsz0/1 bits 1006: 101 set DEMAP_ALL_TYPE, %g1 102 stxa %g0, [%g1]ASI_DTLB_DEMAP 103 stxa %g0, [%g1]ASI_ITLB_DEMAP 104 mov MMU_PCONTEXT, %g1 105 stxa %g3, [%g1]ASI_DMMU 106 membar #Sync 107 sethi %hi(FLUSH_ADDR), %g1 108 flush %g1 ! flush required by immu 1097: 110 ! 111 ! Cross-trap request case 112 ! 113 ! Load interrupt receive data registers 1 and 2 to fetch 114 ! the arguments for the fast trap handler. 115 ! 116 ! Register usage: 117 ! g5: TL>0 handler 118 ! g1: arg1 119 ! g2: arg2 120 ! g3: arg3 121 ! g4: arg4 122 ! 123 mov IRDR_1, %g2 124 ldxa [%g2]ASI_INTR_RECEIVE, %g1 125 mov IRDR_2, %g2 126 ldxa [%g2]ASI_INTR_RECEIVE, %g2 127#ifdef TRAPTRACE 128 TRACE_PTR(%g4, %g6) 129 GET_TRACE_TICK(%g6) 130 stxa %g6, [%g4 + TRAP_ENT_TICK]%asi 131 rdpr %tl, %g6 132 stha %g6, [%g4 + TRAP_ENT_TL]%asi 133 rdpr %tt, %g6 134 stha %g6, [%g4 + TRAP_ENT_TT]%asi 135 rdpr %tpc, %g6 136 stna %g6, [%g4 + TRAP_ENT_TPC]%asi 137 rdpr %tstate, %g6 138 stxa %g6, [%g4 + TRAP_ENT_TSTATE]%asi 139 stna %sp, [%g4 + TRAP_ENT_SP]%asi 140 stna %g5, [%g4 + TRAP_ENT_TR]%asi ! pc of the TL>0 handler 141 stxa %g1, [%g4 + TRAP_ENT_F1]%asi 142 stxa %g2, [%g4 + TRAP_ENT_F3]%asi 143 stxa %g0, [%g4 + TRAP_ENT_F2]%asi 144 stxa %g0, [%g4 + TRAP_ENT_F4]%asi 145 TRACE_NEXT(%g4, %g6, %g3) 146#endif /* TRAPTRACE */ 147 stxa %g0, [%g0]ASI_INTR_RECEIVE_STATUS ! clear the BUSY bit 148 membar #Sync 149#ifdef SF_ERRATA_51 150 ba,pt %icc, 1f 151 nop 152 .align 32 1531: jmp %g5 ! call the fast trap handler 154 nop 155#else 156 jmp %g5 157 nop 158#endif /* SF_ERRATA_51 */ 159 /* Never Reached */ 160 1610: 162 ! We have an interrupt number. 163 ! 164 ! Register usage: 165 ! %g5 - inum 166 ! %g1 - temp 167 ! 168 ! We don't bother to verify that the received inum is valid (it should 169 ! be < MAXIVNUM) since setsoftint_tl1 will do that for us. 170 ! 171 ! clear BUSY bit 172 ! 173 stxa %g0, [%g0]ASI_INTR_RECEIVE_STATUS 174 membar #Sync 175 176 ! setsoftint_tl1 will do all the work, and finish with a retry 177 ! 178 ba,pt %xcc, setsoftint_tl1 179 mov %g5, %g1 ! setsoftint_tl1 expects inum in %g1 180 181 /* Never Reached */ 182 SET_SIZE(vec_interrupt) 183 184 185! 186! See usr/src/uts/sun4u/sys/dmv.h for the Databearing Mondo Vector 187! interrupt format 188! 189! Inputs: 190! g1: value of ASI_INTR_RECEIVE_STATUS 191! g5: word 0 of the interrupt data 192! Register use: 193! g2: dmv inum 194! g3: scratch 195! g4: pointer to dmv_dispatch_table 196! g6: handler pointer from dispatch table 197 198 199 DGDEF(dmv_spurious_cnt) 200 .word 0 201 202 ENTRY_NP(dmv_vector) 203 srlx %g5, DMV_INUM_SHIFT, %g2 204 set DMV_INUM_MASK, %g3 205 and %g2, %g3, %g2 ! %g2 = inum 206 207 set dmv_totalints, %g3 208 ld [%g3], %g3 209 cmp %g2, %g3 210 bge,pn %xcc, 2f ! inum >= dmv_totalints 211 nop 212 213 set dmv_dispatch_table, %g3 214 ldn [%g3], %g4 215 brz,pn %g4, 2f 216 sll %g2, DMV_DISP_SHIFT, %g3 ! %g3 = inum*sizeof(struct dmv_disp) 217 218 add %g4, %g3, %g4 ! %g4 = &dmv_dispatch_table[inum] 219#if (DMV_FUNC != 0) || (DMV_ARG != 8) 220#error "DMV_FUNC or DMV_SIZE has changed" 221#endif 222 ldda [%g4]ASI_NQUAD_LD, %g2 ! %g2=handler %g3=argument 223 mov %g3, %g1 224 brz,pn %g2, 2f 225 nop 226 227 ! we have a handler, so call it 228 ! On entry to the handler, the %g registers are set as follows: 229 ! 230 ! %g1 The argument (arg) passed to dmv_add_intr(). 231 ! %g2 Word 0 of the incoming mondo vector. 232 ! 233 jmp %g2 234 mov %g5, %g2 235 236 ! No handler was listed in the table, so just record it 237 ! as an error condition and continue. There is a race 238 ! window here updating the counter, but that's ok since 239 ! just knowing that spurious interrupts happened is enough, 240 ! we probably won't need to know exactly how many. 2412: 242 set dmv_spurious_cnt, %g1 243 ld [%g1], %g2 244 inc %g2 245 ba,pt %xcc,3f 246 st %g2, [%g1] 247 248 ! When the handler's processing (which should be as quick as 249 ! possible) is complete, the handler must exit by jumping to 250 ! the label dmv_finish_intr. The contents of %g1 at this time 251 ! determine whether a software interrupt will be issued, as 252 ! follows: 253 ! 254 ! If %g1 is less than zero, no interrupt will be queued. 255 ! Otherwise, %g1 will be used as the interrupt number 256 ! to simulate; this means that the behavior of the 257 ! interrupt system will be exactly that which would have 258 ! occurred if the first word of the incoming interrupt 259 ! vector had contained the contents of %g1. 260 261 ENTRY_NP(dmv_finish_intr) 262 brlz,pn %g1,3f 263 nop 264 ! generate an interrupt based on the contents of %g1 265 ba,pt %xcc,vec_interrupt_resume 266 mov %g1, %g5 267 ! We are done 2683: 269 stxa %g0, [%g0]ASI_INTR_RECEIVE_STATUS ! clear the busy bit 270 retry 271 SET_SIZE(dmv_vector) 272 273#endif /* lint */ 274 275#if defined(lint) 276 277void 278vec_intr_spurious(void) 279{} 280 281#else /* lint */ 282 283 DGDEF(vec_spurious_cnt) 284 .word 0 285 286 ENTRY_NP(vec_intr_spurious) 287 sethi %hi(vec_spurious_cnt), %g2 288 ld [%g2 + %lo(vec_spurious_cnt)], %g2 289#ifdef TRAPTRACE 290 TRACE_PTR(%g4, %g6) 291 GET_TRACE_TICK(%g6) 292 stxa %g6, [%g4 + TRAP_ENT_TICK]%asi 293 rdpr %tl, %g6 294 stha %g6, [%g4 + TRAP_ENT_TL]%asi 295 rdpr %tt, %g6 296 or %g6, TT_SPURIOUS_INT, %g6 297 stha %g6, [%g4 + TRAP_ENT_TT]%asi 298 rdpr %tpc, %g6 299 stna %g6, [%g4 + TRAP_ENT_TPC]%asi 300 rdpr %tstate, %g6 301 stxa %g6, [%g4 + TRAP_ENT_TSTATE]%asi 302 stna %sp, [%g4 + TRAP_ENT_SP]%asi 303 stna %g1, [%g4 + TRAP_ENT_TR]%asi ! irsr 304 stna %g2, [%g4 + TRAP_ENT_F1]%asi 305 ldxa [%g0]ASI_INTR_RECEIVE_STATUS, %g5 306 stxa %g5, [%g4 + TRAP_ENT_F2]%asi 307 stxa %g0, [%g4 + TRAP_ENT_F4]%asi 308 TRACE_NEXT(%g4, %g6, %g3) 309#endif /* TRAPTRACE */ 310 cmp %g2, 16 311 bl,a,pt %xcc, 1f 312 inc %g2 313 ! 314 ! prepare for sys_trap() 315 ! %g1 - sys_tl1_panic 316 ! %g2 - panic message 317 ! %g4 - current pil 318 ! 319#ifdef CLEAR_INTR_BUSYBIT_ON_SPURIOUS 320 /* 321 * Certain processors (OPL) need to explicitly 322 * clear the intr busy bit even though it is 323 * not visibly set (spurious intrs) 324 */ 325 stxa %g0, [%g0]ASI_INTR_RECEIVE_STATUS ! clear the BUSY bit 326 membar #Sync 327#endif /* CLEAR_INTR_BUSYBIT_ON_SPURIOUS */ 328 sub %g0, 1, %g4 329 set _not_ready, %g2 330 sethi %hi(sys_tl1_panic), %g1 331 ba,pt %xcc, sys_trap 332 or %g1, %lo(sys_tl1_panic), %g1 333 ! 3341: sethi %hi(vec_spurious_cnt), %g1 335 st %g2, [%g1 + %lo(vec_spurious_cnt)] 336 retry 337 SET_SIZE(vec_intr_spurious) 338 339_not_ready: .asciz "Interrupt Vector Receive Register not READY" 340 341#endif /* lint */ 342