Annotation of src/sys/arch/xen/xen/evtchn.c, Revision 1.18.20.2
1.18.20.2! yamt 1: /* $NetBSD: evtchn.c,v 1.18.20.1 2006/10/22 06:05:20 yamt 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.18.20.2! yamt 67: __KERNEL_RCSID(0, "$NetBSD: evtchn.c,v 1.18.20.1 2006/10/22 06:05:20 yamt 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:
84: #include <machine/xen.h>
85: #include <machine/hypervisor.h>
86: #include <machine/evtchn.h>
1.18 bouyer 87: #ifndef XEN3
1.2 bouyer 88: #include <machine/ctrl_if.h>
1.18 bouyer 89: #endif
1.2 bouyer 90: #include <machine/xenfunc.h>
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: int xen_debug_handler(void *);
121: #ifndef XEN3
1.2 bouyer 122: static int xen_misdirect_handler(void *);
1.18 bouyer 123: #endif
1.2 bouyer 124:
1.18 bouyer 125: // #define IRQ_DEBUG 4
1.2 bouyer 126:
127: void
128: events_default_setup()
129: {
130: int i;
131:
1.5 bouyer 132: /* No VIRQ -> event mappings. */
1.2 bouyer 133: for (i = 0; i < NR_VIRQS; i++)
1.5 bouyer 134: virq_to_evtch[i] = -1;
1.2 bouyer 135:
1.16 bouyer 136: #if NPCI > 0 || NISA > 0
1.5 bouyer 137: /* No PIRQ -> event mappings. */
1.2 bouyer 138: for (i = 0; i < NR_PIRQS; i++)
1.5 bouyer 139: pirq_to_evtch[i] = -1;
140: for (i = 0; i < NR_EVENT_CHANNELS / 32; i++)
141: pirq_needs_unmask_notify[i] = 0;
1.2 bouyer 142: #endif
143:
1.5 bouyer 144: /* No event-channel are 'live' right now. */
1.2 bouyer 145: for (i = 0; i < NR_EVENT_CHANNELS; i++) {
1.5 bouyer 146: evtsource[i] = NULL;
147: evtch_bindcount[i] = 0;
148: hypervisor_mask_event(i);
1.2 bouyer 149: }
150:
151: }
152:
153: void
154: init_events()
155: {
1.5 bouyer 156: int evtch;
1.2 bouyer 157:
1.5 bouyer 158: evtch = bind_virq_to_evtch(VIRQ_DEBUG);
1.12 xtraeme 159: aprint_verbose("debug virtual interrupt using event channel %d\n",
1.5 bouyer 160: evtch);
1.7 bouyer 161: event_set_handler(evtch, &xen_debug_handler, NULL, IPL_DEBUG,
162: "debugev");
1.5 bouyer 163: hypervisor_enable_event(evtch);
164:
1.18 bouyer 165: #ifndef XEN3
1.5 bouyer 166: evtch = bind_virq_to_evtch(VIRQ_MISDIRECT);
1.12 xtraeme 167: aprint_verbose("misdirect virtual interrupt using event channel %d\n",
1.5 bouyer 168: evtch);
1.7 bouyer 169: event_set_handler(evtch, &xen_misdirect_handler, NULL, IPL_DIE,
170: "misdirev");
1.5 bouyer 171: hypervisor_enable_event(evtch);
1.2 bouyer 172:
173: /* This needs to be done early, but after the IRQ subsystem is
174: * alive. */
175: ctrl_if_init();
1.18 bouyer 176: #endif
1.2 bouyer 177:
178: enable_intr(); /* at long last... */
179: }
180:
181: unsigned int
1.14 yamt 182: evtchn_do_event(int evtch, struct intrframe *regs)
1.2 bouyer 183: {
184: struct cpu_info *ci;
185: int ilevel;
186: struct intrhand *ih;
187: int (*ih_fun)(void *, void *);
188: extern struct uvmexp uvmexp;
1.13 bouyer 189: u_int32_t iplmask;
1.2 bouyer 190:
191: #ifdef DIAGNOSTIC
1.5 bouyer 192: if (evtch >= NR_EVENT_CHANNELS) {
193: printf("event number %d > NR_IRQS\n", evtch);
1.14 yamt 194: panic("evtchn_do_event");
1.5 bouyer 195: }
1.2 bouyer 196: #endif
197:
198: #ifdef IRQ_DEBUG
1.5 bouyer 199: if (evtch == IRQ_DEBUG)
1.14 yamt 200: printf("evtchn_do_event: evtch %d\n", evtch);
1.2 bouyer 201: #endif
1.5 bouyer 202: ci = &cpu_info_primary;
1.2 bouyer 203:
1.5 bouyer 204: /*
205: * Shortcut for the debug handler, we want it to always run,
206: * regardless of the IPL level.
207: */
208:
209: if (evtch == debug_port) {
210: xen_debug_handler(NULL);
211: hypervisor_enable_event(evtch);
1.2 bouyer 212: return 0;
213: }
1.5 bouyer 214:
215: #ifdef DIAGNOSTIC
216: if (evtsource[evtch] == NULL) {
1.14 yamt 217: panic("evtchn_do_event: unknown event");
1.5 bouyer 218: }
219: #endif
1.3 bouyer 220: uvmexp.intrs++;
1.5 bouyer 221: evtsource[evtch]->ev_evcnt.ev_count++;
1.2 bouyer 222: ilevel = ci->ci_ilevel;
1.5 bouyer 223: if (evtsource[evtch]->ev_maxlevel <= ilevel) {
1.2 bouyer 224: #ifdef IRQ_DEBUG
1.8 yamt 225: if (evtch == IRQ_DEBUG)
1.5 bouyer 226: printf("evtsource[%d]->ev_maxlevel %d <= ilevel %d\n",
227: evtch, evtsource[evtch]->ev_maxlevel, ilevel);
1.2 bouyer 228: #endif
1.13 bouyer 229: hypervisor_set_ipending(evtsource[evtch]->ev_imask,
230: evtch / 32, evtch % 32);
1.2 bouyer 231: /* leave masked */
232: return 0;
233: }
1.5 bouyer 234: ci->ci_ilevel = evtsource[evtch]->ev_maxlevel;
1.13 bouyer 235: iplmask = evtsource[evtch]->ev_imask;
1.15 yamt 236: sti();
1.2 bouyer 237: #ifdef MULTIPROCESSOR
238: x86_intlock(regs);
239: #endif
1.5 bouyer 240: ih = evtsource[evtch]->ev_handlers;
1.2 bouyer 241: while (ih != NULL) {
242: if (ih->ih_level <= ilevel) {
243: #ifdef IRQ_DEBUG
1.5 bouyer 244: if (evtch == IRQ_DEBUG)
1.2 bouyer 245: printf("ih->ih_level %d <= ilevel %d\n", ih->ih_level, ilevel);
246: #endif
247: #ifdef MULTIPROCESSOR
248: x86_intunlock(regs);
249: #endif
1.15 yamt 250: cli();
1.13 bouyer 251: hypervisor_set_ipending(iplmask,
252: evtch / 32, evtch % 32);
1.2 bouyer 253: /* leave masked */
254: splx(ilevel);
255: return 0;
256: }
1.13 bouyer 257: iplmask &= ~IUNMASK(ci, ih->ih_level);
1.2 bouyer 258: ci->ci_ilevel = ih->ih_level;
259: ih_fun = (void *)ih->ih_fun;
260: ih_fun(ih->ih_arg, regs);
1.5 bouyer 261: ih = ih->ih_evt_next;
1.2 bouyer 262: }
1.15 yamt 263: cli();
1.2 bouyer 264: #ifdef MULTIPROCESSOR
265: x86_intunlock(regs);
266: #endif
1.5 bouyer 267: hypervisor_enable_event(evtch);
1.2 bouyer 268: splx(ilevel);
269:
270: return 0;
271: }
272:
273: int
1.5 bouyer 274: bind_virq_to_evtch(int virq)
1.2 bouyer 275: {
276: evtchn_op_t op;
1.5 bouyer 277: int evtchn, s;
1.2 bouyer 278:
1.4 bouyer 279: s = splhigh();
1.2 bouyer 280: simple_lock(&irq_mapping_update_lock);
281:
1.5 bouyer 282: evtchn = virq_to_evtch[virq];
283: if (evtchn == -1) {
1.2 bouyer 284: op.cmd = EVTCHNOP_bind_virq;
285: op.u.bind_virq.virq = virq;
1.18 bouyer 286: #ifdef XEN3
287: op.u.bind_virq.vcpu = 0;
288: #endif
1.2 bouyer 289: if (HYPERVISOR_event_channel_op(&op) != 0)
290: panic("Failed to bind virtual IRQ %d\n", virq);
291: evtchn = op.u.bind_virq.port;
1.5 bouyer 292: if (virq == VIRQ_DEBUG)
293: debug_port = evtchn;
1.2 bouyer 294:
1.5 bouyer 295: virq_to_evtch[virq] = evtchn;
1.2 bouyer 296: }
297:
1.5 bouyer 298: evtch_bindcount[evtchn]++;
1.2 bouyer 299:
300: simple_unlock(&irq_mapping_update_lock);
1.4 bouyer 301: splx(s);
1.2 bouyer 302:
1.5 bouyer 303: return evtchn;
1.2 bouyer 304: }
305:
306: void
1.5 bouyer 307: unbind_virq_from_evtch(int virq)
1.2 bouyer 308: {
309: evtchn_op_t op;
1.5 bouyer 310: int evtchn = virq_to_evtch[virq];
1.4 bouyer 311: int s = splhigh();
1.2 bouyer 312:
313: simple_lock(&irq_mapping_update_lock);
314:
1.5 bouyer 315: evtch_bindcount[evtchn]--;
316: if (evtch_bindcount[evtchn] == 0) {
1.2 bouyer 317: op.cmd = EVTCHNOP_close;
1.18 bouyer 318: #ifndef XEN3
1.2 bouyer 319: op.u.close.dom = DOMID_SELF;
1.18 bouyer 320: #endif
1.2 bouyer 321: op.u.close.port = evtchn;
322: if (HYPERVISOR_event_channel_op(&op) != 0)
323: panic("Failed to unbind virtual IRQ %d\n", virq);
324:
1.5 bouyer 325: virq_to_evtch[virq] = -1;
1.2 bouyer 326: }
327:
328: simple_unlock(&irq_mapping_update_lock);
1.4 bouyer 329: splx(s);
1.2 bouyer 330: }
331:
1.16 bouyer 332: #if NPCI > 0 || NISA > 0
1.2 bouyer 333: int
1.5 bouyer 334: bind_pirq_to_evtch(int pirq)
1.2 bouyer 335: {
336: evtchn_op_t op;
1.5 bouyer 337: int evtchn, s;
1.2 bouyer 338:
339: if (pirq >= NR_PIRQS) {
340: panic("pirq %d out of bound, increase NR_PIRQS", pirq);
341: }
1.4 bouyer 342:
343: s = splhigh();
1.2 bouyer 344: simple_lock(&irq_mapping_update_lock);
345:
1.5 bouyer 346: evtchn = pirq_to_evtch[pirq];
347: if (evtchn == -1) {
1.2 bouyer 348: op.cmd = EVTCHNOP_bind_pirq;
349: op.u.bind_pirq.pirq = pirq;
350: op.u.bind_pirq.flags = BIND_PIRQ__WILL_SHARE;
351: if (HYPERVISOR_event_channel_op(&op) != 0)
352: panic("Failed to bind physical IRQ %d\n", pirq);
353: evtchn = op.u.bind_pirq.port;
354:
355: #ifdef IRQ_DEBUG
1.8 yamt 356: printf("pirq %d evtchn %d\n", pirq, evtchn);
1.2 bouyer 357: #endif
1.5 bouyer 358: pirq_to_evtch[pirq] = evtchn;
1.2 bouyer 359: }
360:
1.5 bouyer 361: evtch_bindcount[evtchn]++;
1.2 bouyer 362:
363: simple_unlock(&irq_mapping_update_lock);
1.4 bouyer 364: splx(s);
1.2 bouyer 365:
1.5 bouyer 366: return evtchn;
1.2 bouyer 367: }
368:
369: void
1.5 bouyer 370: unbind_pirq_from_evtch(int pirq)
1.2 bouyer 371: {
372: evtchn_op_t op;
1.5 bouyer 373: int evtchn = pirq_to_evtch[pirq];
1.4 bouyer 374: int s = splhigh();
1.2 bouyer 375:
376: simple_lock(&irq_mapping_update_lock);
377:
1.5 bouyer 378: evtch_bindcount[evtchn]--;
379: if (evtch_bindcount[evtchn] == 0) {
1.2 bouyer 380: op.cmd = EVTCHNOP_close;
1.18 bouyer 381: #ifndef XEN3
1.2 bouyer 382: op.u.close.dom = DOMID_SELF;
1.18 bouyer 383: #endif
1.2 bouyer 384: op.u.close.port = evtchn;
385: if (HYPERVISOR_event_channel_op(&op) != 0)
386: panic("Failed to unbind physical IRQ %d\n", pirq);
387:
1.5 bouyer 388: pirq_to_evtch[pirq] = -1;
1.2 bouyer 389: }
390:
391: simple_unlock(&irq_mapping_update_lock);
1.4 bouyer 392: splx(s);
1.2 bouyer 393: }
394:
395: struct pintrhand *
1.18.20.1 yamt 396: pirq_establish(int pirq, int evtch, int (*func)(void *), void *arg, int level,
397: const char *evname)
1.2 bouyer 398: {
399: struct pintrhand *ih;
400: physdev_op_t physdev_op;
401:
402: ih = malloc(sizeof *ih, M_DEVBUF, cold ? M_NOWAIT : M_WAITOK);
403: if (ih == NULL) {
404: printf("pirq_establish: can't malloc handler info\n");
405: return NULL;
406: }
1.7 bouyer 407: if (event_set_handler(evtch, pirq_interrupt, ih, level, evname) != 0) {
1.2 bouyer 408: free(ih, M_DEVBUF);
409: return NULL;
410: }
411: ih->pirq = pirq;
1.5 bouyer 412: ih->evtch = evtch;
1.2 bouyer 413: ih->func = func;
414: ih->arg = arg;
415:
416: physdev_op.cmd = PHYSDEVOP_IRQ_STATUS_QUERY;
417: physdev_op.u.irq_status_query.irq = pirq;
418: if (HYPERVISOR_physdev_op(&physdev_op) < 0)
419: panic("HYPERVISOR_physdev_op(PHYSDEVOP_IRQ_STATUS_QUERY)");
420: if (physdev_op.u.irq_status_query.flags &
421: PHYSDEVOP_IRQ_NEEDS_UNMASK_NOTIFY) {
1.5 bouyer 422: pirq_needs_unmask_notify[evtch >> 5] |= (1 << (evtch & 0x1f));
1.2 bouyer 423: #ifdef IRQ_DEBUG
424: printf("pirq %d needs notify\n", pirq);
425: #endif
426: }
1.5 bouyer 427: hypervisor_enable_event(evtch);
1.2 bouyer 428: return ih;
429: }
430:
431: int
432: pirq_interrupt(void *arg)
433: {
434: struct pintrhand *ih = arg;
435: int ret;
436:
437:
438: ret = ih->func(ih->arg);
439: #ifdef IRQ_DEBUG
1.8 yamt 440: if (ih->evtch == IRQ_DEBUG)
441: printf("pirq_interrupt irq %d ret %d\n", ih->pirq, ret);
1.2 bouyer 442: #endif
443: return ret;
444: }
445:
1.16 bouyer 446: #endif /* NPCI > 0 || NISA > 0 */
1.2 bouyer 447:
448: int
1.7 bouyer 449: event_set_handler(int evtch, int (*func)(void *), void *arg, int level,
450: const char *evname)
1.2 bouyer 451: {
1.5 bouyer 452: struct iplsource *ipls;
453: struct evtsource *evts;
1.13 bouyer 454: struct intrhand *ih, **ihp;
1.2 bouyer 455: struct cpu_info *ci;
1.4 bouyer 456: int s;
1.2 bouyer 457:
458: #ifdef IRQ_DEBUG
1.5 bouyer 459: printf("event_set_handler IRQ %d handler %p\n", evtch, func);
1.2 bouyer 460: #endif
461:
462: #ifdef DIAGNOSTIC
1.5 bouyer 463: if (evtch >= NR_EVENT_CHANNELS) {
464: printf("evtch number %d > NR_EVENT_CHANNELS\n", evtch);
465: panic("event_set_handler");
466: }
1.2 bouyer 467: #endif
468:
469: #if 0
1.5 bouyer 470: printf("event_set_handler evtch %d handler %p level %d\n", evtch,
471: handler, level);
1.2 bouyer 472: #endif
473: MALLOC(ih, struct intrhand *, sizeof (struct intrhand), M_DEVBUF,
474: M_WAITOK|M_ZERO);
475: if (ih == NULL)
476: panic("can't allocate fixed interrupt source");
477:
478:
479: ih->ih_level = level;
1.5 bouyer 480: ih->ih_fun = func;
1.2 bouyer 481: ih->ih_arg = arg;
1.5 bouyer 482: ih->ih_evt_next = NULL;
483: ih->ih_ipl_next = NULL;
1.2 bouyer 484:
485: ci = &cpu_info_primary;
1.4 bouyer 486: s = splhigh();
1.5 bouyer 487: if (ci->ci_isources[level] == NULL) {
488: MALLOC(ipls, struct iplsource *, sizeof (struct iplsource),
489: M_DEVBUF, M_WAITOK|M_ZERO);
490: if (ipls == NULL)
491: panic("can't allocate fixed interrupt source");
492: ipls->ipl_recurse = xenev_stubs[level].ist_recurse;
493: ipls->ipl_resume = xenev_stubs[level].ist_resume;
494: ipls->ipl_handlers = ih;
495: ci->ci_isources[level] = ipls;
496: } else {
497: ipls = ci->ci_isources[level];
498: ih->ih_ipl_next = ipls->ipl_handlers;
499: ipls->ipl_handlers = ih;
500: }
501: if (evtsource[evtch] == NULL) {
502: MALLOC(evts, struct evtsource *, sizeof (struct evtsource),
1.2 bouyer 503: M_DEVBUF, M_WAITOK|M_ZERO);
1.5 bouyer 504: if (evts == NULL)
1.2 bouyer 505: panic("can't allocate fixed interrupt source");
1.5 bouyer 506: evts->ev_handlers = ih;
507: evtsource[evtch] = evts;
1.7 bouyer 508: if (evname)
509: strncpy(evts->ev_evname, evname,
510: sizeof(evts->ev_evname));
511: else
512: snprintf(evts->ev_evname, sizeof(evts->ev_evname),
513: "evt%d", evtch);
1.5 bouyer 514: evcnt_attach_dynamic(&evts->ev_evcnt, EVCNT_TYPE_INTR, NULL,
515: ci->ci_dev->dv_xname, evts->ev_evname);
1.2 bouyer 516: } else {
1.5 bouyer 517: evts = evtsource[evtch];
1.13 bouyer 518: /* sort by IPL order, higher first */
519: for (ihp = &evts->ev_handlers; ; ihp = &((*ihp)->ih_evt_next)) {
520: if ((*ihp)->ih_level < ih->ih_level) {
521: /* insert before *ihp */
522: ih->ih_evt_next = *ihp;
523: *ihp = ih;
524: break;
525: }
526: if ((*ihp)->ih_evt_next == NULL) {
527: (*ihp)->ih_evt_next = ih;
528: break;
529: }
530: }
1.2 bouyer 531: }
532:
1.5 bouyer 533: intr_calculatemasks(evts);
1.4 bouyer 534: splx(s);
1.2 bouyer 535:
536: return 0;
537: }
538:
539: int
1.5 bouyer 540: event_remove_handler(int evtch, int (*func)(void *), void *arg)
1.2 bouyer 541: {
1.5 bouyer 542: struct iplsource *ipls;
543: struct evtsource *evts;
1.2 bouyer 544: struct intrhand *ih;
545: struct intrhand **ihp;
546: struct cpu_info *ci = &cpu_info_primary;
547:
1.5 bouyer 548: evts = evtsource[evtch];
549: if (evts == NULL)
1.2 bouyer 550: return ENOENT;
551:
1.5 bouyer 552: for (ihp = &evts->ev_handlers, ih = evts->ev_handlers;
1.2 bouyer 553: ih != NULL;
1.5 bouyer 554: ihp = &ih->ih_evt_next, ih = ih->ih_evt_next) {
555: if (ih->ih_fun == func && ih->ih_arg == arg)
1.2 bouyer 556: break;
557: }
558: if (ih == NULL)
559: return ENOENT;
1.5 bouyer 560: *ihp = ih->ih_evt_next;
561:
562: ipls = ci->ci_isources[ih->ih_level];
563: for (ihp = &ipls->ipl_handlers, ih = ipls->ipl_handlers;
564: ih != NULL;
565: ihp = &ih->ih_ipl_next, ih = ih->ih_ipl_next) {
566: if (ih->ih_fun == func && ih->ih_arg == arg)
567: break;
568: }
569: if (ih == NULL)
570: panic("event_remove_handler");
571: *ihp = ih->ih_ipl_next;
1.2 bouyer 572: FREE(ih, M_DEVBUF);
1.5 bouyer 573: if (evts->ev_handlers == NULL) {
574: evcnt_detach(&evts->ev_evcnt);
575: FREE(evts, M_DEVBUF);
576: evtsource[evtch] = NULL;
577: } else {
578: intr_calculatemasks(evts);
1.2 bouyer 579: }
580: return 0;
581: }
582:
583: void
1.5 bouyer 584: hypervisor_enable_event(unsigned int evtch)
1.2 bouyer 585: {
586: #ifdef IRQ_DEBUG
1.8 yamt 587: if (evtch == IRQ_DEBUG)
1.5 bouyer 588: printf("hypervisor_enable_evtch: evtch %d\n", evtch);
1.2 bouyer 589: #endif
590:
1.5 bouyer 591: hypervisor_unmask_event(evtch);
1.16 bouyer 592: #if NPCI > 0 || NISA > 0
1.6 bouyer 593: if (pirq_needs_unmask_notify[evtch >> 5] & (1 << (evtch & 0x1f))) {
594: #ifdef IRQ_DEBUG
1.8 yamt 595: if (evtch == IRQ_DEBUG)
1.6 bouyer 596: printf("pirq_notify(%d)\n", evtch);
1.2 bouyer 597: #endif
1.6 bouyer 598: (void)HYPERVISOR_physdev_op(&physdev_op_notify);
599: }
1.16 bouyer 600: #endif /* NPCI > 0 || NISA > 0 */
1.2 bouyer 601: }
602:
1.18 bouyer 603: int
1.2 bouyer 604: xen_debug_handler(void *arg)
605: {
1.5 bouyer 606: struct cpu_info *ci = curcpu();
607: int i;
1.18 bouyer 608: int ci_ilevel = ci->ci_ilevel;
609: int ci_ipending = ci->ci_ipending;
610: int ci_idepth = ci->ci_idepth;
611: u_long upcall_pending =
612: HYPERVISOR_shared_info->vcpu_data[0].evtchn_upcall_pending;
613: u_long upcall_mask =
614: HYPERVISOR_shared_info->vcpu_data[0].evtchn_upcall_mask;
615: u_long pending_sel = HYPERVISOR_shared_info->evtchn_pending_sel;
616: unsigned long evtchn_mask[sizeof(unsigned long) * 8];
617: unsigned long evtchn_pending[sizeof(unsigned long) * 8];
618:
619: u_long p;
620:
621: p = (u_long)&HYPERVISOR_shared_info->evtchn_mask[0];
622: memcpy(evtchn_mask, (void *)p, sizeof(evtchn_mask));
623: p = (u_long)&HYPERVISOR_shared_info->evtchn_pending[0];
624: memcpy(evtchn_pending, (void *)p, sizeof(evtchn_pending));
625:
626: __insn_barrier();
1.2 bouyer 627: printf("debug event\n");
1.5 bouyer 628: printf("ci_ilevel 0x%x ci_ipending 0x%x ci_idepth %d\n",
1.18 bouyer 629: ci_ilevel, ci_ipending, ci_idepth);
630: printf("evtchn_upcall_pending %ld evtchn_upcall_mask %ld"
631: " evtchn_pending_sel 0x%lx\n",
632: upcall_pending, upcall_mask, pending_sel);
1.5 bouyer 633: printf("evtchn_mask");
634: for (i = 0 ; i < 32; i++)
1.18 bouyer 635: printf(" %lx", (u_long)evtchn_mask[i]);
1.5 bouyer 636: printf("\n");
637: printf("evtchn_pending");
638: for (i = 0 ; i < 32; i++)
1.18 bouyer 639: printf(" %lx", (u_long)evtchn_pending[i]);
1.5 bouyer 640: printf("\n");
1.2 bouyer 641: return 0;
642: }
643:
1.18 bouyer 644: #ifndef XEN3
1.2 bouyer 645: static int
646: xen_misdirect_handler(void *arg)
647: {
648: #if 0
649: char *msg = "misdirect\n";
650: (void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(msg), msg);
651: #endif
652: return 0;
653: }
1.18 bouyer 654: #endif
CVSweb <webmaster@jp.NetBSD.org>