Annotation of src/sys/arch/xen/xen/evtchn.c, Revision 1.26
1.26 ! bouyer 1: /* $NetBSD: evtchn.c,v 1.25 2007/12/03 15:34:29 ad Exp $ */
1.18 bouyer 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: * 3. All advertising materials mentioning features or use of this software
15: * must display the following acknowledgement:
16: * This product includes software developed by Manuel Bouyer.
17: * 4. The name of the author may not be used to endorse or promote products
18: * derived from this software without specific prior written permission.
19: *
20: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30: *
31: */
1.2 bouyer 32:
33: /*
34: *
35: * Copyright (c) 2004 Christian Limpach.
36: * Copyright (c) 2004, K A Fraser.
37: * All rights reserved.
38: *
39: * Redistribution and use in source and binary forms, with or without
40: * modification, are permitted provided that the following conditions
41: * are met:
42: * 1. Redistributions of source code must retain the above copyright
43: * notice, this list of conditions and the following disclaimer.
44: * 2. Redistributions in binary form must reproduce the above copyright
45: * notice, this list of conditions and the following disclaimer in the
46: * documentation and/or other materials provided with the distribution.
47: * 3. All advertising materials mentioning features or use of this software
48: * must display the following acknowledgement:
49: * This product includes software developed by Christian Limpach.
50: * 4. The name of the author may not be used to endorse or promote products
51: * derived from this software without specific prior written permission.
52: *
53: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
54: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
55: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
56: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
57: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
58: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
59: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
60: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
61: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
62: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
63: */
64:
65:
66: #include <sys/cdefs.h>
1.26 ! bouyer 67: __KERNEL_RCSID(0, "$NetBSD: evtchn.c,v 1.25 2007/12/03 15:34:29 ad Exp $");
1.18 bouyer 68:
69: #include "opt_xen.h"
70: #include "isa.h"
71: #include "pci.h"
1.2 bouyer 72:
73: #include <sys/param.h>
74: #include <sys/kernel.h>
75: #include <sys/systm.h>
76: #include <sys/proc.h>
77: #include <sys/malloc.h>
78: #include <sys/reboot.h>
79:
80: #include <uvm/uvm.h>
81:
82: #include <machine/intrdefs.h>
83:
1.24 bouyer 84: #include <xen/xen.h>
85: #include <xen/hypervisor.h>
86: #include <xen/evtchn.h>
1.18 bouyer 87: #ifndef XEN3
1.24 bouyer 88: #include <xen/ctrl_if.h>
1.18 bouyer 89: #endif
1.24 bouyer 90: #include <xen/xenfunc.h>
1.2 bouyer 91:
92: /*
93: * This lock protects updates to the following mapping and reference-count
94: * arrays. The lock does not need to be acquired to read the mapping tables.
95: */
96: static struct simplelock irq_mapping_update_lock = SIMPLELOCK_INITIALIZER;
97:
1.5 bouyer 98: /* event handlers */
99: struct evtsource *evtsource[NR_EVENT_CHANNELS];
100:
101: /* Reference counts for bindings to event channels */
102: static u_int8_t evtch_bindcount[NR_EVENT_CHANNELS];
1.2 bouyer 103:
1.5 bouyer 104: /* event-channel <-> VIRQ mapping. */
105: static int virq_to_evtch[NR_VIRQS];
1.2 bouyer 106:
107:
1.16 bouyer 108: #if NPCI > 0 || NISA > 0
1.5 bouyer 109: /* event-channel <-> PIRQ mapping */
110: static int pirq_to_evtch[NR_PIRQS];
1.2 bouyer 111: /* PIRQ needing notify */
1.5 bouyer 112: static u_int32_t pirq_needs_unmask_notify[NR_EVENT_CHANNELS / 32];
1.2 bouyer 113: int pirq_interrupt(void *);
114: physdev_op_t physdev_op_notify = {
115: .cmd = PHYSDEVOP_IRQ_UNMASK_NOTIFY,
116: };
117: #endif
118:
1.5 bouyer 119: int debug_port;
1.18 bouyer 120: #ifndef XEN3
1.2 bouyer 121: static int xen_misdirect_handler(void *);
1.18 bouyer 122: #endif
1.2 bouyer 123:
1.18 bouyer 124: // #define IRQ_DEBUG 4
1.2 bouyer 125:
126: void
127: events_default_setup()
128: {
129: int i;
130:
1.5 bouyer 131: /* No VIRQ -> event mappings. */
1.2 bouyer 132: for (i = 0; i < NR_VIRQS; i++)
1.5 bouyer 133: virq_to_evtch[i] = -1;
1.2 bouyer 134:
1.16 bouyer 135: #if NPCI > 0 || NISA > 0
1.5 bouyer 136: /* No PIRQ -> event mappings. */
1.2 bouyer 137: for (i = 0; i < NR_PIRQS; i++)
1.5 bouyer 138: pirq_to_evtch[i] = -1;
139: for (i = 0; i < NR_EVENT_CHANNELS / 32; i++)
140: pirq_needs_unmask_notify[i] = 0;
1.2 bouyer 141: #endif
142:
1.5 bouyer 143: /* No event-channel are 'live' right now. */
1.2 bouyer 144: for (i = 0; i < NR_EVENT_CHANNELS; i++) {
1.5 bouyer 145: evtsource[i] = NULL;
146: evtch_bindcount[i] = 0;
147: hypervisor_mask_event(i);
1.2 bouyer 148: }
149:
150: }
151:
152: void
153: init_events()
154: {
1.26 ! bouyer 155: #ifndef XEN3
1.5 bouyer 156: int evtch;
157:
1.26 ! bouyer 158: /* no debug port, it doesn't work any more for some reason ... */
! 159: debug_port = -1;
! 160:
1.5 bouyer 161: evtch = bind_virq_to_evtch(VIRQ_MISDIRECT);
1.12 xtraeme 162: aprint_verbose("misdirect virtual interrupt using event channel %d\n",
1.5 bouyer 163: evtch);
1.25 ad 164: event_set_handler(evtch, &xen_misdirect_handler, NULL, IPL_HIGH,
1.7 bouyer 165: "misdirev");
1.5 bouyer 166: hypervisor_enable_event(evtch);
1.2 bouyer 167:
168: /* This needs to be done early, but after the IRQ subsystem is
169: * alive. */
170: ctrl_if_init();
1.18 bouyer 171: #endif
1.26 ! bouyer 172: debug_port = bind_virq_to_evtch(VIRQ_DEBUG);
! 173: aprint_verbose("debug virtual interrupt using event channel %d\n",
! 174: debug_port);
! 175: /*
! 176: * Don't call event_set_handler(), we'll use a shortcut. Just set
! 177: * evtsource[] to a non-NULL value so that evtchn_do_event will
! 178: * be called.
! 179: */
! 180: evtsource[debug_port] = (void *)-1;
! 181: hypervisor_enable_event(debug_port);
1.2 bouyer 182:
1.22 ad 183: x86_enable_intr(); /* at long last... */
1.2 bouyer 184: }
185:
186: unsigned int
1.14 yamt 187: evtchn_do_event(int evtch, struct intrframe *regs)
1.2 bouyer 188: {
189: struct cpu_info *ci;
190: int ilevel;
191: struct intrhand *ih;
192: int (*ih_fun)(void *, void *);
193: extern struct uvmexp uvmexp;
1.13 bouyer 194: u_int32_t iplmask;
1.2 bouyer 195:
196: #ifdef DIAGNOSTIC
1.5 bouyer 197: if (evtch >= NR_EVENT_CHANNELS) {
198: printf("event number %d > NR_IRQS\n", evtch);
1.14 yamt 199: panic("evtchn_do_event");
1.5 bouyer 200: }
1.2 bouyer 201: #endif
202:
203: #ifdef IRQ_DEBUG
1.5 bouyer 204: if (evtch == IRQ_DEBUG)
1.14 yamt 205: printf("evtchn_do_event: evtch %d\n", evtch);
1.2 bouyer 206: #endif
1.5 bouyer 207: ci = &cpu_info_primary;
1.2 bouyer 208:
1.5 bouyer 209: /*
210: * Shortcut for the debug handler, we want it to always run,
211: * regardless of the IPL level.
212: */
213: if (evtch == debug_port) {
214: xen_debug_handler(NULL);
215: hypervisor_enable_event(evtch);
1.2 bouyer 216: return 0;
217: }
1.5 bouyer 218:
219: #ifdef DIAGNOSTIC
220: if (evtsource[evtch] == NULL) {
1.14 yamt 221: panic("evtchn_do_event: unknown event");
1.5 bouyer 222: }
223: #endif
1.3 bouyer 224: uvmexp.intrs++;
1.5 bouyer 225: evtsource[evtch]->ev_evcnt.ev_count++;
1.2 bouyer 226: ilevel = ci->ci_ilevel;
1.5 bouyer 227: if (evtsource[evtch]->ev_maxlevel <= ilevel) {
1.2 bouyer 228: #ifdef IRQ_DEBUG
1.8 yamt 229: if (evtch == IRQ_DEBUG)
1.5 bouyer 230: printf("evtsource[%d]->ev_maxlevel %d <= ilevel %d\n",
231: evtch, evtsource[evtch]->ev_maxlevel, ilevel);
1.2 bouyer 232: #endif
1.13 bouyer 233: hypervisor_set_ipending(evtsource[evtch]->ev_imask,
234: evtch / 32, evtch % 32);
1.2 bouyer 235: /* leave masked */
236: return 0;
237: }
1.5 bouyer 238: ci->ci_ilevel = evtsource[evtch]->ev_maxlevel;
1.13 bouyer 239: iplmask = evtsource[evtch]->ev_imask;
1.15 yamt 240: sti();
1.2 bouyer 241: #ifdef MULTIPROCESSOR
242: x86_intlock(regs);
243: #endif
1.5 bouyer 244: ih = evtsource[evtch]->ev_handlers;
1.2 bouyer 245: while (ih != NULL) {
246: if (ih->ih_level <= ilevel) {
247: #ifdef IRQ_DEBUG
1.5 bouyer 248: if (evtch == IRQ_DEBUG)
1.2 bouyer 249: printf("ih->ih_level %d <= ilevel %d\n", ih->ih_level, ilevel);
250: #endif
251: #ifdef MULTIPROCESSOR
252: x86_intunlock(regs);
253: #endif
1.15 yamt 254: cli();
1.13 bouyer 255: hypervisor_set_ipending(iplmask,
256: evtch / 32, evtch % 32);
1.2 bouyer 257: /* leave masked */
258: splx(ilevel);
259: return 0;
260: }
1.13 bouyer 261: iplmask &= ~IUNMASK(ci, ih->ih_level);
1.2 bouyer 262: ci->ci_ilevel = ih->ih_level;
263: ih_fun = (void *)ih->ih_fun;
264: ih_fun(ih->ih_arg, regs);
1.5 bouyer 265: ih = ih->ih_evt_next;
1.2 bouyer 266: }
1.15 yamt 267: cli();
1.2 bouyer 268: #ifdef MULTIPROCESSOR
269: x86_intunlock(regs);
270: #endif
1.5 bouyer 271: hypervisor_enable_event(evtch);
1.2 bouyer 272: splx(ilevel);
273:
274: return 0;
275: }
276:
277: int
1.5 bouyer 278: bind_virq_to_evtch(int virq)
1.2 bouyer 279: {
280: evtchn_op_t op;
1.5 bouyer 281: int evtchn, s;
1.2 bouyer 282:
1.4 bouyer 283: s = splhigh();
1.2 bouyer 284: simple_lock(&irq_mapping_update_lock);
285:
1.5 bouyer 286: evtchn = virq_to_evtch[virq];
287: if (evtchn == -1) {
1.2 bouyer 288: op.cmd = EVTCHNOP_bind_virq;
289: op.u.bind_virq.virq = virq;
1.18 bouyer 290: #ifdef XEN3
291: op.u.bind_virq.vcpu = 0;
292: #endif
1.2 bouyer 293: if (HYPERVISOR_event_channel_op(&op) != 0)
294: panic("Failed to bind virtual IRQ %d\n", virq);
295: evtchn = op.u.bind_virq.port;
296:
1.5 bouyer 297: virq_to_evtch[virq] = evtchn;
1.2 bouyer 298: }
299:
1.5 bouyer 300: evtch_bindcount[evtchn]++;
1.2 bouyer 301:
302: simple_unlock(&irq_mapping_update_lock);
1.4 bouyer 303: splx(s);
1.2 bouyer 304:
1.5 bouyer 305: return evtchn;
1.2 bouyer 306: }
307:
308: void
1.5 bouyer 309: unbind_virq_from_evtch(int virq)
1.2 bouyer 310: {
311: evtchn_op_t op;
1.5 bouyer 312: int evtchn = virq_to_evtch[virq];
1.4 bouyer 313: int s = splhigh();
1.2 bouyer 314:
315: simple_lock(&irq_mapping_update_lock);
316:
1.5 bouyer 317: evtch_bindcount[evtchn]--;
318: if (evtch_bindcount[evtchn] == 0) {
1.2 bouyer 319: op.cmd = EVTCHNOP_close;
1.18 bouyer 320: #ifndef XEN3
1.2 bouyer 321: op.u.close.dom = DOMID_SELF;
1.18 bouyer 322: #endif
1.2 bouyer 323: op.u.close.port = evtchn;
324: if (HYPERVISOR_event_channel_op(&op) != 0)
325: panic("Failed to unbind virtual IRQ %d\n", virq);
326:
1.5 bouyer 327: virq_to_evtch[virq] = -1;
1.2 bouyer 328: }
329:
330: simple_unlock(&irq_mapping_update_lock);
1.4 bouyer 331: splx(s);
1.2 bouyer 332: }
333:
1.16 bouyer 334: #if NPCI > 0 || NISA > 0
1.2 bouyer 335: int
1.5 bouyer 336: bind_pirq_to_evtch(int pirq)
1.2 bouyer 337: {
338: evtchn_op_t op;
1.5 bouyer 339: int evtchn, s;
1.2 bouyer 340:
341: if (pirq >= NR_PIRQS) {
342: panic("pirq %d out of bound, increase NR_PIRQS", pirq);
343: }
1.4 bouyer 344:
345: s = splhigh();
1.2 bouyer 346: simple_lock(&irq_mapping_update_lock);
347:
1.5 bouyer 348: evtchn = pirq_to_evtch[pirq];
349: if (evtchn == -1) {
1.2 bouyer 350: op.cmd = EVTCHNOP_bind_pirq;
351: op.u.bind_pirq.pirq = pirq;
352: op.u.bind_pirq.flags = BIND_PIRQ__WILL_SHARE;
353: if (HYPERVISOR_event_channel_op(&op) != 0)
354: panic("Failed to bind physical IRQ %d\n", pirq);
355: evtchn = op.u.bind_pirq.port;
356:
357: #ifdef IRQ_DEBUG
1.8 yamt 358: printf("pirq %d evtchn %d\n", pirq, evtchn);
1.2 bouyer 359: #endif
1.5 bouyer 360: pirq_to_evtch[pirq] = evtchn;
1.2 bouyer 361: }
362:
1.5 bouyer 363: evtch_bindcount[evtchn]++;
1.2 bouyer 364:
365: simple_unlock(&irq_mapping_update_lock);
1.4 bouyer 366: splx(s);
1.2 bouyer 367:
1.5 bouyer 368: return evtchn;
1.2 bouyer 369: }
370:
371: void
1.5 bouyer 372: unbind_pirq_from_evtch(int pirq)
1.2 bouyer 373: {
374: evtchn_op_t op;
1.5 bouyer 375: int evtchn = pirq_to_evtch[pirq];
1.4 bouyer 376: int s = splhigh();
1.2 bouyer 377:
378: simple_lock(&irq_mapping_update_lock);
379:
1.5 bouyer 380: evtch_bindcount[evtchn]--;
381: if (evtch_bindcount[evtchn] == 0) {
1.2 bouyer 382: op.cmd = EVTCHNOP_close;
1.18 bouyer 383: #ifndef XEN3
1.2 bouyer 384: op.u.close.dom = DOMID_SELF;
1.18 bouyer 385: #endif
1.2 bouyer 386: op.u.close.port = evtchn;
387: if (HYPERVISOR_event_channel_op(&op) != 0)
388: panic("Failed to unbind physical IRQ %d\n", pirq);
389:
1.5 bouyer 390: pirq_to_evtch[pirq] = -1;
1.2 bouyer 391: }
392:
393: simple_unlock(&irq_mapping_update_lock);
1.4 bouyer 394: splx(s);
1.2 bouyer 395: }
396:
397: struct pintrhand *
1.19 bouyer 398: pirq_establish(int pirq, int evtch, int (*func)(void *), void *arg, int level,
399: const char *evname)
1.2 bouyer 400: {
401: struct pintrhand *ih;
402: physdev_op_t physdev_op;
403:
404: ih = malloc(sizeof *ih, M_DEVBUF, cold ? M_NOWAIT : M_WAITOK);
405: if (ih == NULL) {
406: printf("pirq_establish: can't malloc handler info\n");
407: return NULL;
408: }
1.7 bouyer 409: if (event_set_handler(evtch, pirq_interrupt, ih, level, evname) != 0) {
1.2 bouyer 410: free(ih, M_DEVBUF);
411: return NULL;
412: }
413: ih->pirq = pirq;
1.5 bouyer 414: ih->evtch = evtch;
1.2 bouyer 415: ih->func = func;
416: ih->arg = arg;
417:
418: physdev_op.cmd = PHYSDEVOP_IRQ_STATUS_QUERY;
419: physdev_op.u.irq_status_query.irq = pirq;
420: if (HYPERVISOR_physdev_op(&physdev_op) < 0)
421: panic("HYPERVISOR_physdev_op(PHYSDEVOP_IRQ_STATUS_QUERY)");
422: if (physdev_op.u.irq_status_query.flags &
423: PHYSDEVOP_IRQ_NEEDS_UNMASK_NOTIFY) {
1.5 bouyer 424: pirq_needs_unmask_notify[evtch >> 5] |= (1 << (evtch & 0x1f));
1.2 bouyer 425: #ifdef IRQ_DEBUG
426: printf("pirq %d needs notify\n", pirq);
427: #endif
428: }
1.5 bouyer 429: hypervisor_enable_event(evtch);
1.2 bouyer 430: return ih;
431: }
432:
433: int
434: pirq_interrupt(void *arg)
435: {
436: struct pintrhand *ih = arg;
437: int ret;
438:
439:
440: ret = ih->func(ih->arg);
441: #ifdef IRQ_DEBUG
1.8 yamt 442: if (ih->evtch == IRQ_DEBUG)
443: printf("pirq_interrupt irq %d ret %d\n", ih->pirq, ret);
1.2 bouyer 444: #endif
445: return ret;
446: }
447:
1.16 bouyer 448: #endif /* NPCI > 0 || NISA > 0 */
1.2 bouyer 449:
450: int
1.7 bouyer 451: event_set_handler(int evtch, int (*func)(void *), void *arg, int level,
452: const char *evname)
1.2 bouyer 453: {
1.5 bouyer 454: struct iplsource *ipls;
455: struct evtsource *evts;
1.13 bouyer 456: struct intrhand *ih, **ihp;
1.2 bouyer 457: struct cpu_info *ci;
1.4 bouyer 458: int s;
1.2 bouyer 459:
460: #ifdef IRQ_DEBUG
1.5 bouyer 461: printf("event_set_handler IRQ %d handler %p\n", evtch, func);
1.2 bouyer 462: #endif
463:
464: #ifdef DIAGNOSTIC
1.5 bouyer 465: if (evtch >= NR_EVENT_CHANNELS) {
466: printf("evtch number %d > NR_EVENT_CHANNELS\n", evtch);
467: panic("event_set_handler");
468: }
1.2 bouyer 469: #endif
470:
471: #if 0
1.5 bouyer 472: printf("event_set_handler evtch %d handler %p level %d\n", evtch,
473: handler, level);
1.2 bouyer 474: #endif
475: MALLOC(ih, struct intrhand *, sizeof (struct intrhand), M_DEVBUF,
476: M_WAITOK|M_ZERO);
477: if (ih == NULL)
478: panic("can't allocate fixed interrupt source");
479:
480:
481: ih->ih_level = level;
1.5 bouyer 482: ih->ih_fun = func;
1.2 bouyer 483: ih->ih_arg = arg;
1.5 bouyer 484: ih->ih_evt_next = NULL;
485: ih->ih_ipl_next = NULL;
1.2 bouyer 486:
487: ci = &cpu_info_primary;
1.4 bouyer 488: s = splhigh();
1.5 bouyer 489: if (ci->ci_isources[level] == NULL) {
490: MALLOC(ipls, struct iplsource *, sizeof (struct iplsource),
491: M_DEVBUF, M_WAITOK|M_ZERO);
492: if (ipls == NULL)
493: panic("can't allocate fixed interrupt source");
494: ipls->ipl_recurse = xenev_stubs[level].ist_recurse;
495: ipls->ipl_resume = xenev_stubs[level].ist_resume;
496: ipls->ipl_handlers = ih;
497: ci->ci_isources[level] = ipls;
498: } else {
499: ipls = ci->ci_isources[level];
500: ih->ih_ipl_next = ipls->ipl_handlers;
501: ipls->ipl_handlers = ih;
502: }
503: if (evtsource[evtch] == NULL) {
504: MALLOC(evts, struct evtsource *, sizeof (struct evtsource),
1.2 bouyer 505: M_DEVBUF, M_WAITOK|M_ZERO);
1.5 bouyer 506: if (evts == NULL)
1.2 bouyer 507: panic("can't allocate fixed interrupt source");
1.5 bouyer 508: evts->ev_handlers = ih;
509: evtsource[evtch] = evts;
1.7 bouyer 510: if (evname)
511: strncpy(evts->ev_evname, evname,
512: sizeof(evts->ev_evname));
513: else
514: snprintf(evts->ev_evname, sizeof(evts->ev_evname),
515: "evt%d", evtch);
1.5 bouyer 516: evcnt_attach_dynamic(&evts->ev_evcnt, EVCNT_TYPE_INTR, NULL,
517: ci->ci_dev->dv_xname, evts->ev_evname);
1.2 bouyer 518: } else {
1.5 bouyer 519: evts = evtsource[evtch];
1.13 bouyer 520: /* sort by IPL order, higher first */
521: for (ihp = &evts->ev_handlers; ; ihp = &((*ihp)->ih_evt_next)) {
522: if ((*ihp)->ih_level < ih->ih_level) {
523: /* insert before *ihp */
524: ih->ih_evt_next = *ihp;
525: *ihp = ih;
526: break;
527: }
528: if ((*ihp)->ih_evt_next == NULL) {
529: (*ihp)->ih_evt_next = ih;
530: break;
531: }
532: }
1.2 bouyer 533: }
534:
1.5 bouyer 535: intr_calculatemasks(evts);
1.4 bouyer 536: splx(s);
1.2 bouyer 537:
538: return 0;
539: }
540:
541: int
1.5 bouyer 542: event_remove_handler(int evtch, int (*func)(void *), void *arg)
1.2 bouyer 543: {
1.5 bouyer 544: struct iplsource *ipls;
545: struct evtsource *evts;
1.2 bouyer 546: struct intrhand *ih;
547: struct intrhand **ihp;
548: struct cpu_info *ci = &cpu_info_primary;
549:
1.5 bouyer 550: evts = evtsource[evtch];
551: if (evts == NULL)
1.2 bouyer 552: return ENOENT;
553:
1.5 bouyer 554: for (ihp = &evts->ev_handlers, ih = evts->ev_handlers;
1.2 bouyer 555: ih != NULL;
1.5 bouyer 556: ihp = &ih->ih_evt_next, ih = ih->ih_evt_next) {
557: if (ih->ih_fun == func && ih->ih_arg == arg)
1.2 bouyer 558: break;
559: }
560: if (ih == NULL)
561: return ENOENT;
1.5 bouyer 562: *ihp = ih->ih_evt_next;
563:
564: ipls = ci->ci_isources[ih->ih_level];
565: for (ihp = &ipls->ipl_handlers, ih = ipls->ipl_handlers;
566: ih != NULL;
567: ihp = &ih->ih_ipl_next, ih = ih->ih_ipl_next) {
568: if (ih->ih_fun == func && ih->ih_arg == arg)
569: break;
570: }
571: if (ih == NULL)
572: panic("event_remove_handler");
573: *ihp = ih->ih_ipl_next;
1.2 bouyer 574: FREE(ih, M_DEVBUF);
1.5 bouyer 575: if (evts->ev_handlers == NULL) {
576: evcnt_detach(&evts->ev_evcnt);
577: FREE(evts, M_DEVBUF);
578: evtsource[evtch] = NULL;
579: } else {
580: intr_calculatemasks(evts);
1.2 bouyer 581: }
582: return 0;
583: }
584:
585: void
1.5 bouyer 586: hypervisor_enable_event(unsigned int evtch)
1.2 bouyer 587: {
588: #ifdef IRQ_DEBUG
1.8 yamt 589: if (evtch == IRQ_DEBUG)
1.5 bouyer 590: printf("hypervisor_enable_evtch: evtch %d\n", evtch);
1.2 bouyer 591: #endif
592:
1.5 bouyer 593: hypervisor_unmask_event(evtch);
1.16 bouyer 594: #if NPCI > 0 || NISA > 0
1.6 bouyer 595: if (pirq_needs_unmask_notify[evtch >> 5] & (1 << (evtch & 0x1f))) {
596: #ifdef IRQ_DEBUG
1.8 yamt 597: if (evtch == IRQ_DEBUG)
1.6 bouyer 598: printf("pirq_notify(%d)\n", evtch);
1.2 bouyer 599: #endif
1.6 bouyer 600: (void)HYPERVISOR_physdev_op(&physdev_op_notify);
601: }
1.16 bouyer 602: #endif /* NPCI > 0 || NISA > 0 */
1.2 bouyer 603: }
604:
1.18 bouyer 605: int
1.2 bouyer 606: xen_debug_handler(void *arg)
607: {
1.5 bouyer 608: struct cpu_info *ci = curcpu();
609: int i;
1.24 bouyer 610: int xci_ilevel = ci->ci_ilevel;
611: int xci_ipending = ci->ci_ipending;
612: int xci_idepth = ci->ci_idepth;
1.18 bouyer 613: u_long upcall_pending =
1.21 bouyer 614: HYPERVISOR_shared_info->vcpu_info[0].evtchn_upcall_pending;
1.18 bouyer 615: u_long upcall_mask =
1.21 bouyer 616: HYPERVISOR_shared_info->vcpu_info[0].evtchn_upcall_mask;
617: #ifdef XEN3
618: u_long pending_sel = HYPERVISOR_shared_info->vcpu_info[0].evtchn_pending_sel;
619: #else
1.18 bouyer 620: u_long pending_sel = HYPERVISOR_shared_info->evtchn_pending_sel;
1.21 bouyer 621: #endif
1.18 bouyer 622: unsigned long evtchn_mask[sizeof(unsigned long) * 8];
623: unsigned long evtchn_pending[sizeof(unsigned long) * 8];
624:
625: u_long p;
626:
627: p = (u_long)&HYPERVISOR_shared_info->evtchn_mask[0];
628: memcpy(evtchn_mask, (void *)p, sizeof(evtchn_mask));
629: p = (u_long)&HYPERVISOR_shared_info->evtchn_pending[0];
630: memcpy(evtchn_pending, (void *)p, sizeof(evtchn_pending));
631:
632: __insn_barrier();
1.2 bouyer 633: printf("debug event\n");
1.5 bouyer 634: printf("ci_ilevel 0x%x ci_ipending 0x%x ci_idepth %d\n",
1.24 bouyer 635: xci_ilevel, xci_ipending, xci_idepth);
1.18 bouyer 636: printf("evtchn_upcall_pending %ld evtchn_upcall_mask %ld"
637: " evtchn_pending_sel 0x%lx\n",
638: upcall_pending, upcall_mask, pending_sel);
1.5 bouyer 639: printf("evtchn_mask");
640: for (i = 0 ; i < 32; i++)
1.18 bouyer 641: printf(" %lx", (u_long)evtchn_mask[i]);
1.5 bouyer 642: printf("\n");
643: printf("evtchn_pending");
644: for (i = 0 ; i < 32; i++)
1.18 bouyer 645: printf(" %lx", (u_long)evtchn_pending[i]);
1.5 bouyer 646: printf("\n");
1.2 bouyer 647: return 0;
648: }
649:
1.18 bouyer 650: #ifndef XEN3
1.2 bouyer 651: static int
652: xen_misdirect_handler(void *arg)
653: {
654: #if 0
655: char *msg = "misdirect\n";
656: (void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(msg), msg);
657: #endif
658: return 0;
659: }
1.18 bouyer 660: #endif
CVSweb <webmaster@jp.NetBSD.org>