ia64/xen-unstable

changeset 5703:1d375ce8e0e0

Clean up Xen's event-channel interface, and semantics for binding
to VCPUs.
Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Fri Jul 08 14:17:54 2005 +0000 (2005-07-08)
parents 579d1e771025
children 9b73afea874e 7c3d7c37dfde
files linux-2.6.11-xen-sparse/arch/xen/i386/kernel/smpboot.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
line diff
     1.1 --- a/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/smpboot.c	Fri Jul 08 12:24:58 2005 +0000
     1.2 +++ b/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/smpboot.c	Fri Jul 08 14:17:54 2005 +0000
     1.3 @@ -1533,13 +1533,13 @@ void __init smp_intr_init(void)
     1.4  	int cpu = smp_processor_id();
     1.5  
     1.6  	per_cpu(resched_irq, cpu) =
     1.7 -		bind_ipi_on_cpu_to_irq(cpu, RESCHEDULE_VECTOR);
     1.8 +		bind_ipi_to_irq(RESCHEDULE_VECTOR);
     1.9  	sprintf(resched_name[cpu], "resched%d", cpu);
    1.10  	BUG_ON(request_irq(per_cpu(resched_irq, cpu), smp_reschedule_interrupt,
    1.11  	                   SA_INTERRUPT, resched_name[cpu], NULL));
    1.12  
    1.13  	per_cpu(callfunc_irq, cpu) =
    1.14 -		bind_ipi_on_cpu_to_irq(cpu, CALL_FUNCTION_VECTOR);
    1.15 +		bind_ipi_to_irq(CALL_FUNCTION_VECTOR);
    1.16  	sprintf(callfunc_name[cpu], "callfunc%d", cpu);
    1.17  	BUG_ON(request_irq(per_cpu(callfunc_irq, cpu),
    1.18  	                   smp_call_function_interrupt,
     2.1 --- a/linux-2.6.11-xen-sparse/arch/xen/kernel/evtchn.c	Fri Jul 08 12:24:58 2005 +0000
     2.2 +++ b/linux-2.6.11-xen-sparse/arch/xen/kernel/evtchn.c	Fri Jul 08 14:17:54 2005 +0000
     2.3 @@ -236,17 +236,17 @@ void unbind_virq_from_irq(int virq)
     2.4      spin_unlock(&irq_mapping_update_lock);
     2.5  }
     2.6  
     2.7 -int bind_ipi_on_cpu_to_irq(int cpu, int ipi)
     2.8 +int bind_ipi_on_cpu_to_irq(int ipi)
     2.9  {
    2.10      evtchn_op_t op;
    2.11      int evtchn, irq;
    2.12 +    int cpu = smp_processor_id();
    2.13  
    2.14      spin_lock(&irq_mapping_update_lock);
    2.15  
    2.16      if ( (evtchn = per_cpu(ipi_to_evtchn, cpu)[ipi]) == 0 )
    2.17      {
    2.18 -        op.cmd                 = EVTCHNOP_bind_ipi;
    2.19 -        op.u.bind_ipi.ipi_vcpu = cpu;
    2.20 +        op.cmd = EVTCHNOP_bind_ipi;
    2.21          if ( HYPERVISOR_event_channel_op(&op) != 0 )
    2.22              panic("Failed to bind virtual IPI %d on cpu %d\n", ipi, cpu);
    2.23          evtchn = op.u.bind_ipi.port;
    2.24 @@ -278,9 +278,9 @@ void rebind_evtchn_from_ipi(int cpu, int
    2.25  
    2.26      spin_lock(&irq_mapping_update_lock);
    2.27  
    2.28 -    op.cmd          = EVTCHNOP_rebind;
    2.29 -    op.u.rebind.port = evtchn;
    2.30 -    op.u.rebind.vcpu = newcpu;
    2.31 +    op.cmd              = EVTCHNOP_bind_vcpu;
    2.32 +    op.u.bind_vcpu.port = evtchn;
    2.33 +    op.u.bind_vcpu.vcpu = newcpu;
    2.34      if ( HYPERVISOR_event_channel_op(&op) != 0 )
    2.35         printk(KERN_INFO "Failed to rebind IPI%d to CPU%d\n",ipi,newcpu);
    2.36  
    2.37 @@ -294,18 +294,19 @@ void rebind_evtchn_from_irq(int cpu, int
    2.38  
    2.39      spin_lock(&irq_mapping_update_lock);
    2.40  
    2.41 -    op.cmd          = EVTCHNOP_rebind;
    2.42 -    op.u.rebind.port = evtchn;
    2.43 -    op.u.rebind.vcpu = newcpu;
    2.44 +    op.cmd              = EVTCHNOP_bind_vcpu;
    2.45 +    op.u.bind_vcpu.port = evtchn;
    2.46 +    op.u.bind_vcpu.vcpu = newcpu;
    2.47      if ( HYPERVISOR_event_channel_op(&op) != 0 )
    2.48         printk(KERN_INFO "Failed to rebind IRQ%d to CPU%d\n",irq,newcpu);
    2.49  
    2.50      spin_unlock(&irq_mapping_update_lock);
    2.51  }
    2.52  
    2.53 -void unbind_ipi_on_cpu_from_irq(int cpu, int ipi)
    2.54 +void unbind_ipi_from_irq(int ipi)
    2.55  {
    2.56      evtchn_op_t op;
    2.57 +    int cpu    = smp_processor_id();
    2.58      int evtchn = per_cpu(ipi_to_evtchn, cpu)[ipi];
    2.59      int irq    = irq_to_evtchn[evtchn];
    2.60  
     3.1 --- a/linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/mach-xen/irq_vectors.h	Fri Jul 08 12:24:58 2005 +0000
     3.2 +++ b/linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/mach-xen/irq_vectors.h	Fri Jul 08 14:17:54 2005 +0000
     3.3 @@ -128,8 +128,8 @@
     3.4  /* Dynamic binding of event channels and VIRQ sources to Linux IRQ space. */
     3.5  extern int  bind_virq_to_irq(int virq);
     3.6  extern void unbind_virq_from_irq(int virq);
     3.7 -extern int  bind_ipi_on_cpu_to_irq(int cpu, int ipi);
     3.8 -extern void unbind_ipi_on_cpu_from_irq(int cpu, int ipi);
     3.9 +extern int  bind_ipi_to_irq(int ipi);
    3.10 +extern void unbind_ipi_from_irq(int ipi);
    3.11  extern int  bind_evtchn_to_irq(int evtchn);
    3.12  extern void unbind_evtchn_from_irq(int evtchn);
    3.13  
     4.1 --- a/linux-2.6.11-xen-sparse/include/asm-xen/asm-x86_64/mach-xen/irq_vectors.h	Fri Jul 08 12:24:58 2005 +0000
     4.2 +++ b/linux-2.6.11-xen-sparse/include/asm-xen/asm-x86_64/mach-xen/irq_vectors.h	Fri Jul 08 14:17:54 2005 +0000
     4.3 @@ -126,8 +126,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/xen/common/event_channel.c	Fri Jul 08 12:24:58 2005 +0000
     5.2 +++ b/xen/common/event_channel.c	Fri Jul 08 14:17:54 2005 +0000
     5.3 @@ -220,12 +220,10 @@ static long evtchn_bind_interdomain(evtc
     5.4  
     5.5      chn1->u.interdomain.remote_dom  = d2;
     5.6      chn1->u.interdomain.remote_port = (u16)port2;
     5.7 -    chn1->notify_vcpu_id            = 0;
     5.8      chn1->state                     = ECS_INTERDOMAIN;
     5.9      
    5.10      chn2->u.interdomain.remote_dom  = d1;
    5.11      chn2->u.interdomain.remote_port = (u16)port1;
    5.12 -    chn2->notify_vcpu_id            = 0;
    5.13      chn2->state                     = ECS_INTERDOMAIN;
    5.14  
    5.15   out:
    5.16 @@ -285,10 +283,7 @@ static long evtchn_bind_ipi(evtchn_bind_
    5.17  {
    5.18      struct evtchn *chn;
    5.19      struct domain *d = current->domain;
    5.20 -    int            port, ipi_vcpu = bind->ipi_vcpu;
    5.21 -
    5.22 -    if ( (ipi_vcpu >= MAX_VIRT_CPUS) || (d->vcpu[ipi_vcpu] == NULL) )
    5.23 -        return -EINVAL;
    5.24 +    int            port;
    5.25  
    5.26      spin_lock(&d->evtchn_lock);
    5.27  
    5.28 @@ -296,7 +291,7 @@ static long evtchn_bind_ipi(evtchn_bind_
    5.29      {
    5.30          chn = evtchn_from_port(d, port);
    5.31          chn->state          = ECS_IPI;
    5.32 -        chn->notify_vcpu_id = ipi_vcpu;
    5.33 +        chn->notify_vcpu_id = current->vcpu_id;
    5.34      }
    5.35  
    5.36      spin_unlock(&d->evtchn_lock);
    5.37 @@ -326,8 +321,6 @@ static long evtchn_bind_pirq(evtchn_bind
    5.38  
    5.39      chn = evtchn_from_port(d, port);
    5.40  
    5.41 -    chn->notify_vcpu_id = 0;
    5.42 -
    5.43      d->pirq_to_evtchn[pirq] = port;
    5.44      rc = pirq_guest_bind(d->vcpu[0], pirq, 
    5.45                           !!(bind->flags & BIND_PIRQ__WILL_SHARE));
    5.46 @@ -441,7 +434,9 @@ static long __evtchn_close(struct domain
    5.47          BUG();
    5.48      }
    5.49  
    5.50 -    chn1->state = ECS_FREE;
    5.51 +    /* Reset binding to vcpu0 when the channel is freed. */
    5.52 +    chn1->state          = ECS_FREE;
    5.53 +    chn1->notify_vcpu_id = 0;
    5.54  
    5.55   out:
    5.56      if ( d2 != NULL )
    5.57 @@ -570,26 +565,30 @@ static long evtchn_status(evtchn_status_
    5.58          status->u.virq = chn->u.virq;
    5.59          break;
    5.60      case ECS_IPI:
    5.61 -        status->status     = EVTCHNSTAT_ipi;
    5.62 -        status->u.ipi_vcpu = chn->notify_vcpu_id;
    5.63 +        status->status = EVTCHNSTAT_ipi;
    5.64          break;
    5.65      default:
    5.66          BUG();
    5.67      }
    5.68  
    5.69 +    status->vcpu = chn->notify_vcpu_id;
    5.70 +
    5.71   out:
    5.72      spin_unlock(&d->evtchn_lock);
    5.73      put_domain(d);
    5.74      return rc;
    5.75  }
    5.76  
    5.77 -static long evtchn_rebind(evtchn_rebind_t *bind) 
    5.78 +static long evtchn_bind_vcpu(evtchn_bind_vcpu_t *bind) 
    5.79  {
    5.80      struct domain *d    = current->domain;
    5.81      int            port = bind->port;
    5.82      int            vcpu = bind->vcpu;
    5.83      struct evtchn *chn;
    5.84 -    long             rc = 0;
    5.85 +    long           rc = 0;
    5.86 +
    5.87 +    if ( (vcpu >= MAX_VIRT_CPUS) || (d->vcpu[vcpu] == NULL) )
    5.88 +        return -EINVAL;
    5.89  
    5.90      spin_lock(&d->evtchn_lock);
    5.91  
    5.92 @@ -600,7 +599,17 @@ static long evtchn_rebind(evtchn_rebind_
    5.93      }
    5.94  
    5.95      chn = evtchn_from_port(d, port);
    5.96 -    chn->notify_vcpu_id = vcpu;
    5.97 +    switch ( chn->state )
    5.98 +    {
    5.99 +    case ECS_UNBOUND:
   5.100 +    case ECS_INTERDOMAIN:
   5.101 +    case ECS_PIRQ:
   5.102 +        chn->notify_vcpu_id = vcpu;
   5.103 +        break;
   5.104 +    default:
   5.105 +        rc = -EINVAL;
   5.106 +        break;
   5.107 +    }
   5.108  
   5.109   out:
   5.110      spin_unlock(&d->evtchn_lock);
   5.111 @@ -664,10 +673,8 @@ long do_event_channel_op(evtchn_op_t *uo
   5.112              rc = -EFAULT;
   5.113          break;
   5.114  
   5.115 -    case EVTCHNOP_rebind:
   5.116 -        rc = evtchn_rebind(&op.u.rebind);
   5.117 -        if ( (rc == 0) && (copy_to_user(uop, &op, sizeof(op)) != 0) )
   5.118 -            rc = -EFAULT;
   5.119 +    case EVTCHNOP_bind_vcpu:
   5.120 +        rc = evtchn_bind_vcpu(&op.u.bind_vcpu);
   5.121          break;
   5.122  
   5.123      default:
     6.1 --- a/xen/include/public/dom0_ops.h	Fri Jul 08 12:24:58 2005 +0000
     6.2 +++ b/xen/include/public/dom0_ops.h	Fri Jul 08 14:17:54 2005 +0000
     6.3 @@ -19,7 +19,7 @@
     6.4   * This makes sure that old versions of dom0 tools will stop working in a
     6.5   * well-defined way (rather than crashing the machine, for instance).
     6.6   */
     6.7 -#define DOM0_INTERFACE_VERSION   0xAAAA100D
     6.8 +#define DOM0_INTERFACE_VERSION   0xAAAA100E
     6.9  
    6.10  /************************************************************************/
    6.11  
     7.1 --- a/xen/include/public/event_channel.h	Fri Jul 08 12:24:58 2005 +0000
     7.2 +++ b/xen/include/public/event_channel.h	Fri Jul 08 14:17:54 2005 +0000
     7.3 @@ -89,8 +89,6 @@ typedef struct evtchn_bind_pirq {
     7.4   */
     7.5  #define EVTCHNOP_bind_ipi         7
     7.6  typedef struct evtchn_bind_ipi {
     7.7 -    /* IN parameters. */
     7.8 -    u32 ipi_vcpu;
     7.9      /* OUT parameters. */
    7.10      u32 port;
    7.11  } evtchn_bind_ipi_t;
    7.12 @@ -144,6 +142,7 @@ typedef struct evtchn_status {
    7.13  #define EVTCHNSTAT_virq         4  /* Channel is bound to a virtual IRQ line */
    7.14  #define EVTCHNSTAT_ipi          5  /* Channel is bound to a virtual IPI line */
    7.15      u32     status;
    7.16 +    u32     vcpu;                  /* VCPU to which this channel is bound.   */
    7.17      union {
    7.18          struct {
    7.19              domid_t dom;
    7.20 @@ -154,16 +153,25 @@ typedef struct evtchn_status {
    7.21          } interdomain; /* EVTCHNSTAT_interdomain */
    7.22          u32 pirq;      /* EVTCHNSTAT_pirq        */
    7.23          u32 virq;      /* EVTCHNSTAT_virq        */
    7.24 -        u32 ipi_vcpu;  /* EVTCHNSTAT_ipi         */
    7.25      } u;
    7.26  } evtchn_status_t;
    7.27  
    7.28 -#define EVTCHNOP_rebind        8
    7.29 -typedef struct {
    7.30 +/*
    7.31 + * EVTCHNOP_bind_vcpu: Specify which vcpu a channel should notify when an
    7.32 + * event is pending.
    7.33 + * NOTES:
    7.34 + *  1. IPI- and VIRQ-bound channels always notify the vcpu that initialised
    7.35 + *     the binding. This binding cannot be changed.
    7.36 + *  2. All other channels notify vcpu0 by default. This default is set when
    7.37 + *     the channel is allocated (a port that is freed and subsequently reused
    7.38 + *     has its binding reset to vcpu0).
    7.39 + */
    7.40 +#define EVTCHNOP_bind_vcpu        8
    7.41 +typedef struct evtchn_bind_vcpu {
    7.42      /* IN parameters. */
    7.43 -    u32 port;                         /*  0 */
    7.44 -    u32 vcpu;                         /*  4 */
    7.45 -} evtchn_rebind_t; /* 8 bytes */
    7.46 +    u32 port;
    7.47 +    u32 vcpu;
    7.48 +} evtchn_bind_vcpu_t;
    7.49  
    7.50  typedef struct evtchn_op {
    7.51      u32 cmd; /* EVTCHNOP_* */
    7.52 @@ -176,7 +184,7 @@ typedef struct evtchn_op {
    7.53          evtchn_close_t            close;
    7.54          evtchn_send_t             send;
    7.55          evtchn_status_t           status;
    7.56 -        evtchn_rebind_t           rebind;
    7.57 +        evtchn_bind_vcpu_t        bind_vcpu;
    7.58      } u;
    7.59  } evtchn_op_t;
    7.60