Print this page
restore sparc comments
de-linting of .s files
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/sun4/ml/interrupt.s
+++ new/usr/src/uts/sun4/ml/interrupt.s
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
23 23 */
24 24
25 -#if defined(lint)
26 -#include <sys/types.h>
27 -#include <sys/thread.h>
28 -#else /* lint */
29 25 #include "assym.h"
30 -#endif /* lint */
31 26
32 27 #include <sys/cmn_err.h>
33 28 #include <sys/ftrace.h>
34 29 #include <sys/asm_linkage.h>
35 30 #include <sys/machthread.h>
36 31 #include <sys/machcpuvar.h>
37 32 #include <sys/intreg.h>
38 33 #include <sys/ivintr.h>
39 34
40 35 #ifdef TRAPTRACE
41 36 #include <sys/traptrace.h>
42 37 #endif /* TRAPTRACE */
43 38
44 -#if defined(lint)
45 39
46 -/* ARGSUSED */
47 -void
48 -pil_interrupt(int level)
49 -{}
50 -
51 -#else /* lint */
52 -
53 -
54 40 /*
55 41 * (TT 0x40..0x4F, TL>0) Interrupt Level N Handler (N == 1..15)
56 42 * Register passed from LEVEL_INTERRUPT(level)
57 43 * %g4 - interrupt request level
58 44 */
59 45 ENTRY_NP(pil_interrupt)
60 46 !
61 47 ! Register usage
62 48 ! %g1 - cpu
63 49 ! %g2 - pointer to intr_vec_t (iv)
64 50 ! %g4 - pil
65 51 ! %g3, %g5, %g6, %g7 - temps
66 52 !
67 53 ! Grab the first or list head intr_vec_t off the intr_head[pil]
68 54 ! and panic immediately if list head is NULL. Otherwise, update
69 55 ! intr_head[pil] to next intr_vec_t on the list and clear softint
70 56 ! %clear_softint, if next intr_vec_t is NULL.
71 57 !
72 58 CPU_ADDR(%g1, %g5) ! %g1 = cpu
73 59 !
74 60 ALTENTRY(pil_interrupt_common)
75 61 sll %g4, CPTRSHIFT, %g5 ! %g5 = offset to the pil entry
76 62 add %g1, INTR_HEAD, %g6 ! %g6 = &cpu->m_cpu.intr_head
77 63 add %g6, %g5, %g6 ! %g6 = &cpu->m_cpu.intr_head[pil]
78 64 ldn [%g6], %g2 ! %g2 = cpu->m_cpu.intr_head[pil]
79 65 brnz,pt %g2, 0f ! check list head (iv) is NULL
80 66 nop
81 67 ba ptl1_panic ! panic, list head (iv) is NULL
82 68 mov PTL1_BAD_INTR_VEC, %g1
83 69 0:
84 70 lduh [%g2 + IV_FLAGS], %g7 ! %g7 = iv->iv_flags
85 71 and %g7, IV_SOFTINT_MT, %g3 ! %g3 = iv->iv_flags & IV_SOFTINT_MT
86 72 brz,pt %g3, 1f ! check for multi target softint
87 73 add %g2, IV_PIL_NEXT, %g7 ! g7% = &iv->iv_pil_next
88 74 ld [%g1 + CPU_ID], %g3 ! for multi target softint, use cpuid
89 75 sll %g3, CPTRSHIFT, %g3 ! convert cpuid to offset address
90 76 add %g7, %g3, %g7 ! %g5 = &iv->iv_xpil_next[cpuid]
91 77 1:
92 78 ldn [%g7], %g3 ! %g3 = next intr_vec_t
93 79 brnz,pn %g3, 2f ! branch if next intr_vec_t non NULL
94 80 stn %g3, [%g6] ! update cpu->m_cpu.intr_head[pil]
95 81 add %g1, INTR_TAIL, %g6 ! %g6 = &cpu->m_cpu.intr_tail
96 82 stn %g0, [%g5 + %g6] ! clear cpu->m_cpu.intr_tail[pil]
97 83 mov 1, %g5 ! %g5 = 1
98 84 sll %g5, %g4, %g5 ! %g5 = 1 << pil
99 85 wr %g5, CLEAR_SOFTINT ! clear interrupt on this pil
100 86 2:
101 87 #ifdef TRAPTRACE
102 88 TRACE_PTR(%g5, %g6)
103 89 TRACE_SAVE_TL_GL_REGS(%g5, %g6)
104 90 rdpr %tt, %g6
105 91 stha %g6, [%g5 + TRAP_ENT_TT]%asi ! trap_type = %tt
106 92 rdpr %tpc, %g6
107 93 stna %g6, [%g5 + TRAP_ENT_TPC]%asi ! trap_pc = %tpc
108 94 rdpr %tstate, %g6
109 95 stxa %g6, [%g5 + TRAP_ENT_TSTATE]%asi ! trap_tstate = %tstate
110 96 stna %sp, [%g5 + TRAP_ENT_SP]%asi ! trap_sp = %sp
111 97 stna %g2, [%g5 + TRAP_ENT_TR]%asi ! trap_tr = first intr_vec
112 98 stna %g3, [%g5 + TRAP_ENT_F1]%asi ! trap_f1 = next intr_vec
113 99 GET_TRACE_TICK(%g6, %g3)
114 100 stxa %g6, [%g5 + TRAP_ENT_TICK]%asi ! trap_tick = %tick
115 101 sll %g4, CPTRSHIFT, %g3
116 102 add %g1, INTR_HEAD, %g6
117 103 ldn [%g6 + %g3], %g6 ! %g6=cpu->m_cpu.intr_head[pil]
118 104 stna %g6, [%g5 + TRAP_ENT_F2]%asi ! trap_f2 = intr_head[pil]
119 105 add %g1, INTR_TAIL, %g6
120 106 ldn [%g6 + %g3], %g6 ! %g6=cpu->m_cpu.intr_tail[pil]
121 107 stna %g6, [%g5 + TRAP_ENT_F3]%asi ! trap_f3 = intr_tail[pil]
122 108 stna %g4, [%g5 + TRAP_ENT_F4]%asi ! trap_f4 = pil
123 109 TRACE_NEXT(%g5, %g6, %g3)
124 110 #endif /* TRAPTRACE */
125 111 !
126 112 ! clear the iv_pending flag for this interrupt request
127 113 !
128 114 lduh [%g2 + IV_FLAGS], %g3 ! %g3 = iv->iv_flags
129 115 andn %g3, IV_SOFTINT_PEND, %g3 ! %g3 = !(iv->iv_flags & PEND)
130 116 sth %g3, [%g2 + IV_FLAGS] ! clear IV_SOFTINT_PEND flag
131 117 stn %g0, [%g7] ! clear iv->iv_pil_next or
132 118 ! iv->iv_pil_xnext
133 119
134 120 !
135 121 ! Prepare for sys_trap()
136 122 !
137 123 ! Registers passed to sys_trap()
138 124 ! %g1 - interrupt handler at TL==0
139 125 ! %g2 - pointer to current intr_vec_t (iv),
140 126 ! job queue for intr_thread or current_thread
141 127 ! %g3 - pil
142 128 ! %g4 - initial pil for handler
143 129 !
144 130 ! figure which handler to run and which %pil it starts at
145 131 ! intr_thread starts at DISP_LEVEL to prevent preemption
146 132 ! current_thread starts at PIL_MAX to protect cpu_intr_actv
147 133 !
148 134 mov %g4, %g3 ! %g3 = %g4, pil
149 135 cmp %g4, LOCK_LEVEL
150 136 bg,a,pt %xcc, 3f ! branch if pil > LOCK_LEVEL
151 137 mov PIL_MAX, %g4 ! %g4 = PIL_MAX (15)
152 138 sethi %hi(intr_thread), %g1 ! %g1 = intr_thread
↓ open down ↓ |
89 lines elided |
↑ open up ↑ |
153 139 mov DISP_LEVEL, %g4 ! %g4 = DISP_LEVEL (11)
154 140 ba,pt %xcc, sys_trap
155 141 or %g1, %lo(intr_thread), %g1
156 142 3:
157 143 sethi %hi(current_thread), %g1 ! %g1 = current_thread
158 144 ba,pt %xcc, sys_trap
159 145 or %g1, %lo(current_thread), %g1
160 146 SET_SIZE(pil_interrupt_common)
161 147 SET_SIZE(pil_interrupt)
162 148
163 -#endif /* lint */
164 149
165 -
166 -#ifndef lint
167 150 _spurious:
168 151 .asciz "!interrupt 0x%x at level %d not serviced"
169 152
170 153 /*
171 154 * SERVE_INTR_PRE is called once, just before the first invocation
172 155 * of SERVE_INTR.
173 156 *
174 157 * Registers on entry:
175 158 *
176 159 * iv_p, cpu, regs: may be out-registers
177 160 * ls1, ls2: local scratch registers
178 161 * os1, os2, os3: scratch registers, may be out
179 162 */
180 163
181 164 #define SERVE_INTR_PRE(iv_p, cpu, ls1, ls2, os1, os2, os3, regs) \
182 165 mov iv_p, ls1; \
183 166 mov iv_p, ls2; \
184 167 SERVE_INTR_TRACE(iv_p, os1, os2, os3, regs);
185 168
186 169 /*
187 170 * SERVE_INTR is called immediately after either SERVE_INTR_PRE or
188 171 * SERVE_INTR_NEXT, without intervening code. No register values
189 172 * may be modified.
190 173 *
191 174 * After calling SERVE_INTR, the caller must check if os3 is set. If
192 175 * so, there is another interrupt to process. The caller must call
193 176 * SERVE_INTR_NEXT, immediately followed by SERVE_INTR.
194 177 *
195 178 * Before calling SERVE_INTR_NEXT, the caller may perform accounting
196 179 * and other actions which need to occur after invocation of an interrupt
197 180 * handler. However, the values of ls1 and os3 *must* be preserved and
198 181 * passed unmodified into SERVE_INTR_NEXT.
199 182 *
200 183 * Registers on return from SERVE_INTR:
201 184 *
202 185 * ls1 - the pil just processed
203 186 * ls2 - the pointer to intr_vec_t (iv) just processed
204 187 * os3 - if set, another interrupt needs to be processed
205 188 * cpu, ls1, os3 - must be preserved if os3 is set
206 189 */
207 190
208 191 #define SERVE_INTR(os5, cpu, ls1, ls2, os1, os2, os3, os4) \
209 192 ldn [ls1 + IV_HANDLER], os2; \
210 193 ldn [ls1 + IV_ARG1], %o0; \
211 194 ldn [ls1 + IV_ARG2], %o1; \
212 195 call os2; \
213 196 lduh [ls1 + IV_PIL], ls1; \
214 197 brnz,pt %o0, 2f; \
215 198 mov CE_WARN, %o0; \
216 199 set _spurious, %o1; \
217 200 mov ls2, %o2; \
218 201 call cmn_err; \
219 202 rdpr %pil, %o3; \
220 203 2: ldn [THREAD_REG + T_CPU], cpu; \
221 204 sll ls1, 3, os1; \
222 205 add os1, CPU_STATS_SYS_INTR - 8, os2; \
223 206 ldx [cpu + os2], os3; \
224 207 inc os3; \
225 208 stx os3, [cpu + os2]; \
226 209 sll ls1, CPTRSHIFT, os2; \
227 210 add cpu, INTR_HEAD, os1; \
228 211 add os1, os2, os1; \
229 212 ldn [os1], os3;
230 213
231 214 /*
232 215 * Registers on entry:
233 216 *
234 217 * cpu - cpu pointer (clobbered, set to cpu upon completion)
235 218 * ls1, os3 - preserved from prior call to SERVE_INTR
236 219 * ls2 - local scratch reg (not preserved)
237 220 * os1, os2, os4, os5 - scratch reg, can be out (not preserved)
238 221 */
239 222 #define SERVE_INTR_NEXT(os5, cpu, ls1, ls2, os1, os2, os3, os4) \
240 223 sll ls1, CPTRSHIFT, os4; \
241 224 add cpu, INTR_HEAD, os1; \
242 225 rdpr %pstate, ls2; \
243 226 wrpr ls2, PSTATE_IE, %pstate; \
244 227 lduh [os3 + IV_FLAGS], os2; \
245 228 and os2, IV_SOFTINT_MT, os2; \
246 229 brz,pt os2, 4f; \
247 230 add os3, IV_PIL_NEXT, os2; \
248 231 ld [cpu + CPU_ID], os5; \
249 232 sll os5, CPTRSHIFT, os5; \
250 233 add os2, os5, os2; \
251 234 4: ldn [os2], os5; \
252 235 brnz,pn os5, 5f; \
253 236 stn os5, [os1 + os4]; \
254 237 add cpu, INTR_TAIL, os1; \
255 238 stn %g0, [os1 + os4]; \
256 239 mov 1, os1; \
257 240 sll os1, ls1, os1; \
258 241 wr os1, CLEAR_SOFTINT; \
259 242 5: lduh [os3 + IV_FLAGS], ls1; \
260 243 andn ls1, IV_SOFTINT_PEND, ls1; \
261 244 sth ls1, [os3 + IV_FLAGS]; \
262 245 stn %g0, [os2]; \
263 246 wrpr %g0, ls2, %pstate; \
264 247 mov os3, ls1; \
265 248 mov os3, ls2; \
266 249 SERVE_INTR_TRACE2(os5, os1, os2, os3, os4);
267 250
268 251 #ifdef TRAPTRACE
269 252 /*
270 253 * inum - not modified, _spurious depends on it.
271 254 */
272 255 #define SERVE_INTR_TRACE(inum, os1, os2, os3, os4) \
273 256 rdpr %pstate, os3; \
274 257 andn os3, PSTATE_IE | PSTATE_AM, os2; \
275 258 wrpr %g0, os2, %pstate; \
276 259 TRACE_PTR(os1, os2); \
277 260 ldn [os4 + PC_OFF], os2; \
278 261 stna os2, [os1 + TRAP_ENT_TPC]%asi; \
279 262 ldx [os4 + TSTATE_OFF], os2; \
280 263 stxa os2, [os1 + TRAP_ENT_TSTATE]%asi; \
281 264 mov os3, os4; \
282 265 GET_TRACE_TICK(os2, os3); \
283 266 stxa os2, [os1 + TRAP_ENT_TICK]%asi; \
284 267 TRACE_SAVE_TL_GL_REGS(os1, os2); \
285 268 set TT_SERVE_INTR, os2; \
286 269 rdpr %pil, os3; \
287 270 or os2, os3, os2; \
288 271 stha os2, [os1 + TRAP_ENT_TT]%asi; \
289 272 stna %sp, [os1 + TRAP_ENT_SP]%asi; \
290 273 stna inum, [os1 + TRAP_ENT_TR]%asi; \
291 274 stna %g0, [os1 + TRAP_ENT_F1]%asi; \
292 275 stna %g0, [os1 + TRAP_ENT_F2]%asi; \
293 276 stna %g0, [os1 + TRAP_ENT_F3]%asi; \
294 277 stna %g0, [os1 + TRAP_ENT_F4]%asi; \
295 278 TRACE_NEXT(os1, os2, os3); \
296 279 wrpr %g0, os4, %pstate
297 280 #else /* TRAPTRACE */
298 281 #define SERVE_INTR_TRACE(inum, os1, os2, os3, os4)
299 282 #endif /* TRAPTRACE */
300 283
301 284 #ifdef TRAPTRACE
302 285 /*
303 286 * inum - not modified, _spurious depends on it.
304 287 */
305 288 #define SERVE_INTR_TRACE2(inum, os1, os2, os3, os4) \
306 289 rdpr %pstate, os3; \
307 290 andn os3, PSTATE_IE | PSTATE_AM, os2; \
308 291 wrpr %g0, os2, %pstate; \
309 292 TRACE_PTR(os1, os2); \
310 293 stna %g0, [os1 + TRAP_ENT_TPC]%asi; \
311 294 stxa %g0, [os1 + TRAP_ENT_TSTATE]%asi; \
312 295 mov os3, os4; \
313 296 GET_TRACE_TICK(os2, os3); \
314 297 stxa os2, [os1 + TRAP_ENT_TICK]%asi; \
315 298 TRACE_SAVE_TL_GL_REGS(os1, os2); \
316 299 set TT_SERVE_INTR, os2; \
317 300 rdpr %pil, os3; \
318 301 or os2, os3, os2; \
319 302 stha os2, [os1 + TRAP_ENT_TT]%asi; \
320 303 stna %sp, [os1 + TRAP_ENT_SP]%asi; \
321 304 stna inum, [os1 + TRAP_ENT_TR]%asi; \
↓ open down ↓ |
145 lines elided |
↑ open up ↑ |
322 305 stna %g0, [os1 + TRAP_ENT_F1]%asi; \
323 306 stna %g0, [os1 + TRAP_ENT_F2]%asi; \
324 307 stna %g0, [os1 + TRAP_ENT_F3]%asi; \
325 308 stna %g0, [os1 + TRAP_ENT_F4]%asi; \
326 309 TRACE_NEXT(os1, os2, os3); \
327 310 wrpr %g0, os4, %pstate
328 311 #else /* TRAPTRACE */
329 312 #define SERVE_INTR_TRACE2(inum, os1, os2, os3, os4)
330 313 #endif /* TRAPTRACE */
331 314
332 -#endif /* lint */
333 -
334 -#if defined(lint)
335 -
336 -/*ARGSUSED*/
337 -void
338 -intr_thread(struct regs *regs, uint64_t iv_p, uint_t pil)
339 -{}
340 -
341 -#else /* lint */
342 -
343 315 #define INTRCNT_LIMIT 16
344 316
345 317 /*
346 318 * Handle an interrupt in a new thread.
347 319 * Entry:
348 320 * %o0 = pointer to regs structure
349 321 * %o1 = pointer to current intr_vec_t (iv) to be processed
350 322 * %o2 = pil
351 323 * %sp = on current thread's kernel stack
352 324 * %o7 = return linkage to trap code
353 325 * %g7 = current thread
354 326 * %pstate = normal globals, interrupts enabled,
355 327 * privileged, fp disabled
356 328 * %pil = DISP_LEVEL
357 329 *
358 330 * Register Usage
359 331 * %l0 = return linkage
360 332 * %l1 = pil
361 333 * %l2 - %l3 = scratch
362 334 * %l4 - %l7 = reserved for sys_trap
363 335 * %o2 = cpu
364 336 * %o3 = intr thread
365 337 * %o0 = scratch
366 338 * %o4 - %o5 = scratch
367 339 */
368 340 ENTRY_NP(intr_thread)
369 341 mov %o7, %l0
370 342 mov %o2, %l1
371 343 !
372 344 ! See if we are interrupting another interrupt thread.
373 345 !
374 346 lduh [THREAD_REG + T_FLAGS], %o3
375 347 andcc %o3, T_INTR_THREAD, %g0
376 348 bz,pt %xcc, 1f
377 349 ldn [THREAD_REG + T_CPU], %o2 ! delay - load CPU pointer
378 350
379 351 ! We have interrupted an interrupt thread. Take a timestamp,
380 352 ! compute its interval, and update its cumulative counter.
381 353 add THREAD_REG, T_INTR_START, %o5
382 354 0:
383 355 ldx [%o5], %o3
384 356 brz,pn %o3, 1f
385 357 ! We came in on top of an interrupt thread that had no timestamp.
386 358 ! This could happen if, for instance, an interrupt thread which had
387 359 ! previously blocked is being set up to run again in resume(), but
388 360 ! resume() hasn't yet stored a timestamp for it. Or, it could be in
389 361 ! swtch() after its slice has been accounted for.
390 362 ! Only account for the time slice if the starting timestamp is non-zero.
391 363 RD_CLOCK_TICK(%o4,%l2,%l3,__LINE__)
392 364 sub %o4, %o3, %o4 ! o4 has interval
393 365
394 366 ! A high-level interrupt in current_thread() interrupting here
395 367 ! will account for the interrupted thread's time slice, but
396 368 ! only if t_intr_start is non-zero. Since this code is going to account
397 369 ! for the time slice, we want to "atomically" load the thread's
398 370 ! starting timestamp, calculate the interval with %tick, and zero
399 371 ! its starting timestamp.
400 372 ! To do this, we do a casx on the t_intr_start field, and store 0 to it.
401 373 ! If it has changed since we loaded it above, we need to re-compute the
402 374 ! interval, since a changed t_intr_start implies current_thread placed
403 375 ! a new, later timestamp there after running a high-level interrupt,
404 376 ! and the %tick val in %o4 had become stale.
405 377 mov %g0, %l2
406 378 casx [%o5], %o3, %l2
407 379
408 380 ! If %l2 == %o3, our casx was successful. If not, the starting timestamp
409 381 ! changed between loading it (after label 0b) and computing the
410 382 ! interval above.
411 383 cmp %l2, %o3
412 384 bne,pn %xcc, 0b
413 385
414 386 ! Check for Energy Star mode
415 387 lduh [%o2 + CPU_DIVISOR], %l2 ! delay -- %l2 = clock divisor
416 388 cmp %l2, 1
417 389 bg,a,pn %xcc, 2f
418 390 mulx %o4, %l2, %o4 ! multiply interval by clock divisor iff > 1
419 391 2:
420 392 ! We now know that a valid interval for the interrupted interrupt
421 393 ! thread is in %o4. Update its cumulative counter.
422 394 ldub [THREAD_REG + T_PIL], %l3 ! load PIL
423 395 sllx %l3, 4, %l3 ! convert PIL index to byte offset
424 396 add %l3, CPU_MCPU, %l3 ! CPU_INTRSTAT is too big for use
425 397 add %l3, MCPU_INTRSTAT, %l3 ! as const, add offsets separately
426 398 ldx [%o2 + %l3], %o5 ! old counter in o5
427 399 add %o5, %o4, %o5 ! new counter in o5
428 400 stx %o5, [%o2 + %l3] ! store new counter
429 401
430 402 ! Also update intracct[]
431 403 lduh [%o2 + CPU_MSTATE], %l3
432 404 sllx %l3, 3, %l3
433 405 add %l3, CPU_INTRACCT, %l3
434 406 add %l3, %o2, %l3
435 407 0:
436 408 ldx [%l3], %o5
437 409 add %o5, %o4, %o3
438 410 casx [%l3], %o5, %o3
439 411 cmp %o5, %o3
440 412 bne,pn %xcc, 0b
441 413 nop
442 414
443 415 1:
444 416 !
445 417 ! Get set to run interrupt thread.
446 418 ! There should always be an interrupt thread since we allocate one
447 419 ! for each level on the CPU.
448 420 !
449 421 ! Note that the code in kcpc_overflow_intr -relies- on the ordering
450 422 ! of events here -- in particular that t->t_lwp of the interrupt thread
451 423 ! is set to the pinned thread *before* curthread is changed.
452 424 !
453 425 ldn [%o2 + CPU_INTR_THREAD], %o3 ! interrupt thread pool
454 426 ldn [%o3 + T_LINK], %o4 ! unlink thread from CPU's list
455 427 stn %o4, [%o2 + CPU_INTR_THREAD]
456 428 !
457 429 ! Set bit for this level in CPU's active interrupt bitmask.
458 430 !
459 431 ld [%o2 + CPU_INTR_ACTV], %o5
460 432 mov 1, %o4
461 433 sll %o4, %l1, %o4
462 434 #ifdef DEBUG
463 435 !
464 436 ! ASSERT(!(CPU->cpu_intr_actv & (1 << PIL)))
465 437 !
466 438 andcc %o5, %o4, %g0
467 439 bz,pt %xcc, 0f
468 440 nop
469 441 ! Do not call panic if a panic is already in progress.
470 442 sethi %hi(panic_quiesce), %l2
471 443 ld [%l2 + %lo(panic_quiesce)], %l2
472 444 brnz,pn %l2, 0f
473 445 nop
474 446 sethi %hi(intr_thread_actv_bit_set), %o0
475 447 call panic
476 448 or %o0, %lo(intr_thread_actv_bit_set), %o0
477 449 0:
478 450 #endif /* DEBUG */
479 451 or %o5, %o4, %o5
480 452 st %o5, [%o2 + CPU_INTR_ACTV]
481 453 !
482 454 ! Consider the new thread part of the same LWP so that
483 455 ! window overflow code can find the PCB.
484 456 !
485 457 ldn [THREAD_REG + T_LWP], %o4
486 458 stn %o4, [%o3 + T_LWP]
487 459 !
488 460 ! Threads on the interrupt thread free list could have state already
489 461 ! set to TS_ONPROC, but it helps in debugging if they're TS_FREE
490 462 ! Could eliminate the next two instructions with a little work.
491 463 !
492 464 mov TS_ONPROC, %o4
493 465 st %o4, [%o3 + T_STATE]
494 466 !
495 467 ! Push interrupted thread onto list from new thread.
496 468 ! Set the new thread as the current one.
497 469 ! Set interrupted thread's T_SP because if it is the idle thread,
498 470 ! resume may use that stack between threads.
499 471 !
500 472 stn %o7, [THREAD_REG + T_PC] ! mark pc for resume
501 473 stn %sp, [THREAD_REG + T_SP] ! mark stack for resume
502 474 stn THREAD_REG, [%o3 + T_INTR] ! push old thread
503 475 stn %o3, [%o2 + CPU_THREAD] ! set new thread
504 476 mov %o3, THREAD_REG ! set global curthread register
505 477 ldn [%o3 + T_STACK], %o4 ! interrupt stack pointer
506 478 sub %o4, STACK_BIAS, %sp
507 479 !
508 480 ! Initialize thread priority level from intr_pri
509 481 !
510 482 sethi %hi(intr_pri), %o4
511 483 ldsh [%o4 + %lo(intr_pri)], %o4 ! grab base interrupt priority
512 484 add %l1, %o4, %o4 ! convert level to dispatch priority
513 485 sth %o4, [THREAD_REG + T_PRI]
514 486 stub %l1, [THREAD_REG + T_PIL] ! save pil for intr_passivate
515 487
516 488 ! Store starting timestamp in thread structure.
517 489 add THREAD_REG, T_INTR_START, %o3
518 490 1:
519 491 ldx [%o3], %o5
520 492 RD_CLOCK_TICK(%o4,%l2,%l3,__LINE__)
521 493 casx [%o3], %o5, %o4
522 494 cmp %o4, %o5
523 495 ! If a high-level interrupt occurred while we were attempting to store
524 496 ! the timestamp, try again.
525 497 bne,pn %xcc, 1b
526 498 nop
527 499
528 500 wrpr %g0, %l1, %pil ! lower %pil to new level
529 501 !
530 502 ! Fast event tracing.
531 503 !
532 504 ld [%o2 + CPU_FTRACE_STATE], %o4 ! %o2 = curthread->t_cpu
533 505 btst FTRACE_ENABLED, %o4
534 506 be,pt %icc, 1f ! skip if ftrace disabled
535 507 mov %l1, %o5
536 508 !
537 509 ! Tracing is enabled - write the trace entry.
538 510 !
539 511 save %sp, -SA(MINFRAME), %sp
540 512 set ftrace_intr_thread_format_str, %o0
541 513 mov %i0, %o1
542 514 mov %i1, %o2
543 515 mov %i5, %o3
544 516 call ftrace_3
545 517 ldn [%i0 + PC_OFF], %o4
546 518 restore
547 519 1:
548 520 !
549 521 ! call the handler
550 522 !
551 523 SERVE_INTR_PRE(%o1, %o2, %l1, %l3, %o4, %o5, %o3, %o0)
552 524 !
553 525 ! %o0 and %o1 are now available as scratch registers.
554 526 !
555 527 0:
556 528 SERVE_INTR(%o1, %o2, %l1, %l3, %o4, %o5, %o3, %o0)
557 529 !
558 530 ! If %o3 is set, we must call serve_intr_next, and both %l1 and %o3
559 531 ! must be preserved. %l1 holds our pil, %l3 holds our inum.
560 532 !
561 533 ! Note: %l1 is the pil level we're processing, but we may have a
562 534 ! higher effective pil because a higher-level interrupt may have
563 535 ! blocked.
564 536 !
565 537 wrpr %g0, DISP_LEVEL, %pil
566 538 !
567 539 ! Take timestamp, compute interval, update cumulative counter.
568 540 !
569 541 add THREAD_REG, T_INTR_START, %o5
570 542 1:
571 543 ldx [%o5], %o0
572 544 #ifdef DEBUG
573 545 brnz %o0, 9f
574 546 nop
575 547 ! Do not call panic if a panic is already in progress.
576 548 sethi %hi(panic_quiesce), %o1
577 549 ld [%o1 + %lo(panic_quiesce)], %o1
578 550 brnz,pn %o1, 9f
579 551 nop
580 552 sethi %hi(intr_thread_t_intr_start_zero), %o0
581 553 call panic
582 554 or %o0, %lo(intr_thread_t_intr_start_zero), %o0
583 555 9:
584 556 #endif /* DEBUG */
585 557 RD_CLOCK_TICK(%o1,%l2,%l3,__LINE__)
586 558 sub %o1, %o0, %l2 ! l2 has interval
587 559 !
588 560 ! The general outline of what the code here does is:
589 561 ! 1. load t_intr_start, %tick, and calculate the delta
590 562 ! 2. replace t_intr_start with %tick (if %o3 is set) or 0.
591 563 !
592 564 ! The problem is that a high-level interrupt could arrive at any time.
593 565 ! It will account for (%tick - t_intr_start) for us when it starts,
594 566 ! unless we have set t_intr_start to zero, and then set t_intr_start
595 567 ! to a new %tick when it finishes. To account for this, our first step
596 568 ! is to load t_intr_start and the last is to use casx to store the new
597 569 ! t_intr_start. This guarantees atomicity in reading t_intr_start,
598 570 ! reading %tick, and updating t_intr_start.
599 571 !
600 572 movrz %o3, %g0, %o1
601 573 casx [%o5], %o0, %o1
602 574 cmp %o0, %o1
603 575 bne,pn %xcc, 1b
604 576 !
605 577 ! Check for Energy Star mode
606 578 !
607 579 lduh [%o2 + CPU_DIVISOR], %o0 ! delay -- %o0 = clock divisor
608 580 cmp %o0, 1
609 581 bg,a,pn %xcc, 2f
610 582 mulx %l2, %o0, %l2 ! multiply interval by clock divisor iff > 1
611 583 2:
612 584 !
613 585 ! Update cpu_intrstat. If o3 is set then we will be processing another
614 586 ! interrupt. Above we have set t_intr_start to %tick, not 0. This
615 587 ! means a high-level interrupt can arrive and update the same stats
616 588 ! we're updating. Need to use casx.
617 589 !
618 590 sllx %l1, 4, %o1 ! delay - PIL as byte offset
619 591 add %o1, CPU_MCPU, %o1 ! CPU_INTRSTAT const too big
620 592 add %o1, MCPU_INTRSTAT, %o1 ! add parts separately
621 593 add %o1, %o2, %o1
622 594 1:
623 595 ldx [%o1], %o5 ! old counter in o5
624 596 add %o5, %l2, %o0 ! new counter in o0
625 597 stx %o0, [%o1 + 8] ! store into intrstat[pil][1]
626 598 casx [%o1], %o5, %o0 ! and into intrstat[pil][0]
627 599 cmp %o5, %o0
628 600 bne,pn %xcc, 1b
629 601 nop
630 602
631 603 ! Also update intracct[]
632 604 lduh [%o2 + CPU_MSTATE], %o1
633 605 sllx %o1, 3, %o1
634 606 add %o1, CPU_INTRACCT, %o1
635 607 add %o1, %o2, %o1
636 608 1:
637 609 ldx [%o1], %o5
638 610 add %o5, %l2, %o0
639 611 casx [%o1], %o5, %o0
640 612 cmp %o5, %o0
641 613 bne,pn %xcc, 1b
642 614 nop
643 615
644 616 !
645 617 ! Don't keep a pinned process pinned indefinitely. Bump cpu_intrcnt
646 618 ! for each interrupt handler we invoke. If we hit INTRCNT_LIMIT, then
647 619 ! we've crossed the threshold and we should unpin the pinned threads
648 620 ! by preempt()ing ourselves, which will bubble up the t_intr chain
649 621 ! until hitting the non-interrupt thread, which will then in turn
650 622 ! preempt itself allowing the interrupt processing to resume. Finally,
651 623 ! the scheduler takes over and picks the next thread to run.
652 624 !
653 625 ! If our CPU is quiesced, we cannot preempt because the idle thread
654 626 ! won't ever re-enter the scheduler, and the interrupt will be forever
655 627 ! blocked.
656 628 !
657 629 ! If t_intr is NULL, we're not pinning anyone, so we use a simpler
658 630 ! algorithm. Just check for cpu_kprunrun, and if set then preempt.
659 631 ! This insures we enter the scheduler if a higher-priority thread
660 632 ! has become runnable.
661 633 !
662 634 lduh [%o2 + CPU_FLAGS], %o5 ! don't preempt if quiesced
663 635 andcc %o5, CPU_QUIESCED, %g0
664 636 bnz,pn %xcc, 1f
665 637
666 638 ldn [THREAD_REG + T_INTR], %o5 ! pinning anything?
667 639 brz,pn %o5, 3f ! if not, don't inc intrcnt
668 640
669 641 ldub [%o2 + CPU_INTRCNT], %o5 ! delay - %o5 = cpu_intrcnt
670 642 inc %o5
671 643 cmp %o5, INTRCNT_LIMIT ! have we hit the limit?
672 644 bl,a,pt %xcc, 1f ! no preempt if < INTRCNT_LIMIT
673 645 stub %o5, [%o2 + CPU_INTRCNT] ! delay annul - inc CPU_INTRCNT
674 646 bg,pn %xcc, 2f ! don't inc stats again
675 647 !
676 648 ! We've reached the limit. Set cpu_intrcnt and cpu_kprunrun, and do
677 649 ! CPU_STATS_ADDQ(cp, sys, intrunpin, 1). Then call preempt.
678 650 !
679 651 mov 1, %o4 ! delay
680 652 stub %o4, [%o2 + CPU_KPRUNRUN]
681 653 ldx [%o2 + CPU_STATS_SYS_INTRUNPIN], %o4
682 654 inc %o4
683 655 stx %o4, [%o2 + CPU_STATS_SYS_INTRUNPIN]
684 656 ba 2f
685 657 stub %o5, [%o2 + CPU_INTRCNT] ! delay
686 658 3:
687 659 ! Code for t_intr == NULL
688 660 ldub [%o2 + CPU_KPRUNRUN], %o5
689 661 brz,pt %o5, 1f ! don't preempt unless kprunrun
690 662 2:
691 663 ! Time to call preempt
692 664 mov %o2, %l3 ! delay - save %o2
693 665 call preempt
694 666 mov %o3, %l2 ! delay - save %o3.
695 667 mov %l3, %o2 ! restore %o2
696 668 mov %l2, %o3 ! restore %o3
697 669 wrpr %g0, DISP_LEVEL, %pil ! up from cpu_base_spl
698 670 1:
699 671 !
700 672 ! Do we need to call serve_intr_next and do this again?
701 673 !
702 674 brz,a,pt %o3, 0f
703 675 ld [%o2 + CPU_INTR_ACTV], %o5 ! delay annulled
704 676 !
705 677 ! Restore %pil before calling serve_intr() again. We must check
706 678 ! CPU_BASE_SPL and set %pil to max(our-pil, CPU_BASE_SPL)
707 679 !
708 680 ld [%o2 + CPU_BASE_SPL], %o4
709 681 cmp %o4, %l1
710 682 movl %xcc, %l1, %o4
711 683 wrpr %g0, %o4, %pil
712 684 SERVE_INTR_NEXT(%o1, %o2, %l1, %l3, %o4, %o5, %o3, %o0)
713 685 ba 0b ! compute new stats
714 686 nop
715 687 0:
716 688 !
717 689 ! Clear bit for this level in CPU's interrupt active bitmask.
718 690 !
719 691 mov 1, %o4
720 692 sll %o4, %l1, %o4
721 693 #ifdef DEBUG
722 694 !
723 695 ! ASSERT(CPU->cpu_intr_actv & (1 << PIL))
724 696 !
725 697 andcc %o4, %o5, %g0
726 698 bnz,pt %xcc, 0f
727 699 nop
728 700 ! Do not call panic if a panic is already in progress.
729 701 sethi %hi(panic_quiesce), %l2
730 702 ld [%l2 + %lo(panic_quiesce)], %l2
731 703 brnz,pn %l2, 0f
732 704 nop
733 705 sethi %hi(intr_thread_actv_bit_not_set), %o0
734 706 call panic
735 707 or %o0, %lo(intr_thread_actv_bit_not_set), %o0
736 708 0:
737 709 #endif /* DEBUG */
738 710 andn %o5, %o4, %o5
739 711 st %o5, [%o2 + CPU_INTR_ACTV]
740 712 !
741 713 ! If there is still an interrupted thread underneath this one,
742 714 ! then the interrupt was never blocked and the return is fairly
743 715 ! simple. Otherwise jump to intr_thread_exit.
744 716 !
745 717 ldn [THREAD_REG + T_INTR], %o4 ! pinned thread
746 718 brz,pn %o4, intr_thread_exit ! branch if none
747 719 nop
748 720 !
749 721 ! link the thread back onto the interrupt thread pool
750 722 !
751 723 ldn [%o2 + CPU_INTR_THREAD], %o3
752 724 stn %o3, [THREAD_REG + T_LINK]
753 725 stn THREAD_REG, [%o2 + CPU_INTR_THREAD]
754 726 !
755 727 ! set the thread state to free so kernel debuggers don't see it
756 728 !
757 729 mov TS_FREE, %o5
758 730 st %o5, [THREAD_REG + T_STATE]
759 731 !
760 732 ! Switch back to the interrupted thread and return
761 733 !
762 734 stn %o4, [%o2 + CPU_THREAD]
763 735 membar #StoreLoad ! sync with mutex_exit()
764 736 mov %o4, THREAD_REG
765 737
766 738 ! If we pinned an interrupt thread, store its starting timestamp.
767 739 lduh [THREAD_REG + T_FLAGS], %o5
768 740 andcc %o5, T_INTR_THREAD, %g0
769 741 bz,pt %xcc, 1f
770 742 ldn [THREAD_REG + T_SP], %sp ! delay - restore %sp
771 743
772 744 add THREAD_REG, T_INTR_START, %o3 ! o3 has &curthread->t_intr_star
773 745 0:
774 746 ldx [%o3], %o4 ! o4 = t_intr_start before
775 747 RD_CLOCK_TICK(%o5,%l2,%l3,__LINE__)
776 748 casx [%o3], %o4, %o5 ! put o5 in ts if o4 == ts after
777 749 cmp %o4, %o5
778 750 ! If a high-level interrupt occurred while we were attempting to store
779 751 ! the timestamp, try again.
780 752 bne,pn %xcc, 0b
781 753 ldn [THREAD_REG + T_SP], %sp ! delay - restore %sp
782 754 1:
783 755 ! If the thread being restarted isn't pinning anyone, and no interrupts
784 756 ! are pending, zero out cpu_intrcnt
785 757 ldn [THREAD_REG + T_INTR], %o4
786 758 brnz,pn %o4, 2f
787 759 rd SOFTINT, %o4 ! delay
788 760 set SOFTINT_MASK, %o5
789 761 andcc %o4, %o5, %g0
790 762 bz,a,pt %xcc, 2f
791 763 stub %g0, [%o2 + CPU_INTRCNT] ! delay annul
792 764 2:
793 765 jmp %l0 + 8
794 766 nop
795 767 SET_SIZE(intr_thread)
796 768 /* Not Reached */
797 769
798 770 !
799 771 ! An interrupt returned on what was once (and still might be)
800 772 ! an interrupt thread stack, but the interrupted process is no longer
801 773 ! there. This means the interrupt must have blocked.
802 774 !
803 775 ! There is no longer a thread under this one, so put this thread back
804 776 ! on the CPU's free list and resume the idle thread which will dispatch
805 777 ! the next thread to run.
806 778 !
807 779 ! All traps below DISP_LEVEL are disabled here, but the mondo interrupt
808 780 ! is enabled.
809 781 !
810 782 ENTRY_NP(intr_thread_exit)
811 783 #ifdef TRAPTRACE
812 784 rdpr %pstate, %l2
813 785 andn %l2, PSTATE_IE | PSTATE_AM, %o4
814 786 wrpr %g0, %o4, %pstate ! cpu to known state
815 787 TRACE_PTR(%o4, %o5)
816 788 GET_TRACE_TICK(%o5, %o0)
817 789 stxa %o5, [%o4 + TRAP_ENT_TICK]%asi
818 790 TRACE_SAVE_TL_GL_REGS(%o4, %o5)
819 791 set TT_INTR_EXIT, %o5
820 792 stha %o5, [%o4 + TRAP_ENT_TT]%asi
821 793 stna %g0, [%o4 + TRAP_ENT_TPC]%asi
822 794 stxa %g0, [%o4 + TRAP_ENT_TSTATE]%asi
823 795 stna %sp, [%o4 + TRAP_ENT_SP]%asi
824 796 stna THREAD_REG, [%o4 + TRAP_ENT_TR]%asi
825 797 ld [%o2 + CPU_BASE_SPL], %o5
826 798 stna %o5, [%o4 + TRAP_ENT_F1]%asi
827 799 stna %g0, [%o4 + TRAP_ENT_F2]%asi
828 800 stna %g0, [%o4 + TRAP_ENT_F3]%asi
829 801 stna %g0, [%o4 + TRAP_ENT_F4]%asi
830 802 TRACE_NEXT(%o4, %o5, %o0)
831 803 wrpr %g0, %l2, %pstate
832 804 #endif /* TRAPTRACE */
833 805 ! cpu_stats.sys.intrblk++
834 806 ldx [%o2 + CPU_STATS_SYS_INTRBLK], %o4
835 807 inc %o4
836 808 stx %o4, [%o2 + CPU_STATS_SYS_INTRBLK]
837 809 !
838 810 ! Put thread back on the interrupt thread list.
839 811 !
840 812
841 813 !
842 814 ! Set the CPU's base SPL level.
843 815 !
844 816 #ifdef DEBUG
845 817 !
846 818 ! ASSERT(!(CPU->cpu_intr_actv & (1 << PIL)))
847 819 !
848 820 ld [%o2 + CPU_INTR_ACTV], %o5
849 821 mov 1, %o4
850 822 sll %o4, %l1, %o4
851 823 and %o5, %o4, %o4
852 824 brz,pt %o4, 0f
853 825 nop
854 826 ! Do not call panic if a panic is already in progress.
855 827 sethi %hi(panic_quiesce), %l2
856 828 ld [%l2 + %lo(panic_quiesce)], %l2
857 829 brnz,pn %l2, 0f
858 830 nop
859 831 sethi %hi(intr_thread_exit_actv_bit_set), %o0
860 832 call panic
861 833 or %o0, %lo(intr_thread_exit_actv_bit_set), %o0
862 834 0:
863 835 #endif /* DEBUG */
864 836 call _intr_set_spl ! set CPU's base SPL level
865 837 ld [%o2 + CPU_INTR_ACTV], %o5 ! delay - load active mask
866 838 !
867 839 ! set the thread state to free so kernel debuggers don't see it
868 840 !
869 841 mov TS_FREE, %o4
870 842 st %o4, [THREAD_REG + T_STATE]
871 843 !
872 844 ! Put thread on either the interrupt pool or the free pool and
873 845 ! call swtch() to resume another thread.
874 846 !
875 847 ldn [%o2 + CPU_INTR_THREAD], %o5 ! get list pointer
876 848 stn %o5, [THREAD_REG + T_LINK]
877 849 call swtch ! switch to best thread
878 850 stn THREAD_REG, [%o2 + CPU_INTR_THREAD] ! delay - put thread on list
879 851 ba,a,pt %xcc, . ! swtch() shouldn't return
880 852 SET_SIZE(intr_thread_exit)
881 853
882 854 .global ftrace_intr_thread_format_str
883 855 ftrace_intr_thread_format_str:
884 856 .asciz "intr_thread(): regs=0x%lx, int=0x%lx, pil=0x%lx"
↓ open down ↓ |
532 lines elided |
↑ open up ↑ |
885 857 #ifdef DEBUG
886 858 intr_thread_actv_bit_set:
887 859 .asciz "intr_thread(): cpu_intr_actv bit already set for PIL"
888 860 intr_thread_actv_bit_not_set:
889 861 .asciz "intr_thread(): cpu_intr_actv bit not set for PIL"
890 862 intr_thread_exit_actv_bit_set:
891 863 .asciz "intr_thread_exit(): cpu_intr_actv bit erroneously set for PIL"
892 864 intr_thread_t_intr_start_zero:
893 865 .asciz "intr_thread(): t_intr_start zero upon handler return"
894 866 #endif /* DEBUG */
895 -#endif /* lint */
896 867
897 -#if defined(lint)
898 -
899 868 /*
900 869 * Handle an interrupt in the current thread
901 870 * Entry:
902 871 * %o0 = pointer to regs structure
903 872 * %o1 = pointer to current intr_vec_t (iv) to be processed
904 873 * %o2 = pil
905 874 * %sp = on current thread's kernel stack
906 875 * %o7 = return linkage to trap code
907 876 * %g7 = current thread
908 - * %pstate = normal globals, interrupts enabled,
877 + * %pstate = normal globals, interrupts enabled,
909 878 * privileged, fp disabled
910 879 * %pil = PIL_MAX
911 880 *
912 881 * Register Usage
913 882 * %l0 = return linkage
914 883 * %l1 = old stack
915 884 * %l2 - %l3 = scratch
916 885 * %l4 - %l7 = reserved for sys_trap
917 886 * %o3 = cpu
918 887 * %o0 = scratch
919 888 * %o4 - %o5 = scratch
920 889 */
921 -/* ARGSUSED */
922 -void
923 -current_thread(struct regs *regs, uint64_t iv_p, uint_t pil)
924 -{}
925 -
926 -#else /* lint */
927 -
928 890 ENTRY_NP(current_thread)
929 891
930 892 mov %o7, %l0
931 893 ldn [THREAD_REG + T_CPU], %o3
932 894
933 895 ldn [THREAD_REG + T_ONFAULT], %l2
934 896 brz,pt %l2, no_onfault ! branch if no onfault label set
935 897 nop
936 898 stn %g0, [THREAD_REG + T_ONFAULT]! clear onfault label
937 899 ldn [THREAD_REG + T_LOFAULT], %l3
938 900 stn %g0, [THREAD_REG + T_LOFAULT]! clear lofault data
939 901
940 902 sub %o2, LOCK_LEVEL + 1, %o5
941 903 sll %o5, CPTRSHIFT, %o5
942 904 add %o5, CPU_OFD, %o4 ! %o4 has on_fault data offset
943 905 stn %l2, [%o3 + %o4] ! save onfault label for pil %o2
944 906 add %o5, CPU_LFD, %o4 ! %o4 has lofault data offset
945 907 stn %l3, [%o3 + %o4] ! save lofault data for pil %o2
946 908
947 909 no_onfault:
948 910 ldn [THREAD_REG + T_ONTRAP], %l2
949 911 brz,pt %l2, 6f ! branch if no on_trap protection
950 912 nop
951 913 stn %g0, [THREAD_REG + T_ONTRAP]! clear on_trap protection
952 914 sub %o2, LOCK_LEVEL + 1, %o5
953 915 sll %o5, CPTRSHIFT, %o5
954 916 add %o5, CPU_OTD, %o4 ! %o4 has on_trap data offset
955 917 stn %l2, [%o3 + %o4] ! save on_trap label for pil %o2
956 918
957 919 !
958 920 ! Set bit for this level in CPU's active interrupt bitmask.
959 921 !
960 922 6: ld [%o3 + CPU_INTR_ACTV], %o5 ! o5 has cpu_intr_actv b4 chng
961 923 mov 1, %o4
962 924 sll %o4, %o2, %o4 ! construct mask for level
963 925 #ifdef DEBUG
964 926 !
965 927 ! ASSERT(!(CPU->cpu_intr_actv & (1 << PIL)))
966 928 !
967 929 andcc %o5, %o4, %g0
968 930 bz,pt %xcc, 0f
969 931 nop
970 932 ! Do not call panic if a panic is already in progress.
971 933 sethi %hi(panic_quiesce), %l2
972 934 ld [%l2 + %lo(panic_quiesce)], %l2
973 935 brnz,pn %l2, 0f
974 936 nop
975 937 sethi %hi(current_thread_actv_bit_set), %o0
976 938 call panic
977 939 or %o0, %lo(current_thread_actv_bit_set), %o0
978 940 0:
979 941 #endif /* DEBUG */
980 942 or %o5, %o4, %o4
981 943 !
982 944 ! See if we are interrupting another high-level interrupt.
983 945 !
984 946 srl %o5, LOCK_LEVEL + 1, %o5 ! only look at high-level bits
985 947 brz,pt %o5, 1f
986 948 st %o4, [%o3 + CPU_INTR_ACTV] ! delay - store active mask
987 949 !
988 950 ! We have interrupted another high-level interrupt. Find its PIL,
989 951 ! compute the interval it ran for, and update its cumulative counter.
990 952 !
991 953 ! Register usage:
992 954
993 955 ! o2 = PIL of this interrupt
994 956 ! o5 = high PIL bits of INTR_ACTV (not including this PIL)
995 957 ! l1 = bitmask used to find other active high-level PIL
996 958 ! o4 = index of bit set in l1
997 959 ! Use cpu_intr_actv to find the cpu_pil_high_start[] offset for the
998 960 ! interrupted high-level interrupt.
999 961 ! Create mask for cpu_intr_actv. Begin by looking for bits set
1000 962 ! at one level below the current PIL. Since %o5 contains the active
1001 963 ! mask already shifted right by (LOCK_LEVEL + 1), we start by looking
1002 964 ! at bit (current_pil - (LOCK_LEVEL + 2)).
1003 965 sub %o2, LOCK_LEVEL + 2, %o4
1004 966 mov 1, %l1
1005 967 sll %l1, %o4, %l1
1006 968 2:
1007 969 #ifdef DEBUG
1008 970 ! ASSERT(%l1 != 0) (we didn't shift the bit off the right edge)
1009 971 brnz,pt %l1, 9f
1010 972 nop
1011 973
1012 974 ! Don't panic if a panic is already in progress.
1013 975 sethi %hi(panic_quiesce), %l3
1014 976 ld [%l3 + %lo(panic_quiesce)], %l3
1015 977 brnz,pn %l3, 9f
1016 978 nop
1017 979 sethi %hi(current_thread_nested_PIL_not_found), %o0
1018 980 call panic
1019 981 or %o0, %lo(current_thread_nested_PIL_not_found), %o0
1020 982 9:
1021 983 #endif /* DEBUG */
1022 984 andcc %l1, %o5, %g0 ! test mask against high-level bits of
1023 985 bnz %xcc, 3f ! cpu_intr_actv
1024 986 nop
1025 987 srl %l1, 1, %l1 ! No match. Try next lower PIL.
1026 988 ba,pt %xcc, 2b
1027 989 sub %o4, 1, %o4 ! delay - decrement PIL
1028 990 3:
1029 991 sll %o4, 3, %o4 ! index to byte offset
1030 992 add %o4, CPU_MCPU, %l1 ! CPU_PIL_HIGH_START is too large
1031 993 add %l1, MCPU_PIL_HIGH_START, %l1
1032 994 ldx [%o3 + %l1], %l3 ! load starting timestamp
1033 995 #ifdef DEBUG
1034 996 brnz,pt %l3, 9f
1035 997 nop
1036 998 ! Don't panic if a panic is already in progress.
1037 999 sethi %hi(panic_quiesce), %l1
1038 1000 ld [%l1 + %lo(panic_quiesce)], %l1
1039 1001 brnz,pn %l1, 9f
1040 1002 nop
1041 1003 srl %o4, 3, %o1 ! Find interrupted PIL for panic
1042 1004 add %o1, LOCK_LEVEL + 1, %o1
1043 1005 sethi %hi(current_thread_nested_pil_zero), %o0
1044 1006 call panic
1045 1007 or %o0, %lo(current_thread_nested_pil_zero), %o0
1046 1008 9:
1047 1009 #endif /* DEBUG */
1048 1010 RD_CLOCK_TICK_NO_SUSPEND_CHECK(%l1, %l2)
1049 1011 sub %l1, %l3, %l3 ! interval in %l3
1050 1012 !
1051 1013 ! Check for Energy Star mode
1052 1014 !
1053 1015 lduh [%o3 + CPU_DIVISOR], %l1 ! %l1 = clock divisor
1054 1016 cmp %l1, 1
1055 1017 bg,a,pn %xcc, 2f
1056 1018 mulx %l3, %l1, %l3 ! multiply interval by clock divisor iff > 1
1057 1019 2:
1058 1020 !
1059 1021 ! We need to find the CPU offset of the cumulative counter. We start
1060 1022 ! with %o4, which has (PIL - (LOCK_LEVEL + 1)) * 8. We need PIL * 16,
1061 1023 ! so we shift left 1, then add (LOCK_LEVEL + 1) * 16, which is
1062 1024 ! CPU_INTRSTAT_LOW_PIL_OFFSET.
1063 1025 !
1064 1026 sll %o4, 1, %o4
1065 1027 add %o4, CPU_MCPU, %o4 ! CPU_INTRSTAT const too large
1066 1028 add %o4, MCPU_INTRSTAT, %o4 ! add parts separately
1067 1029 add %o4, CPU_INTRSTAT_LOW_PIL_OFFSET, %o4
1068 1030 ldx [%o3 + %o4], %l1 ! old counter in l1
1069 1031 add %l1, %l3, %l1 ! new counter in l1
1070 1032 stx %l1, [%o3 + %o4] ! store new counter
1071 1033
1072 1034 ! Also update intracct[]
1073 1035 lduh [%o3 + CPU_MSTATE], %o4
1074 1036 sllx %o4, 3, %o4
1075 1037 add %o4, CPU_INTRACCT, %o4
1076 1038 ldx [%o3 + %o4], %l1
1077 1039 add %l1, %l3, %l1
1078 1040 ! Another high-level interrupt is active below this one, so
1079 1041 ! there is no need to check for an interrupt thread. That will be
1080 1042 ! done by the lowest priority high-level interrupt active.
1081 1043 ba,pt %xcc, 5f
1082 1044 stx %l1, [%o3 + %o4] ! delay - store new counter
1083 1045 1:
1084 1046 ! If we haven't interrupted another high-level interrupt, we may be
1085 1047 ! interrupting a low level interrupt thread. If so, compute its interval
1086 1048 ! and update its cumulative counter.
1087 1049 lduh [THREAD_REG + T_FLAGS], %o4
1088 1050 andcc %o4, T_INTR_THREAD, %g0
1089 1051 bz,pt %xcc, 4f
1090 1052 nop
1091 1053
1092 1054 ! We have interrupted an interrupt thread. Take timestamp, compute
1093 1055 ! interval, update cumulative counter.
1094 1056
1095 1057 ! Check t_intr_start. If it is zero, either intr_thread() or
1096 1058 ! current_thread() (at a lower PIL, of course) already did
1097 1059 ! the accounting for the underlying interrupt thread.
1098 1060 ldx [THREAD_REG + T_INTR_START], %o5
1099 1061 brz,pn %o5, 4f
1100 1062 nop
1101 1063
1102 1064 stx %g0, [THREAD_REG + T_INTR_START]
1103 1065 RD_CLOCK_TICK_NO_SUSPEND_CHECK(%o4, %l2)
1104 1066 sub %o4, %o5, %o5 ! o5 has the interval
1105 1067
1106 1068 ! Check for Energy Star mode
1107 1069 lduh [%o3 + CPU_DIVISOR], %o4 ! %o4 = clock divisor
1108 1070 cmp %o4, 1
1109 1071 bg,a,pn %xcc, 2f
1110 1072 mulx %o5, %o4, %o5 ! multiply interval by clock divisor iff > 1
1111 1073 2:
1112 1074 ldub [THREAD_REG + T_PIL], %o4
1113 1075 sllx %o4, 4, %o4 ! PIL index to byte offset
1114 1076 add %o4, CPU_MCPU, %o4 ! CPU_INTRSTAT const too large
1115 1077 add %o4, MCPU_INTRSTAT, %o4 ! add parts separately
1116 1078 ldx [%o3 + %o4], %l2 ! old counter in l2
1117 1079 add %l2, %o5, %l2 ! new counter in l2
1118 1080 stx %l2, [%o3 + %o4] ! store new counter
1119 1081
1120 1082 ! Also update intracct[]
1121 1083 lduh [%o3 + CPU_MSTATE], %o4
1122 1084 sllx %o4, 3, %o4
1123 1085 add %o4, CPU_INTRACCT, %o4
1124 1086 ldx [%o3 + %o4], %l2
1125 1087 add %l2, %o5, %l2
1126 1088 stx %l2, [%o3 + %o4]
1127 1089 4:
1128 1090 !
1129 1091 ! Handle high-level interrupts on separate interrupt stack.
1130 1092 ! No other high-level interrupts are active, so switch to int stack.
1131 1093 !
1132 1094 mov %sp, %l1
1133 1095 ldn [%o3 + CPU_INTR_STACK], %l3
1134 1096 sub %l3, STACK_BIAS, %sp
1135 1097
1136 1098 5:
1137 1099 #ifdef DEBUG
1138 1100 !
1139 1101 ! ASSERT(%o2 > LOCK_LEVEL)
1140 1102 !
1141 1103 cmp %o2, LOCK_LEVEL
1142 1104 bg,pt %xcc, 3f
1143 1105 nop
1144 1106 mov CE_PANIC, %o0
1145 1107 sethi %hi(current_thread_wrong_pil), %o1
1146 1108 call cmn_err ! %o2 has the %pil already
1147 1109 or %o1, %lo(current_thread_wrong_pil), %o1
1148 1110 #endif
1149 1111 3:
1150 1112 ! Store starting timestamp for this PIL in CPU structure at
1151 1113 ! cpu.cpu_m.pil_high_start[PIL - (LOCK_LEVEL + 1)]
1152 1114 sub %o2, LOCK_LEVEL + 1, %o4 ! convert PIL to array index
1153 1115 sllx %o4, 3, %o4 ! index to byte offset
1154 1116 add %o4, CPU_MCPU, %o4 ! CPU_PIL_HIGH_START is too large
1155 1117 add %o4, MCPU_PIL_HIGH_START, %o4
1156 1118 RD_CLOCK_TICK_NO_SUSPEND_CHECK(%o5, %l2)
1157 1119 stx %o5, [%o3 + %o4]
1158 1120
1159 1121 wrpr %g0, %o2, %pil ! enable interrupts
1160 1122
1161 1123 !
1162 1124 ! call the handler
1163 1125 !
1164 1126 SERVE_INTR_PRE(%o1, %o3, %l2, %l3, %o4, %o5, %o2, %o0)
1165 1127 1:
1166 1128 SERVE_INTR(%o1, %o3, %l2, %l3, %o4, %o5, %o2, %o0)
1167 1129
1168 1130 brz,a,pt %o2, 0f ! if %o2, more intrs await
1169 1131 rdpr %pil, %o2 ! delay annulled
1170 1132 SERVE_INTR_NEXT(%o1, %o3, %l2, %l3, %o4, %o5, %o2, %o0)
1171 1133 ba 1b
1172 1134 nop
1173 1135 0:
1174 1136 wrpr %g0, PIL_MAX, %pil ! disable interrupts (1-15)
1175 1137
1176 1138 cmp %o2, PIL_15
1177 1139 bne,pt %xcc, 3f
1178 1140 nop
1179 1141
1180 1142 sethi %hi(cpc_level15_inum), %o1
1181 1143 ldx [%o1 + %lo(cpc_level15_inum)], %o1 ! arg for intr_enqueue_req
1182 1144 brz %o1, 3f
1183 1145 nop
1184 1146
1185 1147 rdpr %pstate, %g5
1186 1148 andn %g5, PSTATE_IE, %g1
1187 1149 wrpr %g0, %g1, %pstate ! Disable vec interrupts
1188 1150
1189 1151 call intr_enqueue_req ! preserves %g5
1190 1152 mov PIL_15, %o0
1191 1153
1192 1154 ! clear perfcntr overflow
1193 1155 mov 1, %o0
1194 1156 sllx %o0, PIL_15, %o0
1195 1157 wr %o0, CLEAR_SOFTINT
1196 1158
1197 1159 wrpr %g0, %g5, %pstate ! Enable vec interrupts
1198 1160
1199 1161 3:
1200 1162 cmp %o2, PIL_14
1201 1163 be tick_rtt ! cpu-specific tick processing
1202 1164 nop
1203 1165 .global current_thread_complete
1204 1166 current_thread_complete:
1205 1167 !
1206 1168 ! Register usage:
1207 1169 !
1208 1170 ! %l1 = stack pointer
1209 1171 ! %l2 = CPU_INTR_ACTV >> (LOCK_LEVEL + 1)
1210 1172 ! %o2 = PIL
1211 1173 ! %o3 = CPU pointer
1212 1174 ! %o4, %o5, %l3, %l4, %l5 = scratch
1213 1175 !
1214 1176 ldn [THREAD_REG + T_CPU], %o3
1215 1177 !
1216 1178 ! Clear bit for this level in CPU's interrupt active bitmask.
1217 1179 !
1218 1180 ld [%o3 + CPU_INTR_ACTV], %l2
1219 1181 mov 1, %o5
1220 1182 sll %o5, %o2, %o5
1221 1183 #ifdef DEBUG
1222 1184 !
1223 1185 ! ASSERT(CPU->cpu_intr_actv & (1 << PIL))
1224 1186 !
1225 1187 andcc %l2, %o5, %g0
1226 1188 bnz,pt %xcc, 0f
1227 1189 nop
1228 1190 ! Do not call panic if a panic is already in progress.
1229 1191 sethi %hi(panic_quiesce), %l2
1230 1192 ld [%l2 + %lo(panic_quiesce)], %l2
1231 1193 brnz,pn %l2, 0f
1232 1194 nop
1233 1195 sethi %hi(current_thread_actv_bit_not_set), %o0
1234 1196 call panic
1235 1197 or %o0, %lo(current_thread_actv_bit_not_set), %o0
1236 1198 0:
1237 1199 #endif /* DEBUG */
1238 1200 andn %l2, %o5, %l2
1239 1201 st %l2, [%o3 + CPU_INTR_ACTV]
1240 1202
1241 1203 ! Take timestamp, compute interval, update cumulative counter.
1242 1204 sub %o2, LOCK_LEVEL + 1, %o4 ! PIL to array index
1243 1205 sllx %o4, 3, %o4 ! index to byte offset
1244 1206 add %o4, CPU_MCPU, %o4 ! CPU_PIL_HIGH_START is too large
1245 1207 add %o4, MCPU_PIL_HIGH_START, %o4
1246 1208 RD_CLOCK_TICK_NO_SUSPEND_CHECK(%o5, %o0)
1247 1209 ldx [%o3 + %o4], %o0
1248 1210 #ifdef DEBUG
1249 1211 ! ASSERT(cpu.cpu_m.pil_high_start[pil - (LOCK_LEVEL + 1)] != 0)
1250 1212 brnz,pt %o0, 9f
1251 1213 nop
1252 1214 ! Don't panic if a panic is already in progress.
1253 1215 sethi %hi(panic_quiesce), %l2
1254 1216 ld [%l2 + %lo(panic_quiesce)], %l2
1255 1217 brnz,pn %l2, 9f
1256 1218 nop
1257 1219 sethi %hi(current_thread_timestamp_zero), %o0
1258 1220 call panic
1259 1221 or %o0, %lo(current_thread_timestamp_zero), %o0
1260 1222 9:
1261 1223 #endif /* DEBUG */
1262 1224 stx %g0, [%o3 + %o4]
1263 1225 sub %o5, %o0, %o5 ! interval in o5
1264 1226
1265 1227 ! Check for Energy Star mode
1266 1228 lduh [%o3 + CPU_DIVISOR], %o4 ! %o4 = clock divisor
1267 1229 cmp %o4, 1
1268 1230 bg,a,pn %xcc, 2f
1269 1231 mulx %o5, %o4, %o5 ! multiply interval by clock divisor iff > 1
1270 1232 2:
1271 1233 sllx %o2, 4, %o4 ! PIL index to byte offset
1272 1234 add %o4, CPU_MCPU, %o4 ! CPU_INTRSTAT too large
1273 1235 add %o4, MCPU_INTRSTAT, %o4 ! add parts separately
1274 1236 ldx [%o3 + %o4], %o0 ! old counter in o0
1275 1237 add %o0, %o5, %o0 ! new counter in o0
1276 1238 stx %o0, [%o3 + %o4] ! store new counter
1277 1239
1278 1240 ! Also update intracct[]
1279 1241 lduh [%o3 + CPU_MSTATE], %o4
1280 1242 sllx %o4, 3, %o4
1281 1243 add %o4, CPU_INTRACCT, %o4
1282 1244 ldx [%o3 + %o4], %o0
1283 1245 add %o0, %o5, %o0
1284 1246 stx %o0, [%o3 + %o4]
1285 1247
1286 1248 !
1287 1249 ! get back on current thread's stack
1288 1250 !
1289 1251 srl %l2, LOCK_LEVEL + 1, %l2
1290 1252 tst %l2 ! any more high-level ints?
1291 1253 movz %xcc, %l1, %sp
1292 1254 !
1293 1255 ! Current register usage:
1294 1256 ! o2 = PIL
1295 1257 ! o3 = CPU pointer
1296 1258 ! l0 = return address
1297 1259 ! l2 = intr_actv shifted right
1298 1260 !
1299 1261 bz,pt %xcc, 3f ! if l2 was zero, no more ints
1300 1262 nop
1301 1263 !
1302 1264 ! We found another high-level interrupt active below the one that just
1303 1265 ! returned. Store a starting timestamp for it in the CPU structure.
1304 1266 !
1305 1267 ! Use cpu_intr_actv to find the cpu_pil_high_start[] offset for the
1306 1268 ! interrupted high-level interrupt.
1307 1269 ! Create mask for cpu_intr_actv. Begin by looking for bits set
1308 1270 ! at one level below the current PIL. Since %l2 contains the active
1309 1271 ! mask already shifted right by (LOCK_LEVEL + 1), we start by looking
1310 1272 ! at bit (current_pil - (LOCK_LEVEL + 2)).
1311 1273 ! %l1 = mask, %o5 = index of bit set in mask
1312 1274 !
1313 1275 mov 1, %l1
1314 1276 sub %o2, LOCK_LEVEL + 2, %o5
1315 1277 sll %l1, %o5, %l1 ! l1 = mask for level
1316 1278 1:
1317 1279 #ifdef DEBUG
1318 1280 ! ASSERT(%l1 != 0) (we didn't shift the bit off the right edge)
1319 1281 brnz,pt %l1, 9f
1320 1282 nop
1321 1283 sethi %hi(current_thread_nested_PIL_not_found), %o0
1322 1284 call panic
1323 1285 or %o0, %lo(current_thread_nested_PIL_not_found), %o0
1324 1286 9:
1325 1287 #endif /* DEBUG */
1326 1288 andcc %l1, %l2, %g0 ! test mask against high-level bits of
1327 1289 bnz %xcc, 2f ! cpu_intr_actv
1328 1290 nop
1329 1291 srl %l1, 1, %l1 ! No match. Try next lower PIL.
1330 1292 ba,pt %xcc, 1b
1331 1293 sub %o5, 1, %o5 ! delay - decrement PIL
1332 1294 2:
1333 1295 sll %o5, 3, %o5 ! convert array index to byte offset
1334 1296 add %o5, CPU_MCPU, %o5 ! CPU_PIL_HIGH_START is too large
1335 1297 add %o5, MCPU_PIL_HIGH_START, %o5
1336 1298 RD_CLOCK_TICK_NO_SUSPEND_CHECK(%o4, %l2)
1337 1299 ! Another high-level interrupt is active below this one, so
1338 1300 ! there is no need to check for an interrupt thread. That will be
1339 1301 ! done by the lowest priority high-level interrupt active.
1340 1302 ba,pt %xcc, 7f
1341 1303 stx %o4, [%o3 + %o5] ! delay - store timestamp
1342 1304 3:
1343 1305 ! If we haven't interrupted another high-level interrupt, we may have
1344 1306 ! interrupted a low level interrupt thread. If so, store a starting
1345 1307 ! timestamp in its thread structure.
1346 1308 lduh [THREAD_REG + T_FLAGS], %o4
1347 1309 andcc %o4, T_INTR_THREAD, %g0
1348 1310 bz,pt %xcc, 7f
1349 1311 nop
1350 1312
1351 1313 RD_CLOCK_TICK_NO_SUSPEND_CHECK(%o4, %l2)
1352 1314 stx %o4, [THREAD_REG + T_INTR_START]
1353 1315
1354 1316 7:
1355 1317 sub %o2, LOCK_LEVEL + 1, %o4
1356 1318 sll %o4, CPTRSHIFT, %o5
1357 1319
1358 1320 ! Check on_trap saved area and restore as needed
1359 1321 add %o5, CPU_OTD, %o4
1360 1322 ldn [%o3 + %o4], %l2
1361 1323 brz,pt %l2, no_ontrp_restore
1362 1324 nop
1363 1325 stn %l2, [THREAD_REG + T_ONTRAP] ! restore
1364 1326 stn %g0, [%o3 + %o4] ! clear
1365 1327
1366 1328 no_ontrp_restore:
1367 1329 ! Check on_fault saved area and restore as needed
1368 1330 add %o5, CPU_OFD, %o4
1369 1331 ldn [%o3 + %o4], %l2
1370 1332 brz,pt %l2, 8f
1371 1333 nop
1372 1334 stn %l2, [THREAD_REG + T_ONFAULT] ! restore
1373 1335 stn %g0, [%o3 + %o4] ! clear
1374 1336 add %o5, CPU_LFD, %o4
1375 1337 ldn [%o3 + %o4], %l2
1376 1338 stn %l2, [THREAD_REG + T_LOFAULT] ! restore
1377 1339 stn %g0, [%o3 + %o4] ! clear
1378 1340
1379 1341
1380 1342 8:
1381 1343 ! Enable interrupts and return
1382 1344 jmp %l0 + 8
1383 1345 wrpr %g0, %o2, %pil ! enable interrupts
1384 1346 SET_SIZE(current_thread)
1385 1347
1386 1348
1387 1349 #ifdef DEBUG
1388 1350 current_thread_wrong_pil:
1389 1351 .asciz "current_thread: unexpected pil level: %d"
1390 1352 current_thread_actv_bit_set:
↓ open down ↓ |
453 lines elided |
↑ open up ↑ |
1391 1353 .asciz "current_thread(): cpu_intr_actv bit already set for PIL"
1392 1354 current_thread_actv_bit_not_set:
1393 1355 .asciz "current_thread(): cpu_intr_actv bit not set for PIL"
1394 1356 current_thread_nested_pil_zero:
1395 1357 .asciz "current_thread(): timestamp zero for nested PIL %d"
1396 1358 current_thread_timestamp_zero:
1397 1359 .asciz "current_thread(): timestamp zero upon handler return"
1398 1360 current_thread_nested_PIL_not_found:
1399 1361 .asciz "current_thread: couldn't find nested high-level PIL"
1400 1362 #endif /* DEBUG */
1401 -#endif /* lint */
1402 1363
1403 1364 /*
1404 1365 * Return a thread's interrupt level.
1405 1366 * Since this isn't saved anywhere but in %l4 on interrupt entry, we
1406 1367 * must dig it out of the save area.
1407 1368 *
1408 1369 * Caller 'swears' that this really is an interrupt thread.
1409 1370 *
1410 1371 * int
1411 1372 * intr_level(t)
1412 1373 * kthread_id_t t;
1413 1374 */
1414 1375
1415 -#if defined(lint)
1416 -
1417 -/* ARGSUSED */
1418 -int
1419 -intr_level(kthread_id_t t)
1420 -{ return (0); }
1421 -
1422 -#else /* lint */
1423 -
1424 1376 ENTRY_NP(intr_level)
1425 1377 retl
1426 1378 ldub [%o0 + T_PIL], %o0 ! return saved pil
1427 1379 SET_SIZE(intr_level)
1428 1380
1429 -#endif /* lint */
1430 -
1431 -#if defined(lint)
1432 -
1433 -/* ARGSUSED */
1434 -int
1435 -disable_pil_intr()
1436 -{ return (0); }
1437 -
1438 -#else /* lint */
1439 -
1440 1381 ENTRY_NP(disable_pil_intr)
1441 1382 rdpr %pil, %o0
1442 1383 retl
1443 1384 wrpr %g0, PIL_MAX, %pil ! disable interrupts (1-15)
1444 1385 SET_SIZE(disable_pil_intr)
1445 1386
1446 -#endif /* lint */
1447 -
1448 -#if defined(lint)
1449 -
1450 -/* ARGSUSED */
1451 -void
1452 -enable_pil_intr(int pil_save)
1453 -{}
1454 -
1455 -#else /* lint */
1456 -
1457 1387 ENTRY_NP(enable_pil_intr)
1458 1388 retl
1459 1389 wrpr %o0, %pil
1460 1390 SET_SIZE(enable_pil_intr)
1461 1391
1462 -#endif /* lint */
1463 -
1464 -#if defined(lint)
1465 -
1466 -/* ARGSUSED */
1467 -uint_t
1468 -disable_vec_intr(void)
1469 -{ return (0); }
1470 -
1471 -#else /* lint */
1472 -
1473 1392 ENTRY_NP(disable_vec_intr)
1474 1393 rdpr %pstate, %o0
1475 1394 andn %o0, PSTATE_IE, %g1
1476 1395 retl
1477 1396 wrpr %g0, %g1, %pstate ! disable interrupt
1478 1397 SET_SIZE(disable_vec_intr)
1479 1398
1480 -#endif /* lint */
1481 -
1482 -#if defined(lint)
1483 -
1484 -/* ARGSUSED */
1485 -void
1486 -enable_vec_intr(uint_t pstate_save)
1487 -{}
1488 -
1489 -#else /* lint */
1490 -
1491 1399 ENTRY_NP(enable_vec_intr)
1492 1400 retl
1493 1401 wrpr %g0, %o0, %pstate
1494 1402 SET_SIZE(enable_vec_intr)
1495 1403
1496 -#endif /* lint */
1497 -
1498 -#if defined(lint)
1499 -
1500 -void
1501 -cbe_level14(void)
1502 -{}
1503 -
1504 -#else /* lint */
1505 -
1506 1404 ENTRY_NP(cbe_level14)
1507 1405 save %sp, -SA(MINFRAME), %sp ! get a new window
1508 1406 !
1509 1407 ! Make sure that this is from TICK_COMPARE; if not just return
1510 1408 !
1511 1409 rd SOFTINT, %l1
1512 1410 set (TICK_INT_MASK | STICK_INT_MASK), %o2
1513 1411 andcc %l1, %o2, %g0
1514 1412 bz,pn %icc, 2f
1515 1413 nop
1516 1414
1517 1415 CPU_ADDR(%o1, %o2)
1518 1416 call cyclic_fire
1519 1417 mov %o1, %o0
1520 1418 2:
1521 1419 ret
1522 1420 restore %g0, 1, %o0
1523 1421 SET_SIZE(cbe_level14)
1524 1422
1525 -#endif /* lint */
1526 1423
1527 -
1528 -#if defined(lint)
1529 -
1530 -/* ARGSUSED */
1531 -void
1532 -kdi_setsoftint(uint64_t iv_p)
1533 -{}
1534 -
1535 -#else /* lint */
1536 -
1537 1424 ENTRY_NP(kdi_setsoftint)
1538 1425 save %sp, -SA(MINFRAME), %sp ! get a new window
1539 1426 rdpr %pstate, %l5
1540 1427 andn %l5, PSTATE_IE, %l1
1541 1428 wrpr %l1, %pstate ! disable interrupt
1542 1429 !
1543 1430 ! We have a pointer to an interrupt vector data structure.
1544 1431 ! Put the request on the cpu's softint priority list and
1545 1432 ! set %set_softint.
1546 1433 !
1547 1434 ! Register usage
1548 1435 ! %i0 - pointer to intr_vec_t (iv)
1549 1436 ! %l2 - requested pil
1550 1437 ! %l4 - cpu
1551 1438 ! %l5 - pstate
1552 1439 ! %l1, %l3, %l6 - temps
1553 1440 !
1554 1441 ! check if a softint is pending for this softint,
1555 1442 ! if one is pending, don't bother queuing another.
1556 1443 !
1557 1444 lduh [%i0 + IV_FLAGS], %l1 ! %l1 = iv->iv_flags
1558 1445 and %l1, IV_SOFTINT_PEND, %l6 ! %l6 = iv->iv_flags & IV_SOFTINT_PEND
1559 1446 brnz,pn %l6, 4f ! branch if softint is already pending
1560 1447 or %l1, IV_SOFTINT_PEND, %l2
1561 1448 sth %l2, [%i0 + IV_FLAGS] ! Set IV_SOFTINT_PEND flag
1562 1449
1563 1450 CPU_ADDR(%l4, %l2) ! %l4 = cpu
1564 1451 lduh [%i0 + IV_PIL], %l2 ! %l2 = iv->iv_pil
1565 1452
1566 1453 !
1567 1454 ! Insert intr_vec_t (iv) to appropriate cpu's softint priority list
1568 1455 !
1569 1456 sll %l2, CPTRSHIFT, %l0 ! %l0 = offset to pil entry
1570 1457 add %l4, INTR_TAIL, %l6 ! %l6 = &cpu->m_cpu.intr_tail
1571 1458 ldn [%l6 + %l0], %l1 ! %l1 = cpu->m_cpu.intr_tail[pil]
1572 1459 ! current tail (ct)
1573 1460 brz,pt %l1, 2f ! branch if current tail is NULL
1574 1461 stn %i0, [%l6 + %l0] ! make intr_vec_t (iv) as new tail
1575 1462 !
1576 1463 ! there's pending intr_vec_t already
1577 1464 !
1578 1465 lduh [%l1 + IV_FLAGS], %l6 ! %l6 = ct->iv_flags
1579 1466 and %l6, IV_SOFTINT_MT, %l6 ! %l6 = ct->iv_flags & IV_SOFTINT_MT
1580 1467 brz,pt %l6, 1f ! check for Multi target softint flag
1581 1468 add %l1, IV_PIL_NEXT, %l3 ! %l3 = &ct->iv_pil_next
1582 1469 ld [%l4 + CPU_ID], %l6 ! for multi target softint, use cpuid
1583 1470 sll %l6, CPTRSHIFT, %l6 ! calculate offset address from cpuid
1584 1471 add %l3, %l6, %l3 ! %l3 = &ct->iv_xpil_next[cpuid]
1585 1472 1:
1586 1473 !
1587 1474 ! update old tail
1588 1475 !
1589 1476 ba,pt %xcc, 3f
1590 1477 stn %i0, [%l3] ! [%l3] = iv, set pil_next field
1591 1478 2:
1592 1479 !
1593 1480 ! no pending intr_vec_t; make intr_vec_t as new head
1594 1481 !
1595 1482 add %l4, INTR_HEAD, %l6 ! %l6 = &cpu->m_cpu.intr_head[pil]
1596 1483 stn %i0, [%l6 + %l0] ! cpu->m_cpu.intr_head[pil] = iv
1597 1484 3:
1598 1485 !
1599 1486 ! Write %set_softint with (1<<pil) to cause a "pil" level trap
↓ open down ↓ |
53 lines elided |
↑ open up ↑ |
1600 1487 !
1601 1488 mov 1, %l1 ! %l1 = 1
1602 1489 sll %l1, %l2, %l1 ! %l1 = 1 << pil
1603 1490 wr %l1, SET_SOFTINT ! trigger required pil softint
1604 1491 4:
1605 1492 wrpr %g0, %l5, %pstate ! %pstate = saved %pstate (in %l5)
1606 1493 ret
1607 1494 restore
1608 1495 SET_SIZE(kdi_setsoftint)
1609 1496
1610 -#endif /* lint */
1611 -
1612 -#if defined(lint)
1613 -
1614 -/*ARGSUSED*/
1615 -void
1616 -setsoftint_tl1(uint64_t iv_p, uint64_t dummy)
1617 -{}
1618 -
1619 -#else /* lint */
1620 -
1621 1497 !
1622 1498 ! Register usage
1623 1499 ! Arguments:
1624 1500 ! %g1 - Pointer to intr_vec_t (iv)
1625 1501 !
1626 1502 ! Internal:
1627 1503 ! %g2 - pil
1628 1504 ! %g4 - cpu
1629 1505 ! %g3,%g5-g7 - temps
1630 1506 !
1631 1507 ENTRY_NP(setsoftint_tl1)
1632 1508 !
1633 1509 ! We have a pointer to an interrupt vector data structure.
1634 1510 ! Put the request on the cpu's softint priority list and
1635 1511 ! set %set_softint.
1636 1512 !
1637 1513 CPU_ADDR(%g4, %g2) ! %g4 = cpu
1638 1514 lduh [%g1 + IV_PIL], %g2 ! %g2 = iv->iv_pil
1639 1515
1640 1516 !
1641 1517 ! Insert intr_vec_t (iv) to appropriate cpu's softint priority list
1642 1518 !
1643 1519 sll %g2, CPTRSHIFT, %g7 ! %g7 = offset to pil entry
1644 1520 add %g4, INTR_TAIL, %g6 ! %g6 = &cpu->m_cpu.intr_tail
1645 1521 ldn [%g6 + %g7], %g5 ! %g5 = cpu->m_cpu.intr_tail[pil]
1646 1522 ! current tail (ct)
1647 1523 brz,pt %g5, 1f ! branch if current tail is NULL
1648 1524 stn %g1, [%g6 + %g7] ! make intr_rec_t (iv) as new tail
1649 1525 !
1650 1526 ! there's pending intr_vec_t already
1651 1527 !
1652 1528 lduh [%g5 + IV_FLAGS], %g6 ! %g6 = ct->iv_flags
1653 1529 and %g6, IV_SOFTINT_MT, %g6 ! %g6 = ct->iv_flags & IV_SOFTINT_MT
1654 1530 brz,pt %g6, 0f ! check for Multi target softint flag
1655 1531 add %g5, IV_PIL_NEXT, %g3 ! %g3 = &ct->iv_pil_next
1656 1532 ld [%g4 + CPU_ID], %g6 ! for multi target softint, use cpuid
1657 1533 sll %g6, CPTRSHIFT, %g6 ! calculate offset address from cpuid
1658 1534 add %g3, %g6, %g3 ! %g3 = &ct->iv_xpil_next[cpuid]
1659 1535 0:
1660 1536 !
1661 1537 ! update old tail
1662 1538 !
1663 1539 ba,pt %xcc, 2f
1664 1540 stn %g1, [%g3] ! [%g3] = iv, set pil_next field
1665 1541 1:
1666 1542 !
1667 1543 ! no pending intr_vec_t; make intr_vec_t as new head
1668 1544 !
1669 1545 add %g4, INTR_HEAD, %g6 ! %g6 = &cpu->m_cpu.intr_head[pil]
1670 1546 stn %g1, [%g6 + %g7] ! cpu->m_cpu.intr_head[pil] = iv
1671 1547 2:
1672 1548 #ifdef TRAPTRACE
1673 1549 TRACE_PTR(%g5, %g6)
1674 1550 GET_TRACE_TICK(%g6, %g3)
1675 1551 stxa %g6, [%g5 + TRAP_ENT_TICK]%asi ! trap_tick = %tick
1676 1552 TRACE_SAVE_TL_GL_REGS(%g5, %g6)
1677 1553 rdpr %tt, %g6
1678 1554 stha %g6, [%g5 + TRAP_ENT_TT]%asi ! trap_type = %tt
1679 1555 rdpr %tpc, %g6
1680 1556 stna %g6, [%g5 + TRAP_ENT_TPC]%asi ! trap_pc = %tpc
1681 1557 rdpr %tstate, %g6
1682 1558 stxa %g6, [%g5 + TRAP_ENT_TSTATE]%asi ! trap_tstate = %tstate
1683 1559 stna %sp, [%g5 + TRAP_ENT_SP]%asi ! trap_sp = %sp
1684 1560 stna %g1, [%g5 + TRAP_ENT_TR]%asi ! trap_tr = iv
1685 1561 ldn [%g1 + IV_PIL_NEXT], %g6 !
1686 1562 stna %g6, [%g5 + TRAP_ENT_F1]%asi ! trap_f1 = iv->iv_pil_next
1687 1563 add %g4, INTR_HEAD, %g6
1688 1564 ldn [%g6 + %g7], %g6 ! %g6=cpu->m_cpu.intr_head[pil]
1689 1565 stna %g6, [%g5 + TRAP_ENT_F2]%asi ! trap_f2 = intr_head[pil]
1690 1566 add %g4, INTR_TAIL, %g6
1691 1567 ldn [%g6 + %g7], %g6 ! %g6=cpu->m_cpu.intr_tail[pil]
1692 1568 stna %g6, [%g5 + TRAP_ENT_F3]%asi ! trap_f3 = intr_tail[pil]
1693 1569 stna %g2, [%g5 + TRAP_ENT_F4]%asi ! trap_f4 = pil
1694 1570 TRACE_NEXT(%g5, %g6, %g3)
↓ open down ↓ |
64 lines elided |
↑ open up ↑ |
1695 1571 #endif /* TRAPTRACE */
1696 1572 !
1697 1573 ! Write %set_softint with (1<<pil) to cause a "pil" level trap
1698 1574 !
1699 1575 mov 1, %g5 ! %g5 = 1
1700 1576 sll %g5, %g2, %g5 ! %g5 = 1 << pil
1701 1577 wr %g5, SET_SOFTINT ! trigger required pil softint
1702 1578 retry
1703 1579 SET_SIZE(setsoftint_tl1)
1704 1580
1705 -#endif /* lint */
1706 -
1707 -#if defined(lint)
1708 -
1709 -/*ARGSUSED*/
1710 -void
1711 -setvecint_tl1(uint64_t inum, uint64_t dummy)
1712 -{}
1713 -
1714 -#else /* lint */
1715 -
1716 1581 !
1717 1582 ! Register usage
1718 1583 ! Arguments:
1719 1584 ! %g1 - inumber
1720 1585 !
1721 1586 ! Internal:
1722 1587 ! %g1 - softint pil mask
1723 1588 ! %g2 - pil of intr_vec_t
1724 1589 ! %g3 - pointer to current intr_vec_t (iv)
1725 1590 ! %g4 - cpu
1726 1591 ! %g5, %g6,%g7 - temps
1727 1592 !
1728 1593 ENTRY_NP(setvecint_tl1)
1729 1594 !
1730 1595 ! Verify the inumber received (should be inum < MAXIVNUM).
1731 1596 !
1732 1597 set MAXIVNUM, %g2
1733 1598 cmp %g1, %g2
1734 1599 bgeu,pn %xcc, .no_ivintr
1735 1600 clr %g2 ! expected in .no_ivintr
1736 1601
1737 1602 !
1738 1603 ! Fetch data from intr_vec_table according to the inum.
1739 1604 !
1740 1605 ! We have an interrupt number. Fetch the interrupt vector requests
1741 1606 ! from the interrupt vector table for a given interrupt number and
1742 1607 ! insert them into cpu's softint priority lists and set %set_softint.
1743 1608 !
1744 1609 set intr_vec_table, %g5 ! %g5 = intr_vec_table
1745 1610 sll %g1, CPTRSHIFT, %g6 ! %g6 = offset to inum entry in table
1746 1611 add %g5, %g6, %g5 ! %g5 = &intr_vec_table[inum]
1747 1612 ldn [%g5], %g3 ! %g3 = pointer to first entry of
1748 1613 ! intr_vec_t list
1749 1614
1750 1615 ! Verify the first intr_vec_t pointer for a given inum and it should
1751 1616 ! not be NULL. This used to be guarded by DEBUG but broken drivers can
1752 1617 ! cause spurious tick interrupts when the softint register is programmed
1753 1618 ! with 1 << 0 at the end of this routine. Now we always check for a
1754 1619 ! valid intr_vec_t pointer.
1755 1620 brz,pn %g3, .no_ivintr
1756 1621 nop
1757 1622
1758 1623 !
1759 1624 ! Traverse the intr_vec_t link list, put each item on to corresponding
1760 1625 ! CPU softint priority queue, and compose the final softint pil mask.
1761 1626 !
1762 1627 ! At this point:
1763 1628 ! %g3 = intr_vec_table[inum]
1764 1629 !
1765 1630 CPU_ADDR(%g4, %g2) ! %g4 = cpu
1766 1631 mov %g0, %g1 ! %g1 = 0, initialize pil mask to 0
1767 1632 0:
1768 1633 !
1769 1634 ! Insert next intr_vec_t (iv) to appropriate cpu's softint priority list
1770 1635 !
1771 1636 ! At this point:
1772 1637 ! %g1 = softint pil mask
1773 1638 ! %g3 = pointer to next intr_vec_t (iv)
1774 1639 ! %g4 = cpu
1775 1640 !
1776 1641 lduh [%g3 + IV_PIL], %g2 ! %g2 = iv->iv_pil
1777 1642 sll %g2, CPTRSHIFT, %g7 ! %g7 = offset to pil entry
1778 1643 add %g4, INTR_TAIL, %g6 ! %g6 = &cpu->m_cpu.intr_tail
1779 1644 ldn [%g6 + %g7], %g5 ! %g5 = cpu->m_cpu.intr_tail[pil]
1780 1645 ! current tail (ct)
1781 1646 brz,pt %g5, 2f ! branch if current tail is NULL
1782 1647 stn %g3, [%g6 + %g7] ! make intr_vec_t (iv) as new tail
1783 1648 ! cpu->m_cpu.intr_tail[pil] = iv
1784 1649 !
1785 1650 ! there's pending intr_vec_t already
1786 1651 !
1787 1652 lduh [%g5 + IV_FLAGS], %g6 ! %g6 = ct->iv_flags
1788 1653 and %g6, IV_SOFTINT_MT, %g6 ! %g6 = ct->iv_flags & IV_SOFTINT_MT
1789 1654 brz,pt %g6, 1f ! check for Multi target softint flag
1790 1655 add %g5, IV_PIL_NEXT, %g5 ! %g5 = &ct->iv_pil_next
1791 1656 ld [%g4 + CPU_ID], %g6 ! for multi target softint, use cpuid
1792 1657 sll %g6, CPTRSHIFT, %g6 ! calculate offset address from cpuid
1793 1658 add %g5, %g6, %g5 ! %g5 = &ct->iv_xpil_next[cpuid]
1794 1659 1:
1795 1660 !
1796 1661 ! update old tail
1797 1662 !
1798 1663 ba,pt %xcc, 3f
1799 1664 stn %g3, [%g5] ! [%g5] = iv, set pil_next field
1800 1665 2:
1801 1666 !
1802 1667 ! no pending intr_vec_t; make intr_vec_t as new head
1803 1668 !
1804 1669 add %g4, INTR_HEAD, %g6 ! %g6 = &cpu->m_cpu.intr_head[pil]
1805 1670 stn %g3, [%g6 + %g7] ! cpu->m_cpu.intr_head[pil] = iv
1806 1671 3:
1807 1672 #ifdef TRAPTRACE
1808 1673 TRACE_PTR(%g5, %g6)
1809 1674 TRACE_SAVE_TL_GL_REGS(%g5, %g6)
1810 1675 rdpr %tt, %g6
1811 1676 stha %g6, [%g5 + TRAP_ENT_TT]%asi ! trap_type = %tt`
1812 1677 rdpr %tpc, %g6
1813 1678 stna %g6, [%g5 + TRAP_ENT_TPC]%asi ! trap_pc = %tpc
1814 1679 rdpr %tstate, %g6
1815 1680 stxa %g6, [%g5 + TRAP_ENT_TSTATE]%asi ! trap_tstate = %tstate
1816 1681 stna %sp, [%g5 + TRAP_ENT_SP]%asi ! trap_sp = %sp
1817 1682 stna %g3, [%g5 + TRAP_ENT_TR]%asi ! trap_tr = iv
1818 1683 stna %g1, [%g5 + TRAP_ENT_F1]%asi ! trap_f1 = pil mask
1819 1684 add %g4, INTR_HEAD, %g6
1820 1685 ldn [%g6 + %g7], %g6 ! %g6=cpu->m_cpu.intr_head[pil]
1821 1686 stna %g6, [%g5 + TRAP_ENT_F2]%asi ! trap_f2 = intr_head[pil]
1822 1687 add %g4, INTR_TAIL, %g6
1823 1688 ldn [%g6 + %g7], %g6 ! %g6=cpu->m_cpu.intr_tail[pil]
1824 1689 stna %g6, [%g5 + TRAP_ENT_F3]%asi ! trap_f3 = intr_tail[pil]
1825 1690 stna %g2, [%g5 + TRAP_ENT_F4]%asi ! trap_f4 = pil
1826 1691 GET_TRACE_TICK(%g6, %g7)
1827 1692 stxa %g6, [%g5 + TRAP_ENT_TICK]%asi ! trap_tick = %tick
1828 1693 TRACE_NEXT(%g5, %g6, %g7)
1829 1694 #endif /* TRAPTRACE */
1830 1695 mov 1, %g6 ! %g6 = 1
1831 1696 sll %g6, %g2, %g6 ! %g6 = 1 << pil
1832 1697 or %g1, %g6, %g1 ! %g1 |= (1 << pil), pil mask
1833 1698 ldn [%g3 + IV_VEC_NEXT], %g3 ! %g3 = pointer to next intr_vec_t (iv)
1834 1699 brnz,pn %g3, 0b ! iv->iv_vec_next is non NULL, goto 0b
1835 1700 nop
1836 1701 wr %g1, SET_SOFTINT ! triggered one or more pil softints
1837 1702 retry
↓ open down ↓ |
112 lines elided |
↑ open up ↑ |
1838 1703
1839 1704 .no_ivintr:
1840 1705 ! no_ivintr: arguments: rp, inum (%g1), pil (%g2 == 0)
1841 1706 mov %g2, %g3
1842 1707 mov %g1, %g2
1843 1708 set no_ivintr, %g1
1844 1709 ba,pt %xcc, sys_trap
1845 1710 mov PIL_15, %g4
1846 1711 SET_SIZE(setvecint_tl1)
1847 1712
1848 -#endif /* lint */
1849 -
1850 -#if defined(lint)
1851 -
1852 -/*ARGSUSED*/
1853 -void
1854 -wr_clr_softint(uint_t value)
1855 -{}
1856 -
1857 -#else
1858 -
1859 1713 ENTRY_NP(wr_clr_softint)
1860 1714 retl
1861 1715 wr %o0, CLEAR_SOFTINT
1862 1716 SET_SIZE(wr_clr_softint)
1863 1717
1864 -#endif /* lint */
1865 -
1866 -#if defined(lint)
1867 -
1868 -/*ARGSUSED*/
1869 -void
1870 -intr_enqueue_req(uint_t pil, uint64_t inum)
1871 -{}
1872 -
1873 -#else /* lint */
1874 -
1875 1718 /*
1876 1719 * intr_enqueue_req
1877 1720 *
1878 1721 * %o0 - pil
1879 1722 * %o1 - pointer to intr_vec_t (iv)
1880 1723 * %o5 - preserved
1881 1724 * %g5 - preserved
1882 1725 */
1883 1726 ENTRY_NP(intr_enqueue_req)
1884 1727 !
1885 1728 CPU_ADDR(%g4, %g1) ! %g4 = cpu
1886 1729
1887 1730 !
1888 1731 ! Insert intr_vec_t (iv) to appropriate cpu's softint priority list
1889 1732 !
1890 1733 sll %o0, CPTRSHIFT, %o0 ! %o0 = offset to pil entry
1891 1734 add %g4, INTR_TAIL, %g6 ! %g6 = &cpu->m_cpu.intr_tail
1892 1735 ldn [%o0 + %g6], %g1 ! %g1 = cpu->m_cpu.intr_tail[pil]
1893 1736 ! current tail (ct)
1894 1737 brz,pt %g1, 2f ! branch if current tail is NULL
1895 1738 stn %o1, [%g6 + %o0] ! make intr_vec_t (iv) as new tail
1896 1739
1897 1740 !
1898 1741 ! there's pending intr_vec_t already
1899 1742 !
1900 1743 lduh [%g1 + IV_FLAGS], %g6 ! %g6 = ct->iv_flags
1901 1744 and %g6, IV_SOFTINT_MT, %g6 ! %g6 = ct->iv_flags & IV_SOFTINT_MT
1902 1745 brz,pt %g6, 1f ! check for Multi target softint flag
1903 1746 add %g1, IV_PIL_NEXT, %g3 ! %g3 = &ct->iv_pil_next
1904 1747 ld [%g4 + CPU_ID], %g6 ! for multi target softint, use cpuid
1905 1748 sll %g6, CPTRSHIFT, %g6 ! calculate offset address from cpuid
1906 1749 add %g3, %g6, %g3 ! %g3 = &ct->iv_xpil_next[cpuid]
1907 1750 1:
1908 1751 !
1909 1752 ! update old tail
1910 1753 !
1911 1754 ba,pt %xcc, 3f
1912 1755 stn %o1, [%g3] ! {%g5] = iv, set pil_next field
1913 1756 2:
↓ open down ↓ |
29 lines elided |
↑ open up ↑ |
1914 1757 !
1915 1758 ! no intr_vec_t's queued so make intr_vec_t as new head
1916 1759 !
1917 1760 add %g4, INTR_HEAD, %g6 ! %g6 = &cpu->m_cpu.intr_head[pil]
1918 1761 stn %o1, [%g6 + %o0] ! cpu->m_cpu.intr_head[pil] = iv
1919 1762 3:
1920 1763 retl
1921 1764 nop
1922 1765 SET_SIZE(intr_enqueue_req)
1923 1766
1924 -#endif /* lint */
1925 -
1926 1767 /*
1927 1768 * Set CPU's base SPL level, based on which interrupt levels are active.
1928 1769 * Called at spl7 or above.
1929 1770 */
1930 1771
1931 -#if defined(lint)
1932 -
1933 -void
1934 -set_base_spl(void)
1935 -{}
1936 -
1937 -#else /* lint */
1938 -
1939 1772 ENTRY_NP(set_base_spl)
1940 1773 ldn [THREAD_REG + T_CPU], %o2 ! load CPU pointer
1941 1774 ld [%o2 + CPU_INTR_ACTV], %o5 ! load active interrupts mask
1942 1775
1943 1776 /*
1944 1777 * WARNING: non-standard callinq sequence; do not call from C
1945 1778 * %o2 = pointer to CPU
1946 1779 * %o5 = updated CPU_INTR_ACTV
1947 1780 */
1948 1781 _intr_set_spl: ! intr_thread_exit enters here
1949 1782 !
1950 1783 ! Determine highest interrupt level active. Several could be blocked
1951 1784 ! at higher levels than this one, so must convert flags to a PIL
1952 1785 ! Normally nothing will be blocked, so test this first.
1953 1786 !
1954 1787 brz,pt %o5, 1f ! nothing active
1955 1788 sra %o5, 11, %o3 ! delay - set %o3 to bits 15-11
1956 1789 set _intr_flag_table, %o1
1957 1790 tst %o3 ! see if any of the bits set
1958 1791 ldub [%o1 + %o3], %o3 ! load bit number
1959 1792 bnz,a,pn %xcc, 1f ! yes, add 10 and we're done
1960 1793 add %o3, 11-1, %o3 ! delay - add bit number - 1
1961 1794
1962 1795 sra %o5, 6, %o3 ! test bits 10-6
1963 1796 tst %o3
1964 1797 ldub [%o1 + %o3], %o3
1965 1798 bnz,a,pn %xcc, 1f
1966 1799 add %o3, 6-1, %o3
1967 1800
1968 1801 sra %o5, 1, %o3 ! test bits 5-1
1969 1802 ldub [%o1 + %o3], %o3
1970 1803
1971 1804 !
1972 1805 ! highest interrupt level number active is in %l6
1973 1806 !
1974 1807 1:
1975 1808 retl
1976 1809 st %o3, [%o2 + CPU_BASE_SPL] ! delay - store base priority
1977 1810 SET_SIZE(set_base_spl)
1978 1811
↓ open down ↓ |
30 lines elided |
↑ open up ↑ |
1979 1812 /*
1980 1813 * Table that finds the most significant bit set in a five bit field.
1981 1814 * Each entry is the high-order bit number + 1 of it's index in the table.
1982 1815 * This read-only data is in the text segment.
1983 1816 */
1984 1817 _intr_flag_table:
1985 1818 .byte 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4
1986 1819 .byte 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
1987 1820 .align 4
1988 1821
1989 -#endif /* lint */
1990 -
1991 1822 /*
1992 1823 * int
1993 1824 * intr_passivate(from, to)
1994 1825 * kthread_id_t from; interrupt thread
1995 1826 * kthread_id_t to; interrupted thread
1996 1827 */
1997 1828
1998 -#if defined(lint)
1999 -
2000 -/* ARGSUSED */
2001 -int
2002 -intr_passivate(kthread_id_t from, kthread_id_t to)
2003 -{ return (0); }
2004 -
2005 -#else /* lint */
2006 -
2007 1829 ENTRY_NP(intr_passivate)
2008 1830 save %sp, -SA(MINFRAME), %sp ! get a new window
2009 1831
2010 1832 flushw ! force register windows to stack
2011 1833 !
2012 1834 ! restore registers from the base of the stack of the interrupt thread.
2013 1835 !
2014 1836 ldn [%i0 + T_STACK], %i2 ! get stack save area pointer
2015 1837 ldn [%i2 + (0*GREGSIZE)], %l0 ! load locals
2016 1838 ldn [%i2 + (1*GREGSIZE)], %l1
2017 1839 ldn [%i2 + (2*GREGSIZE)], %l2
2018 1840 ldn [%i2 + (3*GREGSIZE)], %l3
2019 1841 ldn [%i2 + (4*GREGSIZE)], %l4
2020 1842 ldn [%i2 + (5*GREGSIZE)], %l5
2021 1843 ldn [%i2 + (6*GREGSIZE)], %l6
2022 1844 ldn [%i2 + (7*GREGSIZE)], %l7
2023 1845 ldn [%i2 + (8*GREGSIZE)], %o0 ! put ins from stack in outs
2024 1846 ldn [%i2 + (9*GREGSIZE)], %o1
2025 1847 ldn [%i2 + (10*GREGSIZE)], %o2
2026 1848 ldn [%i2 + (11*GREGSIZE)], %o3
2027 1849 ldn [%i2 + (12*GREGSIZE)], %o4
2028 1850 ldn [%i2 + (13*GREGSIZE)], %o5
2029 1851 ldn [%i2 + (14*GREGSIZE)], %i4
2030 1852 ! copy stack/pointer without using %sp
2031 1853 ldn [%i2 + (15*GREGSIZE)], %i5
2032 1854 !
2033 1855 ! put registers into the save area at the top of the interrupted
2034 1856 ! thread's stack, pointed to by %l7 in the save area just loaded.
2035 1857 !
2036 1858 ldn [%i1 + T_SP], %i3 ! get stack save area pointer
2037 1859 stn %l0, [%i3 + STACK_BIAS + (0*GREGSIZE)] ! save locals
2038 1860 stn %l1, [%i3 + STACK_BIAS + (1*GREGSIZE)]
2039 1861 stn %l2, [%i3 + STACK_BIAS + (2*GREGSIZE)]
2040 1862 stn %l3, [%i3 + STACK_BIAS + (3*GREGSIZE)]
2041 1863 stn %l4, [%i3 + STACK_BIAS + (4*GREGSIZE)]
2042 1864 stn %l5, [%i3 + STACK_BIAS + (5*GREGSIZE)]
2043 1865 stn %l6, [%i3 + STACK_BIAS + (6*GREGSIZE)]
2044 1866 stn %l7, [%i3 + STACK_BIAS + (7*GREGSIZE)]
2045 1867 stn %o0, [%i3 + STACK_BIAS + (8*GREGSIZE)] ! save ins using outs
2046 1868 stn %o1, [%i3 + STACK_BIAS + (9*GREGSIZE)]
2047 1869 stn %o2, [%i3 + STACK_BIAS + (10*GREGSIZE)]
2048 1870 stn %o3, [%i3 + STACK_BIAS + (11*GREGSIZE)]
2049 1871 stn %o4, [%i3 + STACK_BIAS + (12*GREGSIZE)]
2050 1872 stn %o5, [%i3 + STACK_BIAS + (13*GREGSIZE)]
2051 1873 stn %i4, [%i3 + STACK_BIAS + (14*GREGSIZE)]
2052 1874 ! fp, %i7 copied using %i4
↓ open down ↓ |
36 lines elided |
↑ open up ↑ |
2053 1875 stn %i5, [%i3 + STACK_BIAS + (15*GREGSIZE)]
2054 1876 stn %g0, [%i2 + ((8+6)*GREGSIZE)]
2055 1877 ! clear fp in save area
2056 1878
2057 1879 ! load saved pil for return
2058 1880 ldub [%i0 + T_PIL], %i0
2059 1881 ret
2060 1882 restore
2061 1883 SET_SIZE(intr_passivate)
2062 1884
2063 -#endif /* lint */
2064 -
2065 -#if defined(lint)
2066 -
2067 1885 /*
2068 1886 * intr_get_time() is a resource for interrupt handlers to determine how
2069 1887 * much time has been spent handling the current interrupt. Such a function
2070 1888 * is needed because higher level interrupts can arrive during the
2071 1889 * processing of an interrupt, thus making direct comparisons of %tick by
2072 1890 * the handler inaccurate. intr_get_time() only returns time spent in the
2073 1891 * current interrupt handler.
2074 1892 *
2075 1893 * The caller must be calling from an interrupt handler running at a pil
2076 1894 * below or at lock level. Timings are not provided for high-level
2077 1895 * interrupts.
2078 1896 *
2079 1897 * The first time intr_get_time() is called while handling an interrupt,
2080 1898 * it returns the time since the interrupt handler was invoked. Subsequent
2081 1899 * calls will return the time since the prior call to intr_get_time(). Time
2082 - * is returned as ticks, adjusted for any clock divisor due to power
2083 - * management. Use tick2ns() to convert ticks to nsec. Warning: ticks may
1900 + * is returned as ticks, adjusted for any clock divisor due to power
1901 + * management. Use tick2ns() to convert ticks to nsec. Warning: ticks may
2084 1902 * not be the same across CPUs.
2085 1903 *
2086 1904 * Theory Of Intrstat[][]:
2087 1905 *
2088 1906 * uint64_t intrstat[pil][0..1] is an array indexed by pil level, with two
2089 1907 * uint64_ts per pil.
2090 1908 *
2091 1909 * intrstat[pil][0] is a cumulative count of the number of ticks spent
2092 1910 * handling all interrupts at the specified pil on this CPU. It is
2093 1911 * exported via kstats to the user.
2094 1912 *
2095 1913 * intrstat[pil][1] is always a count of ticks less than or equal to the
2096 1914 * value in [0]. The difference between [1] and [0] is the value returned
2097 1915 * by a call to intr_get_time(). At the start of interrupt processing,
2098 1916 * [0] and [1] will be equal (or nearly so). As the interrupt consumes
2099 1917 * time, [0] will increase, but [1] will remain the same. A call to
2100 1918 * intr_get_time() will return the difference, then update [1] to be the
2101 1919 * same as [0]. Future calls will return the time since the last call.
2102 1920 * Finally, when the interrupt completes, [1] is updated to the same as [0].
2103 1921 *
2104 1922 * Implementation:
2105 1923 *
2106 1924 * intr_get_time() works much like a higher level interrupt arriving. It
2107 1925 * "checkpoints" the timing information by incrementing intrstat[pil][0]
2108 1926 * to include elapsed running time, and by setting t_intr_start to %tick.
2109 1927 * It then sets the return value to intrstat[pil][0] - intrstat[pil][1],
2110 1928 * and updates intrstat[pil][1] to be the same as the new value of
2111 1929 * intrstat[pil][0].
2112 1930 *
2113 1931 * In the normal handling of interrupts, after an interrupt handler returns
2114 1932 * and the code in intr_thread() updates intrstat[pil][0], it then sets
2115 1933 * intrstat[pil][1] to the new value of intrstat[pil][0]. When [0] == [1],
2116 1934 * the timings are reset, i.e. intr_get_time() will return [0] - [1] which
↓ open down ↓ |
23 lines elided |
↑ open up ↑ |
2117 1935 * is 0.
2118 1936 *
2119 1937 * Whenever interrupts arrive on a CPU which is handling a lower pil
2120 1938 * interrupt, they update the lower pil's [0] to show time spent in the
2121 1939 * handler that they've interrupted. This results in a growing discrepancy
2122 1940 * between [0] and [1], which is returned the next time intr_get_time() is
2123 1941 * called. Time spent in the higher-pil interrupt will not be returned in
2124 1942 * the next intr_get_time() call from the original interrupt, because
2125 1943 * the higher-pil interrupt's time is accumulated in intrstat[higherpil][].
2126 1944 */
2127 -
2128 -/*ARGSUSED*/
2129 -uint64_t
2130 -intr_get_time(void)
2131 -{ return 0; }
2132 -#else /* lint */
2133 -
2134 1945 ENTRY_NP(intr_get_time)
2135 1946 #ifdef DEBUG
2136 1947 !
2137 1948 ! Lots of asserts, but just check panic_quiesce first.
2138 1949 ! Don't bother with lots of tests if we're just ignoring them.
2139 1950 !
2140 1951 sethi %hi(panic_quiesce), %o0
2141 1952 ld [%o0 + %lo(panic_quiesce)], %o0
2142 1953 brnz,pn %o0, 2f
2143 1954 nop
2144 1955 !
2145 1956 ! ASSERT(%pil <= LOCK_LEVEL)
2146 1957 !
2147 1958 rdpr %pil, %o1
2148 1959 cmp %o1, LOCK_LEVEL
2149 1960 ble,pt %xcc, 0f
2150 1961 sethi %hi(intr_get_time_high_pil), %o0 ! delay
2151 1962 call panic
2152 1963 or %o0, %lo(intr_get_time_high_pil), %o0
2153 1964 0:
2154 1965 !
2155 1966 ! ASSERT((t_flags & T_INTR_THREAD) != 0 && t_pil > 0)
2156 1967 !
2157 1968 lduh [THREAD_REG + T_FLAGS], %o2
2158 1969 andcc %o2, T_INTR_THREAD, %g0
2159 1970 bz,pn %xcc, 1f
2160 1971 ldub [THREAD_REG + T_PIL], %o1 ! delay
2161 1972 brnz,pt %o1, 0f
2162 1973 1:
2163 1974 sethi %hi(intr_get_time_not_intr), %o0
2164 1975 call panic
2165 1976 or %o0, %lo(intr_get_time_not_intr), %o0
2166 1977 0:
2167 1978 !
2168 1979 ! ASSERT(t_intr_start != 0)
2169 1980 !
2170 1981 ldx [THREAD_REG + T_INTR_START], %o1
2171 1982 brnz,pt %o1, 2f
2172 1983 sethi %hi(intr_get_time_no_start_time), %o0 ! delay
2173 1984 call panic
2174 1985 or %o0, %lo(intr_get_time_no_start_time), %o0
2175 1986 2:
2176 1987 #endif /* DEBUG */
2177 1988 !
2178 1989 ! %o0 = elapsed time and return value
2179 1990 ! %o1 = pil
2180 1991 ! %o2 = scratch
2181 1992 ! %o3 = scratch
2182 1993 ! %o4 = scratch
2183 1994 ! %o5 = cpu
2184 1995 !
2185 1996 wrpr %g0, PIL_MAX, %pil ! make this easy -- block normal intrs
2186 1997 ldn [THREAD_REG + T_CPU], %o5
2187 1998 ldub [THREAD_REG + T_PIL], %o1
2188 1999 ldx [THREAD_REG + T_INTR_START], %o3 ! %o3 = t_intr_start
2189 2000 !
2190 2001 ! Calculate elapsed time since t_intr_start. Update t_intr_start,
2191 2002 ! get delta, and multiply by cpu_divisor if necessary.
2192 2003 !
2193 2004 RD_CLOCK_TICK_NO_SUSPEND_CHECK(%o2, %o0)
2194 2005 stx %o2, [THREAD_REG + T_INTR_START]
2195 2006 sub %o2, %o3, %o0
2196 2007
2197 2008 lduh [%o5 + CPU_DIVISOR], %o4
2198 2009 cmp %o4, 1
2199 2010 bg,a,pn %xcc, 1f
2200 2011 mulx %o0, %o4, %o0 ! multiply interval by clock divisor iff > 1
2201 2012 1:
2202 2013 ! Update intracct[]
2203 2014 lduh [%o5 + CPU_MSTATE], %o4
2204 2015 sllx %o4, 3, %o4
2205 2016 add %o4, CPU_INTRACCT, %o4
2206 2017 ldx [%o5 + %o4], %o2
2207 2018 add %o2, %o0, %o2
2208 2019 stx %o2, [%o5 + %o4]
2209 2020
2210 2021 !
2211 2022 ! Increment cpu_m.intrstat[pil][0]. Calculate elapsed time since
2212 2023 ! cpu_m.intrstat[pil][1], which is either when the interrupt was
2213 2024 ! first entered, or the last time intr_get_time() was invoked. Then
2214 2025 ! update cpu_m.intrstat[pil][1] to match [0].
2215 2026 !
2216 2027 sllx %o1, 4, %o3
2217 2028 add %o3, CPU_MCPU, %o3
2218 2029 add %o3, MCPU_INTRSTAT, %o3
2219 2030 add %o3, %o5, %o3 ! %o3 = cpu_m.intrstat[pil][0]
2220 2031 ldx [%o3], %o2
2221 2032 add %o2, %o0, %o2 ! %o2 = new value for intrstat
2222 2033 stx %o2, [%o3]
2223 2034 ldx [%o3 + 8], %o4 ! %o4 = cpu_m.intrstat[pil][1]
2224 2035 sub %o2, %o4, %o0 ! %o0 is elapsed time since %o4
2225 2036 stx %o2, [%o3 + 8] ! make [1] match [0], resetting time
2226 2037
2227 2038 ld [%o5 + CPU_BASE_SPL], %o2 ! restore %pil to the greater
2228 2039 cmp %o2, %o1 ! of either our pil %o1 or
2229 2040 movl %xcc, %o1, %o2 ! cpu_base_spl.
2230 2041 retl
2231 2042 wrpr %g0, %o2, %pil
↓ open down ↓ |
88 lines elided |
↑ open up ↑ |
2232 2043 SET_SIZE(intr_get_time)
2233 2044
2234 2045 #ifdef DEBUG
2235 2046 intr_get_time_high_pil:
2236 2047 .asciz "intr_get_time(): %pil > LOCK_LEVEL"
2237 2048 intr_get_time_not_intr:
2238 2049 .asciz "intr_get_time(): not called from an interrupt thread"
2239 2050 intr_get_time_no_start_time:
2240 2051 .asciz "intr_get_time(): t_intr_start == 0"
2241 2052 #endif /* DEBUG */
2242 -#endif /* lint */
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX