ia64/xen-unstable

changeset 2932:cbdc0480194e

bitkeeper revision 1.1159.1.401 (41923739R6r2c-dNxHPSxOagRn-R3g)

Setup cpu-local interrupt handline.
Add support for ipi event channels.
author cl349@freefall.cl.cam.ac.uk
date Wed Nov 10 15:43:53 2004 +0000 (2004-11-10)
parents b12c5094e28c
children 23aab6d318e5
files linux-2.6.9-xen-sparse/arch/xen/i386/kernel/smpboot.c linux-2.6.9-xen-sparse/arch/xen/i386/kernel/time.c linux-2.6.9-xen-sparse/arch/xen/kernel/evtchn.c linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/mach-xen/irq_vectors.h xen/common/event_channel.c xen/common/keyhandler.c xen/include/public/event_channel.h xen/include/xen/sched.h
line diff
     1.1 --- a/linux-2.6.9-xen-sparse/arch/xen/i386/kernel/smpboot.c	Wed Nov 10 14:32:43 2004 +0000
     1.2 +++ b/linux-2.6.9-xen-sparse/arch/xen/i386/kernel/smpboot.c	Wed Nov 10 15:43:53 2004 +0000
     1.3 @@ -441,6 +441,32 @@ int cpucount;
     1.4  
     1.5  extern int cpu_idle(void);
     1.6  
     1.7 +
     1.8 +static irqreturn_t local_debug_interrupt(int irq, void *dev_id,
     1.9 +					 struct pt_regs *regs)
    1.10 +{
    1.11 +	xxprint("local_debug_interrupt\n");
    1.12 +
    1.13 +	return IRQ_HANDLED;
    1.14 +}
    1.15 +
    1.16 +static struct irqaction local_irq_debug = {
    1.17 +	local_debug_interrupt, SA_INTERRUPT, CPU_MASK_NONE, "ldebug",
    1.18 +	NULL, NULL
    1.19 +};
    1.20 +
    1.21 +void local_setup_debug(void)
    1.22 +{
    1.23 +	int time_irq;
    1.24 +
    1.25 +	time_irq = bind_virq_to_irq(VIRQ_DEBUG);
    1.26 +	(void)setup_irq(time_irq, &local_irq_debug);
    1.27 +}
    1.28 +
    1.29 +
    1.30 +extern void setup_misdirect_virq(void);
    1.31 +extern void local_setup_timer(void);
    1.32 +
    1.33  /*
    1.34   * Activate a secondary processor.
    1.35   */
    1.36 @@ -455,29 +481,18 @@ int __init start_secondary(void *unused)
    1.37  	smp_callin();
    1.38  	while (!cpu_isset(smp_processor_id(), smp_commenced_mask))
    1.39  		rep_nop();
    1.40 -#if 1
    1.41 -	if (0) {
    1.42 -		char *msg = "start_secondary\n";
    1.43 -		char *msg2 = "delay2\n";
    1.44 -		int timeout;
    1.45 -		(void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(msg), msg);
    1.46 -		for (timeout = 0; timeout < 50000; timeout++) {
    1.47 -			udelay(100);
    1.48 -			if (timeout == 20000) {
    1.49 -				(void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(msg2), msg2);
    1.50 -				timeout = 0;
    1.51 -			}
    1.52 -		}
    1.53 -	}
    1.54 -	// enable_APIC_timer();
    1.55 +	setup_misdirect_virq();
    1.56 +	local_setup_timer();
    1.57 +	local_setup_debug();	/* XXX */
    1.58 +	local_irq_enable();
    1.59  	/*
    1.60  	 * low-memory mappings have been cleared, flush them from
    1.61  	 * the local TLBs too.
    1.62  	 */
    1.63 -	// local_flush_tlb();
    1.64 +	local_flush_tlb();
    1.65  	cpu_set(smp_processor_id(), cpu_online_map);
    1.66  	wmb();
    1.67 -	if (10) {
    1.68 +	if (01) {
    1.69  		char *msg2 = "delay2\n";
    1.70  		int timeout;
    1.71  		for (timeout = 0; timeout < 50000; timeout++) {
    1.72 @@ -489,32 +504,6 @@ int __init start_secondary(void *unused)
    1.73  		}
    1.74  	}
    1.75  	return cpu_idle();
    1.76 -#else
    1.77 -	/*
    1.78 -	 * Dont put anything before smp_callin(), SMP
    1.79 -	 * booting is too fragile that we want to limit the
    1.80 -	 * things done here to the most necessary things.
    1.81 -	 */
    1.82 -	cpu_init();
    1.83 -	smp_callin();
    1.84 -	while (!cpu_isset(smp_processor_id(), smp_commenced_mask))
    1.85 -		rep_nop();
    1.86 -	setup_secondary_APIC_clock();
    1.87 -	if (nmi_watchdog == NMI_IO_APIC) {
    1.88 -		disable_8259A_irq(0);
    1.89 -		enable_NMI_through_LVT0(NULL);
    1.90 -		enable_8259A_irq(0);
    1.91 -	}
    1.92 -	enable_APIC_timer();
    1.93 -	/*
    1.94 -	 * low-memory mappings have been cleared, flush them from
    1.95 -	 * the local TLBs too.
    1.96 -	 */
    1.97 -	local_flush_tlb();
    1.98 -	cpu_set(smp_processor_id(), cpu_online_map);
    1.99 -	wmb();
   1.100 -	return cpu_idle();
   1.101 -#endif
   1.102  }
   1.103  
   1.104  /*
     2.1 --- a/linux-2.6.9-xen-sparse/arch/xen/i386/kernel/time.c	Wed Nov 10 14:32:43 2004 +0000
     2.2 +++ b/linux-2.6.9-xen-sparse/arch/xen/i386/kernel/time.c	Wed Nov 10 15:43:53 2004 +0000
     2.3 @@ -702,6 +702,35 @@ void time_resume(void)
     2.4  	last_update_from_xen = 0;
     2.5  }
     2.6  
     2.7 +#ifdef CONFIG_SMP
     2.8 +static irqreturn_t local_timer_interrupt(int irq, void *dev_id,
     2.9 +					 struct pt_regs *regs)
    2.10 +{
    2.11 +	static int xxx = 0;
    2.12 +	if ((xxx++ % 100) == 0)
    2.13 +		xxprint("local_timer_interrupt\n");
    2.14 +
    2.15 +	/* XXX add processed_system_time loop thingy */
    2.16 +	if (regs)
    2.17 +		update_process_times(user_mode(regs));
    2.18 +
    2.19 +	return IRQ_HANDLED;
    2.20 +}
    2.21 +
    2.22 +static struct irqaction local_irq_timer = {
    2.23 +	local_timer_interrupt, SA_INTERRUPT, CPU_MASK_NONE, "ltimer",
    2.24 +	NULL, NULL
    2.25 +};
    2.26 +
    2.27 +void local_setup_timer(void)
    2.28 +{
    2.29 +	int time_irq;
    2.30 +
    2.31 +	time_irq = bind_virq_to_irq(VIRQ_TIMER);
    2.32 +	(void)setup_irq(time_irq, &local_irq_timer);
    2.33 +}
    2.34 +#endif
    2.35 +
    2.36  /*
    2.37   * /proc/sys/xen: This really belongs in another file. It can stay here for
    2.38   * now however.
     3.1 --- a/linux-2.6.9-xen-sparse/arch/xen/kernel/evtchn.c	Wed Nov 10 14:32:43 2004 +0000
     3.2 +++ b/linux-2.6.9-xen-sparse/arch/xen/kernel/evtchn.c	Wed Nov 10 15:43:53 2004 +0000
     3.3 @@ -61,7 +61,11 @@ static int evtchn_to_irq[NR_EVENT_CHANNE
     3.4  static int irq_to_evtchn[NR_IRQS];
     3.5  
     3.6  /* IRQ <-> VIRQ mapping. */
     3.7 -static int virq_to_irq[NR_VIRQS];
     3.8 +DEFINE_PER_CPU(int, virq_to_irq[NR_VIRQS]);
     3.9 +
    3.10 +#define NR_IPIS 8
    3.11 +/* IRQ <-> IPI mapping. */
    3.12 +DEFINE_PER_CPU(int, ipi_to_evtchn[NR_IPIS]);
    3.13  
    3.14  /* Reference counts for bindings to IRQs. */
    3.15  static int irq_bindcount[NR_IRQS];
    3.16 @@ -141,10 +145,11 @@ int bind_virq_to_irq(int virq)
    3.17  {
    3.18      evtchn_op_t op;
    3.19      int evtchn, irq;
    3.20 +    int cpu = smp_processor_id();
    3.21  
    3.22      spin_lock(&irq_mapping_update_lock);
    3.23  
    3.24 -    if ( (irq = virq_to_irq[virq]) == -1 )
    3.25 +    if ( (irq = per_cpu(virq_to_irq, cpu)[virq]) == -1 )
    3.26      {
    3.27          op.cmd              = EVTCHNOP_bind_virq;
    3.28          op.u.bind_virq.virq = virq;
    3.29 @@ -156,7 +161,7 @@ int bind_virq_to_irq(int virq)
    3.30          evtchn_to_irq[evtchn] = irq;
    3.31          irq_to_evtchn[irq]    = evtchn;
    3.32  
    3.33 -        virq_to_irq[virq] = irq;
    3.34 +        per_cpu(virq_to_irq, cpu)[virq] = irq;
    3.35      }
    3.36  
    3.37      irq_bindcount[irq]++;
    3.38 @@ -169,7 +174,8 @@ int bind_virq_to_irq(int virq)
    3.39  void unbind_virq_from_irq(int virq)
    3.40  {
    3.41      evtchn_op_t op;
    3.42 -    int irq    = virq_to_irq[virq];
    3.43 +    int cpu    = smp_processor_id();
    3.44 +    int irq    = per_cpu(virq_to_irq, cpu)[virq];
    3.45      int evtchn = irq_to_evtchn[irq];
    3.46  
    3.47      spin_lock(&irq_mapping_update_lock);
    3.48 @@ -184,12 +190,48 @@ void unbind_virq_from_irq(int virq)
    3.49  
    3.50          evtchn_to_irq[evtchn] = -1;
    3.51          irq_to_evtchn[irq]    = -1;
    3.52 -        virq_to_irq[virq]     = -1;
    3.53 +        per_cpu(virq_to_irq, cpu)[virq]     = -1;
    3.54      }
    3.55  
    3.56      spin_unlock(&irq_mapping_update_lock);
    3.57  }
    3.58  
    3.59 +void bind_ipi_on_cpu(int cpu, int ipi)
    3.60 +{
    3.61 +    evtchn_op_t op;
    3.62 +
    3.63 +    spin_lock(&irq_mapping_update_lock);
    3.64 +
    3.65 +    if (per_cpu(ipi_to_evtchn, cpu)[ipi] == 0) {
    3.66 +        op.cmd                 = EVTCHNOP_bind_ipi;
    3.67 +        op.u.bind_ipi.ipi_edom = cpu;
    3.68 +        if ( HYPERVISOR_event_channel_op(&op) != 0 )
    3.69 +            panic("Failed to bind virtual IPI %d on cpu %d\n", ipi, cpu);
    3.70 +
    3.71 +        per_cpu(ipi_to_evtchn, cpu)[ipi] = op.u.bind_ipi.port;
    3.72 +    }
    3.73 +
    3.74 +    spin_unlock(&irq_mapping_update_lock);
    3.75 +}
    3.76 +
    3.77 +void unbind_ipi_on_cpu(int cpu, int ipi)
    3.78 +{
    3.79 +    evtchn_op_t op;
    3.80 +    int evtchn = per_cpu(ipi_to_evtchn, cpu)[ipi];
    3.81 +
    3.82 +    spin_lock(&irq_mapping_update_lock);
    3.83 +
    3.84 +    op.cmd          = EVTCHNOP_close;
    3.85 +    op.u.close.dom  = DOMID_SELF;
    3.86 +    op.u.close.port = evtchn;
    3.87 +    if ( HYPERVISOR_event_channel_op(&op) != 0 )
    3.88 +	panic("Failed to unbind virtual IPI %d on cpu %d\n", ipi, cpu);
    3.89 +
    3.90 +    per_cpu(ipi_to_evtchn, cpu)[ipi] = 0;
    3.91 +
    3.92 +    spin_unlock(&irq_mapping_update_lock);
    3.93 +}
    3.94 +
    3.95  int bind_evtchn_to_irq(int evtchn)
    3.96  {
    3.97      int irq;
    3.98 @@ -414,6 +456,11 @@ static struct irqaction misdirect_action
    3.99      NULL
   3.100  };
   3.101  
   3.102 +void setup_misdirect_virq(void)
   3.103 +{
   3.104 +    (void)setup_irq(bind_virq_to_irq(VIRQ_MISDIRECT), &misdirect_action);
   3.105 +}
   3.106 +
   3.107  static irqreturn_t xen_dbg(int irq, void *dev_id, struct pt_regs *regs)
   3.108  {
   3.109       char *msg = "debug\n";
   3.110 @@ -433,11 +480,12 @@ static struct irqaction xen_action = {
   3.111  void irq_suspend(void)
   3.112  {
   3.113      int pirq, virq, irq, evtchn;
   3.114 +    int cpu = smp_processor_id(); /* XXX */
   3.115  
   3.116      /* Unbind VIRQs from event channels. */
   3.117      for ( virq = 0; virq < NR_VIRQS; virq++ )
   3.118      {
   3.119 -        if ( (irq = virq_to_irq[virq]) == -1 )
   3.120 +        if ( (irq = per_cpu(virq_to_irq, cpu)[virq]) == -1 )
   3.121              continue;
   3.122          evtchn = irq_to_evtchn[irq];
   3.123  
   3.124 @@ -457,13 +505,14 @@ void irq_resume(void)
   3.125  {
   3.126      evtchn_op_t op;
   3.127      int         virq, irq, evtchn;
   3.128 +    int cpu = smp_processor_id(); /* XXX */
   3.129  
   3.130      for ( evtchn = 0; evtchn < NR_EVENT_CHANNELS; evtchn++ )
   3.131          mask_evtchn(evtchn); /* New event-channel space is not 'live' yet. */
   3.132  
   3.133      for ( virq = 0; virq < NR_VIRQS; virq++ )
   3.134      {
   3.135 -        if ( (irq = virq_to_irq[virq]) == -1 )
   3.136 +        if ( (irq = per_cpu(virq_to_irq, cpu)[virq]) == -1 )
   3.137              continue;
   3.138  
   3.139          /* Get a new binding from Xen. */
   3.140 @@ -485,12 +534,14 @@ void irq_resume(void)
   3.141  void __init init_IRQ(void)
   3.142  {
   3.143      int i;
   3.144 +    int cpu;
   3.145  
   3.146      spin_lock_init(&irq_mapping_update_lock);
   3.147  
   3.148      /* No VIRQ -> IRQ mappings. */
   3.149 -    for ( i = 0; i < NR_VIRQS; i++ )
   3.150 -        virq_to_irq[i] = -1;
   3.151 +    for ( cpu = 0; cpu < NR_CPUS; cpu++ )
   3.152 +	for ( i = 0; i < NR_VIRQS; i++ )
   3.153 +	    per_cpu(virq_to_irq, cpu)[i] = -1;
   3.154  
   3.155      /* No event-channel -> IRQ mappings. */
   3.156      for ( i = 0; i < NR_EVENT_CHANNELS; i++ )
   3.157 @@ -525,7 +576,7 @@ void __init init_IRQ(void)
   3.158          irq_desc[pirq_to_irq(i)].handler = &pirq_type;
   3.159      }
   3.160  
   3.161 -    (void)setup_irq(bind_virq_to_irq(VIRQ_MISDIRECT), &misdirect_action);
   3.162 +    (void)setup_misdirect_virq();
   3.163  
   3.164      printk("debug_int\n");
   3.165  	(void)setup_irq(bind_virq_to_irq(VIRQ_DEBUG), &xen_action);
     4.1 --- a/linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/mach-xen/irq_vectors.h	Wed Nov 10 14:32:43 2004 +0000
     4.2 +++ b/linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/mach-xen/irq_vectors.h	Wed Nov 10 15:43:53 2004 +0000
     4.3 @@ -138,6 +138,8 @@
     4.4  /* Dynamic binding of event channels and VIRQ sources to Linux IRQ space. */
     4.5  extern int  bind_virq_to_irq(int virq);
     4.6  extern void unbind_virq_from_irq(int virq);
     4.7 +extern int  bind_ipi_on_cpu(int cpu, int ipi);
     4.8 +extern void unbind_ipi_on_cpu(int cpu, int ipi);
     4.9  extern int  bind_evtchn_to_irq(int evtchn);
    4.10  extern void unbind_evtchn_from_irq(int evtchn);
    4.11  
     5.1 --- a/xen/common/event_channel.c	Wed Nov 10 14:32:43 2004 +0000
     5.2 +++ b/xen/common/event_channel.c	Wed Nov 10 15:43:53 2004 +0000
     5.3 @@ -270,6 +270,33 @@ static long evtchn_bind_virq(evtchn_bind
     5.4          return port;
     5.5  
     5.6      bind->port = port;
     5.7 +    printk("evtchn_bind_virq %d/%d virq %d -> %d\n",
     5.8 +           d->id, ed->eid, virq, port);
     5.9 +    return 0;
    5.10 +}
    5.11 +
    5.12 +static long evtchn_bind_ipi(evtchn_bind_ipi_t *bind)
    5.13 +{
    5.14 +    struct exec_domain *ed = current;
    5.15 +    struct domain *d = ed->domain;
    5.16 +    int            port, ipi_edom = bind->ipi_edom;
    5.17 +
    5.18 +    spin_lock(&d->event_channel_lock);
    5.19 +
    5.20 +    if ( (port = get_free_port(d)) >= 0 )
    5.21 +    {
    5.22 +        d->event_channel[port].state      = ECS_IPI;
    5.23 +        d->event_channel[port].u.ipi_edom = ipi_edom;
    5.24 +    }
    5.25 +
    5.26 +    spin_unlock(&d->event_channel_lock);
    5.27 +
    5.28 +    if ( port < 0 )
    5.29 +        return port;
    5.30 +
    5.31 +    bind->port = port;
    5.32 +    printk("evtchn_bind_ipi %d/%d ipi_edom %d -> %d\n",
    5.33 +           d->id, current->eid, ipi_edom, port);
    5.34      return 0;
    5.35  }
    5.36  
    5.37 @@ -307,6 +334,8 @@ static long evtchn_bind_pirq(evtchn_bind
    5.38          return rc;
    5.39  
    5.40      bind->port = port;
    5.41 +    printk("evtchn_bind_pirq %d/%d pirq %d -> port %d\n",
    5.42 +           d->id, current->eid, pirq, port);
    5.43      return 0;
    5.44  }
    5.45  
    5.46 @@ -352,6 +381,9 @@ static long __evtchn_close(struct domain
    5.47                  ed->virq_to_evtchn[chn1[port1].u.virq] = 0;
    5.48          break;
    5.49  
    5.50 +    case ECS_IPI:
    5.51 +        break;
    5.52 +
    5.53      case ECS_INTERDOMAIN:
    5.54          if ( d2 == NULL )
    5.55          {
    5.56 @@ -516,6 +548,10 @@ static long evtchn_status(evtchn_status_
    5.57          status->status = EVTCHNSTAT_virq;
    5.58          status->u.virq = chn[port].u.virq;
    5.59          break;
    5.60 +    case ECS_IPI:
    5.61 +        status->status     = EVTCHNSTAT_ipi;
    5.62 +        status->u.ipi_edom = chn[port].u.ipi_edom;
    5.63 +        break;
    5.64      default:
    5.65          BUG();
    5.66      }
    5.67 @@ -555,6 +591,12 @@ long do_event_channel_op(evtchn_op_t *uo
    5.68              rc = -EFAULT; /* Cleaning up here would be a mess! */
    5.69          break;
    5.70  
    5.71 +    case EVTCHNOP_bind_ipi:
    5.72 +        rc = evtchn_bind_ipi(&op.u.bind_ipi);
    5.73 +        if ( (rc == 0) && (copy_to_user(uop, &op, sizeof(op)) != 0) )
    5.74 +            rc = -EFAULT; /* Cleaning up here would be a mess! */
    5.75 +        break;
    5.76 +
    5.77      case EVTCHNOP_bind_pirq:
    5.78          rc = evtchn_bind_pirq(&op.u.bind_pirq);
    5.79          if ( (rc == 0) && (copy_to_user(uop, &op, sizeof(op)) != 0) )
     6.1 --- a/xen/common/keyhandler.c	Wed Nov 10 14:32:43 2004 +0000
     6.2 +++ b/xen/common/keyhandler.c	Wed Nov 10 15:43:53 2004 +0000
     6.3 @@ -107,15 +107,14 @@ void do_task_queues(unsigned char key)
     6.4                     ed->ed_flags,
     6.5                     ed->vcpu_info->evtchn_upcall_pending, 
     6.6                     ed->vcpu_info->evtchn_upcall_mask);
     6.7 +            printk("Notifying guest... %d/%d\n", d->id, ed->eid); 
     6.8 +            printk("port %d/%d stat %d %d %d\n",
     6.9 +                   VIRQ_DEBUG, ed->virq_to_evtchn[VIRQ_DEBUG],
    6.10 +                   test_bit(ed->virq_to_evtchn[VIRQ_DEBUG], &d->shared_info->evtchn_pending[0]),
    6.11 +                   test_bit(ed->virq_to_evtchn[VIRQ_DEBUG], &d->shared_info->evtchn_mask[0]),
    6.12 +                   test_bit(ed->virq_to_evtchn[VIRQ_DEBUG]>>5, &ed->vcpu_info->evtchn_pending_sel));
    6.13 +            send_guest_virq(ed, VIRQ_DEBUG);
    6.14          }
    6.15 -        ed = d->exec_domain[0];
    6.16 -        printk("Notifying guest... %d/%d\n", d->id, ed->eid); 
    6.17 -        printk("port %d/%d stat %d %d %d\n",
    6.18 -               VIRQ_DEBUG, ed->virq_to_evtchn[VIRQ_DEBUG],
    6.19 -               test_bit(ed->virq_to_evtchn[VIRQ_DEBUG], &d->shared_info->evtchn_pending[0]),
    6.20 -               test_bit(ed->virq_to_evtchn[VIRQ_DEBUG], &d->shared_info->evtchn_mask[0]),
    6.21 -               test_bit(ed->virq_to_evtchn[VIRQ_DEBUG]>>5, &ed->vcpu_info->evtchn_pending_sel));
    6.22 -        send_guest_virq(d->exec_domain[0], VIRQ_DEBUG);
    6.23      }
    6.24  
    6.25      read_unlock(&domlist_lock);
     7.1 --- a/xen/include/public/event_channel.h	Wed Nov 10 14:32:43 2004 +0000
     7.2 +++ b/xen/include/public/event_channel.h	Wed Nov 10 15:43:53 2004 +0000
     7.3 @@ -128,6 +128,7 @@ typedef struct {
     7.4  #define EVTCHNSTAT_interdomain  2  /* Channel is connected to remote domain. */
     7.5  #define EVTCHNSTAT_pirq         3  /* Channel is bound to a phys IRQ line.   */
     7.6  #define EVTCHNSTAT_virq         4  /* Channel is bound to a virtual IRQ line */
     7.7 +#define EVTCHNSTAT_ipi          5  /* Channel is bound to a virtual IPI line */
     7.8      u32     status;                   /*  8 */
     7.9      union {                           /* 12 */
    7.10          struct {
    7.11 @@ -140,9 +141,22 @@ typedef struct {
    7.12          } PACKED interdomain; /* EVTCHNSTAT_interdomain */
    7.13          u32 pirq;      /* EVTCHNSTAT_pirq        */   /* 12 */
    7.14          u32 virq;      /* EVTCHNSTAT_virq        */   /* 12 */
    7.15 +        u32 ipi_edom;  /* EVTCHNSTAT_ipi         */   /* 12 */
    7.16      } PACKED u;
    7.17  } PACKED evtchn_status_t; /* 20 bytes */
    7.18  
    7.19 +/*
    7.20 + * EVTCHNOP_bind_ipi: Bind a local event channel to receive events.
    7.21 + */
    7.22 +#define EVTCHNOP_bind_ipi         7
    7.23 +typedef struct {
    7.24 +    /* IN parameters. */
    7.25 +    u32 ipi_edom;                     /*  0 */
    7.26 +    /* OUT parameters. */
    7.27 +    u32 port;                         /*  4 */
    7.28 +} PACKED evtchn_bind_ipi_t; /* 8 bytes */
    7.29 +
    7.30 +
    7.31  typedef struct {
    7.32      u32 cmd; /* EVTCHNOP_* */         /*  0 */
    7.33      u32 __reserved;                   /*  4 */
    7.34 @@ -154,6 +168,7 @@ typedef struct {
    7.35          evtchn_close_t            close;
    7.36          evtchn_send_t             send;
    7.37          evtchn_status_t           status;
    7.38 +        evtchn_bind_ipi_t         bind_ipi;
    7.39          u8                        __dummy[24];
    7.40      } PACKED u;
    7.41  } PACKED evtchn_op_t; /* 32 bytes */
     8.1 --- a/xen/include/xen/sched.h	Wed Nov 10 14:32:43 2004 +0000
     8.2 +++ b/xen/include/xen/sched.h	Wed Nov 10 15:43:53 2004 +0000
     8.3 @@ -36,6 +36,7 @@ typedef struct event_channel_st
     8.4  #define ECS_INTERDOMAIN  2 /* Channel is bound to another domain.            */
     8.5  #define ECS_PIRQ         3 /* Channel is bound to a physical IRQ line.       */
     8.6  #define ECS_VIRQ         4 /* Channel is bound to a virtual IRQ line.        */
     8.7 +#define ECS_IPI          5 /* Channel is bound to a virtual IPI line.        */
     8.8      u16 state;
     8.9      union {
    8.10          struct {
    8.11 @@ -47,6 +48,7 @@ typedef struct event_channel_st
    8.12          } __attribute__ ((packed)) interdomain; /* state == ECS_INTERDOMAIN */
    8.13          u16 pirq; /* state == ECS_PIRQ */
    8.14          u16 virq; /* state == ECS_VIRQ */
    8.15 +        u32 ipi_edom; /* state == ECS_IPI */
    8.16      } u;
    8.17  } event_channel_t;
    8.18