[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.3 and 1.3.2.8

version 1.3, 2005/03/11 15:48:40 version 1.3.2.8, 2005/04/28 10:36:43
Line 55  __KERNEL_RCSID(0, "$NetBSD$");
Line 55  __KERNEL_RCSID(0, "$NetBSD$");
   
 #include "opt_xen.h"  #include "opt_xen.h"
   
 struct pic xenev_pic = {  
         .pic_dev = {  
                 .dv_xname = "xen_fakepic",  
         },  
         .pic_type = PIC_XEN,  
         .pic_lock = __SIMPLELOCK_UNLOCKED,  
 };  
   
 /*  /*
  * 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 irq_mapping_update_lock = SIMPLELOCK_INITIALIZER;
   
 /* IRQ <-> event-channel mappings. */  /* event handlers */
 int evtchn_to_irq[NR_EVENT_CHANNELS];  struct evtsource *evtsource[NR_EVENT_CHANNELS];
 int irq_to_evtchn[NR_IRQS];  uint8_t evtch_maskcount[NR_EVENT_CHANNELS];
   
 /* IRQ <-> VIRQ mapping. */  /* Reference counts for bindings to event channels */
 static int virq_to_irq[NR_VIRQS];  static u_int8_t evtch_bindcount[NR_EVENT_CHANNELS];
   
   /* event-channel <-> VIRQ mapping. */
   static int virq_to_evtch[NR_VIRQS];
   
   
 #ifdef DOM0OPS  #ifdef DOM0OPS
 /* IRQ <-> PIRQ mapping */  /* event-channel <-> PIRQ mapping */
 static int pirq_to_irq[NR_PIRQS];  static int pirq_to_evtch[NR_PIRQS];
 /* PIRQ needing notify */  /* PIRQ needing notify */
 static u_int32_t irq_needs_unmask_notify[NR_IRQS / 32];  static u_int32_t pirq_needs_unmask_notify[NR_EVENT_CHANNELS / 32];
 int pirq_interrupt(void *);  int pirq_interrupt(void *);
 void pirq_notify(int);  
 physdev_op_t physdev_op_notify = {  physdev_op_t physdev_op_notify = {
         .cmd = PHYSDEVOP_IRQ_UNMASK_NOTIFY,          .cmd = PHYSDEVOP_IRQ_UNMASK_NOTIFY,
 };  };
 #endif  #endif
   
 /* Reference counts for bindings to IRQs. */  int debug_port;
 static int irq_bindcount[NR_IRQS];  
   
 #if 0  
 static int xen_die_handler(void *);  
 #endif  
 static int xen_debug_handler(void *);  static int xen_debug_handler(void *);
 static int xen_misdirect_handler(void *);  static int xen_misdirect_handler(void *);
   
Line 105  events_default_setup()
Line 94  events_default_setup()
 {  {
         int i;          int i;
   
         /* No VIRQ -> IRQ mappings. */          /* No VIRQ -> event mappings. */
         for (i = 0; i < NR_VIRQS; i++)          for (i = 0; i < NR_VIRQS; i++)
                 virq_to_irq[i] = -1;                  virq_to_evtch[i] = -1;
   
 #ifdef DOM0OPS  #ifdef DOM0OPS
         /* No PIRQ -> IRQ mappings. */          /* No PIRQ -> event mappings. */
         for (i = 0; i < NR_PIRQS; i++)          for (i = 0; i < NR_PIRQS; i++)
                 pirq_to_irq[i] = -1;                  pirq_to_evtch[i] = -1;
         for (i = 0; i < NR_IRQS / 32; i++)          for (i = 0; i < NR_EVENT_CHANNELS / 32; i++)
                 irq_needs_unmask_notify[i] = 0;                  pirq_needs_unmask_notify[i] = 0;
 #endif  #endif
   
         /* No event-channel -> IRQ mappings. */          /* No event-channel are 'live' right now. */
         for (i = 0; i < NR_EVENT_CHANNELS; i++) {          for (i = 0; i < NR_EVENT_CHANNELS; i++) {
                 evtchn_to_irq[i] = -1;                  evtsource[i] = NULL;
                 hypervisor_mask_event(i); /* No event channels are 'live' right now. */                  evtch_bindcount[i] = 0;
                   hypervisor_mask_event(i);
         }          }
   
         /* No IRQ -> event-channel mappings. */  
         for (i = 0; i < NR_IRQS; i++)  
                 irq_to_evtchn[i] = -1;  
 }  }
   
 void  void
 init_events()  init_events()
 {  {
         int irq;          int evtch;
   
         irq = bind_virq_to_irq(VIRQ_DEBUG);          evtch = bind_virq_to_evtch(VIRQ_DEBUG);
         event_set_handler(irq, &xen_debug_handler, NULL, IPL_DEBUG);          aprint_verbose("debug vitual interrupt using event channel %d\n",
         hypervisor_enable_irq(irq);              evtch);
           event_set_handler(evtch, &xen_debug_handler, NULL, IPL_DEBUG,
         irq = bind_virq_to_irq(VIRQ_MISDIRECT);              "debugev");
         event_set_handler(irq, &xen_misdirect_handler, NULL, IPL_DIE);          hypervisor_enable_event(evtch);
         hypervisor_enable_irq(irq);  
           evtch = bind_virq_to_evtch(VIRQ_MISDIRECT);
           aprint_verbose("misdirect vitual interrupt using event channel %d\n",
               evtch);
           event_set_handler(evtch, &xen_misdirect_handler, NULL, IPL_DIE,
               "misdirev");
           hypervisor_enable_event(evtch);
   
         /* This needs to be done early, but after the IRQ subsystem is          /* This needs to be done early, but after the IRQ subsystem is
          * alive. */           * alive. */
Line 149  init_events()
Line 142  init_events()
 }  }
   
 unsigned int  unsigned int
 do_event(int irq, struct intrframe *regs)  do_event(int evtch, struct intrframe *regs)
 {  {
         struct cpu_info *ci;          struct cpu_info *ci;
         int ilevel;          int ilevel;
Line 157  do_event(int irq, struct intrframe *regs
Line 150  do_event(int irq, struct intrframe *regs
         int     (*ih_fun)(void *, void *);          int     (*ih_fun)(void *, void *);
         extern struct uvmexp uvmexp;          extern struct uvmexp uvmexp;
   
         if (irq >= NR_IRQS) {  
 #ifdef DIAGNOSTIC  #ifdef DIAGNOSTIC
                 printf("event irq number %d > NR_IRQS\n", irq);          if (evtch >= NR_EVENT_CHANNELS) {
 #endif                  printf("event number %d > NR_IRQS\n", evtch);
                 return ENOENT;                  panic("do_event");
         }          }
   #endif
   
 #ifdef IRQ_DEBUG  #ifdef IRQ_DEBUG
         if (irq == IRQ_DEBUG)          if (evtch == IRQ_DEBUG)
                 printf("do_event: irq %d\n", irq);                  printf("do_event: evtch %d\n", evtch);
 #endif  
 #if 0 /* DDD */  
         if (irq >= 3 && irq != 7) {  
                 ci = &cpu_info_primary;  
                 printf("do_event %d/%d called, ilevel %d\n", irq,  
                        irq_to_evtchn[irq], ci->ci_ilevel);  
         }  
 #endif  #endif
   
         ci = &cpu_info_primary;          ci = &cpu_info_primary;
   
         hypervisor_acknowledge_irq(irq);          /*
         if (ci->ci_isources[irq] == NULL) {           * Shortcut for the debug handler, we want it to always run,
                 printf("ci_isources[%d] is NULL\n", irq);           * regardless of the IPL level.
                 hypervisor_enable_irq(irq);           */
   
           if (evtch == debug_port) {
                   xen_debug_handler(NULL);
                   hypervisor_enable_event(evtch);
                 return 0;                  return 0;
         }          }
   
   #ifdef DIAGNOSTIC
           if (evtsource[evtch] == NULL) {
                   panic("do_event: unknown event");
           }
   #endif
         uvmexp.intrs++;          uvmexp.intrs++;
         ci->ci_isources[irq]->is_evcnt.ev_count++;          evtsource[evtch]->ev_evcnt.ev_count++;
         ilevel = ci->ci_ilevel;          ilevel = ci->ci_ilevel;
         if (ci->ci_isources[irq]->is_maxlevel <= ilevel) {          if (evtsource[evtch]->ev_maxlevel <= ilevel) {
 #ifdef IRQ_DEBUG  #ifdef IRQ_DEBUG
                 if (irq == IRQ_DEBUG)                  if (evtch == IRQ_DEBUG)
                     printf("ci_isources[%d]->is_maxlevel %d <= ilevel %d\n", irq,                      printf("evtsource[%d]->ev_maxlevel %d <= ilevel %d\n",
                     ci->ci_isources[irq]->is_maxlevel, ilevel);                      evtch, evtsource[evtch]->ev_maxlevel, ilevel);
 #endif  #endif
                 ci->ci_ipending |= 1 << irq;                  hypervisor_set_ipending(evtch, evtch / 32, evtch % 32);
                 /* leave masked */                  /* leave masked */
                 return 0;                  return 0;
         }          }
         ci->ci_ilevel = ci->ci_isources[irq]->is_maxlevel;          ci->ci_ilevel = evtsource[evtch]->ev_maxlevel;
         /* sti */          /* sti */
         ci->ci_idepth++;          ci->ci_idepth++;
 #ifdef MULTIPROCESSOR  #ifdef MULTIPROCESSOR
         x86_intlock(regs);          x86_intlock(regs);
 #endif  #endif
         ih = ci->ci_isources[irq]->is_handlers;          ih = evtsource[evtch]->ev_handlers;
         while (ih != NULL) {          while (ih != NULL) {
                 if (ih->ih_level <= ilevel) {                  if (ih->ih_level <= ilevel) {
 #ifdef IRQ_DEBUG  #ifdef IRQ_DEBUG
                 if (irq == IRQ_DEBUG)                  if (evtch == IRQ_DEBUG)
                     printf("ih->ih_level %d <= ilevel %d\n", ih->ih_level, ilevel);                      printf("ih->ih_level %d <= ilevel %d\n", ih->ih_level, ilevel);
 #endif  #endif
 #ifdef MULTIPROCESSOR  #ifdef MULTIPROCESSOR
                         x86_intunlock(regs);                          x86_intunlock(regs);
 #endif  #endif
                         ci->ci_ipending |= 1 << irq;                          hypervisor_set_ipending(evtch, evtch / 32, evtch % 32);
                         /* leave masked */                          /* leave masked */
                         ci->ci_idepth--;                          ci->ci_idepth--;
                         splx(ilevel);                          splx(ilevel);
Line 222  do_event(int irq, struct intrframe *regs
Line 217  do_event(int irq, struct intrframe *regs
                 ci->ci_ilevel = ih->ih_level;                  ci->ci_ilevel = ih->ih_level;
                 ih_fun = (void *)ih->ih_fun;                  ih_fun = (void *)ih->ih_fun;
                 ih_fun(ih->ih_arg, regs);                  ih_fun(ih->ih_arg, regs);
                 ih = ih->ih_next;                  ih = ih->ih_evt_next;
         }          }
 #ifdef MULTIPROCESSOR  #ifdef MULTIPROCESSOR
         x86_intunlock(regs);          x86_intunlock(regs);
 #endif  #endif
         hypervisor_enable_irq(irq);          hypervisor_enable_event(evtch);
         ci->ci_idepth--;          ci->ci_idepth--;
         splx(ilevel);          splx(ilevel);
   
 #if 0 /* DDD */  
         if (irq >= 3)  
                 if (irq != 7) printf("do_event %d done, ipending %08x\n", irq,  
                     ci->ci_ipending);  
 #endif  
   
         return 0;          return 0;
 }  }
   
 static int  
 find_unbound_irq(void)  
 {  
         int irq;  
   
         for (irq = 0; irq < NR_IRQS; irq++)  
                 if (irq_bindcount[irq] == 0)  
                         break;  
   
         if (irq == NR_IRQS)  
                 panic("No available IRQ to bind to: increase NR_IRQS!\n");  
   
         return irq;  
 }  
   
 int  int
 bind_virq_to_irq(int virq)  bind_virq_to_evtch(int virq)
 {  {
         evtchn_op_t op;          evtchn_op_t op;
         int evtchn, irq;          int evtchn, s;
   
           s = splhigh();
         simple_lock(&irq_mapping_update_lock);          simple_lock(&irq_mapping_update_lock);
   
         irq = virq_to_irq[virq];          evtchn = virq_to_evtch[virq];
         if (irq == -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;
                 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;
                   if (virq == VIRQ_DEBUG)
                           debug_port = evtchn;
   
                 irq = find_unbound_irq();                  virq_to_evtch[virq] = evtchn;
                 evtchn_to_irq[evtchn] = irq;  
                 irq_to_evtchn[irq] = evtchn;  
   
                 virq_to_irq[virq] = irq;  
         }          }
   
         irq_bindcount[irq]++;          evtch_bindcount[evtchn]++;
   
         simple_unlock(&irq_mapping_update_lock);          simple_unlock(&irq_mapping_update_lock);
           splx(s);
   
         return irq;          return evtchn;
 }  }
   
 void  void
 unbind_virq_from_irq(int virq)  unbind_virq_from_evtch(int virq)
 {  {
         evtchn_op_t op;          evtchn_op_t op;
         int irq = virq_to_irq[virq];          int evtchn = virq_to_evtch[virq];
         int evtchn = irq_to_evtchn[irq];          int s = splhigh();
   
         simple_lock(&irq_mapping_update_lock);          simple_lock(&irq_mapping_update_lock);
   
         irq_bindcount[irq]--;          evtch_bindcount[evtchn]--;
         if (irq_bindcount[irq] == 0) {          if (evtch_bindcount[evtchn] == 0) {
                 op.cmd = EVTCHNOP_close;                  op.cmd = EVTCHNOP_close;
                 op.u.close.dom = DOMID_SELF;                  op.u.close.dom = DOMID_SELF;
                 op.u.close.port = evtchn;                  op.u.close.port = evtchn;
                 if (HYPERVISOR_event_channel_op(&op) != 0)                  if (HYPERVISOR_event_channel_op(&op) != 0)
                         panic("Failed to unbind virtual IRQ %d\n", virq);                          panic("Failed to unbind virtual IRQ %d\n", virq);
   
                 evtchn_to_irq[evtchn] = -1;                  virq_to_evtch[virq] = -1;
                 irq_to_evtchn[irq] = -1;  
                 virq_to_irq[virq] = -1;  
         }          }
   
         simple_unlock(&irq_mapping_update_lock);          simple_unlock(&irq_mapping_update_lock);
           splx(s);
 }  }
   
 #ifdef DOM0OPS  #ifdef DOM0OPS
 int  int
 bind_pirq_to_irq(int pirq)  bind_pirq_to_evtch(int pirq)
 {  {
         evtchn_op_t op;          evtchn_op_t op;
         int evtchn, irq;          int evtchn, s;
   
         if (pirq >= NR_PIRQS) {          if (pirq >= NR_PIRQS) {
                 panic("pirq %d out of bound, increase NR_PIRQS", pirq);                  panic("pirq %d out of bound, increase NR_PIRQS", pirq);
         }          }
   
           s = splhigh();
         simple_lock(&irq_mapping_update_lock);          simple_lock(&irq_mapping_update_lock);
   
         irq = pirq_to_irq[pirq];          evtchn = pirq_to_evtch[pirq];
         if (irq == -1) {          if (evtchn == -1) {
                 op.cmd = EVTCHNOP_bind_pirq;                  op.cmd = EVTCHNOP_bind_pirq;
                 op.u.bind_pirq.pirq = pirq;                  op.u.bind_pirq.pirq = pirq;
                 op.u.bind_pirq.flags = BIND_PIRQ__WILL_SHARE;                  op.u.bind_pirq.flags = BIND_PIRQ__WILL_SHARE;
Line 331  bind_pirq_to_irq(int pirq)
Line 306  bind_pirq_to_irq(int pirq)
                         panic("Failed to bind physical IRQ %d\n", pirq);                          panic("Failed to bind physical IRQ %d\n", pirq);
                 evtchn = op.u.bind_pirq.port;                  evtchn = op.u.bind_pirq.port;
   
                 irq = find_unbound_irq();  
 #ifdef IRQ_DEBUG  #ifdef IRQ_DEBUG
                 printf("pirq %d irq %d evtchn %d\n", pirq, irq, evtchn);                  printf("pirq %d evtchn %d\n", pirq, evtchn);
 #endif  #endif
                 evtchn_to_irq[evtchn] = irq;                  pirq_to_evtch[pirq] = evtchn;
                 irq_to_evtchn[irq] = evtchn;  
   
                 pirq_to_irq[pirq] = irq;  
         }          }
   
         irq_bindcount[irq]++;          evtch_bindcount[evtchn]++;
   
         simple_unlock(&irq_mapping_update_lock);          simple_unlock(&irq_mapping_update_lock);
           splx(s);
   
         return irq;          return evtchn;
 }  }
   
 void  void
 unbind_pirq_from_irq(int pirq)  unbind_pirq_from_evtch(int pirq)
 {  {
         evtchn_op_t op;          evtchn_op_t op;
         int irq = pirq_to_irq[pirq];          int evtchn = pirq_to_evtch[pirq];
         int evtchn = irq_to_evtchn[irq];          int s = splhigh();
   
         simple_lock(&irq_mapping_update_lock);          simple_lock(&irq_mapping_update_lock);
   
         irq_bindcount[irq]--;          evtch_bindcount[evtchn]--;
         if (irq_bindcount[irq] == 0) {          if (evtch_bindcount[evtchn] == 0) {
                 op.cmd = EVTCHNOP_close;                  op.cmd = EVTCHNOP_close;
                 op.u.close.dom = DOMID_SELF;                  op.u.close.dom = DOMID_SELF;
                 op.u.close.port = evtchn;                  op.u.close.port = evtchn;
                 if (HYPERVISOR_event_channel_op(&op) != 0)                  if (HYPERVISOR_event_channel_op(&op) != 0)
                         panic("Failed to unbind physical IRQ %d\n", pirq);                          panic("Failed to unbind physical IRQ %d\n", pirq);
   
                 evtchn_to_irq[evtchn] = -1;                  pirq_to_evtch[pirq] = -1;
                 irq_to_evtchn[irq] = -1;  
                 pirq_to_irq[pirq] = -1;  
         }          }
   
         simple_unlock(&irq_mapping_update_lock);          simple_unlock(&irq_mapping_update_lock);
           splx(s);
 }  }
   
 struct pintrhand *  struct pintrhand *
 pirq_establish(int pirq, int irq, int (*func)(void *), void *arg, int level)  pirq_establish(int pirq, int evtch, int (*func)(void *), void *arg, int level)
 {  {
         struct pintrhand *ih;          struct pintrhand *ih;
         physdev_op_t physdev_op;          physdev_op_t physdev_op;
           char evname[8];
   
         ih = malloc(sizeof *ih, M_DEVBUF, cold ? M_NOWAIT : M_WAITOK);          ih = malloc(sizeof *ih, M_DEVBUF, cold ? M_NOWAIT : M_WAITOK);
         if (ih == NULL) {          if (ih == NULL) {
                 printf("pirq_establish: can't malloc handler info\n");                  printf("pirq_establish: can't malloc handler info\n");
                 return NULL;                  return NULL;
         }          }
         if (event_set_handler(irq, pirq_interrupt, ih, level) != 0) {          snprintf(evname, sizeof(evname), "irq%d", pirq);
           if (event_set_handler(evtch, pirq_interrupt, ih, level, evname) != 0) {
                 free(ih, M_DEVBUF);                  free(ih, M_DEVBUF);
                 return NULL;                  return NULL;
         }          }
         ih->pirq = pirq;          ih->pirq = pirq;
         ih->irq = irq;          ih->evtch = evtch;
         ih->func = func;          ih->func = func;
         ih->arg = arg;          ih->arg = arg;
   
Line 399  pirq_establish(int pirq, int irq, int (*
Line 372  pirq_establish(int pirq, int irq, int (*
                 panic("HYPERVISOR_physdev_op(PHYSDEVOP_IRQ_STATUS_QUERY)");                  panic("HYPERVISOR_physdev_op(PHYSDEVOP_IRQ_STATUS_QUERY)");
         if (physdev_op.u.irq_status_query.flags &          if (physdev_op.u.irq_status_query.flags &
             PHYSDEVOP_IRQ_NEEDS_UNMASK_NOTIFY) {              PHYSDEVOP_IRQ_NEEDS_UNMASK_NOTIFY) {
                 irq_needs_unmask_notify[irq >> 5] |= (1 << (irq & 0x1f));                  pirq_needs_unmask_notify[evtch >> 5] |= (1 << (evtch & 0x1f));
 #ifdef IRQ_DEBUG  #ifdef IRQ_DEBUG
                 printf("pirq %d needs notify\n", pirq);                  printf("pirq %d needs notify\n", pirq);
 #endif  #endif
         }          }
         hypervisor_enable_irq(irq);          hypervisor_enable_event(evtch);
         return ih;          return ih;
 }  }
   
Line 417  pirq_interrupt(void *arg)
Line 390  pirq_interrupt(void *arg)
   
         ret = ih->func(ih->arg);          ret = ih->func(ih->arg);
 #ifdef IRQ_DEBUG  #ifdef IRQ_DEBUG
         if (ih->irq == IRQ_DEBUG)          if (ih->evtch == IRQ_DEBUG)
             printf("pirq_interrupt irq %d/%d ret %d\n", ih->irq, ih->pirq, ret);              printf("pirq_interrupt irq %d ret %d\n", ih->pirq, ret);
 #endif  #endif
         return ret;          return ret;
 }  }
   
 void  
 pirq_notify(int irq)  
 {  
   
         if (irq_needs_unmask_notify[irq >> 5] & (1 << (irq & 0x1f))) {  
 #ifdef  IRQ_DEBUG  
                 if (irq == IRQ_DEBUG)  
                     printf("pirq_notify(%d)\n", irq);  
 #endif  
                 (void)HYPERVISOR_physdev_op(&physdev_op_notify);  
         }  
 }  
   
 #endif /* DOM0OPS */  #endif /* DOM0OPS */
   
 int  int
 bind_evtchn_to_irq(int evtchn)  event_set_handler(int evtch, int (*func)(void *), void *arg, int level,
       const char *evname)
 {  {
         int irq;          struct iplsource *ipls;
           struct evtsource *evts;
         simple_lock(&irq_mapping_update_lock);  
   
         irq = evtchn_to_irq[evtchn];  
         if (irq == -1) {  
                 irq = find_unbound_irq();  
                 evtchn_to_irq[evtchn] = irq;  
                 irq_to_evtchn[irq] = evtchn;  
         }  
   
         irq_bindcount[irq]++;  
   
         simple_unlock(&irq_mapping_update_lock);  
   
         return irq;  
 }  
   
 int  
 unbind_evtchn_to_irq(int evtchn)  
 {  
         int irq;  
   
         simple_lock(&irq_mapping_update_lock);  
   
         irq = evtchn_to_irq[evtchn];  
         if (irq == -1) {  
                 return ENOENT;  
         }  
         irq_bindcount[irq]--;  
         if (irq_bindcount[irq] == 0) {  
                 evtchn_to_irq[evtchn] = -1;  
                 irq_to_evtchn[irq] = -1;  
         }  
   
         simple_unlock(&irq_mapping_update_lock);  
   
         return irq;  
 }  
   
 int  
 event_set_handler(int irq, ev_handler_t handler, void *arg, int level)  
 {  
         struct intrsource *isp;  
         struct intrhand *ih;          struct intrhand *ih;
         struct cpu_info *ci;          struct cpu_info *ci;
           int s;
   
 #ifdef IRQ_DEBUG  #ifdef IRQ_DEBUG
         printf("event_set_handler IRQ %d handler %p\n", irq, handler);          printf("event_set_handler IRQ %d handler %p\n", evtch, func);
 #endif  #endif
   
         if (irq >= NR_IRQS) {  
 #ifdef DIAGNOSTIC  #ifdef DIAGNOSTIC
                 printf("irq number %d > NR_IRQS\n", irq);          if (evtch >= NR_EVENT_CHANNELS) {
 #endif                  printf("evtch number %d > NR_EVENT_CHANNELS\n", evtch);
                 return ENOENT;                  panic("event_set_handler");
         }          }
   #endif
   
 #if 0  #if 0
         printf("event_set_handler irq %d/%d handler %p level %d\n", irq,          printf("event_set_handler evtch %d handler %p level %d\n", evtch,
                irq_to_evtchn[irq], handler, level);                 handler, level);
 #endif  #endif
         MALLOC(ih, struct intrhand *, sizeof (struct intrhand), M_DEVBUF,          MALLOC(ih, struct intrhand *, sizeof (struct intrhand), M_DEVBUF,
             M_WAITOK|M_ZERO);              M_WAITOK|M_ZERO);
Line 510  event_set_handler(int irq, ev_handler_t 
Line 430  event_set_handler(int irq, ev_handler_t 
   
   
         ih->ih_level = level;          ih->ih_level = level;
         ih->ih_fun = handler;          ih->ih_fun = func;
         ih->ih_arg = arg;          ih->ih_arg = arg;
         ih->ih_next = NULL;          ih->ih_evt_next = NULL;
           ih->ih_ipl_next = NULL;
   
         ci = &cpu_info_primary;          ci = &cpu_info_primary;
         if (ci->ci_isources[irq] == NULL) {          s = splhigh();
                 MALLOC(isp, struct intrsource *, sizeof (struct intrsource),          if (ci->ci_isources[level] == NULL) {
                   MALLOC(ipls, struct iplsource *, sizeof (struct iplsource),
                       M_DEVBUF, M_WAITOK|M_ZERO);
                   if (ipls == NULL)
                           panic("can't allocate fixed interrupt source");
                   ipls->ipl_recurse = xenev_stubs[level].ist_recurse;
                   ipls->ipl_resume = xenev_stubs[level].ist_resume;
                   ipls->ipl_handlers = ih;
                   ci->ci_isources[level] = ipls;
           } else {
                   ipls = ci->ci_isources[level];
                   ih->ih_ipl_next = ipls->ipl_handlers;
                   ipls->ipl_handlers = ih;
           }
           if (evtsource[evtch] == NULL) {
                   MALLOC(evts, struct evtsource *, sizeof (struct evtsource),
                     M_DEVBUF, M_WAITOK|M_ZERO);                      M_DEVBUF, M_WAITOK|M_ZERO);
                 if (isp == NULL)                  if (evts == NULL)
                         panic("can't allocate fixed interrupt source");                          panic("can't allocate fixed interrupt source");
                 isp->is_recurse = xenev_stubs[irq].ist_recurse;                  evts->ev_handlers = ih;
                 isp->is_resume = xenev_stubs[irq].ist_resume;                  evtsource[evtch] = evts;
                 isp->is_handlers = ih;                  if (evname)
                 isp->is_pic = &xenev_pic;                          strncpy(evts->ev_evname, evname,
                 ci->ci_isources[irq] = isp;                              sizeof(evts->ev_evname));
                 snprintf(isp->is_evname, sizeof(isp->is_evname), "irq%d", irq);                  else
                 evcnt_attach_dynamic(&isp->is_evcnt, EVCNT_TYPE_INTR, NULL,                          snprintf(evts->ev_evname, sizeof(evts->ev_evname),
                     ci->ci_dev->dv_xname, isp->is_evname);                              "evt%d", evtch);
                   evcnt_attach_dynamic(&evts->ev_evcnt, EVCNT_TYPE_INTR, NULL,
                       ci->ci_dev->dv_xname, evts->ev_evname);
         } else {          } else {
                 isp = ci->ci_isources[irq];                  evts = evtsource[evtch];
                 ih->ih_next = isp->is_handlers;                  ih->ih_evt_next = evts->ev_handlers;
                 isp->is_handlers = ih;                  evts->ev_handlers = ih;
         }          }
   
         intr_calculatemasks(ci);          intr_calculatemasks(evts);
           splx(s);
   
         return 0;          return 0;
 }  }
   
 int  int
 event_remove_handler(int irq, ev_handler_t handler, void *arg)  event_remove_handler(int evtch, int (*func)(void *), void *arg)
 {  {
         struct intrsource *isp;          struct iplsource *ipls;
           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 = &cpu_info_primary;
   
         isp = ci->ci_isources[irq];          evts = evtsource[evtch];
         if (isp == NULL)          if (evts == NULL)
                 return ENOENT;                  return ENOENT;
   
         for (ihp = &isp->is_handlers, ih = isp->is_handlers;          for (ihp = &evts->ev_handlers, ih = evts->ev_handlers;
             ih != NULL;              ih != NULL;
             ihp = &ih->ih_next, ih = ih->ih_next) {              ihp = &ih->ih_evt_next, ih = ih->ih_evt_next) {
                 if (ih->ih_fun == handler && ih->ih_arg == arg)                  if (ih->ih_fun == func && ih->ih_arg == arg)
                         break;                          break;
         }          }
         if (ih == NULL)          if (ih == NULL)
                 return ENOENT;                  return ENOENT;
         *ihp = ih->ih_next;          *ihp = ih->ih_evt_next;
   
           ipls = ci->ci_isources[ih->ih_level];
           for (ihp = &ipls->ipl_handlers, ih = ipls->ipl_handlers;
               ih != NULL;
               ihp = &ih->ih_ipl_next, ih = ih->ih_ipl_next) {
                   if (ih->ih_fun == func && ih->ih_arg == arg)
                           break;
           }
           if (ih == NULL)
                   panic("event_remove_handler");
           *ihp = ih->ih_ipl_next;
         FREE(ih, M_DEVBUF);          FREE(ih, M_DEVBUF);
         if (isp->is_handlers == NULL) {          if (evts->ev_handlers == NULL) {
                 evcnt_detach(&isp->is_evcnt);                  evcnt_detach(&evts->ev_evcnt);
                 FREE(isp, M_DEVBUF);                  FREE(evts, M_DEVBUF);
                 ci->ci_isources[irq] = NULL;                  evtsource[evtch] = NULL;
           } else {
                   intr_calculatemasks(evts);
         }          }
         intr_calculatemasks(ci);  
         return 0;          return 0;
 }  }
   
 void  void
 hypervisor_enable_irq(unsigned int irq)  hypervisor_enable_event(unsigned int evtch)
 {  {
 #ifdef IRQ_DEBUG  #ifdef IRQ_DEBUG
         if (irq == IRQ_DEBUG)          if (evtch == IRQ_DEBUG)
                 printf("hypervisor_enable_irq: irq %d\n", irq);                  printf("hypervisor_enable_evtch: evtch %d\n", evtch);
 #endif  #endif
   
         hypervisor_unmask_event(irq_to_evtchn[irq]);          hypervisor_unmask_event(evtch);
 #ifdef DOM0OPS  #ifdef DOM0OPS
         pirq_notify(irq);          if (pirq_needs_unmask_notify[evtch >> 5] & (1 << (evtch & 0x1f))) {
 #endif  #ifdef  IRQ_DEBUG
 }                  if (evtch == IRQ_DEBUG)
                       printf("pirq_notify(%d)\n", evtch);
 void  
 hypervisor_disable_irq(unsigned int irq)  
 {  
 #ifdef IRQ_DEBUG  
         if (irq == IRQ_DEBUG)  
                 printf("hypervisor_disable_irq: irq %d\n", irq);  
 #endif  
   
         hypervisor_mask_event(irq_to_evtchn[irq]);  
 }  
   
 void  
 hypervisor_acknowledge_irq(unsigned int irq)  
 {  
 #ifdef IRQ_DEBUG  
         if (irq == IRQ_DEBUG)  
                 printf("hypervisor_acknowledge_irq: irq %d\n", irq);  
 #endif  #endif
         hypervisor_mask_event(irq_to_evtchn[irq]);                  (void)HYPERVISOR_physdev_op(&physdev_op_notify);
         hypervisor_clear_event(irq_to_evtchn[irq]);          }
 }  #endif /* DOM0OPS */
   
 #if 0  
 static int  
 xen_die_handler(void *arg)  
 {  
         printf("hypervisor: DIE event received...\n");  
         cpu_reboot(0, NULL);  
         /* NOTREACHED */  
         return 0;  
 }  }
 #endif  
   
 static int  static int
 xen_debug_handler(void *arg)  xen_debug_handler(void *arg)
 {  {
           struct cpu_info *ci = curcpu();
           int i;
         printf("debug event\n");          printf("debug event\n");
           printf("ci_ilevel 0x%x ci_ipending 0x%x ci_idepth %d\n",
               ci->ci_ilevel, ci->ci_ipending, ci->ci_idepth);
           printf("evtchn_upcall_pending %d evtchn_upcall_mask %d"
               " evtchn_pending_sel 0x%x\n",
                   HYPERVISOR_shared_info->vcpu_data[0].evtchn_upcall_pending,
                   HYPERVISOR_shared_info->vcpu_data[0].evtchn_upcall_mask,
                   HYPERVISOR_shared_info->evtchn_pending_sel);
           printf("evtchn_mask");
           for (i = 0 ; i < 32; i++)
                   printf(" %x", HYPERVISOR_shared_info->evtchn_mask[i]);
           printf("\n");
           printf("evtchn_pending");
           for (i = 0 ; i < 32; i++)
                   printf(" %x", HYPERVISOR_shared_info->evtchn_pending[i]);
           printf("\n");
         return 0;          return 0;
 }  }
   

Legend:
Removed from v.1.3  
changed lines
  Added in v.1.3.2.8

CVSweb <webmaster@jp.NetBSD.org>