direct-io.hg

changeset 5709:215d8b2f3d94

Manual merge.
author kaf24@firebug.cl.cam.ac.uk
date Sat Jul 09 10:24:14 2005 +0000 (2005-07-09)
parents 49a00af50777 05b63285047c
children a28952e73253 8579c57c7fce c1a7ed266c7e
files linux-2.6.11-xen-sparse/arch/xen/i386/kernel/smpboot.c linux-2.6.11-xen-sparse/arch/xen/kernel/ctrl_if.c linux-2.6.11-xen-sparse/arch/xen/kernel/evtchn.c linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/mach-xen/irq_vectors.h linux-2.6.11-xen-sparse/include/asm-xen/asm-x86_64/mach-xen/irq_vectors.h xen/common/event_channel.c xen/include/public/dom0_ops.h xen/include/public/event_channel.h xen/include/public/io/domain_controller.h
line diff
     1.1 --- a/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/smpboot.c	Sat Jul 09 10:01:49 2005 +0000
     1.2 +++ b/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/smpboot.c	Sat Jul 09 10:24:14 2005 +0000
     1.3 @@ -1312,7 +1312,7 @@ void __devinit smp_prepare_boot_cpu(void
     1.4  
     1.5  /* hotplug down/up funtion pointer and target vcpu */
     1.6  struct vcpu_hotplug_handler_t {
     1.7 -	void (*fn)();
     1.8 +	void (*fn)(int vcpu);
     1.9  	u32 vcpu;
    1.10  };
    1.11  static struct vcpu_hotplug_handler_t vcpu_hotplug_handler;
    1.12 @@ -1333,11 +1333,8 @@ static int __devinit cpu_enable(unsigned
    1.13  	while (!cpu_online(cpu))
    1.14  		cpu_relax();
    1.15  
    1.16 -   /* re-route bound IRQs 0 to cpu */
    1.17 -   rebind_evtchn_from_irq(0, cpu,  per_cpu(resched_irq, cpu));
    1.18 -   rebind_evtchn_from_irq(0, cpu, per_cpu(callfunc_irq, cpu));
    1.19 +	fixup_irqs(cpu_online_map);
    1.20  
    1.21 -	fixup_irqs(cpu_online_map);
    1.22  	/* counter the disable in fixup_irqs() */
    1.23  	local_irq_enable();
    1.24  	return 0;
    1.25 @@ -1359,18 +1356,9 @@ int __cpu_disable(void)
    1.26  	if (cpu == 0)
    1.27  		return -EBUSY;
    1.28  
    1.29 -	/* Allow any queued timer interrupts to get serviced */
    1.30 -	local_irq_enable();
    1.31 -	mdelay(1);
    1.32 -	local_irq_disable();
    1.33 -
    1.34  	cpu_clear(cpu, map);
    1.35  	fixup_irqs(map);
    1.36  
    1.37 -   /* re-route IRQs from dead vcpu to another */
    1.38 -   rebind_evtchn_from_irq(cpu, 0,  per_cpu(resched_irq, cpu));
    1.39 -   rebind_evtchn_from_irq(cpu, 0, per_cpu(callfunc_irq, cpu));
    1.40 -
    1.41  	/* It's now safe to remove this processor from the online map */
    1.42  	cpu_clear(cpu, cpu_online_map);
    1.43  
    1.44 @@ -1533,13 +1521,13 @@ void __init smp_intr_init(void)
    1.45  	int cpu = smp_processor_id();
    1.46  
    1.47  	per_cpu(resched_irq, cpu) =
    1.48 -		bind_ipi_on_cpu_to_irq(cpu, RESCHEDULE_VECTOR);
    1.49 +		bind_ipi_on_cpu_to_irq(RESCHEDULE_VECTOR);
    1.50  	sprintf(resched_name[cpu], "resched%d", cpu);
    1.51  	BUG_ON(request_irq(per_cpu(resched_irq, cpu), smp_reschedule_interrupt,
    1.52  	                   SA_INTERRUPT, resched_name[cpu], NULL));
    1.53  
    1.54  	per_cpu(callfunc_irq, cpu) =
    1.55 -		bind_ipi_on_cpu_to_irq(cpu, CALL_FUNCTION_VECTOR);
    1.56 +		bind_ipi_on_cpu_to_irq(CALL_FUNCTION_VECTOR);
    1.57  	sprintf(callfunc_name[cpu], "callfunc%d", cpu);
    1.58  	BUG_ON(request_irq(per_cpu(callfunc_irq, cpu),
    1.59  	                   smp_call_function_interrupt,
     2.1 --- a/linux-2.6.11-xen-sparse/arch/xen/kernel/ctrl_if.c	Sat Jul 09 10:01:49 2005 +0000
     2.2 +++ b/linux-2.6.11-xen-sparse/arch/xen/kernel/ctrl_if.c	Sat Jul 09 10:24:14 2005 +0000
     2.3 @@ -491,6 +491,8 @@ void ctrl_if_resume(void)
     2.4           * pick up its end of the event channel from 
     2.5           */
     2.6          evtchn_op_t op;
     2.7 +	extern void bind_evtchn_to_cpu(unsigned port, unsigned cpu);
     2.8 +
     2.9          op.cmd = EVTCHNOP_bind_interdomain;
    2.10          op.u.bind_interdomain.dom1 = DOMID_SELF;
    2.11          op.u.bind_interdomain.dom2 = DOMID_SELF;
    2.12 @@ -500,6 +502,7 @@ void ctrl_if_resume(void)
    2.13              BUG();
    2.14          xen_start_info.domain_controller_evtchn = op.u.bind_interdomain.port1;
    2.15          initdom_ctrlif_domcontroller_port   = op.u.bind_interdomain.port2;
    2.16 +	bind_evtchn_to_cpu(op.u.bind_interdomain.port1, 0);
    2.17      }
    2.18  
    2.19      /* Sync up with shared indexes. */
     3.1 --- a/linux-2.6.11-xen-sparse/arch/xen/kernel/evtchn.c	Sat Jul 09 10:01:49 2005 +0000
     3.2 +++ b/linux-2.6.11-xen-sparse/arch/xen/kernel/evtchn.c	Sat Jul 09 10:24:14 2005 +0000
     3.3 @@ -86,7 +86,7 @@ static u32 cpu_evtchn_mask[NR_CPUS][NR_E
     3.4       cpu_evtchn_mask[cpu][idx] &                \
     3.5       ~(sh)->evtchn_mask[idx])
     3.6  
     3.7 -static void bind_evtchn_to_cpu(unsigned int chn, unsigned int cpu)
     3.8 +void bind_evtchn_to_cpu(unsigned int chn, unsigned int cpu)
     3.9  {
    3.10      clear_bit(chn, (unsigned long *)cpu_evtchn_mask[cpu_evtchn[chn]]);
    3.11      set_bit(chn, (unsigned long *)cpu_evtchn_mask[cpu]);
    3.12 @@ -99,8 +99,9 @@ static void bind_evtchn_to_cpu(unsigned 
    3.13      ((sh)->evtchn_pending[idx] &                \
    3.14       ~(sh)->evtchn_mask[idx])
    3.15  
    3.16 -#define bind_evtchn_to_cpu(chn,cpu) ((void)0)
    3.17 -
    3.18 +void bind_evtchn_to_cpu(unsigned int chn, unsigned int cpu)
    3.19 +{
    3.20 +}
    3.21  #endif
    3.22  
    3.23  /* Upcall to generic IRQ layer. */
    3.24 @@ -228,6 +229,13 @@ void unbind_virq_from_irq(int virq)
    3.25          if ( HYPERVISOR_event_channel_op(&op) != 0 )
    3.26              panic("Failed to unbind virtual IRQ %d\n", virq);
    3.27  
    3.28 +	/* This is a slight hack.  Interdomain ports can be allocated
    3.29 +	   directly by userspace, and at that point they get bound by
    3.30 +	   Xen to vcpu 0.  We therefore need to make sure that if we
    3.31 +	   get an event on an event channel we don't know about vcpu 0
    3.32 +	   handles it.  Binding channels to vcpu 0 when closing them
    3.33 +	   achieves this. */
    3.34 +	bind_evtchn_to_cpu(evtchn, 0);
    3.35          evtchn_to_irq[evtchn] = -1;
    3.36          irq_to_evtchn[irq]    = -1;
    3.37          per_cpu(virq_to_irq, cpu)[virq]     = -1;
    3.38 @@ -236,17 +244,17 @@ void unbind_virq_from_irq(int virq)
    3.39      spin_unlock(&irq_mapping_update_lock);
    3.40  }
    3.41  
    3.42 -int bind_ipi_on_cpu_to_irq(int cpu, int ipi)
    3.43 +int bind_ipi_on_cpu_to_irq(int ipi)
    3.44  {
    3.45      evtchn_op_t op;
    3.46      int evtchn, irq;
    3.47 +    int cpu = smp_processor_id();
    3.48  
    3.49      spin_lock(&irq_mapping_update_lock);
    3.50  
    3.51      if ( (evtchn = per_cpu(ipi_to_evtchn, cpu)[ipi]) == 0 )
    3.52      {
    3.53 -        op.cmd                 = EVTCHNOP_bind_ipi;
    3.54 -        op.u.bind_ipi.ipi_vcpu = cpu;
    3.55 +        op.cmd = EVTCHNOP_bind_ipi;
    3.56          if ( HYPERVISOR_event_channel_op(&op) != 0 )
    3.57              panic("Failed to bind virtual IPI %d on cpu %d\n", ipi, cpu);
    3.58          evtchn = op.u.bind_ipi.port;
    3.59 @@ -271,41 +279,10 @@ int bind_ipi_on_cpu_to_irq(int cpu, int 
    3.60      return irq;
    3.61  }
    3.62  
    3.63 -void rebind_evtchn_from_ipi(int cpu, int newcpu, int ipi)
    3.64 +void unbind_ipi_from_irq(int ipi)
    3.65  {
    3.66      evtchn_op_t op;
    3.67 -    int evtchn = per_cpu(ipi_to_evtchn, cpu)[ipi];
    3.68 -
    3.69 -    spin_lock(&irq_mapping_update_lock);
    3.70 -
    3.71 -    op.cmd          = EVTCHNOP_rebind;
    3.72 -    op.u.rebind.port = evtchn;
    3.73 -    op.u.rebind.vcpu = newcpu;
    3.74 -    if ( HYPERVISOR_event_channel_op(&op) != 0 )
    3.75 -       printk(KERN_INFO "Failed to rebind IPI%d to CPU%d\n",ipi,newcpu);
    3.76 -
    3.77 -    spin_unlock(&irq_mapping_update_lock);
    3.78 -}
    3.79 -
    3.80 -void rebind_evtchn_from_irq(int cpu, int newcpu, int irq)
    3.81 -{
    3.82 -    evtchn_op_t op;
    3.83 -    int evtchn = irq_to_evtchn[irq];
    3.84 -
    3.85 -    spin_lock(&irq_mapping_update_lock);
    3.86 -
    3.87 -    op.cmd          = EVTCHNOP_rebind;
    3.88 -    op.u.rebind.port = evtchn;
    3.89 -    op.u.rebind.vcpu = newcpu;
    3.90 -    if ( HYPERVISOR_event_channel_op(&op) != 0 )
    3.91 -       printk(KERN_INFO "Failed to rebind IRQ%d to CPU%d\n",irq,newcpu);
    3.92 -
    3.93 -    spin_unlock(&irq_mapping_update_lock);
    3.94 -}
    3.95 -
    3.96 -void unbind_ipi_on_cpu_from_irq(int cpu, int ipi)
    3.97 -{
    3.98 -    evtchn_op_t op;
    3.99 +    int cpu    = smp_processor_id();
   3.100      int evtchn = per_cpu(ipi_to_evtchn, cpu)[ipi];
   3.101      int irq    = irq_to_evtchn[evtchn];
   3.102  
   3.103 @@ -319,6 +296,8 @@ void unbind_ipi_on_cpu_from_irq(int cpu,
   3.104  	if ( HYPERVISOR_event_channel_op(&op) != 0 )
   3.105  	    panic("Failed to unbind virtual IPI %d on cpu %d\n", ipi, cpu);
   3.106  
   3.107 +	/* See comments in unbind_virq_from_irq */
   3.108 +	bind_evtchn_to_cpu(evtchn, 0);
   3.109          evtchn_to_irq[evtchn] = -1;
   3.110          irq_to_evtchn[irq]    = -1;
   3.111  	per_cpu(ipi_to_evtchn, cpu)[ipi] = 0;
   3.112 @@ -362,6 +341,59 @@ void unbind_evtchn_from_irq(int evtchn)
   3.113      spin_unlock(&irq_mapping_update_lock);
   3.114  }
   3.115  
   3.116 +static void do_nothing_function(void *ign)
   3.117 +{
   3.118 +}
   3.119 +
   3.120 +/* Rebind an evtchn so that it gets delivered to a specific cpu */
   3.121 +static void rebind_irq_to_cpu(unsigned irq, unsigned tcpu)
   3.122 +{
   3.123 +    evtchn_op_t op;
   3.124 +    int evtchn;
   3.125 +
   3.126 +    spin_lock(&irq_mapping_update_lock);
   3.127 +    evtchn = irq_to_evtchn[irq];
   3.128 +    if (!VALID_EVTCHN(evtchn)) {
   3.129 +	spin_unlock(&irq_mapping_update_lock);
   3.130 +	return;
   3.131 +    }
   3.132 +
   3.133 +    /* Tell Xen to send future instances of this interrupt to the
   3.134 +       other vcpu */
   3.135 +    op.cmd = EVTCHNOP_bind_vcpu;
   3.136 +    op.u.bind_vcpu.port = evtchn;
   3.137 +    op.u.bind_vcpu.vcpu = tcpu;
   3.138 +
   3.139 +    /* If this fails, it usually just indicates that we're dealing
   3.140 +       with a virq or IPI channel, which don't actually need to be
   3.141 +       rebound.  Ignore it, but don't do the xenlinux-level rebind
   3.142 +       in that case. */
   3.143 +    if (HYPERVISOR_event_channel_op(&op) >= 0)
   3.144 +	bind_evtchn_to_cpu(evtchn, tcpu);
   3.145 +
   3.146 +    spin_unlock(&irq_mapping_update_lock);
   3.147 +
   3.148 +    /* Now send the new target processor a NOP IPI.  When this
   3.149 +       returns, it will check for any pending interrupts, and so
   3.150 +       service any that got delivered to the wrong processor by
   3.151 +       mistake. */
   3.152 +    /* XXX: The only time this is called with interrupts disabled is
   3.153 +       from the hotplug/hotunplug path.  In that case, all cpus are
   3.154 +       stopped with interrupts disabled, and the missed interrupts
   3.155 +       will be picked up when they start again.  This is kind of a
   3.156 +       hack.
   3.157 +    */
   3.158 +    if (!irqs_disabled()) {
   3.159 +	smp_call_function(do_nothing_function, NULL, 0, 0);
   3.160 +    }
   3.161 +}
   3.162 +
   3.163 +
   3.164 +static void set_affinity_irq(unsigned irq, cpumask_t dest)
   3.165 +{
   3.166 +    unsigned tcpu = first_cpu(dest);
   3.167 +    rebind_irq_to_cpu(irq, tcpu);
   3.168 +}
   3.169  
   3.170  /*
   3.171   * Interface to generic handling in irq.c
   3.172 @@ -424,7 +456,7 @@ static struct hw_interrupt_type dynirq_t
   3.173      disable_dynirq,
   3.174      ack_dynirq,
   3.175      end_dynirq,
   3.176 -    NULL
   3.177 +    set_affinity_irq
   3.178  };
   3.179  
   3.180  static inline void pirq_unmask_notify(int pirq)
   3.181 @@ -473,6 +505,7 @@ static unsigned int startup_pirq(unsigne
   3.182  
   3.183      pirq_query_unmask(irq_to_pirq(irq));
   3.184  
   3.185 +    bind_evtchn_to_cpu(evtchn, 0);
   3.186      evtchn_to_irq[evtchn] = irq;
   3.187      irq_to_evtchn[irq]    = evtchn;
   3.188  
   3.189 @@ -498,6 +531,7 @@ static void shutdown_pirq(unsigned int i
   3.190      if ( HYPERVISOR_event_channel_op(&op) != 0 )
   3.191          panic("Failed to unbind physical IRQ %d\n", irq);
   3.192  
   3.193 +    bind_evtchn_to_cpu(evtchn, 0);
   3.194      evtchn_to_irq[evtchn] = -1;
   3.195      irq_to_evtchn[irq]    = -1;
   3.196  }
   3.197 @@ -548,7 +582,7 @@ static struct hw_interrupt_type pirq_typ
   3.198      disable_pirq,
   3.199      ack_pirq,
   3.200      end_pirq,
   3.201 -    NULL
   3.202 +    set_affinity_irq
   3.203  };
   3.204  
   3.205  void irq_suspend(void)
   3.206 @@ -597,6 +631,7 @@ void irq_resume(void)
   3.207          evtchn = op.u.bind_virq.port;
   3.208          
   3.209          /* Record the new mapping. */
   3.210 +	bind_evtchn_to_cpu(evtchn, 0);
   3.211          evtchn_to_irq[evtchn] = irq;
   3.212          irq_to_evtchn[irq]    = evtchn;
   3.213  
     4.1 --- a/linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/mach-xen/irq_vectors.h	Sat Jul 09 10:01:49 2005 +0000
     4.2 +++ b/linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/mach-xen/irq_vectors.h	Sat Jul 09 10:24:14 2005 +0000
     4.3 @@ -128,8 +128,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_to_irq(int cpu, int ipi);
     4.8 -extern void unbind_ipi_on_cpu_from_irq(int cpu, int ipi);
     4.9 +extern int  bind_ipi_to_irq(int ipi);
    4.10 +extern void unbind_ipi_from_irq(int ipi);
    4.11  extern int  bind_evtchn_to_irq(int evtchn);
    4.12  extern void unbind_evtchn_from_irq(int evtchn);
    4.13  
     5.1 --- a/linux-2.6.11-xen-sparse/include/asm-xen/asm-x86_64/mach-xen/irq_vectors.h	Sat Jul 09 10:01:49 2005 +0000
     5.2 +++ b/linux-2.6.11-xen-sparse/include/asm-xen/asm-x86_64/mach-xen/irq_vectors.h	Sat Jul 09 10:24:14 2005 +0000
     5.3 @@ -126,8 +126,8 @@
     5.4  /* Dynamic binding of event channels and VIRQ sources to Linux IRQ space. */
     5.5  extern int  bind_virq_to_irq(int virq);
     5.6  extern void unbind_virq_from_irq(int virq);
     5.7 -extern int  bind_ipi_on_cpu_to_irq(int cpu, int ipi);
     5.8 -extern void unbind_ipi_on_cpu_from_irq(int cpu, int ipi);
     5.9 +extern int  bind_ipi_to_irq(int ipi);
    5.10 +extern void unbind_ipi_from_irq(int ipi);
    5.11  extern int  bind_evtchn_to_irq(int evtchn);
    5.12  extern void unbind_evtchn_from_irq(int evtchn);
    5.13  
     6.1 --- a/xen/common/event_channel.c	Sat Jul 09 10:01:49 2005 +0000
     6.2 +++ b/xen/common/event_channel.c	Sat Jul 09 10:24:14 2005 +0000
     6.3 @@ -220,12 +220,10 @@ static long evtchn_bind_interdomain(evtc
     6.4  
     6.5      chn1->u.interdomain.remote_dom  = d2;
     6.6      chn1->u.interdomain.remote_port = (u16)port2;
     6.7 -    chn1->notify_vcpu_id            = 0;
     6.8      chn1->state                     = ECS_INTERDOMAIN;
     6.9      
    6.10      chn2->u.interdomain.remote_dom  = d1;
    6.11      chn2->u.interdomain.remote_port = (u16)port1;
    6.12 -    chn2->notify_vcpu_id            = 0;
    6.13      chn2->state                     = ECS_INTERDOMAIN;
    6.14  
    6.15   out:
    6.16 @@ -285,10 +283,7 @@ static long evtchn_bind_ipi(evtchn_bind_
    6.17  {
    6.18      struct evtchn *chn;
    6.19      struct domain *d = current->domain;
    6.20 -    int            port, ipi_vcpu = bind->ipi_vcpu;
    6.21 -
    6.22 -    if ( (ipi_vcpu >= MAX_VIRT_CPUS) || (d->vcpu[ipi_vcpu] == NULL) )
    6.23 -        return -EINVAL;
    6.24 +    int            port;
    6.25  
    6.26      spin_lock(&d->evtchn_lock);
    6.27  
    6.28 @@ -296,7 +291,7 @@ static long evtchn_bind_ipi(evtchn_bind_
    6.29      {
    6.30          chn = evtchn_from_port(d, port);
    6.31          chn->state          = ECS_IPI;
    6.32 -        chn->notify_vcpu_id = ipi_vcpu;
    6.33 +        chn->notify_vcpu_id = current->vcpu_id;
    6.34      }
    6.35  
    6.36      spin_unlock(&d->evtchn_lock);
    6.37 @@ -326,8 +321,6 @@ static long evtchn_bind_pirq(evtchn_bind
    6.38  
    6.39      chn = evtchn_from_port(d, port);
    6.40  
    6.41 -    chn->notify_vcpu_id = 0;
    6.42 -
    6.43      d->pirq_to_evtchn[pirq] = port;
    6.44      rc = pirq_guest_bind(d->vcpu[0], pirq, 
    6.45                           !!(bind->flags & BIND_PIRQ__WILL_SHARE));
    6.46 @@ -441,7 +434,9 @@ static long __evtchn_close(struct domain
    6.47          BUG();
    6.48      }
    6.49  
    6.50 -    chn1->state = ECS_FREE;
    6.51 +    /* Reset binding to vcpu0 when the channel is freed. */
    6.52 +    chn1->state          = ECS_FREE;
    6.53 +    chn1->notify_vcpu_id = 0;
    6.54  
    6.55   out:
    6.56      if ( d2 != NULL )
    6.57 @@ -570,37 +565,55 @@ static long evtchn_status(evtchn_status_
    6.58          status->u.virq = chn->u.virq;
    6.59          break;
    6.60      case ECS_IPI:
    6.61 -        status->status     = EVTCHNSTAT_ipi;
    6.62 -        status->u.ipi_vcpu = chn->notify_vcpu_id;
    6.63 +        status->status = EVTCHNSTAT_ipi;
    6.64          break;
    6.65      default:
    6.66          BUG();
    6.67      }
    6.68  
    6.69 +    status->vcpu = chn->notify_vcpu_id;
    6.70 +
    6.71   out:
    6.72      spin_unlock(&d->evtchn_lock);
    6.73      put_domain(d);
    6.74      return rc;
    6.75  }
    6.76  
    6.77 -static long evtchn_rebind(evtchn_rebind_t *bind) 
    6.78 +static long evtchn_bind_vcpu(evtchn_bind_vcpu_t *bind) 
    6.79  {
    6.80      struct domain *d    = current->domain;
    6.81      int            port = bind->port;
    6.82      int            vcpu = bind->vcpu;
    6.83      struct evtchn *chn;
    6.84 -    long             rc = 0;
    6.85 +    long           rc = 0;
    6.86 +
    6.87 +    if ( (vcpu >= MAX_VIRT_CPUS) || (d->vcpu[vcpu] == NULL) ) {
    6.88 +        printf("vcpu %d bad.\n", vcpu);
    6.89 +        return -EINVAL;
    6.90 +    }
    6.91  
    6.92      spin_lock(&d->evtchn_lock);
    6.93  
    6.94      if ( !port_is_valid(d, port) )
    6.95      {
    6.96 +        printf("port %d bad.\n", port);
    6.97          rc = -EINVAL;
    6.98          goto out;
    6.99      }
   6.100  
   6.101      chn = evtchn_from_port(d, port);
   6.102 -    chn->notify_vcpu_id = vcpu;
   6.103 +    switch ( chn->state )
   6.104 +    {
   6.105 +    case ECS_UNBOUND:
   6.106 +    case ECS_INTERDOMAIN:
   6.107 +    case ECS_PIRQ:
   6.108 +        chn->notify_vcpu_id = vcpu;
   6.109 +        break;
   6.110 +    default:
   6.111 +        printf("evtchn type %d can't be rebound.\n", chn->state);
   6.112 +        rc = -EINVAL;
   6.113 +        break;
   6.114 +    }
   6.115  
   6.116   out:
   6.117      spin_unlock(&d->evtchn_lock);
   6.118 @@ -664,10 +677,8 @@ long do_event_channel_op(evtchn_op_t *uo
   6.119              rc = -EFAULT;
   6.120          break;
   6.121  
   6.122 -    case EVTCHNOP_rebind:
   6.123 -        rc = evtchn_rebind(&op.u.rebind);
   6.124 -        if ( (rc == 0) && (copy_to_user(uop, &op, sizeof(op)) != 0) )
   6.125 -            rc = -EFAULT;
   6.126 +    case EVTCHNOP_bind_vcpu:
   6.127 +        rc = evtchn_bind_vcpu(&op.u.bind_vcpu);
   6.128          break;
   6.129  
   6.130      default:
     7.1 --- a/xen/include/public/dom0_ops.h	Sat Jul 09 10:01:49 2005 +0000
     7.2 +++ b/xen/include/public/dom0_ops.h	Sat Jul 09 10:24:14 2005 +0000
     7.3 @@ -19,7 +19,7 @@
     7.4   * This makes sure that old versions of dom0 tools will stop working in a
     7.5   * well-defined way (rather than crashing the machine, for instance).
     7.6   */
     7.7 -#define DOM0_INTERFACE_VERSION   0xAAAA100D
     7.8 +#define DOM0_INTERFACE_VERSION   0xAAAA100E
     7.9  
    7.10  /************************************************************************/
    7.11  
     8.1 --- a/xen/include/public/event_channel.h	Sat Jul 09 10:01:49 2005 +0000
     8.2 +++ b/xen/include/public/event_channel.h	Sat Jul 09 10:24:14 2005 +0000
     8.3 @@ -89,8 +89,6 @@ typedef struct evtchn_bind_pirq {
     8.4   */
     8.5  #define EVTCHNOP_bind_ipi         7
     8.6  typedef struct evtchn_bind_ipi {
     8.7 -    /* IN parameters. */
     8.8 -    u32 ipi_vcpu;
     8.9      /* OUT parameters. */
    8.10      u32 port;
    8.11  } evtchn_bind_ipi_t;
    8.12 @@ -144,6 +142,7 @@ typedef struct evtchn_status {
    8.13  #define EVTCHNSTAT_virq         4  /* Channel is bound to a virtual IRQ line */
    8.14  #define EVTCHNSTAT_ipi          5  /* Channel is bound to a virtual IPI line */
    8.15      u32     status;
    8.16 +    u32     vcpu;                  /* VCPU to which this channel is bound.   */
    8.17      union {
    8.18          struct {
    8.19              domid_t dom;
    8.20 @@ -154,16 +153,25 @@ typedef struct evtchn_status {
    8.21          } interdomain; /* EVTCHNSTAT_interdomain */
    8.22          u32 pirq;      /* EVTCHNSTAT_pirq        */
    8.23          u32 virq;      /* EVTCHNSTAT_virq        */
    8.24 -        u32 ipi_vcpu;  /* EVTCHNSTAT_ipi         */
    8.25      } u;
    8.26  } evtchn_status_t;
    8.27  
    8.28 -#define EVTCHNOP_rebind        8
    8.29 -typedef struct {
    8.30 +/*
    8.31 + * EVTCHNOP_bind_vcpu: Specify which vcpu a channel should notify when an
    8.32 + * event is pending.
    8.33 + * NOTES:
    8.34 + *  1. IPI- and VIRQ-bound channels always notify the vcpu that initialised
    8.35 + *     the binding. This binding cannot be changed.
    8.36 + *  2. All other channels notify vcpu0 by default. This default is set when
    8.37 + *     the channel is allocated (a port that is freed and subsequently reused
    8.38 + *     has its binding reset to vcpu0).
    8.39 + */
    8.40 +#define EVTCHNOP_bind_vcpu        8
    8.41 +typedef struct evtchn_bind_vcpu {
    8.42      /* IN parameters. */
    8.43 -    u32 port;                         /*  0 */
    8.44 -    u32 vcpu;                         /*  4 */
    8.45 -} evtchn_rebind_t; /* 8 bytes */
    8.46 +    u32 port;
    8.47 +    u32 vcpu;
    8.48 +} evtchn_bind_vcpu_t;
    8.49  
    8.50  typedef struct evtchn_op {
    8.51      u32 cmd; /* EVTCHNOP_* */
    8.52 @@ -176,7 +184,7 @@ typedef struct evtchn_op {
    8.53          evtchn_close_t            close;
    8.54          evtchn_send_t             send;
    8.55          evtchn_status_t           status;
    8.56 -        evtchn_rebind_t           rebind;
    8.57 +        evtchn_bind_vcpu_t        bind_vcpu;
    8.58      } u;
    8.59  } evtchn_op_t;
    8.60