| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: evtchn.c,v 1.62.2.1 2013/12/17 22:39:17 riz Exp $ */ | | 1 | /* $NetBSD: evtchn.c,v 1.62.2.2 2015/04/14 14:59:11 msaitoh Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 2006 Manuel Bouyer. | | 4 | * Copyright (c) 2006 Manuel Bouyer. |
5 | * | | 5 | * |
6 | * Redistribution and use in source and binary forms, with or without | | 6 | * Redistribution and use in source and binary forms, with or without |
7 | * modification, are permitted provided that the following conditions | | 7 | * modification, are permitted provided that the following conditions |
8 | * are met: | | 8 | * are met: |
9 | * 1. Redistributions of source code must retain the above copyright | | 9 | * 1. Redistributions of source code must retain the above copyright |
10 | * notice, this list of conditions and the following disclaimer. | | 10 | * notice, this list of conditions and the following disclaimer. |
11 | * 2. Redistributions in binary form must reproduce the above copyright | | 11 | * 2. Redistributions in binary form must reproduce the above copyright |
12 | * notice, this list of conditions and the following disclaimer in the | | 12 | * notice, this list of conditions and the following disclaimer in the |
13 | * documentation and/or other materials provided with the distribution. | | 13 | * documentation and/or other materials provided with the distribution. |
14 | * | | 14 | * |
| @@ -44,27 +44,27 @@ | | | @@ -44,27 +44,27 @@ |
44 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | | 44 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
45 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | | 45 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
46 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | | 46 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
47 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | | 47 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
48 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | | 48 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
49 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | | 49 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
50 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | | 50 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
51 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | | 51 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
52 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | | 52 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
53 | */ | | 53 | */ |
54 | | | 54 | |
55 | | | 55 | |
56 | #include <sys/cdefs.h> | | 56 | #include <sys/cdefs.h> |
57 | __KERNEL_RCSID(0, "$NetBSD: evtchn.c,v 1.62.2.1 2013/12/17 22:39:17 riz Exp $"); | | 57 | __KERNEL_RCSID(0, "$NetBSD: evtchn.c,v 1.62.2.2 2015/04/14 14:59:11 msaitoh Exp $"); |
58 | | | 58 | |
59 | #include "opt_xen.h" | | 59 | #include "opt_xen.h" |
60 | #include "isa.h" | | 60 | #include "isa.h" |
61 | #include "pci.h" | | 61 | #include "pci.h" |
62 | | | 62 | |
63 | #include <sys/param.h> | | 63 | #include <sys/param.h> |
64 | #include <sys/cpu.h> | | 64 | #include <sys/cpu.h> |
65 | #include <sys/kernel.h> | | 65 | #include <sys/kernel.h> |
66 | #include <sys/systm.h> | | 66 | #include <sys/systm.h> |
67 | #include <sys/device.h> | | 67 | #include <sys/device.h> |
68 | #include <sys/proc.h> | | 68 | #include <sys/proc.h> |
69 | #include <sys/kmem.h> | | 69 | #include <sys/kmem.h> |
70 | #include <sys/reboot.h> | | 70 | #include <sys/reboot.h> |
| @@ -544,51 +544,62 @@ struct pintrhand * | | | @@ -544,51 +544,62 @@ struct pintrhand * |
544 | pirq_establish(int pirq, int evtch, int (*func)(void *), void *arg, int level, | | 544 | pirq_establish(int pirq, int evtch, int (*func)(void *), void *arg, int level, |
545 | const char *evname) | | 545 | const char *evname) |
546 | { | | 546 | { |
547 | struct pintrhand *ih; | | 547 | struct pintrhand *ih; |
548 | physdev_op_t physdev_op; | | 548 | physdev_op_t physdev_op; |
549 | | | 549 | |
550 | ih = kmem_zalloc(sizeof(struct pintrhand), | | 550 | ih = kmem_zalloc(sizeof(struct pintrhand), |
551 | cold ? KM_NOSLEEP : KM_SLEEP); | | 551 | cold ? KM_NOSLEEP : KM_SLEEP); |
552 | if (ih == NULL) { | | 552 | if (ih == NULL) { |
553 | printf("pirq_establish: can't allocate handler info\n"); | | 553 | printf("pirq_establish: can't allocate handler info\n"); |
554 | return NULL; | | 554 | return NULL; |
555 | } | | 555 | } |
556 | | | 556 | |
557 | if (event_set_handler(evtch, pirq_interrupt, ih, level, evname) != 0) { | | | |
558 | kmem_free(ih, sizeof(struct pintrhand)); | | | |
559 | return NULL; | | | |
560 | } | | | |
561 | | | | |
562 | ih->pirq = pirq; | | 557 | ih->pirq = pirq; |
563 | ih->evtch = evtch; | | 558 | ih->evtch = evtch; |
564 | ih->func = func; | | 559 | ih->func = func; |
565 | ih->arg = arg; | | 560 | ih->arg = arg; |
566 | | | 561 | |
| | | 562 | if (event_set_handler(evtch, pirq_interrupt, ih, level, evname) != 0) { |
| | | 563 | kmem_free(ih, sizeof(struct pintrhand)); |
| | | 564 | return NULL; |
| | | 565 | } |
| | | 566 | |
567 | physdev_op.cmd = PHYSDEVOP_IRQ_STATUS_QUERY; | | 567 | physdev_op.cmd = PHYSDEVOP_IRQ_STATUS_QUERY; |
568 | physdev_op.u.irq_status_query.irq = pirq; | | 568 | physdev_op.u.irq_status_query.irq = pirq; |
569 | if (HYPERVISOR_physdev_op(&physdev_op) < 0) | | 569 | if (HYPERVISOR_physdev_op(&physdev_op) < 0) |
570 | panic("HYPERVISOR_physdev_op(PHYSDEVOP_IRQ_STATUS_QUERY)"); | | 570 | panic("HYPERVISOR_physdev_op(PHYSDEVOP_IRQ_STATUS_QUERY)"); |
571 | if (physdev_op.u.irq_status_query.flags & | | 571 | if (physdev_op.u.irq_status_query.flags & |
572 | PHYSDEVOP_IRQ_NEEDS_UNMASK_NOTIFY) { | | 572 | PHYSDEVOP_IRQ_NEEDS_UNMASK_NOTIFY) { |
573 | pirq_needs_unmask_notify[evtch >> 5] |= (1 << (evtch & 0x1f)); | | 573 | pirq_needs_unmask_notify[evtch >> 5] |= (1 << (evtch & 0x1f)); |
574 | #ifdef IRQ_DEBUG | | 574 | #ifdef IRQ_DEBUG |
575 | printf("pirq %d needs notify\n", pirq); | | 575 | printf("pirq %d needs notify\n", pirq); |
576 | #endif | | 576 | #endif |
577 | } | | 577 | } |
578 | hypervisor_enable_event(evtch); | | 578 | hypervisor_enable_event(evtch); |
579 | return ih; | | 579 | return ih; |
580 | } | | 580 | } |
581 | | | 581 | |
| | | 582 | void |
| | | 583 | pirq_disestablish(struct pintrhand *ih) |
| | | 584 | { |
| | | 585 | int error = event_remove_handler(ih->evtch, pirq_interrupt, ih); |
| | | 586 | if (error) { |
| | | 587 | printf("pirq_disestablish(%p): %d\n", ih, error); |
| | | 588 | return; |
| | | 589 | } |
| | | 590 | kmem_free(ih, sizeof(struct pintrhand)); |
| | | 591 | } |
| | | 592 | |
582 | int | | 593 | int |
583 | pirq_interrupt(void *arg) | | 594 | pirq_interrupt(void *arg) |
584 | { | | 595 | { |
585 | struct pintrhand *ih = arg; | | 596 | struct pintrhand *ih = arg; |
586 | int ret; | | 597 | int ret; |
587 | | | 598 | |
588 | | | 599 | |
589 | ret = ih->func(ih->arg); | | 600 | ret = ih->func(ih->arg); |
590 | #ifdef IRQ_DEBUG | | 601 | #ifdef IRQ_DEBUG |
591 | if (ih->evtch == IRQ_DEBUG) | | 602 | if (ih->evtch == IRQ_DEBUG) |
592 | printf("pirq_interrupt irq %d ret %d\n", ih->pirq, ret); | | 603 | printf("pirq_interrupt irq %d ret %d\n", ih->pirq, ret); |
593 | #endif | | 604 | #endif |
594 | return ret; | | 605 | return ret; |
| @@ -766,38 +777,38 @@ event_remove_handler(int evtch, int (*fu | | | @@ -766,38 +777,38 @@ event_remove_handler(int evtch, int (*fu |
766 | mutex_spin_enter(&evtlock[evtch]); | | 777 | mutex_spin_enter(&evtlock[evtch]); |
767 | for (ihp = &evts->ev_handlers, ih = evts->ev_handlers; | | 778 | for (ihp = &evts->ev_handlers, ih = evts->ev_handlers; |
768 | ih != NULL; | | 779 | ih != NULL; |
769 | ihp = &ih->ih_evt_next, ih = ih->ih_evt_next) { | | 780 | ihp = &ih->ih_evt_next, ih = ih->ih_evt_next) { |
770 | if (ih->ih_realfun == func && ih->ih_realarg == arg) | | 781 | if (ih->ih_realfun == func && ih->ih_realarg == arg) |
771 | break; | | 782 | break; |
772 | } | | 783 | } |
773 | if (ih == NULL) { | | 784 | if (ih == NULL) { |
774 | mutex_spin_exit(&evtlock[evtch]); | | 785 | mutex_spin_exit(&evtlock[evtch]); |
775 | return ENOENT; | | 786 | return ENOENT; |
776 | } | | 787 | } |
777 | ci = ih->ih_cpu; | | 788 | ci = ih->ih_cpu; |
778 | *ihp = ih->ih_evt_next; | | 789 | *ihp = ih->ih_evt_next; |
779 | mutex_spin_exit(&evtlock[evtch]); | | | |
780 | | | 790 | |
781 | ipls = ci->ci_isources[ih->ih_level]; | | 791 | ipls = ci->ci_isources[ih->ih_level]; |
782 | for (ihp = &ipls->ipl_handlers, ih = ipls->ipl_handlers; | | 792 | for (ihp = &ipls->ipl_handlers, ih = ipls->ipl_handlers; |
783 | ih != NULL; | | 793 | ih != NULL; |
784 | ihp = &ih->ih_ipl_next, ih = ih->ih_ipl_next) { | | 794 | ihp = &ih->ih_ipl_next, ih = ih->ih_ipl_next) { |
785 | if (ih->ih_realfun == func && ih->ih_realarg == arg) | | 795 | if (ih->ih_realfun == func && ih->ih_realarg == arg) |
786 | break; | | 796 | break; |
787 | } | | 797 | } |
788 | if (ih == NULL) | | 798 | if (ih == NULL) |
789 | panic("event_remove_handler"); | | 799 | panic("event_remove_handler"); |
790 | *ihp = ih->ih_ipl_next; | | 800 | *ihp = ih->ih_ipl_next; |
| | | 801 | mutex_spin_exit(&evtlock[evtch]); |
791 | kmem_free(ih, sizeof (struct intrhand)); | | 802 | kmem_free(ih, sizeof (struct intrhand)); |
792 | if (evts->ev_handlers == NULL) { | | 803 | if (evts->ev_handlers == NULL) { |
793 | xen_atomic_clear_bit(&ci->ci_evtmask[0], evtch); | | 804 | xen_atomic_clear_bit(&ci->ci_evtmask[0], evtch); |
794 | evcnt_detach(&evts->ev_evcnt); | | 805 | evcnt_detach(&evts->ev_evcnt); |
795 | kmem_free(evts, sizeof (struct evtsource)); | | 806 | kmem_free(evts, sizeof (struct evtsource)); |
796 | evtsource[evtch] = NULL; | | 807 | evtsource[evtch] = NULL; |
797 | } else { | | 808 | } else { |
798 | intr_calculatemasks(evts, evtch, ci); | | 809 | intr_calculatemasks(evts, evtch, ci); |
799 | } | | 810 | } |
800 | return 0; | | 811 | return 0; |
801 | } | | 812 | } |
802 | | | 813 | |
803 | void | | 814 | void |