xref: /titanic_50/usr/src/uts/i86pc/io/apix/apix_intr.c (revision fd1eb05fda4c54e99109b82c9484c44d0cf10661)
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