8354 sync regcomp(3C) with upstream (fix make catalog)
[unleashed/tickless.git] / usr / src / uts / sun4u / ml / mach_interrupt.s
blob61e156d3ccabe3aab88be56290b2aac9bb708218
1 /*
2 * CDDL HEADER START
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]
19 * CDDL HEADER END
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #if defined(lint)
27 #include <sys/types.h>
28 #include <sys/thread.h>
29 #else /* lint */
30 #include "assym.h"
31 #endif /* lint */
33 #include <sys/asm_linkage.h>
34 #include <sys/machthread.h>
35 #include <sys/machcpuvar.h>
36 #include <sys/mmu.h>
37 #include <sys/intreg.h>
38 #include <sys/dmv.h>
40 #ifdef TRAPTRACE
41 #include <sys/traptrace.h>
42 #endif /* TRAPTRACE */
45 #if defined(lint)
47 void
48 vec_interrupt(void)
51 #else /* lint */
53 vec_uiii_irdr_tab:
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.
67 mov IRDR_0, %g2
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
73 .empty
76 vec_interrupt_resume:
77 set KERNELBASE, %g4
78 cmp %g5, %g4
79 bl,a,pt %xcc, 0f ! an interrupt number found
80 nop
82 ! intercept OBP xcalls and set PCONTEXT=0
84 set _end, %g4 ! _end is highest kernel address
85 cmp %g5, %g4
86 bl,a,pt %xcc, 7f
87 nop
89 #ifndef _OPL
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
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
109 #endif /* _OPL */
113 ! Cross-trap request case
115 ! Load interrupt receive data registers 1 and 2 to fetch
116 ! the arguments for the fast trap handler.
118 ! Register usage:
119 ! g5: TL>0 handler
120 ! g1: arg1
121 ! g2: arg2
122 ! g3: arg3
123 ! g4: arg4
125 mov IRDR_1, %g2
126 ldxa [%g2]ASI_INTR_RECEIVE, %g1
127 mov IRDR_2, %g2
128 ldxa [%g2]ASI_INTR_RECEIVE, %g2
129 #ifdef TRAPTRACE
130 TRACE_PTR(%g4, %g6)
131 GET_TRACE_TICK(%g6, %g3)
132 stxa %g6, [%g4 + TRAP_ENT_TICK]%asi
133 rdpr %tl, %g6
134 stha %g6, [%g4 + TRAP_ENT_TL]%asi
135 rdpr %tt, %g6
136 stha %g6, [%g4 + TRAP_ENT_TT]%asi
137 rdpr %tpc, %g6
138 stna %g6, [%g4 + TRAP_ENT_TPC]%asi
139 rdpr %tstate, %g6
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
150 membar #Sync
151 #ifdef SF_ERRATA_51
152 ba,pt %icc, 1f
154 .align 32
155 1: jmp %g5 ! call the fast trap handler
157 #else
158 jmp %g5
160 #endif /* SF_ERRATA_51 */
161 /* Never Reached */
164 ! We have an interrupt number.
166 ! Register usage:
167 ! %g5 - inum
168 ! %g1 - temp
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.
173 ! clear BUSY bit
175 stxa %g0, [%g0]ASI_INTR_RECEIVE_STATUS
176 membar #Sync
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
183 /* Never Reached */
184 SET_SIZE(vec_interrupt)
188 ! See usr/src/uts/sun4u/sys/dmv.h for the Databearing Mondo Vector
189 ! interrupt format
191 ! Inputs:
192 ! g1: value of ASI_INTR_RECEIVE_STATUS
193 ! g5: word 0 of the interrupt data
194 ! Register use:
195 ! g2: dmv inum
196 ! g3: scratch
197 ! g4: pointer to dmv_dispatch_table
198 ! g6: handler pointer from dispatch table
201 DGDEF(dmv_spurious_cnt)
202 .word 0
204 ENTRY_NP(dmv_vector)
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
210 ld [%g3], %g3
211 cmp %g2, %g3
212 bge,pn %xcc, 2f ! inum >= dmv_totalints
215 set dmv_dispatch_table, %g3
216 ldn [%g3], %g4
217 brz,pn %g4, 2f
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"
223 #endif
224 ldda [%g4]ASI_NQUAD_LD, %g2 ! %g2=handler %g3=argument
225 mov %g3, %g1
226 brz,pn %g2, 2f
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.
235 jmp %g2
236 mov %g5, %g2
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
245 ld [%g1], %g2
246 inc %g2
247 ba,pt %xcc,3f
248 st %g2, [%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
254 ! follows:
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)
264 brlz,pn %g1,3f
266 ! generate an interrupt based on the contents of %g1
267 ba,pt %xcc,vec_interrupt_resume
268 mov %g1, %g5
269 ! We are done
271 stxa %g0, [%g0]ASI_INTR_RECEIVE_STATUS ! clear the busy bit
272 retry
273 SET_SIZE(dmv_vector)
275 #endif /* lint */
277 #if defined(lint)
279 void
280 vec_intr_spurious(void)
283 #else /* lint */
285 DGDEF(vec_spurious_cnt)
286 .word 0
288 ENTRY_NP(vec_intr_spurious)
289 sethi %hi(vec_spurious_cnt), %g2
290 ld [%g2 + %lo(vec_spurious_cnt)], %g2
291 #ifdef TRAPTRACE
292 TRACE_PTR(%g4, %g6)
293 GET_TRACE_TICK(%g6, %g3)
294 stxa %g6, [%g4 + TRAP_ENT_TICK]%asi
295 rdpr %tl, %g6
296 stha %g6, [%g4 + TRAP_ENT_TL]%asi
297 rdpr %tt, %g6
298 or %g6, TT_SPURIOUS_INT, %g6
299 stha %g6, [%g4 + TRAP_ENT_TT]%asi
300 rdpr %tpc, %g6
301 stna %g6, [%g4 + TRAP_ENT_TPC]%asi
302 rdpr %tstate, %g6
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 */
312 cmp %g2, 16
313 bl,a,pt %xcc, 1f
314 inc %g2
316 ! prepare for sys_trap()
317 ! %g1 - sys_tl1_panic
318 ! %g2 - panic message
319 ! %g4 - current pil
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
328 membar #Sync
329 #endif /* CLEAR_INTR_BUSYBIT_ON_SPURIOUS */
330 sub %g0, 1, %g4
331 set _not_ready, %g2
332 sethi %hi(sys_tl1_panic), %g1
333 ba,pt %xcc, sys_trap
334 or %g1, %lo(sys_tl1_panic), %g1
336 1: sethi %hi(vec_spurious_cnt), %g1
337 st %g2, [%g1 + %lo(vec_spurious_cnt)]
338 retry
339 SET_SIZE(vec_intr_spurious)
341 _not_ready: .asciz "Interrupt Vector Receive Register not READY"
343 #endif /* lint */