1 /*        $NetBSD: evtchn.c,v 1.100 2022/09/07 00:40:19 knakahara Exp $         */
2 
3 /*
4  * Copyright (c) 2006 Manuel Bouyer.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *
26  */
27 
28 /*
29  *
30  * Copyright (c) 2004 Christian Limpach.
31  * Copyright (c) 2004, K A Fraser.
32  * All rights reserved.
33  *
34  * Redistribution and use in source and binary forms, with or without
35  * modification, are permitted provided that the following conditions
36  * are met:
37  * 1. Redistributions of source code must retain the above copyright
38  *    notice, this list of conditions and the following disclaimer.
39  * 2. Redistributions in binary form must reproduce the above copyright
40  *    notice, this list of conditions and the following disclaimer in the
41  *    documentation and/or other materials provided with the distribution.
42  *
43  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
44  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
45  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
46  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
47  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
48  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
49  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
50  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
51  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
52  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
53  */
54 
55 
56 #include <sys/cdefs.h>
57 __KERNEL_RCSID(0, "$NetBSD: evtchn.c,v 1.100 2022/09/07 00:40:19 knakahara Exp $");
58 
59 #include "opt_xen.h"
60 #include "isa.h"
61 #include "pci.h"
62 
63 #include <sys/param.h>
64 #include <sys/cpu.h>
65 #include <sys/kernel.h>
66 #include <sys/systm.h>
67 #include <sys/device.h>
68 #include <sys/proc.h>
69 #include <sys/kmem.h>
70 #include <sys/reboot.h>
71 #include <sys/mutex.h>
72 #include <sys/interrupt.h>
73 #include <sys/xcall.h>
74 
75 #include <uvm/uvm.h>
76 
77 #include <xen/intr.h>
78 
79 #include <xen/xen.h>
80 #include <xen/hypervisor.h>
81 #include <xen/evtchn.h>
82 #include <xen/xenfunc.h>
83 
84 /* maximum number of (v)CPUs supported */
85 #ifdef XENPV
86 #define NBSD_XEN_MAX_VCPUS XEN_LEGACY_MAX_VCPUS
87 #else
88 #include <xen/include/public/hvm/hvm_info_table.h>
89 #define NBSD_XEN_MAX_VCPUS HVM_MAX_VCPUS
90 #endif
91 
92 #define   NR_PIRQS  NR_EVENT_CHANNELS
93 
94 /*
95  * This lock protects updates to the following mapping and reference-count
96  * arrays. The lock does not need to be acquired to read the mapping tables.
97  */
98 static kmutex_t evtchn_lock;
99 
100 /* event handlers */
101 struct evtsource *evtsource[NR_EVENT_CHANNELS];
102 
103 /* Reference counts for bindings to event channels XXX: redo for SMP */
104 static uint8_t evtch_bindcount[NR_EVENT_CHANNELS];
105 
106 /* event-channel <-> VCPU mapping for IPIs. XXX: redo for SMP. */
107 static evtchn_port_t vcpu_ipi_to_evtch[NBSD_XEN_MAX_VCPUS];
108 
109 /* event-channel <-> VCPU mapping for VIRQ_TIMER.  XXX: redo for SMP. */
110 static int virq_timer_to_evtch[NBSD_XEN_MAX_VCPUS];
111 
112 /* event-channel <-> VIRQ mapping. */
113 static int virq_to_evtch[NR_VIRQS];
114 
115 
116 #if defined(XENPV) && (NPCI > 0 || NISA > 0)
117 /* event-channel <-> PIRQ mapping */
118 static int pirq_to_evtch[NR_PIRQS];
119 /* PIRQ needing notify */
120 static int evtch_to_pirq_eoi[NR_EVENT_CHANNELS];
121 int pirq_interrupt(void *);
122 #endif /* defined(XENPV) && (NPCI > 0 || NISA > 0) */
123 
124 static void xen_evtchn_mask(struct pic *, int);
125 static void xen_evtchn_unmask(struct pic *, int);
126 static void xen_evtchn_addroute(struct pic *, struct cpu_info *, int, int, int);
127 static void xen_evtchn_delroute(struct pic *, struct cpu_info *, int, int, int);
128 static bool xen_evtchn_trymask(struct pic *, int);
129 static void xen_intr_get_devname(const char *, char *, size_t);
130 static void xen_intr_get_assigned(const char *, kcpuset_t *);
131 static uint64_t xen_intr_get_count(const char *, u_int);
132 
133 struct pic xen_pic = {
134           .pic_name = "xenev0",
135           .pic_type = PIC_XEN,
136           .pic_vecbase = 0,
137           .pic_apicid = 0,
138           .pic_lock = __SIMPLELOCK_UNLOCKED,
139           .pic_hwmask = xen_evtchn_mask,
140           .pic_hwunmask = xen_evtchn_unmask,
141           .pic_addroute = xen_evtchn_addroute,
142           .pic_delroute = xen_evtchn_delroute,
143           .pic_trymask = xen_evtchn_trymask,
144           .pic_level_stubs = xenev_stubs,
145           .pic_edge_stubs = xenev_stubs,
146           .pic_intr_get_devname = xen_intr_get_devname,
147           .pic_intr_get_assigned = xen_intr_get_assigned,
148           .pic_intr_get_count = xen_intr_get_count,
149 };
150 
151 /*
152  * We try to stick to the traditional x86 PIC semantics wrt Xen
153  * events.
154  *
155  * PIC pins exist in a global namespace which may be hierarchical, and
156  * are mapped to a cpu bus concept called 'IRQ' numbers, which are
157  * also global, but linear. Thus a PIC, pin tuple will always map to
158  * an IRQ number. These tuples can alias to the same IRQ number, thus
159  * causing IRQ "sharing". IRQ numbers can be bound to specific CPUs,
160  * and to specific callback vector indices on the CPU called idt_vec,
161  * which are aliases to handlers meant to run on destination
162  * CPUs. This binding can also happen at interrupt time and resolved
163  * 'round-robin' between all CPUs, depending on the lapic setup. In
164  * this case, all CPUs need to have identical idt_vec->handler
165  * mappings.
166  *
167  * The job of pic_addroute() is to setup the 'wiring' between the
168  * source pin, and the destination CPU handler, ideally on a specific
169  * CPU in MP systems (or 'round-robin').
170  *
171  * On Xen, a global namespace of 'events' exist, which are initially
172  * bound to nothing. This is similar to the relationship between
173  * realworld realworld IRQ numbers wrt PIC pins, since before routing,
174  * IRQ numbers by themselves have no causal connection setup with the
175  * real world. (Except for the hardwired cases on the PC Architecture,
176  * which we ignore for the purpose of this description). However the
177  * really important routing is from pin to idt_vec. On PIC_XEN, all
178  * three (pic, irq, idt_vec) belong to the same namespace and are
179  * identical. Further, the mapping between idt_vec and the actual
180  * callback handler is setup via calls to the evtchn.h api - this
181  * last bit is analogous to x86/idt.c:idt_vec_set() on real h/w
182  *
183  * For now we handle two cases:
184  * - IPC style events - eg: timer, PV devices, etc.
185  * - dom0 physical irq bound events.
186  *
187  * In the case of IPC style events, we currently externalise the
188  * event binding by using evtchn.h functions. From the POV of
189  * PIC_XEN ,  'pin' , 'irq' and 'idt_vec' are all identical to the
190  * port number of the event.
191  *
192  * In the case of dom0 physical irq bound events, we currently
193  * event binding by exporting evtchn.h functions. From the POV of
194  * PIC_LAPIC/PIC_IOAPIC, the 'pin' is the hardware pin, the 'irq' is
195  * the x86 global irq number  - the port number is extracted out of a
196  * global array (this is currently kludgy and breaks API abstraction)
197  * and the binding happens during pic_addroute() of the ioapic.
198  *
199  * Later when we integrate more tightly with x86/intr.c, we will be
200  * able to conform better to (PIC_LAPIC/PIC_IOAPIC)->PIC_XEN
201  * cascading model.
202  */
203 
204 int debug_port = -1;
205 
206 /* #define IRQ_DEBUG 4 */
207 
208 /* http://mail-index.netbsd.org/port-amd64/2004/02/22/0000.html */
209 #ifdef MULTIPROCESSOR
210 
211 /*
212  * intr_biglock_wrapper: grab biglock and call a real interrupt handler.
213  */
214 
215 int
xen_intr_biglock_wrapper(void * vp)216 xen_intr_biglock_wrapper(void *vp)
217 {
218           struct intrhand *ih = vp;
219           int ret;
220 
221           KERNEL_LOCK(1, NULL);
222 
223           ret = (*ih->ih_realfun)(ih->ih_realarg);
224 
225           KERNEL_UNLOCK_ONE(NULL);
226 
227           return ret;
228 }
229 #endif /* MULTIPROCESSOR */
230 
231 void
events_default_setup(void)232 events_default_setup(void)
233 {
234           int i;
235 
236           /* No VCPU -> event mappings. */
237           for (i = 0; i < NBSD_XEN_MAX_VCPUS; i++)
238                     vcpu_ipi_to_evtch[i] = -1;
239 
240           /* No VIRQ_TIMER -> event mappings. */
241           for (i = 0; i < NBSD_XEN_MAX_VCPUS; i++)
242                     virq_timer_to_evtch[i] = -1;
243 
244           /* No VIRQ -> event mappings. */
245           for (i = 0; i < NR_VIRQS; i++)
246                     virq_to_evtch[i] = -1;
247 
248 #if defined(XENPV) && (NPCI > 0 || NISA > 0)
249           /* No PIRQ -> event mappings. */
250           for (i = 0; i < NR_PIRQS; i++)
251                     pirq_to_evtch[i] = -1;
252           for (i = 0; i < NR_EVENT_CHANNELS; i++)
253                     evtch_to_pirq_eoi[i] = -1;
254 #endif /* defined(XENPV) && (NPCI > 0 || NISA > 0) */
255 
256           /* No event-channel are 'live' right now. */
257           for (i = 0; i < NR_EVENT_CHANNELS; i++) {
258                     evtsource[i] = NULL;
259                     evtch_bindcount[i] = 0;
260                     hypervisor_mask_event(i);
261           }
262 
263 }
264 
265 void
events_init(void)266 events_init(void)
267 {
268           mutex_init(&evtchn_lock, MUTEX_DEFAULT, IPL_NONE);
269 
270           (void)events_resume();
271 }
272 
273 bool
events_resume(void)274 events_resume(void)
275 {
276           debug_port = bind_virq_to_evtch(VIRQ_DEBUG);
277 
278           KASSERT(debug_port != -1);
279 
280           aprint_verbose("VIRQ_DEBUG interrupt using event channel %d\n",
281               debug_port);
282           /*
283            * Don't call event_set_handler(), we'll use a shortcut. Just set
284            * evtsource[] to a non-NULL value so that evtchn_do_event will
285            * be called.
286            */
287           evtsource[debug_port] = (void *)-1;
288           xen_atomic_set_bit(&curcpu()->ci_evtmask[0], debug_port);
289           hypervisor_unmask_event(debug_port);
290           x86_enable_intr();            /* at long last... */
291 
292           return true;
293 }
294 
295 bool
events_suspend(void)296 events_suspend(void)
297 {
298           int evtch;
299 
300           x86_disable_intr();
301 
302           /* VIRQ_DEBUG is the last interrupt to remove */
303           evtch = unbind_virq_from_evtch(VIRQ_DEBUG);
304 
305           KASSERT(evtch != -1);
306 
307           hypervisor_mask_event(evtch);
308           /* Remove the non-NULL value set in events_init() */
309           evtsource[evtch] = NULL;
310           aprint_verbose("VIRQ_DEBUG interrupt disabled, "
311               "event channel %d removed\n", evtch);
312 
313           return true;
314 }
315 
316 unsigned int
evtchn_do_event(int evtch,struct intrframe * regs)317 evtchn_do_event(int evtch, struct intrframe *regs)
318 {
319           struct cpu_info *ci;
320           int ilevel;
321           struct intrhand *ih;
322           int       (*ih_fun)(void *, void *);
323           uint64_t iplmask;
324 
325           KASSERTMSG(evtch >= 0, "negative evtch: %d", evtch);
326           KASSERTMSG(evtch < NR_EVENT_CHANNELS,
327               "evtch number %d > NR_EVENT_CHANNELS", evtch);
328 
329 #ifdef IRQ_DEBUG
330           if (evtch == IRQ_DEBUG)
331                     printf("evtchn_do_event: evtch %d\n", evtch);
332 #endif
333           ci = curcpu();
334 
335           /*
336            * Shortcut for the debug handler, we want it to always run,
337            * regardless of the IPL level.
338            */
339           if (__predict_false(evtch == debug_port)) {
340                     xen_debug_handler(NULL);
341                     hypervisor_unmask_event(debug_port);
342                     return 0;
343           }
344 
345           KASSERTMSG(evtsource[evtch] != NULL, "unknown event %d", evtch);
346 
347           if (evtsource[evtch]->ev_cpu != ci)
348                     return 0;
349 
350           ci->ci_data.cpu_nintr++;
351           evtsource[evtch]->ev_evcnt.ev_count++;
352           ilevel = ci->ci_ilevel;
353 
354           if (evtsource[evtch]->ev_maxlevel <= ilevel) {
355 #ifdef IRQ_DEBUG
356                     if (evtch == IRQ_DEBUG)
357                         printf("evtsource[%d]->ev_maxlevel %d <= ilevel %d\n",
358                         evtch, evtsource[evtch]->ev_maxlevel, ilevel);
359 #endif
360                     hypervisor_set_ipending(evtsource[evtch]->ev_imask,
361                                                   evtch >> LONG_SHIFT,
362                                                   evtch & LONG_MASK);
363                     ih = evtsource[evtch]->ev_handlers;
364                     while (ih != NULL) {
365                               ih->ih_pending++;
366                               ih = ih->ih_evt_next;
367                     }
368 
369                     /* leave masked */
370 
371                     return 0;
372           }
373           ci->ci_ilevel = evtsource[evtch]->ev_maxlevel;
374           iplmask = evtsource[evtch]->ev_imask;
375           KASSERT(ci->ci_ilevel >= IPL_VM);
376           KASSERT(cpu_intr_p());
377           x86_enable_intr();
378           ih = evtsource[evtch]->ev_handlers;
379           while (ih != NULL) {
380                     KASSERT(ih->ih_cpu == ci);
381 #if 0
382                     if (ih->ih_cpu != ci) {
383                               hypervisor_send_event(ih->ih_cpu, evtch);
384                               iplmask &= ~(1ULL << XEN_IPL2SIR(ih->ih_level));
385                               ih = ih->ih_evt_next;
386                               continue;
387                     }
388 #endif
389                     if (ih->ih_level <= ilevel) {
390 #ifdef IRQ_DEBUG
391                     if (evtch == IRQ_DEBUG)
392                         printf("ih->ih_level %d <= ilevel %d\n", ih->ih_level, ilevel);
393 #endif
394                               x86_disable_intr();
395                               hypervisor_set_ipending(iplmask,
396                                   evtch >> LONG_SHIFT, evtch & LONG_MASK);
397                               /* leave masked */
398                               while (ih != NULL) {
399                                         ih->ih_pending++;
400                                         ih = ih->ih_evt_next;
401                               }
402                               goto splx;
403                     }
404                     iplmask &= ~(1ULL << XEN_IPL2SIR(ih->ih_level));
405                     ci->ci_ilevel = ih->ih_level;
406                     ih->ih_pending = 0;
407                     ih_fun = (void *)ih->ih_fun;
408                     ih_fun(ih->ih_arg, regs);
409                     ih = ih->ih_evt_next;
410           }
411           x86_disable_intr();
412           hypervisor_unmask_event(evtch);
413 #if defined(XENPV) && (NPCI > 0 || NISA > 0)
414           hypervisor_ack_pirq_event(evtch);
415 #endif /* defined(XENPV) && (NPCI > 0 || NISA > 0) */
416 
417 splx:
418           ci->ci_ilevel = ilevel;
419           return 0;
420 }
421 
422 #define PRIuCPUID   "lu" /* XXX: move this somewhere more appropriate */
423 
424 /* PIC callbacks */
425 /* pic "pin"s are conceptually mapped to event port numbers */
426 static void
xen_evtchn_mask(struct pic * pic,int pin)427 xen_evtchn_mask(struct pic *pic, int pin)
428 {
429           evtchn_port_t evtchn = pin;
430 
431           KASSERT(pic->pic_type == PIC_XEN);
432           KASSERT(evtchn < NR_EVENT_CHANNELS);
433 
434           hypervisor_mask_event(evtchn);
435 }
436 
437 static void
xen_evtchn_unmask(struct pic * pic,int pin)438 xen_evtchn_unmask(struct pic *pic, int pin)
439 {
440           evtchn_port_t evtchn = pin;
441 
442           KASSERT(pic->pic_type == PIC_XEN);
443           KASSERT(evtchn < NR_EVENT_CHANNELS);
444 
445           hypervisor_unmask_event(evtchn);
446 
447 }
448 
449 
450 static void
xen_evtchn_addroute(struct pic * pic,struct cpu_info * ci,int pin,int idt_vec,int type)451 xen_evtchn_addroute(struct pic *pic, struct cpu_info *ci, int pin, int idt_vec, int type)
452 {
453 
454           evtchn_port_t evtchn = pin;
455 
456           /* Events are simulated as level triggered interrupts */
457           KASSERT(type == IST_LEVEL);
458 
459           KASSERT(evtchn < NR_EVENT_CHANNELS);
460 #if notyet
461           evtchn_port_t boundport = idt_vec;
462 #endif
463 
464           KASSERT(pic->pic_type == PIC_XEN);
465 
466           xen_atomic_set_bit(&ci->ci_evtmask[0], evtchn);
467 
468 }
469 
470 static void
xen_evtchn_delroute(struct pic * pic,struct cpu_info * ci,int pin,int idt_vec,int type)471 xen_evtchn_delroute(struct pic *pic, struct cpu_info *ci, int pin, int idt_vec, int type)
472 {
473           /*
474            * XXX: In the future, this is a great place to
475            * 'unbind' events to underlying events and cpus.
476            * For now, just disable interrupt servicing on this cpu for
477            * this pin aka cpu.
478            */
479           evtchn_port_t evtchn = pin;
480 
481           /* Events are simulated as level triggered interrupts */
482           KASSERT(type == IST_LEVEL);
483 
484           KASSERT(evtchn < NR_EVENT_CHANNELS);
485 #if notyet
486           evtchn_port_t boundport = idt_vec;
487 #endif
488 
489           KASSERT(pic->pic_type == PIC_XEN);
490 
491           xen_atomic_clear_bit(&ci->ci_evtmask[0], evtchn);
492 }
493 
494 /*
495  * xen_evtchn_trymask(pic, pin)
496  *
497  *        If there are interrupts pending on the bus-shared pic, return
498  *        false.  Otherwise, mask interrupts on the bus-shared pic and
499  *        return true.
500  */
501 static bool
xen_evtchn_trymask(struct pic * pic,int pin)502 xen_evtchn_trymask(struct pic *pic, int pin)
503 {
504           volatile struct shared_info *s = HYPERVISOR_shared_info;
505           unsigned long masked __diagused;
506 
507           /* Mask it.  */
508           masked = xen_atomic_test_and_set_bit(&s->evtchn_mask[0], pin);
509 
510           /*
511            * Caller is responsible for calling trymask only when the
512            * interrupt pin is not masked, and for serializing calls to
513            * trymask.
514            */
515           KASSERT(!masked);
516 
517           /*
518            * Check whether there were any interrupts pending when we
519            * masked it.  If there were, unmask and abort.
520            */
521           if (xen_atomic_test_bit(&s->evtchn_pending[0], pin)) {
522                     xen_atomic_clear_bit(&s->evtchn_mask[0], pin);
523                     return false;
524           }
525 
526           /* Success: masked, not pending.  */
527           return true;
528 }
529 
530 evtchn_port_t
bind_vcpu_to_evtch(cpuid_t vcpu)531 bind_vcpu_to_evtch(cpuid_t vcpu)
532 {
533           evtchn_op_t op;
534           evtchn_port_t evtchn;
535 
536           mutex_spin_enter(&evtchn_lock);
537 
538           evtchn = vcpu_ipi_to_evtch[vcpu];
539           if (evtchn == -1) {
540                     op.cmd = EVTCHNOP_bind_ipi;
541                     op.u.bind_ipi.vcpu = (uint32_t) vcpu;
542                     if (HYPERVISOR_event_channel_op(&op) != 0)
543                               panic("Failed to bind ipi to VCPU %"PRIuCPUID"\n", vcpu);
544                     evtchn = op.u.bind_ipi.port;
545 
546                     vcpu_ipi_to_evtch[vcpu] = evtchn;
547           }
548 
549           evtch_bindcount[evtchn]++;
550 
551           mutex_spin_exit(&evtchn_lock);
552 
553           return evtchn;
554 }
555 
556 int
bind_virq_to_evtch(int virq)557 bind_virq_to_evtch(int virq)
558 {
559           evtchn_op_t op;
560           int evtchn;
561 
562           mutex_spin_enter(&evtchn_lock);
563 
564           /*
565            * XXX: The only per-cpu VIRQ we currently use is VIRQ_TIMER.
566            * Please re-visit this implementation when others are used.
567            * Note: VIRQ_DEBUG is special-cased, and not used or bound on APs.
568            * XXX: event->virq/ipi can be unified in a linked-list
569            * implementation.
570            */
571           struct cpu_info *ci = curcpu();
572 
573           if (virq == VIRQ_DEBUG && ci != &cpu_info_primary) {
574                     mutex_spin_exit(&evtchn_lock);
575                     return -1;
576           }
577 
578           if (virq == VIRQ_TIMER) {
579                     evtchn = virq_timer_to_evtch[ci->ci_vcpuid];
580           } else {
581                     evtchn = virq_to_evtch[virq];
582           }
583 
584           /* Allocate a channel if there is none already allocated */
585           if (evtchn == -1) {
586                     op.cmd = EVTCHNOP_bind_virq;
587                     op.u.bind_virq.virq = virq;
588                     op.u.bind_virq.vcpu = ci->ci_vcpuid;
589                     if (HYPERVISOR_event_channel_op(&op) != 0)
590                               panic("Failed to bind virtual IRQ %d\n", virq);
591                     evtchn = op.u.bind_virq.port;
592           }
593 
594           /* Set event channel */
595           if (virq == VIRQ_TIMER) {
596                     virq_timer_to_evtch[ci->ci_vcpuid] = evtchn;
597           } else {
598                     virq_to_evtch[virq] = evtchn;
599           }
600 
601           /* Increase ref counter */
602           evtch_bindcount[evtchn]++;
603 
604           mutex_spin_exit(&evtchn_lock);
605 
606           return evtchn;
607 }
608 
609 int
unbind_virq_from_evtch(int virq)610 unbind_virq_from_evtch(int virq)
611 {
612           evtchn_op_t op;
613           int evtchn;
614 
615           struct cpu_info *ci = curcpu();
616 
617           if (virq == VIRQ_TIMER) {
618                     evtchn = virq_timer_to_evtch[ci->ci_vcpuid];
619           }
620           else {
621                     evtchn = virq_to_evtch[virq];
622           }
623 
624           if (evtchn == -1) {
625                     return -1;
626           }
627 
628           mutex_spin_enter(&evtchn_lock);
629 
630           evtch_bindcount[evtchn]--;
631           if (evtch_bindcount[evtchn] == 0) {
632                     op.cmd = EVTCHNOP_close;
633                     op.u.close.port = evtchn;
634                     if (HYPERVISOR_event_channel_op(&op) != 0)
635                               panic("Failed to unbind virtual IRQ %d\n", virq);
636 
637                     if (virq == VIRQ_TIMER) {
638                               virq_timer_to_evtch[ci->ci_vcpuid] = -1;
639                     } else {
640                               virq_to_evtch[virq] = -1;
641                     }
642           }
643 
644           mutex_spin_exit(&evtchn_lock);
645 
646           return evtchn;
647 }
648 
649 #if defined(XENPV) && (NPCI > 0 || NISA > 0)
650 int
get_pirq_to_evtch(int pirq)651 get_pirq_to_evtch(int pirq)
652 {
653           int evtchn;
654 
655           if (pirq == -1) /* Match previous behaviour */
656                     return -1;
657 
658           if (pirq >= NR_PIRQS) {
659                     panic("pirq %d out of bound, increase NR_PIRQS", pirq);
660           }
661           mutex_spin_enter(&evtchn_lock);
662 
663           evtchn = pirq_to_evtch[pirq];
664 
665           mutex_spin_exit(&evtchn_lock);
666 
667           return evtchn;
668 }
669 
670 int
bind_pirq_to_evtch(int pirq)671 bind_pirq_to_evtch(int pirq)
672 {
673           evtchn_op_t op;
674           int evtchn;
675 
676           if (pirq >= NR_PIRQS) {
677                     panic("pirq %d out of bound, increase NR_PIRQS", pirq);
678           }
679 
680           mutex_spin_enter(&evtchn_lock);
681 
682           evtchn = pirq_to_evtch[pirq];
683           if (evtchn == -1) {
684                     op.cmd = EVTCHNOP_bind_pirq;
685                     op.u.bind_pirq.pirq = pirq;
686                     op.u.bind_pirq.flags = BIND_PIRQ__WILL_SHARE;
687                     if (HYPERVISOR_event_channel_op(&op) != 0)
688                               panic("Failed to bind physical IRQ %d\n", pirq);
689                     evtchn = op.u.bind_pirq.port;
690 
691 #ifdef IRQ_DEBUG
692                     printf("pirq %d evtchn %d\n", pirq, evtchn);
693 #endif
694                     pirq_to_evtch[pirq] = evtchn;
695           }
696 
697           evtch_bindcount[evtchn]++;
698 
699           mutex_spin_exit(&evtchn_lock);
700 
701           return evtchn;
702 }
703 
704 int
unbind_pirq_from_evtch(int pirq)705 unbind_pirq_from_evtch(int pirq)
706 {
707           evtchn_op_t op;
708           int evtchn = pirq_to_evtch[pirq];
709 
710           mutex_spin_enter(&evtchn_lock);
711 
712           evtch_bindcount[evtchn]--;
713           if (evtch_bindcount[evtchn] == 0) {
714                     op.cmd = EVTCHNOP_close;
715                     op.u.close.port = evtchn;
716                     if (HYPERVISOR_event_channel_op(&op) != 0)
717                               panic("Failed to unbind physical IRQ %d\n", pirq);
718 
719                     pirq_to_evtch[pirq] = -1;
720           }
721 
722           mutex_spin_exit(&evtchn_lock);
723 
724           return evtchn;
725 }
726 
727 struct pintrhand *
pirq_establish(int pirq,int evtch,int (* func)(void *),void * arg,int level,const char * intrname,const char * xname,bool known_mpsafe)728 pirq_establish(int pirq, int evtch, int (*func)(void *), void *arg, int level,
729     const char *intrname, const char *xname, bool known_mpsafe)
730 {
731           struct pintrhand *ih;
732 
733           ih = kmem_zalloc(sizeof(struct pintrhand),
734               cold ? KM_NOSLEEP : KM_SLEEP);
735           if (ih == NULL) {
736                     printf("pirq_establish: can't allocate handler info\n");
737                     return NULL;
738           }
739 
740           KASSERT(evtch > 0);
741 
742           ih->pirq = pirq;
743           ih->evtch = evtch;
744           ih->func = func;
745           ih->arg = arg;
746 
747           if (event_set_handler(evtch, pirq_interrupt, ih, level, intrname,
748               xname, known_mpsafe, NULL) == NULL) {
749                     kmem_free(ih, sizeof(struct pintrhand));
750                     return NULL;
751           }
752 
753           hypervisor_prime_pirq_event(pirq, evtch);
754           hypervisor_unmask_event(evtch);
755           hypervisor_ack_pirq_event(evtch);
756           return ih;
757 }
758 
759 void
pirq_disestablish(struct pintrhand * ih)760 pirq_disestablish(struct pintrhand *ih)
761 {
762           int error = event_remove_handler(ih->evtch, pirq_interrupt, ih);
763           if (error) {
764                     printf("pirq_disestablish(%p): %d\n", ih, error);
765                     return;
766           }
767           kmem_free(ih, sizeof(struct pintrhand));
768 }
769 
770 int
pirq_interrupt(void * arg)771 pirq_interrupt(void *arg)
772 {
773           struct pintrhand *ih = arg;
774           int ret;
775 
776           ret = ih->func(ih->arg);
777 #ifdef IRQ_DEBUG
778           if (ih->evtch == IRQ_DEBUG)
779               printf("pirq_interrupt irq %d ret %d\n", ih->pirq, ret);
780 #endif
781           return ret;
782 }
783 
784 #endif /* defined(XENPV) && (NPCI > 0 || NISA > 0) */
785 
786 
787 /*
788  * Recalculate the interrupt from scratch for an event source.
789  */
790 static void
intr_calculatemasks(struct evtsource * evts,int evtch,struct cpu_info * ci)791 intr_calculatemasks(struct evtsource *evts, int evtch, struct cpu_info *ci)
792 {
793           struct intrhand *ih;
794           int cpu_receive = 0;
795 
796           evts->ev_maxlevel = IPL_NONE;
797           evts->ev_imask = 0;
798           for (ih = evts->ev_handlers; ih != NULL; ih = ih->ih_evt_next) {
799                     KASSERT(ih->ih_cpu == curcpu());
800                     if (ih->ih_level > evts->ev_maxlevel)
801                               evts->ev_maxlevel = ih->ih_level;
802                     evts->ev_imask |= (1 << XEN_IPL2SIR(ih->ih_level));
803                     if (ih->ih_cpu == ci)
804                               cpu_receive = 1;
805           }
806           if (cpu_receive)
807                     xen_atomic_set_bit(&curcpu()->ci_evtmask[0], evtch);
808           else
809                     xen_atomic_clear_bit(&curcpu()->ci_evtmask[0], evtch);
810 }
811 
812 
813 struct event_set_handler_args {
814           struct intrhand *ih;
815           struct intrsource *ipls;
816           struct evtsource *evts;
817           int evtch;
818 };
819 
820 /*
821  * Called on bound CPU to handle event_set_handler()
822  * caller (on initiating CPU) holds cpu_lock on our behalf
823  * arg1: struct event_set_handler_args *
824  * arg2: NULL
825  */
826 
827 static void
event_set_handler_xcall(void * arg1,void * arg2)828 event_set_handler_xcall(void *arg1, void *arg2)
829 {
830           struct event_set_handler_args *esh_args = arg1;
831           struct intrhand **ihp, *ih = esh_args->ih;
832           struct evtsource *evts = esh_args->evts;
833 
834           const u_long psl = x86_read_psl();
835           x86_disable_intr();
836           /* sort by IPL order, higher first */
837           for (ihp = &evts->ev_handlers; *ihp != NULL;
838               ihp = &((*ihp)->ih_evt_next)) {
839                     if ((*ihp)->ih_level < ih->ih_level)
840                               break;
841           }
842           /* insert before *ihp */
843           ih->ih_evt_next = *ihp;
844           *ihp = ih;
845 #ifndef XENPV
846           evts->ev_isl->is_handlers = evts->ev_handlers;
847 #endif
848           /* register per-cpu handler for spllower() */
849           struct cpu_info *ci = ih->ih_cpu;
850           int sir = XEN_IPL2SIR(ih->ih_level);
851           KASSERT(sir >= SIR_XENIPL_VM && sir <= SIR_XENIPL_HIGH);
852 
853           KASSERT(ci == curcpu());
854           if (ci->ci_isources[sir] == NULL) {
855                     KASSERT(esh_args->ipls != NULL);
856                     ci->ci_isources[sir] = esh_args->ipls;
857           }
858           struct intrsource *ipls = ci->ci_isources[sir];
859           ih->ih_next = ipls->is_handlers;
860           ipls->is_handlers = ih;
861           x86_intr_calculatemasks(ci);
862 
863           intr_calculatemasks(evts, esh_args->evtch, ci);
864           x86_write_psl(psl);
865 }
866 
867 struct intrhand *
event_set_handler(int evtch,int (* func)(void *),void * arg,int level,const char * intrname,const char * xname,bool mpsafe,struct cpu_info * ci)868 event_set_handler(int evtch, int (*func)(void *), void *arg, int level,
869     const char *intrname, const char *xname, bool mpsafe, struct cpu_info *ci)
870 {
871           struct event_set_handler_args esh_args;
872           char intrstr_buf[INTRIDBUF];
873           bool bind = false;
874 
875           memset(&esh_args, 0, sizeof(esh_args));
876 
877           /*
878            * if ci is not specified, we bind to the current cpu.
879            * if ci has been proviced by the called, we assume
880            * he will do the EVTCHNOP_bind_vcpu if needed.
881            */
882           if (ci == NULL) {
883                     ci = curcpu();
884                     bind = true;
885           }
886 
887 
888 #ifdef IRQ_DEBUG
889           printf("event_set_handler IRQ %d handler %p\n", evtch, func);
890 #endif
891 
892           KASSERTMSG(evtch >= 0, "negative evtch: %d", evtch);
893           KASSERTMSG(evtch < NR_EVENT_CHANNELS,
894               "evtch number %d > NR_EVENT_CHANNELS", evtch);
895           KASSERT(xname != NULL);
896 
897 #if 0
898           printf("event_set_handler evtch %d handler %p level %d\n", evtch,
899                  handler, level);
900 #endif
901           esh_args.ih = kmem_zalloc(sizeof (struct intrhand), KM_NOSLEEP);
902           if (esh_args.ih == NULL)
903                     panic("can't allocate fixed interrupt source");
904 
905 
906           esh_args.ih->ih_pic = &xen_pic;
907           esh_args.ih->ih_level = level;
908           esh_args.ih->ih_fun = esh_args.ih->ih_realfun = func;
909           esh_args.ih->ih_arg = esh_args.ih->ih_realarg = arg;
910           esh_args.ih->ih_evt_next = NULL;
911           esh_args.ih->ih_next = NULL;
912           esh_args.ih->ih_pending = 0;
913           esh_args.ih->ih_cpu = ci;
914           esh_args.ih->ih_pin = evtch;
915 #ifdef MULTIPROCESSOR
916           if (!mpsafe) {
917                     esh_args.ih->ih_fun = xen_intr_biglock_wrapper;
918                     esh_args.ih->ih_arg = esh_args.ih;
919           }
920 #endif /* MULTIPROCESSOR */
921           KASSERT(mpsafe || level < IPL_HIGH);
922 
923           mutex_enter(&cpu_lock);
924           /* allocate IPL source if needed */
925           int sir = XEN_IPL2SIR(level);
926           if (ci->ci_isources[sir] == NULL) {
927                     struct intrsource *ipls;
928                     ipls = kmem_zalloc(sizeof (struct intrsource), KM_NOSLEEP);
929                     if (ipls == NULL)
930                               panic("can't allocate fixed interrupt source");
931                     ipls->is_recurse = xenev_stubs[level - IPL_VM].ist_recurse;
932                     ipls->is_resume = xenev_stubs[level - IPL_VM].ist_resume;
933                     ipls->is_pic = &xen_pic;
934                     esh_args.ipls = ipls;
935                     /*
936                      * note that we can't set ci_isources here, as
937                      * the assembly can't handle is_handlers being NULL
938                      */
939           }
940           /* register handler for event channel */
941           if (evtsource[evtch] == NULL) {
942                     struct evtsource *evts;
943                     evtchn_op_t op;
944                     if (intrname == NULL)
945                               intrname = intr_create_intrid(-1, &xen_pic, evtch,
946                                   intrstr_buf, sizeof(intrstr_buf));
947                     evts = kmem_zalloc(sizeof (struct evtsource),
948                         KM_NOSLEEP);
949                     if (evts == NULL)
950                               panic("can't allocate fixed interrupt source");
951 
952                     evts->ev_cpu = ci;
953                     strlcpy(evts->ev_intrname, intrname, sizeof(evts->ev_intrname));
954 
955                     evcnt_attach_dynamic(&evts->ev_evcnt, EVCNT_TYPE_INTR, NULL,
956                         device_xname(ci->ci_dev), evts->ev_intrname);
957                     if (bind) {
958                               op.cmd = EVTCHNOP_bind_vcpu;
959                               op.u.bind_vcpu.port = evtch;
960                               op.u.bind_vcpu.vcpu = ci->ci_vcpuid;
961                               if (HYPERVISOR_event_channel_op(&op) != 0) {
962                                         panic("Failed to bind event %d to VCPU  %s %d",
963                                             evtch, device_xname(ci->ci_dev),
964                                             ci->ci_vcpuid);
965                               }
966                     }
967 #ifndef XENPV
968                     evts->ev_isl = intr_allocate_io_intrsource(intrname);
969                     evts->ev_isl->is_pic = &xen_pic;
970 #endif
971                     evtsource[evtch] = evts;
972           }
973           esh_args.evts = evtsource[evtch];
974 
975           // append device name
976           if (esh_args.evts->ev_xname[0] != '\0') {
977                     strlcat(esh_args.evts->ev_xname, ", ",
978                         sizeof(esh_args.evts->ev_xname));
979           }
980           strlcat(esh_args.evts->ev_xname, xname,
981               sizeof(esh_args.evts->ev_xname));
982 
983           esh_args.evtch = evtch;
984 
985           if (ci == curcpu() || !mp_online) {
986                     event_set_handler_xcall(&esh_args, NULL);
987           } else {
988                     uint64_t where = xc_unicast(0, event_set_handler_xcall,
989                         &esh_args, NULL, ci);
990                     xc_wait(where);
991           }
992 
993           mutex_exit(&cpu_lock);
994           return esh_args.ih;
995 }
996 
997 /*
998  * Called on bound CPU to handle event_remove_handler()
999  * caller (on initiating CPU) holds cpu_lock on our behalf
1000  * arg1: evtch
1001  * arg2: struct intrhand *ih
1002  */
1003 
1004 static void
event_remove_handler_xcall(void * arg1,void * arg2)1005 event_remove_handler_xcall(void *arg1, void *arg2)
1006 {
1007           struct intrsource *ipls;
1008           struct evtsource *evts;
1009           struct intrhand **ihp;
1010           struct cpu_info *ci;
1011           struct intrhand *ih = arg2;
1012           int evtch = (intptr_t)(arg1);
1013 
1014           evts = evtsource[evtch];
1015           KASSERT(evts != NULL);
1016           KASSERT(ih != NULL);
1017           ci = ih->ih_cpu;
1018           KASSERT(ci == curcpu());
1019 
1020           const u_long psl = x86_read_psl();
1021           x86_disable_intr();
1022 
1023           for (ihp = &evts->ev_handlers; *ihp != NULL;
1024               ihp = &(*ihp)->ih_evt_next) {
1025                     if ((*ihp) == ih)
1026                               break;
1027           }
1028           if (*(ihp) == NULL) {
1029                     panic("event_remove_handler_xcall: not in ev_handlers");
1030           }
1031 
1032           *ihp = ih->ih_evt_next;
1033 
1034           int sir = XEN_IPL2SIR(ih->ih_level);
1035           KASSERT(sir >= SIR_XENIPL_VM && sir <= SIR_XENIPL_HIGH);
1036           ipls = ci->ci_isources[sir];
1037           for (ihp = &ipls->is_handlers; *ihp != NULL; ihp = &(*ihp)->ih_next) {
1038                     if (*ihp == ih)
1039                               break;
1040           }
1041           if (*ihp == NULL)
1042                     panic("event_remove_handler_xcall: not in is_handlers");
1043           *ihp = ih->ih_next;
1044           intr_calculatemasks(evts, evtch, ci);
1045 #ifndef XENPV
1046           evts->ev_isl->is_handlers = evts->ev_handlers;
1047 #endif
1048           if (evts->ev_handlers == NULL)
1049                     xen_atomic_clear_bit(&ci->ci_evtmask[0], evtch);
1050 
1051           x86_write_psl(psl);
1052 }
1053 
1054 int
event_remove_handler(int evtch,int (* func)(void *),void * arg)1055 event_remove_handler(int evtch, int (*func)(void *), void *arg)
1056 {
1057           struct intrhand *ih;
1058           struct cpu_info *ci;
1059           struct evtsource *evts;
1060 
1061           mutex_enter(&cpu_lock);
1062           evts = evtsource[evtch];
1063           if (evts == NULL)
1064                     return ENOENT;
1065 
1066           for (ih = evts->ev_handlers; ih != NULL; ih = ih->ih_evt_next) {
1067                     if (ih->ih_realfun == func && ih->ih_realarg == arg)
1068                               break;
1069           }
1070           if (ih == NULL) {
1071                     mutex_exit(&cpu_lock);
1072                     return ENOENT;
1073           }
1074           ci = ih->ih_cpu;
1075 
1076           if (ci == curcpu() || !mp_online) {
1077                     event_remove_handler_xcall((void *)(intptr_t)evtch, ih);
1078           } else {
1079                     uint64_t where = xc_unicast(0, event_remove_handler_xcall,
1080                         (void *)(intptr_t)evtch, ih, ci);
1081                     xc_wait(where);
1082           }
1083 
1084           kmem_free(ih, sizeof (struct intrhand));
1085           if (evts->ev_handlers == NULL) {
1086 #ifndef XENPV
1087                     KASSERT(evts->ev_isl->is_handlers == NULL);
1088                     intr_free_io_intrsource(evts->ev_intrname);
1089 #endif
1090                     evcnt_detach(&evts->ev_evcnt);
1091                     kmem_free(evts, sizeof (struct evtsource));
1092                     evtsource[evtch] = NULL;
1093           }
1094           mutex_exit(&cpu_lock);
1095           return 0;
1096 }
1097 
1098 #if defined(XENPV) && (NPCI > 0 || NISA > 0)
1099 void
hypervisor_prime_pirq_event(int pirq,unsigned int evtch)1100 hypervisor_prime_pirq_event(int pirq, unsigned int evtch)
1101 {
1102           struct physdev_irq_status_query irq_status;
1103           irq_status.irq = pirq;
1104           if (HYPERVISOR_physdev_op(PHYSDEVOP_irq_status_query, &irq_status) < 0)
1105                     panic("HYPERVISOR_physdev_op(PHYSDEVOP_IRQ_STATUS_QUERY)");
1106           if (irq_status.flags & XENIRQSTAT_needs_eoi) {
1107                     evtch_to_pirq_eoi[evtch] = pirq;
1108 #ifdef IRQ_DEBUG
1109                     printf("pirq %d needs notify\n", pirq);
1110 #endif
1111           }
1112 }
1113 
1114 void
hypervisor_ack_pirq_event(unsigned int evtch)1115 hypervisor_ack_pirq_event(unsigned int evtch)
1116 {
1117 #ifdef IRQ_DEBUG
1118           if (evtch == IRQ_DEBUG)
1119                     printf("%s: evtch %d\n", __func__, evtch);
1120 #endif
1121 
1122           if (evtch_to_pirq_eoi[evtch] > 0) {
1123                     struct physdev_eoi eoi;
1124                     eoi.irq = evtch_to_pirq_eoi[evtch];
1125 #ifdef  IRQ_DEBUG
1126                     if (evtch == IRQ_DEBUG)
1127                         printf("pirq_notify(%d)\n", evtch);
1128 #endif
1129                     (void)HYPERVISOR_physdev_op(PHYSDEVOP_eoi, &eoi);
1130           }
1131 }
1132 #endif /* defined(XENPV) && (NPCI > 0 || NISA > 0) */
1133 
1134 int
xen_debug_handler(void * arg)1135 xen_debug_handler(void *arg)
1136 {
1137           struct cpu_info *ci = curcpu();
1138           int i;
1139           int xci_ilevel = ci->ci_ilevel;
1140           int xci_ipending = ci->ci_ipending;
1141           int xci_idepth = ci->ci_idepth;
1142           u_long upcall_pending = ci->ci_vcpu->evtchn_upcall_pending;
1143           u_long upcall_mask = ci->ci_vcpu->evtchn_upcall_mask;
1144           u_long pending_sel = ci->ci_vcpu->evtchn_pending_sel;
1145           unsigned long evtchn_mask[sizeof(unsigned long) * 8];
1146           unsigned long evtchn_pending[sizeof(unsigned long) * 8];
1147 
1148           u_long p;
1149 
1150           p = (u_long)&HYPERVISOR_shared_info->evtchn_mask[0];
1151           memcpy(evtchn_mask, (void *)p, sizeof(evtchn_mask));
1152           p = (u_long)&HYPERVISOR_shared_info->evtchn_pending[0];
1153           memcpy(evtchn_pending, (void *)p, sizeof(evtchn_pending));
1154 
1155           __insn_barrier();
1156           printf("debug event\n");
1157           printf("ci_ilevel 0x%x ci_ipending 0x%x ci_idepth %d\n",
1158               xci_ilevel, xci_ipending, xci_idepth);
1159           printf("evtchn_upcall_pending %ld evtchn_upcall_mask %ld"
1160               " evtchn_pending_sel 0x%lx\n",
1161                     upcall_pending, upcall_mask, pending_sel);
1162           printf("evtchn_mask");
1163           for (i = 0 ; i <= LONG_MASK; i++)
1164                     printf(" %lx", (u_long)evtchn_mask[i]);
1165           printf("\n");
1166           printf("evtchn_pending");
1167           for (i = 0 ; i <= LONG_MASK; i++)
1168                     printf(" %lx", (u_long)evtchn_pending[i]);
1169           printf("\n");
1170           return 0;
1171 }
1172 
1173 static struct evtsource *
event_get_handler(const char * intrid)1174 event_get_handler(const char *intrid)
1175 {
1176           for (int i = 0; i < NR_EVENT_CHANNELS; i++) {
1177                     if (evtsource[i] == NULL || i == debug_port)
1178                               continue;
1179 
1180                     struct evtsource *evp = evtsource[i];
1181 
1182                     if (strcmp(evp->ev_intrname, intrid) == 0)
1183                               return evp;
1184           }
1185 
1186           return NULL;
1187 }
1188 
1189 static uint64_t
xen_intr_get_count(const char * intrid,u_int cpu_idx)1190 xen_intr_get_count(const char *intrid, u_int cpu_idx)
1191 {
1192           int count = 0;
1193           struct evtsource *evp;
1194 
1195           mutex_spin_enter(&evtchn_lock);
1196 
1197           evp = event_get_handler(intrid);
1198           if (evp != NULL && cpu_idx == cpu_index(evp->ev_cpu))
1199                     count = evp->ev_evcnt.ev_count;
1200 
1201           mutex_spin_exit(&evtchn_lock);
1202 
1203           return count;
1204 }
1205 
1206 static void
xen_intr_get_assigned(const char * intrid,kcpuset_t * cpuset)1207 xen_intr_get_assigned(const char *intrid, kcpuset_t *cpuset)
1208 {
1209           struct evtsource *evp;
1210 
1211           kcpuset_zero(cpuset);
1212 
1213           mutex_spin_enter(&evtchn_lock);
1214 
1215           evp = event_get_handler(intrid);
1216           if (evp != NULL)
1217                     kcpuset_set(cpuset, cpu_index(evp->ev_cpu));
1218 
1219           mutex_spin_exit(&evtchn_lock);
1220 }
1221 
1222 static void
xen_intr_get_devname(const char * intrid,char * buf,size_t len)1223 xen_intr_get_devname(const char *intrid, char *buf, size_t len)
1224 {
1225           struct evtsource *evp;
1226 
1227           mutex_spin_enter(&evtchn_lock);
1228 
1229           evp = event_get_handler(intrid);
1230           strlcpy(buf, evp ? evp->ev_xname : "unknown", len);
1231 
1232           mutex_spin_exit(&evtchn_lock);
1233 }
1234 
1235 #ifdef XENPV
1236 /*
1237  * MI interface for subr_interrupt.
1238  */
1239 struct intrids_handler *
interrupt_construct_intrids(const kcpuset_t * cpuset)1240 interrupt_construct_intrids(const kcpuset_t *cpuset)
1241 {
1242           struct intrids_handler *ii_handler;
1243           intrid_t *ids;
1244           int i, count, off;
1245           struct evtsource *evp;
1246 
1247           if (kcpuset_iszero(cpuset))
1248                     return 0;
1249 
1250           /*
1251            * Count the number of interrupts which affinity to any cpu of "cpuset".
1252            */
1253           count = 0;
1254           for (i = 0; i < NR_EVENT_CHANNELS; i++) {
1255                     evp = evtsource[i];
1256 
1257                     if (evp == NULL || i == debug_port)
1258                               continue;
1259 
1260                     if (!kcpuset_isset(cpuset, cpu_index(evp->ev_cpu)))
1261                               continue;
1262 
1263                     count++;
1264           }
1265 
1266           ii_handler = kmem_zalloc(sizeof(int) + sizeof(intrid_t) * count,
1267               KM_SLEEP);
1268           if (ii_handler == NULL)
1269                     return NULL;
1270           ii_handler->iih_nids = count;
1271           if (count == 0)
1272                     return ii_handler;
1273 
1274           ids = ii_handler->iih_intrids;
1275           mutex_spin_enter(&evtchn_lock);
1276           for (i = 0, off = 0; i < NR_EVENT_CHANNELS && off < count; i++) {
1277                     evp = evtsource[i];
1278 
1279                     if (evp == NULL || i == debug_port)
1280                               continue;
1281 
1282                     if (!kcpuset_isset(cpuset, cpu_index(evp->ev_cpu)))
1283                               continue;
1284 
1285                     snprintf(ids[off], sizeof(intrid_t), "%s", evp->ev_intrname);
1286                     off++;
1287           }
1288           mutex_spin_exit(&evtchn_lock);
1289           return ii_handler;
1290 }
1291 __strong_alias(interrupt_get_count, xen_intr_get_count);
1292 __strong_alias(interrupt_get_assigned, xen_intr_get_assigned);
1293 __strong_alias(interrupt_get_devname, xen_intr_get_devname);
1294 __strong_alias(x86_intr_get_count, xen_intr_get_count);
1295 __strong_alias(x86_intr_get_assigned, xen_intr_get_assigned);
1296 __strong_alias(x86_intr_get_devname, xen_intr_get_devname);
1297 #endif /* XENPV */
1298