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

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/sys/arch/xen/xen/evtchn.c between version 1.47 and 1.47.6.1

version 1.47, 2010/12/20 00:25:46 version 1.47.6.1, 2011/06/03 13:27:42
Line 61  __KERNEL_RCSID(0, "$NetBSD$");
Line 61  __KERNEL_RCSID(0, "$NetBSD$");
 #include "pci.h"  #include "pci.h"
   
 #include <sys/param.h>  #include <sys/param.h>
   #include <sys/cpu.h>
 #include <sys/kernel.h>  #include <sys/kernel.h>
 #include <sys/systm.h>  #include <sys/systm.h>
 #include <sys/device.h>  #include <sys/device.h>
Line 82  __KERNEL_RCSID(0, "$NetBSD$");
Line 83  __KERNEL_RCSID(0, "$NetBSD$");
  * This lock protects updates to the following mapping and reference-count   * This lock protects updates to the following mapping and reference-count
  * arrays. The lock does not need to be acquired to read the mapping tables.   * arrays. The lock does not need to be acquired to read the mapping tables.
  */   */
 static struct simplelock irq_mapping_update_lock = SIMPLELOCK_INITIALIZER;  static struct simplelock evtchn_lock = SIMPLELOCK_INITIALIZER;
   
 /* event handlers */  /* event handlers */
 struct evtsource *evtsource[NR_EVENT_CHANNELS];  struct evtsource *evtsource[NR_EVENT_CHANNELS];
   
 /* Reference counts for bindings to event channels */  /* Reference counts for bindings to event channels XXX: redo for SMP */
 static uint8_t evtch_bindcount[NR_EVENT_CHANNELS];  static uint8_t evtch_bindcount[NR_EVENT_CHANNELS];
   
   /* event-channel <-> VCPU mapping for IPIs. XXX: redo for SMP. */
   static evtchn_port_t vcpu_ipi_to_evtch[MAX_VIRT_CPUS];
   
   /* event-channel <-> VCPU mapping for VIRQ_TIMER.  XXX: redo for SMP. */
   static int virq_timer_to_evtch[MAX_VIRT_CPUS];
   
 /* event-channel <-> VIRQ mapping. */  /* event-channel <-> VIRQ mapping. */
 static int virq_to_evtch[NR_VIRQS];  static int virq_to_evtch[NR_VIRQS];
   
Line 137  events_default_setup(void)
Line 144  events_default_setup(void)
 {  {
         int i;          int i;
   
           /* No VCPU -> event mappings. */
           for (i = 0; i < MAX_VIRT_CPUS; i++)
                   vcpu_ipi_to_evtch[i] = -1;
   
           /* No VIRQ_TIMER -> event mappings. */
           for (i = 0; i < MAX_VIRT_CPUS; i++)
                   virq_timer_to_evtch[i] = -1;
   
         /* No VIRQ -> event mappings. */          /* No VIRQ -> event mappings. */
         for (i = 0; i < NR_VIRQS; i++)          for (i = 0; i < NR_VIRQS; i++)
                 virq_to_evtch[i] = -1;                  virq_to_evtch[i] = -1;
Line 162  void
Line 177  void
 events_init(void)  events_init(void)
 {  {
         debug_port = bind_virq_to_evtch(VIRQ_DEBUG);          debug_port = bind_virq_to_evtch(VIRQ_DEBUG);
           KASSERT(debug_port != -1);
   
         aprint_verbose("debug virtual interrupt using event channel %d\n",          aprint_verbose("debug virtual interrupt using event channel %d\n",
             debug_port);              debug_port);
         /*          /*
Line 197  evtchn_do_event(int evtch, struct intrfr
Line 214  evtchn_do_event(int evtch, struct intrfr
         if (evtch == IRQ_DEBUG)          if (evtch == IRQ_DEBUG)
                 printf("evtchn_do_event: evtch %d\n", evtch);                  printf("evtchn_do_event: evtch %d\n", evtch);
 #endif  #endif
         ci = &cpu_info_primary;          ci = curcpu();
   
         /*          /*
          * Shortcut for the debug handler, we want it to always run,           * Shortcut for the debug handler, we want it to always run,
Line 231  evtchn_do_event(int evtch, struct intrfr
Line 248  evtchn_do_event(int evtch, struct intrfr
         ci->ci_ilevel = evtsource[evtch]->ev_maxlevel;          ci->ci_ilevel = evtsource[evtch]->ev_maxlevel;
         iplmask = evtsource[evtch]->ev_imask;          iplmask = evtsource[evtch]->ev_imask;
         sti();          sti();
           simple_lock(&evtsource[evtch]->ev_lock);
         ih = evtsource[evtch]->ev_handlers;          ih = evtsource[evtch]->ev_handlers;
         while (ih != NULL) {          while (ih != NULL) {
                 if (ih->ih_level <= ilevel) {                  if (ih->ih_level <= ilevel) {
Line 242  evtchn_do_event(int evtch, struct intrfr
Line 260  evtchn_do_event(int evtch, struct intrfr
                         hypervisor_set_ipending(iplmask,                          hypervisor_set_ipending(iplmask,
                             evtch >> LONG_SHIFT, evtch & LONG_MASK);                              evtch >> LONG_SHIFT, evtch & LONG_MASK);
                         /* leave masked */                          /* leave masked */
                           simple_unlock(&evtsource[evtch]->ev_lock);
                         goto splx;                          goto splx;
                 }                  }
                 iplmask &= ~IUNMASK(ci, ih->ih_level);                  iplmask &= ~IUNMASK(ci, ih->ih_level);
Line 250  evtchn_do_event(int evtch, struct intrfr
Line 269  evtchn_do_event(int evtch, struct intrfr
                 ih_fun(ih->ih_arg, regs);                  ih_fun(ih->ih_arg, regs);
                 ih = ih->ih_evt_next;                  ih = ih->ih_evt_next;
         }          }
           simple_unlock(&evtsource[evtch]->ev_lock);
         cli();          cli();
         hypervisor_enable_event(evtch);          hypervisor_enable_event(evtch);
 splx:  splx:
Line 292  splx:
Line 312  splx:
         return 0;          return 0;
 }  }
   
   #define PRIuCPUID       "lu" /* XXX: move this somewhere more appropriate */
   
   evtchn_port_t
   bind_vcpu_to_evtch(cpuid_t vcpu)
   {
           evtchn_op_t op;
           evtchn_port_t evtchn;
           int s;
   
           s = splhigh();
           simple_lock(&evtchn_lock);
   
           evtchn = vcpu_ipi_to_evtch[vcpu];
           if (evtchn == -1) {
                   op.cmd = EVTCHNOP_bind_ipi;
                   op.u.bind_ipi.vcpu = (uint32_t) vcpu;
                   if (HYPERVISOR_event_channel_op(&op) != 0)
                           panic("Failed to bind ipi to VCPU %"PRIuCPUID"\n", vcpu);
                   evtchn = op.u.bind_ipi.port;
   
                   vcpu_ipi_to_evtch[vcpu] = evtchn;
           }
   
           evtch_bindcount[evtchn]++;
   
           simple_unlock(&evtchn_lock);
           splx(s);
   
           return evtchn;
   }
   
 int  int
 bind_virq_to_evtch(int virq)  bind_virq_to_evtch(int virq)
 {  {
Line 299  bind_virq_to_evtch(int virq)
Line 350  bind_virq_to_evtch(int virq)
         int evtchn, s;          int evtchn, s;
   
         s = splhigh();          s = splhigh();
         simple_lock(&irq_mapping_update_lock);          simple_lock(&evtchn_lock);
   
         evtchn = virq_to_evtch[virq];          /*
            * XXX: The only per-cpu VIRQ we currently use is VIRQ_TIMER.
            * Please re-visit this implementation when others are used.
            * Note: VIRQ_DEBUG is special-cased, and not used or bound on APs.
            * XXX: event->virq/ipi can be unified in a linked-list
            * implementation.
            */
           struct cpu_info *ci = curcpu();
   
           if (virq == VIRQ_DEBUG && ci != &cpu_info_primary) {
                   return -1;
           }
   
           if (virq == VIRQ_TIMER) {
                   evtchn = virq_timer_to_evtch[ci->ci_cpuid];
           }
           else {
                   evtchn = virq_to_evtch[virq];
           }
         if (evtchn == -1) {          if (evtchn == -1) {
                 op.cmd = EVTCHNOP_bind_virq;                  op.cmd = EVTCHNOP_bind_virq;
                 op.u.bind_virq.virq = virq;                  op.u.bind_virq.virq = virq;
                 op.u.bind_virq.vcpu = 0;                  op.u.bind_virq.vcpu = ci->ci_cpuid;
                 if (HYPERVISOR_event_channel_op(&op) != 0)                  if (HYPERVISOR_event_channel_op(&op) != 0)
                         panic("Failed to bind virtual IRQ %d\n", virq);                          panic("Failed to bind virtual IRQ %d\n", virq);
                 evtchn = op.u.bind_virq.port;                  evtchn = op.u.bind_virq.port;
Line 315  bind_virq_to_evtch(int virq)
Line 384  bind_virq_to_evtch(int virq)
   
         evtch_bindcount[evtchn]++;          evtch_bindcount[evtchn]++;
   
         simple_unlock(&irq_mapping_update_lock);          simple_unlock(&evtchn_lock);
         splx(s);          splx(s);
   
         return evtchn;          return evtchn;
Line 325  int
Line 394  int
 unbind_virq_from_evtch(int virq)  unbind_virq_from_evtch(int virq)
 {  {
         evtchn_op_t op;          evtchn_op_t op;
         int evtchn = virq_to_evtch[virq];          int evtchn;
         int s = splhigh();          int s;
   
           struct cpu_info *ci = curcpu();
   
         simple_lock(&irq_mapping_update_lock);          if (virq == VIRQ_TIMER) {
                   evtchn = virq_timer_to_evtch[ci->ci_cpuid];
           }
           else {
                   evtchn = virq_to_evtch[virq];
           }
   
           if (evtchn == -1) {
                   return -1;
           }
   
           s = splhigh();
           simple_lock(&evtchn_lock);
   
         evtch_bindcount[evtchn]--;          evtch_bindcount[evtchn]--;
         if (evtch_bindcount[evtchn] == 0) {          if (evtch_bindcount[evtchn] == 0) {
Line 340  unbind_virq_from_evtch(int virq)
Line 423  unbind_virq_from_evtch(int virq)
                 virq_to_evtch[virq] = -1;                  virq_to_evtch[virq] = -1;
         }          }
   
         simple_unlock(&irq_mapping_update_lock);          simple_unlock(&evtchn_lock);
         splx(s);          splx(s);
   
         return evtchn;          return evtchn;
Line 358  bind_pirq_to_evtch(int pirq)
Line 441  bind_pirq_to_evtch(int pirq)
         }          }
   
         s = splhigh();          s = splhigh();
         simple_lock(&irq_mapping_update_lock);          simple_lock(&evtchn_lock);
   
         evtchn = pirq_to_evtch[pirq];          evtchn = pirq_to_evtch[pirq];
         if (evtchn == -1) {          if (evtchn == -1) {
Line 377  bind_pirq_to_evtch(int pirq)
Line 460  bind_pirq_to_evtch(int pirq)
   
         evtch_bindcount[evtchn]++;          evtch_bindcount[evtchn]++;
   
         simple_unlock(&irq_mapping_update_lock);          simple_unlock(&evtchn_lock);
         splx(s);          splx(s);
   
         return evtchn;          return evtchn;
Line 390  unbind_pirq_from_evtch(int pirq)
Line 473  unbind_pirq_from_evtch(int pirq)
         int evtchn = pirq_to_evtch[pirq];          int evtchn = pirq_to_evtch[pirq];
         int s = splhigh();          int s = splhigh();
   
         simple_lock(&irq_mapping_update_lock);          simple_lock(&evtchn_lock);
   
         evtch_bindcount[evtchn]--;          evtch_bindcount[evtchn]--;
         if (evtch_bindcount[evtchn] == 0) {          if (evtch_bindcount[evtchn] == 0) {
Line 402  unbind_pirq_from_evtch(int pirq)
Line 485  unbind_pirq_from_evtch(int pirq)
                 pirq_to_evtch[pirq] = -1;                  pirq_to_evtch[pirq] = -1;
         }          }
   
         simple_unlock(&irq_mapping_update_lock);          simple_unlock(&evtchn_lock);
         splx(s);          splx(s);
   
         return evtchn;          return evtchn;
Line 465  int
Line 548  int
 event_set_handler(int evtch, int (*func)(void *), void *arg, int level,  event_set_handler(int evtch, int (*func)(void *), void *arg, int level,
     const char *evname)      const char *evname)
 {  {
         struct cpu_info *ci = &cpu_info_primary;          struct cpu_info *ci = curcpu(); /* XXX: pass in ci ? */
         struct evtsource *evts;          struct evtsource *evts;
         struct intrhand *ih, **ihp;          struct intrhand *ih, **ihp;
         int s;          int s;
Line 517  event_set_handler(int evtch, int (*func)
Line 600  event_set_handler(int evtch, int (*func)
                     M_DEVBUF, M_WAITOK|M_ZERO);                      M_DEVBUF, M_WAITOK|M_ZERO);
                 if (evts == NULL)                  if (evts == NULL)
                         panic("can't allocate fixed interrupt source");                          panic("can't allocate fixed interrupt source");
   
                 evts->ev_handlers = ih;                  evts->ev_handlers = ih;
                   simple_lock_init(&evts->ev_lock);
                 evtsource[evtch] = evts;                  evtsource[evtch] = evts;
                 if (evname)                  if (evname)
                         strncpy(evts->ev_evname, evname,                          strncpy(evts->ev_evname, evname,
Line 530  event_set_handler(int evtch, int (*func)
Line 615  event_set_handler(int evtch, int (*func)
         } else {          } else {
                 evts = evtsource[evtch];                  evts = evtsource[evtch];
                 /* sort by IPL order, higher first */                  /* sort by IPL order, higher first */
                   simple_lock(&evts->ev_lock);
                 for (ihp = &evts->ev_handlers; ; ihp = &((*ihp)->ih_evt_next)) {                  for (ihp = &evts->ev_handlers; ; ihp = &((*ihp)->ih_evt_next)) {
                         if ((*ihp)->ih_level < ih->ih_level) {                          if ((*ihp)->ih_level < ih->ih_level) {
                                 /* insert before *ihp */                                  /* insert before *ihp */
Line 542  event_set_handler(int evtch, int (*func)
Line 628  event_set_handler(int evtch, int (*func)
                                 break;                                  break;
                         }                          }
                 }                  }
                   simple_unlock(&evts->ev_lock);
         }          }
   
         intr_calculatemasks(evts);          intr_calculatemasks(evts);
Line 553  event_set_handler(int evtch, int (*func)
Line 640  event_set_handler(int evtch, int (*func)
 void  void
 event_set_iplhandler(struct intrhand *ih, int level)  event_set_iplhandler(struct intrhand *ih, int level)
 {  {
         struct cpu_info *ci = &cpu_info_primary;          struct cpu_info *ci = curcpu();
         struct iplsource *ipls;          struct iplsource *ipls;
   
         if (ci->ci_isources[level] == NULL) {          if (ci->ci_isources[level] == NULL) {
Line 579  event_remove_handler(int evtch, int (*fu
Line 666  event_remove_handler(int evtch, int (*fu
         struct evtsource *evts;          struct evtsource *evts;
         struct intrhand *ih;          struct intrhand *ih;
         struct intrhand **ihp;          struct intrhand **ihp;
         struct cpu_info *ci = &cpu_info_primary;          struct cpu_info *ci = curcpu();
   
         evts = evtsource[evtch];          evts = evtsource[evtch];
         if (evts == NULL)          if (evts == NULL)
                 return ENOENT;                  return ENOENT;
   
           simple_lock(&evts->ev_lock);
         for (ihp = &evts->ev_handlers, ih = evts->ev_handlers;          for (ihp = &evts->ev_handlers, ih = evts->ev_handlers;
             ih != NULL;              ih != NULL;
             ihp = &ih->ih_evt_next, ih = ih->ih_evt_next) {              ihp = &ih->ih_evt_next, ih = ih->ih_evt_next) {
                 if (ih->ih_fun == func && ih->ih_arg == arg)                  if (ih->ih_fun == func && ih->ih_arg == arg)
                         break;                          break;
         }          }
         if (ih == NULL)          if (ih == NULL) {
                   simple_unlock(&evts->ev_lock);
                 return ENOENT;                  return ENOENT;
           }
         *ihp = ih->ih_evt_next;          *ihp = ih->ih_evt_next;
           simple_unlock(&evts->ev_lock);
   
         ipls = ci->ci_isources[ih->ih_level];          ipls = ci->ci_isources[ih->ih_level];
         for (ihp = &ipls->ipl_handlers, ih = ipls->ipl_handlers;          for (ihp = &ipls->ipl_handlers, ih = ipls->ipl_handlers;

Legend:
Removed from v.1.47  
changed lines
  Added in v.1.47.6.1

CVSweb <webmaster@jp.NetBSD.org>