[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.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>