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