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>
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__