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.
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.
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]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
27 #include <sys/types.h>
28 #include <sys/thread.h>
33 #include <sys/asm_linkage.h>
34 #include <sys/machthread.h>
35 #include <sys/machcpuvar.h>
37 #include <sys/intreg.h>
41 #include <sys/traptrace.h>
42 #endif /* TRAPTRACE */
54 .byte UIII_IRDR_0, UIII_IRDR_1, UIII_IRDR_2, UIII_IRDR_3
55 .byte UIII_IRDR_4, UIII_IRDR_5, UIII_IRDR_6, UIII_IRDR_7
58 * (TT 0x60, TL>0) Interrupt Vector Handler
59 * Globals are the Interrupt Globals.
61 ENTRY_NP
(vec_interrupt
)
63 ! Load the interrupt receive data register
0.
64 ! It could
be a fast
trap handler address
(pc
> KERNELBASE
) at TL
>0
65 ! or an interrupt number.
68 ldxa
[%g2
]ASI_INTR_RECEIVE
, %g5
! %g5
= PC
or Interrupt Number
70 ! If the high bit of IRDR_0 is set
, then this is
a
71 ! data bearing mondo vector.
72 brlz
,pt
%g5
, dmv_vector
79 bl,a,pt
%xcc
, 0f
! an interrupt number found
82 ! intercept OBP xcalls
and set PCONTEXT
=0
84 set _end
, %g4
! _end is highest kernel address
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
98 clr
%g3
! kernel
: PCONTEXT
=0
99 xor %g3
, %g1
, %g3
! user
: clr N_pgsz0
/1 bits
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
107 sethi
%hi
(FLUSH_ADDR
), %g1
108 flush
%g1
! flush required by immu
113 ! Cross-
trap request case
115 ! Load interrupt receive data registers
1 and 2 to fetch
116 ! the arguments for the fast
trap handler.
126 ldxa
[%g2
]ASI_INTR_RECEIVE
, %g1
128 ldxa
[%g2
]ASI_INTR_RECEIVE
, %g2
131 GET_TRACE_TICK
(%g6
, %g3
)
132 stxa
%g6
, [%g4
+ TRAP_ENT_TICK
]%asi
134 stha
%g6
, [%g4
+ TRAP_ENT_TL
]%asi
136 stha
%g6
, [%g4
+ TRAP_ENT_TT
]%asi
138 stna
%g6
, [%g4
+ TRAP_ENT_TPC
]%asi
140 stxa
%g6
, [%g4
+ TRAP_ENT_TSTATE
]%asi
141 stna
%sp
, [%g4
+ TRAP_ENT_SP
]%asi
142 stna
%g5
, [%g4
+ TRAP_ENT_TR
]%asi
! pc of the TL
>0 handler
143 stxa
%g1
, [%g4
+ TRAP_ENT_F1
]%asi
144 stxa
%g2
, [%g4
+ TRAP_ENT_F3
]%asi
145 stxa
%g0
, [%g4
+ TRAP_ENT_F2
]%asi
146 stxa
%g0
, [%g4
+ TRAP_ENT_F4
]%asi
147 TRACE_NEXT
(%g4
, %g6
, %g3
)
148 #endif /* TRAPTRACE */
149 stxa
%g0
, [%g0
]ASI_INTR_RECEIVE_STATUS
! clear the BUSY bit
155 1: jmp
%g5
! call the fast
trap handler
160 #endif /* SF_ERRATA_51 */
164 ! We have an interrupt number.
170 ! We don
't bother to verify that the received inum is valid (it should
171 ! be < MAXIVNUM) since setvecint_tl1 will do that for us.
175 stxa %g0, [%g0]ASI_INTR_RECEIVE_STATUS
178 ! setvecint_tl1 will do all the work, and finish with a retry
180 ba,pt %xcc, setvecint_tl1
181 mov %g5, %g1 ! setvecint_tl1 expects inum in %g1
184 SET_SIZE(vec_interrupt)
188 ! See usr/src/uts/sun4u/sys/dmv.h for the Databearing Mondo Vector
192 ! g1: value of ASI_INTR_RECEIVE_STATUS
193 ! g5: word 0 of the interrupt data
197 ! g4: pointer to dmv_dispatch_table
198 ! g6: handler pointer from dispatch table
201 DGDEF(dmv_spurious_cnt)
205 srlx %g5, DMV_INUM_SHIFT, %g2
206 set DMV_INUM_MASK, %g3
207 and %g2, %g3, %g2 ! %g2 = inum
209 set dmv_totalints, %g3
212 bge,pn %xcc, 2f ! inum >= dmv_totalints
215 set dmv_dispatch_table, %g3
218 sll %g2, DMV_DISP_SHIFT, %g3 ! %g3 = inum*sizeof(struct dmv_disp)
220 add %g4, %g3, %g4 ! %g4 = &dmv_dispatch_table[inum]
221 #if (DMV_FUNC != 0) || (DMV_ARG != 8)
222 #error "DMV_FUNC or DMV_SIZE has changed"
224 ldda [%g4]ASI_NQUAD_LD, %g2 ! %g2=handler %g3=argument
229 ! we have a handler, so call it
230 ! On entry to the handler, the %g registers are set as follows:
232 ! %g1 The argument (arg) passed to dmv_add_intr().
233 ! %g2 Word 0 of the incoming mondo vector.
238 ! No handler was listed in the table, so just record it
239 ! as an error condition and continue. There is a race
240 ! window here updating the counter, but that's ok since
241 ! just knowing that spurious interrupts happened is enough
,
242 ! we probably won
't need to know exactly how many.
244 set dmv_spurious_cnt, %g1
250 ! When the handler's processing
(which should
be as quick as
251 ! possible
) is complete
, the handler must exit by jumping to
252 ! the label dmv_finish_intr. The contents of
%g1 at this time
253 ! determine whether
a software interrupt will
be issued
, as
256 ! If
%g1 is less than zero
, no interrupt will
be queued.
257 ! Otherwise
, %g1 will
be used as the interrupt number
258 ! to simulate; this means that the behavior of the
259 ! interrupt system will
be exactly that which would have
260 ! occurred if the first word of the incoming interrupt
261 ! vector had contained the contents of
%g1.
263 ENTRY_NP
(dmv_finish_intr
)
266 ! generate an interrupt based on the contents of
%g1
267 ba,pt
%xcc
,vec_interrupt_resume
271 stxa
%g0
, [%g0
]ASI_INTR_RECEIVE_STATUS
! clear the busy bit
280 vec_intr_spurious
(void
)
285 DGDEF
(vec_spurious_cnt
)
288 ENTRY_NP
(vec_intr_spurious
)
289 sethi
%hi
(vec_spurious_cnt
), %g2
290 ld [%g2
+ %lo
(vec_spurious_cnt
)], %g2
293 GET_TRACE_TICK
(%g6
, %g3
)
294 stxa
%g6
, [%g4
+ TRAP_ENT_TICK
]%asi
296 stha
%g6
, [%g4
+ TRAP_ENT_TL
]%asi
298 or %g6
, TT_SPURIOUS_INT
, %g6
299 stha
%g6
, [%g4
+ TRAP_ENT_TT
]%asi
301 stna
%g6
, [%g4
+ TRAP_ENT_TPC
]%asi
303 stxa
%g6
, [%g4
+ TRAP_ENT_TSTATE
]%asi
304 stna
%sp
, [%g4
+ TRAP_ENT_SP
]%asi
305 stna
%g1
, [%g4
+ TRAP_ENT_TR
]%asi
! irsr
306 stna
%g2
, [%g4
+ TRAP_ENT_F1
]%asi
307 ldxa
[%g0
]ASI_INTR_RECEIVE_STATUS
, %g5
308 stxa
%g5
, [%g4
+ TRAP_ENT_F2
]%asi
309 stxa
%g0
, [%g4
+ TRAP_ENT_F4
]%asi
310 TRACE_NEXT
(%g4
, %g6
, %g3
)
311 #endif /* TRAPTRACE */
316 ! prepare for sys_trap
()
317 ! %g1
- sys_tl1_panic
318 ! %g2
- panic message
321 #ifdef CLEAR_INTR_BUSYBIT_ON_SPURIOUS
323 * Certain processors (OPL) need to explicitly
324 * clear the intr busy bit even though it is
325 * not visibly set (spurious intrs)
327 stxa
%g0
, [%g0
]ASI_INTR_RECEIVE_STATUS
! clear the BUSY bit
329 #endif /* CLEAR_INTR_BUSYBIT_ON_SPURIOUS */
332 sethi
%hi
(sys_tl1_panic
), %g1
334 or %g1
, %lo
(sys_tl1_panic
), %g1
336 1: sethi
%hi
(vec_spurious_cnt
), %g1
337 st %g2
, [%g1
+ %lo
(vec_spurious_cnt
)]
339 SET_SIZE
(vec_intr_spurious
)
341 _not_ready
: .asciz "Interrupt Vector Receive Register not READY"