ia64/xen-unstable

changeset 8351:455b2b93542c

Fix unmask_evtchn() when the port is bound to a different
VCPU.

Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Tue Dec 13 19:20:29 2005 +0100 (2005-12-13)
parents 62d9ac63e7f5
children a7bb7b704071
files linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c linux-2.6-xen-sparse/include/asm-xen/evtchn.h xen/common/event_channel.c xen/include/public/event_channel.h xen/include/xen/event.h
line diff
     1.1 --- a/linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c	Tue Dec 13 18:08:26 2005 +0000
     1.2 +++ b/linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c	Tue Dec 13 19:20:29 2005 +0100
     1.3 @@ -639,6 +639,44 @@ void notify_remote_via_irq(int irq)
     1.4  }
     1.5  EXPORT_SYMBOL(notify_remote_via_irq);
     1.6  
     1.7 +void mask_evtchn(int port)
     1.8 +{
     1.9 +	shared_info_t *s = HYPERVISOR_shared_info;
    1.10 +	synch_set_bit(port, &s->evtchn_mask[0]);
    1.11 +}
    1.12 +EXPORT_SYMBOL(mask_evtchn);
    1.13 +
    1.14 +void unmask_evtchn(int port)
    1.15 +{
    1.16 +	shared_info_t *s = HYPERVISOR_shared_info;
    1.17 +	unsigned int cpu = smp_processor_id();
    1.18 +	vcpu_info_t *vcpu_info = &s->vcpu_info[cpu];
    1.19 +
    1.20 +	/* Slow path (hypercall) if this is a non-local port. */
    1.21 +	if (unlikely(cpu != cpu_from_evtchn(port))) {
    1.22 +		evtchn_op_t op = { .cmd = EVTCHNOP_unmask,
    1.23 +				   .u.unmask.port = port };
    1.24 +		(void)HYPERVISOR_event_channel_op(&op);
    1.25 +		return;
    1.26 +	}
    1.27 +
    1.28 +	synch_clear_bit(port, &s->evtchn_mask[0]);
    1.29 +
    1.30 +	/*
    1.31 +	 * The following is basically the equivalent of 'hw_resend_irq'. Just
    1.32 +	 * like a real IO-APIC we 'lose the interrupt edge' if the channel is
    1.33 +	 * masked.
    1.34 +	 */
    1.35 +	if (synch_test_bit(port, &s->evtchn_pending[0]) && 
    1.36 +	    !synch_test_and_set_bit(port / BITS_PER_LONG,
    1.37 +				    &vcpu_info->evtchn_pending_sel)) {
    1.38 +		vcpu_info->evtchn_upcall_pending = 1;
    1.39 +		if (!vcpu_info->evtchn_upcall_mask)
    1.40 +			force_evtchn_callback();
    1.41 +	}
    1.42 +}
    1.43 +EXPORT_SYMBOL(unmask_evtchn);
    1.44 +
    1.45  void irq_resume(void)
    1.46  {
    1.47  	evtchn_op_t op;
     2.1 --- a/linux-2.6-xen-sparse/include/asm-xen/evtchn.h	Tue Dec 13 18:08:26 2005 +0000
     2.2 +++ b/linux-2.6-xen-sparse/include/asm-xen/evtchn.h	Tue Dec 13 19:20:29 2005 +0100
     2.3 @@ -79,46 +79,16 @@ extern int bind_ipi_to_irqhandler(
     2.4   */
     2.5  extern void unbind_from_irqhandler(unsigned int irq, void *dev_id);
     2.6  
     2.7 -/*
     2.8 - * Unlike notify_remote_via_evtchn(), this is safe to use across
     2.9 - * save/restore. Notifications on a broken connection are silently dropped.
    2.10 - */
    2.11 -void notify_remote_via_irq(int irq);
    2.12 -
    2.13  extern void irq_resume(void);
    2.14  
    2.15  /* Entry point for notifications into Linux subsystems. */
    2.16  asmlinkage void evtchn_do_upcall(struct pt_regs *regs);
    2.17  
    2.18  /* Entry point for notifications into the userland character device. */
    2.19 -void evtchn_device_upcall(int port);
    2.20 -
    2.21 -static inline void mask_evtchn(int port)
    2.22 -{
    2.23 -	shared_info_t *s = HYPERVISOR_shared_info;
    2.24 -	synch_set_bit(port, &s->evtchn_mask[0]);
    2.25 -}
    2.26 -
    2.27 -static inline void unmask_evtchn(int port)
    2.28 -{
    2.29 -	shared_info_t *s = HYPERVISOR_shared_info;
    2.30 -	vcpu_info_t *vcpu_info = &s->vcpu_info[smp_processor_id()];
    2.31 +extern void evtchn_device_upcall(int port);
    2.32  
    2.33 -	synch_clear_bit(port, &s->evtchn_mask[0]);
    2.34 -
    2.35 -	/*
    2.36 -	 * The following is basically the equivalent of 'hw_resend_irq'. Just
    2.37 -	 * like a real IO-APIC we 'lose the interrupt edge' if the channel is
    2.38 -	 * masked.
    2.39 -	 */
    2.40 -	if (synch_test_bit(port, &s->evtchn_pending[0]) && 
    2.41 -	    !synch_test_and_set_bit(port / BITS_PER_LONG,
    2.42 -				    &vcpu_info->evtchn_pending_sel)) {
    2.43 -		vcpu_info->evtchn_upcall_pending = 1;
    2.44 -		if (!vcpu_info->evtchn_upcall_mask)
    2.45 -			force_evtchn_callback();
    2.46 -	}
    2.47 -}
    2.48 +extern void mask_evtchn(int port);
    2.49 +extern void unmask_evtchn(int port);
    2.50  
    2.51  static inline void clear_evtchn(int port)
    2.52  {
    2.53 @@ -134,6 +104,12 @@ static inline void notify_remote_via_evt
    2.54  	(void)HYPERVISOR_event_channel_op(&op);
    2.55  }
    2.56  
    2.57 +/*
    2.58 + * Unlike notify_remote_via_evtchn(), this is safe to use across
    2.59 + * save/restore. Notifications on a broken connection are silently dropped.
    2.60 + */
    2.61 +extern void notify_remote_via_irq(int irq);
    2.62 +
    2.63  #endif /* __ASM_EVTCHN_H__ */
    2.64  
    2.65  /*
     3.1 --- a/xen/common/event_channel.c	Tue Dec 13 18:08:26 2005 +0000
     3.2 +++ b/xen/common/event_channel.c	Tue Dec 13 19:20:29 2005 +0100
     3.3 @@ -3,7 +3,7 @@
     3.4   * 
     3.5   * Event notifications from VIRQs, PIRQs, and other domains.
     3.6   * 
     3.7 - * Copyright (c) 2003-2004, K A Fraser.
     3.8 + * Copyright (c) 2003-2005, K A Fraser.
     3.9   * 
    3.10   * This program is distributed in the hope that it will be useful,
    3.11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    3.12 @@ -541,6 +541,41 @@ static long evtchn_bind_vcpu(evtchn_bind
    3.13      return rc;
    3.14  }
    3.15  
    3.16 +static long evtchn_unmask(evtchn_unmask_t *unmask)
    3.17 +{
    3.18 +    struct domain *d = current->domain;
    3.19 +    shared_info_t *s = d->shared_info;
    3.20 +    int            port = unmask->port;
    3.21 +    struct vcpu   *v;
    3.22 +
    3.23 +    spin_lock(&d->evtchn_lock);
    3.24 +
    3.25 +    if ( unlikely(!port_is_valid(d, port)) )
    3.26 +    {
    3.27 +        spin_unlock(&d->evtchn_lock);
    3.28 +        return -EINVAL;
    3.29 +    }
    3.30 +
    3.31 +    v = d->vcpu[evtchn_from_port(d, port)->notify_vcpu_id];
    3.32 +
    3.33 +    /*
    3.34 +     * These operations must happen in strict order. Based on
    3.35 +     * include/xen/event.h:evtchn_set_pending(). 
    3.36 +     */
    3.37 +    if ( test_and_clear_bit(port, &s->evtchn_mask[0]) &&
    3.38 +         test_bit          (port, &s->evtchn_pending[0]) &&
    3.39 +         !test_and_set_bit (port / BITS_PER_LONG,
    3.40 +                            &v->vcpu_info->evtchn_pending_sel) &&
    3.41 +         !test_and_set_bit (0, &v->vcpu_info->evtchn_upcall_pending) )
    3.42 +    {
    3.43 +        evtchn_notify(v);
    3.44 +    }
    3.45 +
    3.46 +    spin_unlock(&d->evtchn_lock);
    3.47 +
    3.48 +    return 0;
    3.49 +}
    3.50 +
    3.51  long do_event_channel_op(evtchn_op_t *uop)
    3.52  {
    3.53      long rc;
    3.54 @@ -602,6 +637,10 @@ long do_event_channel_op(evtchn_op_t *uo
    3.55          rc = evtchn_bind_vcpu(&op.u.bind_vcpu);
    3.56          break;
    3.57  
    3.58 +    case EVTCHNOP_unmask:
    3.59 +        rc = evtchn_unmask(&op.u.unmask);
    3.60 +        break;
    3.61 +
    3.62      default:
    3.63          rc = -ENOSYS;
    3.64          break;
     4.1 --- a/xen/include/public/event_channel.h	Tue Dec 13 18:08:26 2005 +0000
     4.2 +++ b/xen/include/public/event_channel.h	Tue Dec 13 19:20:29 2005 +0100
     4.3 @@ -164,6 +164,16 @@ typedef struct evtchn_bind_vcpu {
     4.4      uint32_t vcpu;
     4.5  } evtchn_bind_vcpu_t;
     4.6  
     4.7 +/*
     4.8 + * EVTCHNOP_unmask: Unmask the specified local event-channel port and deliver
     4.9 + * a notification to the appropriate VCPU if an event is pending.
    4.10 + */
    4.11 +#define EVTCHNOP_unmask           9
    4.12 +typedef struct evtchn_unmask {
    4.13 +    /* IN parameters. */
    4.14 +    evtchn_port_t port;
    4.15 +} evtchn_unmask_t;
    4.16 +
    4.17  typedef struct evtchn_op {
    4.18      uint32_t cmd; /* EVTCHNOP_* */
    4.19      union {
    4.20 @@ -176,6 +186,7 @@ typedef struct evtchn_op {
    4.21          evtchn_send_t             send;
    4.22          evtchn_status_t           status;
    4.23          evtchn_bind_vcpu_t        bind_vcpu;
    4.24 +        evtchn_unmask_t           unmask;
    4.25      } u;
    4.26  } evtchn_op_t;
    4.27  
     5.1 --- a/xen/include/xen/event.h	Tue Dec 13 18:08:26 2005 +0000
     5.2 +++ b/xen/include/xen/event.h	Tue Dec 13 19:20:29 2005 +0100
     5.3 @@ -3,7 +3,7 @@
     5.4   * 
     5.5   * A nice interface for passing asynchronous events to guest OSes.
     5.6   * 
     5.7 - * Copyright (c) 2002, K A Fraser
     5.8 + * Copyright (c) 2002-2005, K A Fraser
     5.9   */
    5.10  
    5.11  #ifndef __XEN_EVENT_H__