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