[BACK]Return to evtchn.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / arch / xen / xen

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>