1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2018 Western Digital Corporation. All rights reserved.
25 */
26
27 #include <sys/cpuvar.h>
28 #include <sys/cpu_event.h>
29 #include <sys/param.h>
30 #include <sys/cmn_err.h>
31 #include <sys/t_lock.h>
32 #include <sys/kmem.h>
33 #include <sys/machlock.h>
34 #include <sys/systm.h>
35 #include <sys/archsystm.h>
36 #include <sys/atomic.h>
37 #include <sys/sdt.h>
38 #include <sys/processor.h>
39 #include <sys/time.h>
40 #include <sys/psm.h>
41 #include <sys/smp_impldefs.h>
42 #include <sys/cram.h>
43 #include <sys/apic.h>
44 #include <sys/pit.h>
45 #include <sys/ddi.h>
46 #include <sys/sunddi.h>
47 #include <sys/ddi_impldefs.h>
48 #include <sys/pci.h>
49 #include <sys/promif.h>
50 #include <sys/x86_archext.h>
51 #include <sys/cpc_impl.h>
52 #include <sys/uadmin.h>
53 #include <sys/panic.h>
54 #include <sys/debug.h>
55 #include <sys/trap.h>
56 #include <sys/machsystm.h>
57 #include <sys/sysmacros.h>
58 #include <sys/rm_platter.h>
59 #include <sys/privregs.h>
60 #include <sys/note.h>
61 #include <sys/pci_intr_lib.h>
62 #include <sys/spl.h>
63 #include <sys/clock.h>
64 #include <sys/dditypes.h>
65 #include <sys/sunddi.h>
66 #include <sys/x_call.h>
67 #include <sys/reboot.h>
68 #include <vm/hat_i86.h>
69 #include <sys/stack.h>
70 #include <sys/apix.h>
71
72 static void apix_post_hardint(int);
73
74 /*
75 * Insert an vector into the tail of the interrupt pending list
76 */
77 static __inline__ void
apix_insert_pending_av(apix_impl_t * apixp,struct autovec * avp,int ipl)78 apix_insert_pending_av(apix_impl_t *apixp, struct autovec *avp, int ipl)
79 {
80 struct autovec **head = apixp->x_intr_head;
81 struct autovec **tail = apixp->x_intr_tail;
82
83 avp->av_ipl_link = NULL;
84 if (tail[ipl] == NULL) {
85 head[ipl] = tail[ipl] = avp;
86 return;
87 }
88
89 tail[ipl]->av_ipl_link = avp;
90 tail[ipl] = avp;
91 }
92
93 /*
94 * Remove and return an vector from the head of hardware interrupt
95 * pending list.
96 */
97 static __inline__ struct autovec *
apix_remove_pending_av(apix_impl_t * apixp,int ipl)98 apix_remove_pending_av(apix_impl_t *apixp, int ipl)
99 {
100 struct cpu *cpu = CPU;
101 struct autovec **head = apixp->x_intr_head;
102 struct autovec **tail = apixp->x_intr_tail;
103 struct autovec *avp = head[ipl];
104
105 if (avp == NULL)
106 return (NULL);
107
108 if (avp->av_vector != NULL && avp->av_prilevel < cpu->cpu_base_spl) {
109 /*
110 * If there is blocked higher level interrupts, return
111 * NULL to quit handling of current IPL level.
112 */
113 apixp->x_intr_pending |= (1 << avp->av_prilevel);
114 return (NULL);
115 }
116
117 avp->av_flags &= ~AV_PENTRY_PEND;
118 avp->av_flags |= AV_PENTRY_ONPROC;
119 head[ipl] = avp->av_ipl_link;
120 avp->av_ipl_link = NULL;
121
122 if (head[ipl] == NULL)
123 tail[ipl] = NULL;
124
125 return (avp);
126 }
127
128 /*
129 * add_pending_hardint:
130 *
131 * Add hardware interrupts to the interrupt pending list.
132 */
133 static void
apix_add_pending_hardint(int vector)134 apix_add_pending_hardint(int vector)
135 {
136 uint32_t cpuid = psm_get_cpu_id();
137 apix_impl_t *apixp = apixs[cpuid];
138 apix_vector_t *vecp = apixp->x_vectbl[vector];
139 struct autovec *p, *prevp = NULL;
140 int ipl;
141
142 /*
143 * The MSI interrupt not supporting per-vector masking could
144 * be triggered on a false vector as a result of rebinding
145 * operation cannot programme MSI address & data atomically.
146 * Add ISR of this interrupt to the pending list for such
147 * suspicious interrupt.
148 */
149 APIX_DO_FAKE_INTR(cpuid, vector);
150 if (vecp == NULL)
151 return;
152
153 for (p = vecp->v_autovect; p != NULL; p = p->av_link) {
154 if (p->av_vector == NULL)
155 continue; /* skip freed entry */
156
157 ipl = p->av_prilevel;
158 prevp = p;
159
160 /* set pending at specified priority level */
161 apixp->x_intr_pending |= (1 << ipl);
162
163 if (p->av_flags & AV_PENTRY_PEND)
164 continue; /* already in the pending list */
165 p->av_flags |= AV_PENTRY_PEND;
166
167 /* insert into pending list by it original IPL */
168 apix_insert_pending_av(apixp, p, ipl);
169 }
170
171 /* last one of the linked list */
172 if (prevp && ((prevp->av_flags & AV_PENTRY_LEVEL) != 0))
173 prevp->av_flags |= (vector & AV_PENTRY_VECTMASK);
174 }
175
176 /*
177 * Walk pending hardware interrupts at given priority level, invoking
178 * each interrupt handler as we go.
179 */
180 extern uint64_t intr_get_time(void);
181
182 static void
apix_dispatch_pending_autovect(uint_t ipl)183 apix_dispatch_pending_autovect(uint_t ipl)
184 {
185 uint32_t cpuid = psm_get_cpu_id();
186 apix_impl_t *apixp = apixs[cpuid];
187 struct autovec *av;
188
189 while ((av = apix_remove_pending_av(apixp, ipl)) != NULL) {
190 uint_t r;
191 uint_t (*intr)() = av->av_vector;
192 caddr_t arg1 = av->av_intarg1;
193 caddr_t arg2 = av->av_intarg2;
194 dev_info_t *dip = av->av_dip;
195 uchar_t vector = av->av_flags & AV_PENTRY_VECTMASK;
196
197 if (intr == NULL)
198 continue;
199
200 /* Don't enable interrupts during x-calls */
201 if (ipl != XC_HI_PIL)
202 sti();
203
204 DTRACE_PROBE4(interrupt__start, dev_info_t *, dip,
205 void *, intr, caddr_t, arg1, caddr_t, arg2);
206 r = (*intr)(arg1, arg2);
207 DTRACE_PROBE4(interrupt__complete, dev_info_t *, dip,
208 void *, intr, caddr_t, arg1, uint_t, r);
209
210 if (av->av_ticksp && av->av_prilevel <= LOCK_LEVEL)
211 atomic_add_64(av->av_ticksp, intr_get_time());
212
213 cli();
214
215 if (vector) {
216 if ((av->av_flags & AV_PENTRY_PEND) == 0)
217 av->av_flags &= ~AV_PENTRY_VECTMASK;
218
219 apix_post_hardint(vector);
220 }
221
222 /* mark it as idle */
223 av->av_flags &= ~AV_PENTRY_ONPROC;
224 }
225 }
226
227 static caddr_t
apix_do_softint_prolog(struct cpu * cpu,uint_t pil,uint_t oldpil,caddr_t stackptr)228 apix_do_softint_prolog(struct cpu *cpu, uint_t pil, uint_t oldpil,
229 caddr_t stackptr)
230 {
231 kthread_t *t, *volatile it;
232 struct machcpu *mcpu = &cpu->cpu_m;
233 hrtime_t now;
234
235 UNREFERENCED_1PARAMETER(oldpil);
236 ASSERT(pil > mcpu->mcpu_pri && pil > cpu->cpu_base_spl);
237
238 atomic_and_32((uint32_t *)&mcpu->mcpu_softinfo.st_pending, ~(1 << pil));
239
240 mcpu->mcpu_pri = pil;
241
242 now = tsc_read();
243
244 /*
245 * Get set to run interrupt thread.
246 * There should always be an interrupt thread since we
247 * allocate one for each level on the CPU.
248 */
249 it = cpu->cpu_intr_thread;
250 ASSERT(it != NULL);
251 cpu->cpu_intr_thread = it->t_link;
252
253 /* t_intr_start could be zero due to cpu_intr_swtch_enter. */
254 t = cpu->cpu_thread;
255 if ((t->t_flag & T_INTR_THREAD) && t->t_intr_start != 0) {
256 hrtime_t intrtime = now - t->t_intr_start;
257 mcpu->intrstat[pil][0] += intrtime;
258 cpu->cpu_intracct[cpu->cpu_mstate] += intrtime;
259 t->t_intr_start = 0;
260 }
261
262 /*
263 * Note that the code in kcpc_overflow_intr -relies- on the
264 * ordering of events here - in particular that t->t_lwp of
265 * the interrupt thread is set to the pinned thread *before*
266 * curthread is changed.
267 */
268 it->t_lwp = t->t_lwp;
269 it->t_state = TS_ONPROC;
270
271 /*
272 * Push interrupted thread onto list from new thread.
273 * Set the new thread as the current one.
274 * Set interrupted thread's T_SP because if it is the idle thread,
275 * resume() may use that stack between threads.
276 */
277
278 ASSERT(SA((uintptr_t)stackptr) == (uintptr_t)stackptr);
279 t->t_sp = (uintptr_t)stackptr;
280
281 it->t_intr = t;
282 cpu->cpu_thread = it;
283
284 /*
285 * Set bit for this pil in CPU's interrupt active bitmask.
286 */
287 ASSERT((cpu->cpu_intr_actv & (1 << pil)) == 0);
288 cpu->cpu_intr_actv |= (1 << pil);
289
290 /*
291 * Initialize thread priority level from intr_pri
292 */
293 it->t_pil = (uchar_t)pil;
294 it->t_pri = (pri_t)pil + intr_pri;
295 it->t_intr_start = now;
296
297 return (it->t_stk);
298 }
299
300 static void
apix_do_softint_epilog(struct cpu * cpu,uint_t oldpil)301 apix_do_softint_epilog(struct cpu *cpu, uint_t oldpil)
302 {
303 struct machcpu *mcpu = &cpu->cpu_m;
304 kthread_t *t, *it;
305 uint_t pil, basespl;
306 hrtime_t intrtime;
307 hrtime_t now = tsc_read();
308
309 it = cpu->cpu_thread;
310 pil = it->t_pil;
311
312 cpu->cpu_stats.sys.intr[pil - 1]++;
313
314 ASSERT(cpu->cpu_intr_actv & (1 << pil));
315 cpu->cpu_intr_actv &= ~(1 << pil);
316
317 intrtime = now - it->t_intr_start;
318 mcpu->intrstat[pil][0] += intrtime;
319 cpu->cpu_intracct[cpu->cpu_mstate] += intrtime;
320
321 /*
322 * If there is still an interrupted thread underneath this one
323 * then the interrupt was never blocked and the return is
324 * fairly simple. Otherwise it isn't.
325 */
326 if ((t = it->t_intr) == NULL) {
327 /*
328 * Put thread back on the interrupt thread list.
329 * This was an interrupt thread, so set CPU's base SPL.
330 */
331 set_base_spl();
332 /* mcpu->mcpu_pri = cpu->cpu_base_spl; */
333
334 /*
335 * If there are pending interrupts, send a softint to
336 * re-enter apix_do_interrupt() and get them processed.
337 */
338 if (apixs[cpu->cpu_id]->x_intr_pending)
339 siron();
340
341 it->t_state = TS_FREE;
342 it->t_link = cpu->cpu_intr_thread;
343 cpu->cpu_intr_thread = it;
344 (void) splhigh();
345 sti();
346 swtch();
347 /*NOTREACHED*/
348 panic("dosoftint_epilog: swtch returned");
349 }
350 it->t_link = cpu->cpu_intr_thread;
351 cpu->cpu_intr_thread = it;
352 it->t_state = TS_FREE;
353 cpu->cpu_thread = t;
354 if (t->t_flag & T_INTR_THREAD)
355 t->t_intr_start = now;
356 basespl = cpu->cpu_base_spl;
357 pil = MAX(oldpil, basespl);
358 mcpu->mcpu_pri = pil;
359 }
360
361 /*
362 * Dispatch a soft interrupt
363 */
364 static void
apix_dispatch_softint(uint_t oldpil,uint_t arg2)365 apix_dispatch_softint(uint_t oldpil, uint_t arg2)
366 {
367 struct cpu *cpu = CPU;
368
369 UNREFERENCED_1PARAMETER(arg2);
370
371 sti();
372 av_dispatch_softvect((int)cpu->cpu_thread->t_pil);
373 cli();
374
375 /*
376 * Must run softint_epilog() on the interrupt thread stack, since
377 * there may not be a return from it if the interrupt thread blocked.
378 */
379 apix_do_softint_epilog(cpu, oldpil);
380 }
381
382 /*
383 * Deliver any softints the current interrupt priority allows.
384 * Called with interrupts disabled.
385 */
386 int
apix_do_softint(struct regs * regs)387 apix_do_softint(struct regs *regs)
388 {
389 struct cpu *cpu = CPU;
390 int oldipl;
391 int newipl;
392 volatile uint16_t pending;
393 caddr_t newsp;
394
395 while ((pending = cpu->cpu_softinfo.st_pending) != 0) {
396 newipl = bsrw_insn(pending);
397 oldipl = cpu->cpu_pri;
398 if (newipl <= oldipl || newipl <= cpu->cpu_base_spl)
399 return (-1);
400
401 newsp = apix_do_softint_prolog(cpu, newipl, oldipl,
402 (caddr_t)regs);
403 ASSERT(newsp != NULL);
404 switch_sp_and_call(newsp, apix_dispatch_softint, oldipl, 0);
405 }
406
407 return (0);
408 }
409
410 static int
apix_hilevel_intr_prolog(struct cpu * cpu,uint_t pil,uint_t oldpil,struct regs * rp)411 apix_hilevel_intr_prolog(struct cpu *cpu, uint_t pil, uint_t oldpil,
412 struct regs *rp)
413 {
414 struct machcpu *mcpu = &cpu->cpu_m;
415 hrtime_t intrtime;
416 hrtime_t now = tsc_read();
417 apix_impl_t *apixp = apixs[cpu->cpu_id];
418 uint_t mask;
419
420 ASSERT(pil > mcpu->mcpu_pri && pil > cpu->cpu_base_spl);
421
422 if (pil == CBE_HIGH_PIL) { /* 14 */
423 cpu->cpu_profile_pil = oldpil;
424 if (USERMODE(rp->r_cs)) {
425 cpu->cpu_profile_pc = 0;
426 cpu->cpu_profile_upc = rp->r_pc;
427 cpu->cpu_cpcprofile_pc = 0;
428 cpu->cpu_cpcprofile_upc = rp->r_pc;
429 } else {
430 cpu->cpu_profile_pc = rp->r_pc;
431 cpu->cpu_profile_upc = 0;
432 cpu->cpu_cpcprofile_pc = rp->r_pc;
433 cpu->cpu_cpcprofile_upc = 0;
434 }
435 }
436
437 mcpu->mcpu_pri = pil;
438
439 mask = cpu->cpu_intr_actv & CPU_INTR_ACTV_HIGH_LEVEL_MASK;
440 if (mask != 0) {
441 int nestpil;
442
443 /*
444 * We have interrupted another high-level interrupt.
445 * Load starting timestamp, compute interval, update
446 * cumulative counter.
447 */
448 nestpil = bsrw_insn((uint16_t)mask);
449 intrtime = now -
450 mcpu->pil_high_start[nestpil - (LOCK_LEVEL + 1)];
451 mcpu->intrstat[nestpil][0] += intrtime;
452 cpu->cpu_intracct[cpu->cpu_mstate] += intrtime;
453 } else {
454 kthread_t *t = cpu->cpu_thread;
455
456 /*
457 * See if we are interrupting a low-level interrupt thread.
458 * If so, account for its time slice only if its time stamp
459 * is non-zero.
460 */
461 if ((t->t_flag & T_INTR_THREAD) != 0 && t->t_intr_start != 0) {
462 intrtime = now - t->t_intr_start;
463 mcpu->intrstat[t->t_pil][0] += intrtime;
464 cpu->cpu_intracct[cpu->cpu_mstate] += intrtime;
465 t->t_intr_start = 0;
466 }
467 }
468
469 /* store starting timestamp in CPu structure for this IPL */
470 mcpu->pil_high_start[pil - (LOCK_LEVEL + 1)] = now;
471
472 if (pil == 15) {
473 /*
474 * To support reentrant level 15 interrupts, we maintain a
475 * recursion count in the top half of cpu_intr_actv. Only
476 * when this count hits zero do we clear the PIL 15 bit from
477 * the lower half of cpu_intr_actv.
478 */
479 uint16_t *refcntp = (uint16_t *)&cpu->cpu_intr_actv + 1;
480 (*refcntp)++;
481 }
482
483 cpu->cpu_intr_actv |= (1 << pil);
484 /* clear pending ipl level bit */
485 apixp->x_intr_pending &= ~(1 << pil);
486
487 return (mask);
488 }
489
490 static int
apix_hilevel_intr_epilog(struct cpu * cpu,uint_t oldpil)491 apix_hilevel_intr_epilog(struct cpu *cpu, uint_t oldpil)
492 {
493 struct machcpu *mcpu = &cpu->cpu_m;
494 uint_t mask, pil;
495 hrtime_t intrtime;
496 hrtime_t now = tsc_read();
497
498 pil = mcpu->mcpu_pri;
499 cpu->cpu_stats.sys.intr[pil - 1]++;
500
501 ASSERT(cpu->cpu_intr_actv & (1 << pil));
502
503 if (pil == 15) {
504 /*
505 * To support reentrant level 15 interrupts, we maintain a
506 * recursion count in the top half of cpu_intr_actv. Only
507 * when this count hits zero do we clear the PIL 15 bit from
508 * the lower half of cpu_intr_actv.
509 */
510 uint16_t *refcntp = (uint16_t *)&cpu->cpu_intr_actv + 1;
511
512 ASSERT(*refcntp > 0);
513
514 if (--(*refcntp) == 0)
515 cpu->cpu_intr_actv &= ~(1 << pil);
516 } else {
517 cpu->cpu_intr_actv &= ~(1 << pil);
518 }
519
520 ASSERT(mcpu->pil_high_start[pil - (LOCK_LEVEL + 1)] != 0);
521
522 intrtime = now - mcpu->pil_high_start[pil - (LOCK_LEVEL + 1)];
523 mcpu->intrstat[pil][0] += intrtime;
524 cpu->cpu_intracct[cpu->cpu_mstate] += intrtime;
525
526 /*
527 * Check for lower-pil nested high-level interrupt beneath
528 * current one. If so, place a starting timestamp in its
529 * pil_high_start entry.
530 */
531 mask = cpu->cpu_intr_actv & CPU_INTR_ACTV_HIGH_LEVEL_MASK;
532 if (mask != 0) {
533 int nestpil;
534
535 /*
536 * find PIL of nested interrupt
537 */
538 nestpil = bsrw_insn((uint16_t)mask);
539 ASSERT(nestpil < pil);
540 mcpu->pil_high_start[nestpil - (LOCK_LEVEL + 1)] = now;
541 /*
542 * (Another high-level interrupt is active below this one,
543 * so there is no need to check for an interrupt
544 * thread. That will be done by the lowest priority
545 * high-level interrupt active.)
546 */
547 } else {
548 /*
549 * Check to see if there is a low-level interrupt active.
550 * If so, place a starting timestamp in the thread
551 * structure.
552 */
553 kthread_t *t = cpu->cpu_thread;
554
555 if (t->t_flag & T_INTR_THREAD)
556 t->t_intr_start = now;
557 }
558
559 mcpu->mcpu_pri = oldpil;
560 if (pil < CBE_HIGH_PIL)
561 (void) (*setlvlx)(oldpil, 0);
562
563 return (mask);
564 }
565
566 /*
567 * Dispatch a hilevel interrupt (one above LOCK_LEVEL)
568 */
569 static void
apix_dispatch_pending_hilevel(uint_t ipl,uint_t arg2)570 apix_dispatch_pending_hilevel(uint_t ipl, uint_t arg2)
571 {
572 UNREFERENCED_1PARAMETER(arg2);
573
574 apix_dispatch_pending_autovect(ipl);
575 }
576
577 static __inline__ int
apix_do_pending_hilevel(struct cpu * cpu,struct regs * rp)578 apix_do_pending_hilevel(struct cpu *cpu, struct regs *rp)
579 {
580 volatile uint16_t pending;
581 uint_t newipl, oldipl;
582 caddr_t newsp;
583
584 while ((pending = HILEVEL_PENDING(cpu)) != 0) {
585 newipl = bsrw_insn(pending);
586 ASSERT(newipl > LOCK_LEVEL && newipl > cpu->cpu_base_spl);
587 oldipl = cpu->cpu_pri;
588 if (newipl <= oldipl)
589 return (-1);
590
591 /*
592 * High priority interrupts run on this cpu's interrupt stack.
593 */
594 if (apix_hilevel_intr_prolog(cpu, newipl, oldipl, rp) == 0) {
595 newsp = cpu->cpu_intr_stack;
596 switch_sp_and_call(newsp, apix_dispatch_pending_hilevel,
597 newipl, 0);
598 } else { /* already on the interrupt stack */
599 apix_dispatch_pending_hilevel(newipl, 0);
600 }
601 (void) apix_hilevel_intr_epilog(cpu, oldipl);
602 }
603
604 return (0);
605 }
606
607 /*
608 * Get an interrupt thread and swith to it. It's called from do_interrupt().
609 * The IF flag is cleared and thus all maskable interrupts are blocked at
610 * the time of calling.
611 */
612 static caddr_t
apix_intr_thread_prolog(struct cpu * cpu,uint_t pil,caddr_t stackptr)613 apix_intr_thread_prolog(struct cpu *cpu, uint_t pil, caddr_t stackptr)
614 {
615 apix_impl_t *apixp = apixs[cpu->cpu_id];
616 struct machcpu *mcpu = &cpu->cpu_m;
617 hrtime_t now = tsc_read();
618 kthread_t *t, *volatile it;
619
620 ASSERT(pil > mcpu->mcpu_pri && pil > cpu->cpu_base_spl);
621
622 apixp->x_intr_pending &= ~(1 << pil);
623 ASSERT((cpu->cpu_intr_actv & (1 << pil)) == 0);
624 cpu->cpu_intr_actv |= (1 << pil);
625 mcpu->mcpu_pri = pil;
626
627 /*
628 * Get set to run interrupt thread.
629 * There should always be an interrupt thread since we
630 * allocate one for each level on the CPU.
631 */
632 /* t_intr_start could be zero due to cpu_intr_swtch_enter. */
633 t = cpu->cpu_thread;
634 if ((t->t_flag & T_INTR_THREAD) && t->t_intr_start != 0) {
635 hrtime_t intrtime = now - t->t_intr_start;
636 mcpu->intrstat[pil][0] += intrtime;
637 cpu->cpu_intracct[cpu->cpu_mstate] += intrtime;
638 t->t_intr_start = 0;
639 }
640
641 /*
642 * Push interrupted thread onto list from new thread.
643 * Set the new thread as the current one.
644 * Set interrupted thread's T_SP because if it is the idle thread,
645 * resume() may use that stack between threads.
646 */
647
648 ASSERT(SA((uintptr_t)stackptr) == (uintptr_t)stackptr);
649
650 t->t_sp = (uintptr_t)stackptr; /* mark stack in curthread for resume */
651
652 /*
653 * Note that the code in kcpc_overflow_intr -relies- on the
654 * ordering of events here - in particular that t->t_lwp of
655 * the interrupt thread is set to the pinned thread *before*
656 * curthread is changed.
657 */
658 it = cpu->cpu_intr_thread;
659 cpu->cpu_intr_thread = it->t_link;
660 it->t_intr = t;
661 it->t_lwp = t->t_lwp;
662
663 /*
664 * (threads on the interrupt thread free list could have state
665 * preset to TS_ONPROC, but it helps in debugging if
666 * they're TS_FREE.)
667 */
668 it->t_state = TS_ONPROC;
669
670 cpu->cpu_thread = it;
671
672 /*
673 * Initialize thread priority level from intr_pri
674 */
675 it->t_pil = (uchar_t)pil;
676 it->t_pri = (pri_t)pil + intr_pri;
677 it->t_intr_start = now;
678
679 return (it->t_stk);
680 }
681
682 static void
apix_intr_thread_epilog(struct cpu * cpu,uint_t oldpil)683 apix_intr_thread_epilog(struct cpu *cpu, uint_t oldpil)
684 {
685 struct machcpu *mcpu = &cpu->cpu_m;
686 kthread_t *t, *it = cpu->cpu_thread;
687 uint_t pil, basespl;
688 hrtime_t intrtime;
689 hrtime_t now = tsc_read();
690
691 pil = it->t_pil;
692 cpu->cpu_stats.sys.intr[pil - 1]++;
693
694 ASSERT(cpu->cpu_intr_actv & (1 << pil));
695 cpu->cpu_intr_actv &= ~(1 << pil);
696
697 ASSERT(it->t_intr_start != 0);
698 intrtime = now - it->t_intr_start;
699 mcpu->intrstat[pil][0] += intrtime;
700 cpu->cpu_intracct[cpu->cpu_mstate] += intrtime;
701
702 /*
703 * If there is still an interrupted thread underneath this one
704 * then the interrupt was never blocked and the return is
705 * fairly simple. Otherwise it isn't.
706 */
707 if ((t = it->t_intr) == NULL) {
708 /*
709 * The interrupted thread is no longer pinned underneath
710 * the interrupt thread. This means the interrupt must
711 * have blocked, and the interrupted thread has been
712 * unpinned, and has probably been running around the
713 * system for a while.
714 *
715 * Since there is no longer a thread under this one, put
716 * this interrupt thread back on the CPU's free list and
717 * resume the idle thread which will dispatch the next
718 * thread to run.
719 */
720 cpu->cpu_stats.sys.intrblk++;
721
722 /*
723 * Put thread back on the interrupt thread list.
724 * This was an interrupt thread, so set CPU's base SPL.
725 */
726 set_base_spl();
727 basespl = cpu->cpu_base_spl;
728 mcpu->mcpu_pri = basespl;
729 (*setlvlx)(basespl, 0);
730
731 /*
732 * If there are pending interrupts, send a softint to
733 * re-enter apix_do_interrupt() and get them processed.
734 */
735 if (apixs[cpu->cpu_id]->x_intr_pending)
736 siron();
737
738 it->t_state = TS_FREE;
739 /*
740 * Return interrupt thread to pool
741 */
742 it->t_link = cpu->cpu_intr_thread;
743 cpu->cpu_intr_thread = it;
744
745 (void) splhigh();
746 sti();
747 swtch();
748 /*NOTREACHED*/
749 panic("dosoftint_epilog: swtch returned");
750 }
751
752 /*
753 * Return interrupt thread to the pool
754 */
755 it->t_link = cpu->cpu_intr_thread;
756 cpu->cpu_intr_thread = it;
757 it->t_state = TS_FREE;
758
759 cpu->cpu_thread = t;
760 if (t->t_flag & T_INTR_THREAD)
761 t->t_intr_start = now;
762 basespl = cpu->cpu_base_spl;
763 mcpu->mcpu_pri = MAX(oldpil, basespl);
764 (*setlvlx)(mcpu->mcpu_pri, 0);
765 }
766
767
768 static void
apix_dispatch_pending_hardint(uint_t oldpil,uint_t arg2)769 apix_dispatch_pending_hardint(uint_t oldpil, uint_t arg2)
770 {
771 struct cpu *cpu = CPU;
772
773 UNREFERENCED_1PARAMETER(arg2);
774
775 apix_dispatch_pending_autovect((int)cpu->cpu_thread->t_pil);
776
777 /*
778 * Must run intr_thread_epilog() on the interrupt thread stack, since
779 * there may not be a return from it if the interrupt thread blocked.
780 */
781 apix_intr_thread_epilog(cpu, oldpil);
782 }
783
784 static __inline__ int
apix_do_pending_hardint(struct cpu * cpu,struct regs * rp)785 apix_do_pending_hardint(struct cpu *cpu, struct regs *rp)
786 {
787 volatile uint16_t pending;
788 uint_t newipl, oldipl;
789 caddr_t newsp;
790
791 while ((pending = LOWLEVEL_PENDING(cpu)) != 0) {
792 newipl = bsrw_insn(pending);
793 ASSERT(newipl <= LOCK_LEVEL);
794 oldipl = cpu->cpu_pri;
795 if (newipl <= oldipl || newipl <= cpu->cpu_base_spl)
796 return (-1);
797
798 /*
799 * Run this interrupt in a separate thread.
800 */
801 newsp = apix_intr_thread_prolog(cpu, newipl, (caddr_t)rp);
802 ASSERT(newsp != NULL);
803 switch_sp_and_call(newsp, apix_dispatch_pending_hardint,
804 oldipl, 0);
805 }
806
807 return (0);
808 }
809
810 /*
811 * Unmask level triggered interrupts
812 */
813 static void
apix_post_hardint(int vector)814 apix_post_hardint(int vector)
815 {
816 apix_vector_t *vecp = xv_vector(psm_get_cpu_id(), vector);
817 int irqno = vecp->v_inum;
818
819 ASSERT(vecp->v_type == APIX_TYPE_FIXED && apic_level_intr[irqno]);
820
821 apix_level_intr_post_dispatch(irqno);
822 }
823
824 static void
apix_dispatch_by_vector(uint_t vector)825 apix_dispatch_by_vector(uint_t vector)
826 {
827 struct cpu *cpu = CPU;
828 apix_vector_t *vecp = xv_vector(cpu->cpu_id, vector);
829 struct autovec *avp;
830 uint_t r, (*intr)();
831 caddr_t arg1, arg2;
832 dev_info_t *dip;
833
834 if (vecp == NULL ||
835 (avp = vecp->v_autovect) == NULL || avp->av_vector == NULL)
836 return;
837
838 avp->av_flags |= AV_PENTRY_ONPROC;
839 intr = avp->av_vector;
840 arg1 = avp->av_intarg1;
841 arg2 = avp->av_intarg2;
842 dip = avp->av_dip;
843
844 if (avp->av_prilevel != XC_HI_PIL)
845 sti();
846
847 DTRACE_PROBE4(interrupt__start, dev_info_t *, dip,
848 void *, intr, caddr_t, arg1, caddr_t, arg2);
849 r = (*intr)(arg1, arg2);
850 DTRACE_PROBE4(interrupt__complete, dev_info_t *, dip,
851 void *, intr, caddr_t, arg1, uint_t, r);
852
853 cli();
854 avp->av_flags &= ~AV_PENTRY_ONPROC;
855 }
856
857
858 static void
apix_dispatch_hilevel(uint_t vector,uint_t arg2)859 apix_dispatch_hilevel(uint_t vector, uint_t arg2)
860 {
861 UNREFERENCED_1PARAMETER(arg2);
862
863 apix_dispatch_by_vector(vector);
864 }
865
866 static void
apix_dispatch_lowlevel(uint_t vector,uint_t oldipl)867 apix_dispatch_lowlevel(uint_t vector, uint_t oldipl)
868 {
869 struct cpu *cpu = CPU;
870
871 apix_dispatch_by_vector(vector);
872
873 /*
874 * Must run intr_thread_epilog() on the interrupt thread stack, since
875 * there may not be a return from it if the interrupt thread blocked.
876 */
877 apix_intr_thread_epilog(cpu, oldipl);
878 }
879
880 /*
881 * Interrupt service routine, called with interrupts disabled.
882 */
883 void
apix_do_interrupt(struct regs * rp,trap_trace_rec_t * ttp)884 apix_do_interrupt(struct regs *rp, trap_trace_rec_t *ttp)
885 {
886 struct cpu *cpu = CPU;
887 int vector = rp->r_trapno, newipl, oldipl = cpu->cpu_pri, ret;
888 apix_vector_t *vecp = NULL;
889
890 #ifdef TRAPTRACE
891 ttp->ttr_marker = TT_INTERRUPT;
892 ttp->ttr_cpuid = cpu->cpu_id;
893 ttp->ttr_ipl = 0xff;
894 ttp->ttr_pri = (uchar_t)oldipl;
895 ttp->ttr_spl = cpu->cpu_base_spl;
896 ttp->ttr_vector = 0xff;
897 #endif /* TRAPTRACE */
898
899 cpu_idle_exit(CPU_IDLE_CB_FLAG_INTR);
900
901 ++*(uint16_t *)&cpu->cpu_m.mcpu_istamp;
902
903 /*
904 * If it's a softint go do it now.
905 */
906 if (rp->r_trapno == T_SOFTINT) {
907 /*
908 * It might be the case that when an interrupt is triggered,
909 * the spl is raised to high by splhigh(). Later when do_splx()
910 * is called to restore the spl, both hardware and software
911 * interrupt pending flags are check and an SOFTINT is faked
912 * accordingly.
913 */
914 (void) apix_do_pending_hilevel(cpu, rp);
915 (void) apix_do_pending_hardint(cpu, rp);
916 (void) apix_do_softint(rp);
917 ASSERT(!interrupts_enabled());
918 #ifdef TRAPTRACE
919 ttp->ttr_vector = T_SOFTINT;
920 #endif
921 /*
922 * We need to check again for pending interrupts that may have
923 * arrived while the softint was running.
924 */
925 goto do_pending;
926 }
927
928 /*
929 * Send EOI to local APIC
930 */
931 newipl = (*setlvl)(oldipl, (int *)&rp->r_trapno);
932 #ifdef TRAPTRACE
933 ttp->ttr_ipl = (uchar_t)newipl;
934 #endif /* TRAPTRACE */
935
936 /*
937 * Bail if it is a spurious interrupt
938 */
939 if (newipl == -1)
940 return;
941
942 vector = rp->r_trapno;
943 vecp = xv_vector(cpu->cpu_id, vector);
944 #ifdef TRAPTRACE
945 ttp->ttr_vector = (short)vector;
946 #endif /* TRAPTRACE */
947
948 /*
949 * Direct dispatch for IPI, MSI, MSI-X
950 */
951 if (vecp && vecp->v_type != APIX_TYPE_FIXED &&
952 newipl > MAX(oldipl, cpu->cpu_base_spl)) {
953 caddr_t newsp;
954
955 if (INTR_PENDING(apixs[cpu->cpu_id], newipl)) {
956 /*
957 * There are already vectors pending at newipl,
958 * queue this one and fall through to process
959 * all pending.
960 */
961 apix_add_pending_hardint(vector);
962 } else if (newipl > LOCK_LEVEL) {
963 if (apix_hilevel_intr_prolog(cpu, newipl, oldipl, rp)
964 == 0) {
965 newsp = cpu->cpu_intr_stack;
966 switch_sp_and_call(newsp, apix_dispatch_hilevel,
967 vector, 0);
968 } else {
969 apix_dispatch_hilevel(vector, 0);
970 }
971 (void) apix_hilevel_intr_epilog(cpu, oldipl);
972 } else {
973 newsp = apix_intr_thread_prolog(cpu, newipl,
974 (caddr_t)rp);
975 switch_sp_and_call(newsp, apix_dispatch_lowlevel,
976 vector, oldipl);
977 }
978 } else {
979 /* Add to per-pil pending queue */
980 apix_add_pending_hardint(vector);
981 if (newipl <= MAX(oldipl, cpu->cpu_base_spl) ||
982 !apixs[cpu->cpu_id]->x_intr_pending)
983 return;
984 }
985
986 do_pending:
987 if (apix_do_pending_hilevel(cpu, rp) < 0)
988 return;
989
990 do {
991 ret = apix_do_pending_hardint(cpu, rp);
992
993 /*
994 * Deliver any pending soft interrupts.
995 */
996 (void) apix_do_softint(rp);
997 } while (!ret && LOWLEVEL_PENDING(cpu));
998 }
999