debuggers.hg
changeset 10987:ffa5b2975dff
[XEN] Add Xen-attached event channels, which will be used
by HVM for the ioreq_packet port.
Signed-off-by: Keir Fraser <keir@xensource.com>
by HVM for the ioreq_packet port.
Signed-off-by: Keir Fraser <keir@xensource.com>
author | kfraser@localhost.localdomain |
---|---|
date | Fri Aug 04 20:34:44 2006 +0100 (2006-08-04) |
parents | 49dcd838b7df |
children | 353404fe850c |
files | xen/common/event_channel.c xen/include/xen/event.h xen/include/xen/sched.h |
line diff
1.1 --- a/xen/common/event_channel.c Fri Aug 04 20:30:12 2006 +0100 1.2 +++ b/xen/common/event_channel.c Fri Aug 04 20:34:44 2006 +0100 1.3 @@ -333,6 +333,14 @@ static long __evtchn_close(struct domain 1.4 } 1.5 1.6 chn1 = evtchn_from_port(d1, port1); 1.7 + 1.8 + /* Guest cannot close a Xen-attached event channel. */ 1.9 + if ( unlikely(chn1->consumer_is_xen) ) 1.10 + { 1.11 + rc = -EINVAL; 1.12 + goto out; 1.13 + } 1.14 + 1.15 switch ( chn1->state ) 1.16 { 1.17 case ECS_FREE: 1.18 @@ -441,6 +449,7 @@ long evtchn_send(unsigned int lport) 1.19 { 1.20 struct evtchn *lchn, *rchn; 1.21 struct domain *ld = current->domain, *rd; 1.22 + struct vcpu *rvcpu; 1.23 int rport, ret = 0; 1.24 1.25 spin_lock(&ld->evtchn_lock); 1.26 @@ -452,13 +461,32 @@ long evtchn_send(unsigned int lport) 1.27 } 1.28 1.29 lchn = evtchn_from_port(ld, lport); 1.30 + 1.31 + /* Guest cannot send via a Xen-attached event channel. */ 1.32 + if ( unlikely(lchn->consumer_is_xen) ) 1.33 + { 1.34 + spin_unlock(&ld->evtchn_lock); 1.35 + return -EINVAL; 1.36 + } 1.37 + 1.38 switch ( lchn->state ) 1.39 { 1.40 case ECS_INTERDOMAIN: 1.41 rd = lchn->u.interdomain.remote_dom; 1.42 rport = lchn->u.interdomain.remote_port; 1.43 rchn = evtchn_from_port(rd, rport); 1.44 - evtchn_set_pending(rd->vcpu[rchn->notify_vcpu_id], rport); 1.45 + rvcpu = rd->vcpu[rchn->notify_vcpu_id]; 1.46 + if ( rchn->consumer_is_xen ) 1.47 + { 1.48 + /* Xen consumers need notification only if they are blocked. */ 1.49 + if ( test_and_clear_bit(_VCPUF_blocked_in_xen, 1.50 + &rvcpu->vcpu_flags) ) 1.51 + vcpu_wake(rvcpu); 1.52 + } 1.53 + else 1.54 + { 1.55 + evtchn_set_pending(rvcpu, rport); 1.56 + } 1.57 break; 1.58 case ECS_IPI: 1.59 evtchn_set_pending(ld->vcpu[lchn->notify_vcpu_id], lport); 1.60 @@ -638,6 +666,14 @@ long evtchn_bind_vcpu(unsigned int port, 1.61 } 1.62 1.63 chn = evtchn_from_port(d, port); 1.64 + 1.65 + /* Guest cannot re-bind a Xen-attached event channel. */ 1.66 + if ( unlikely(chn->consumer_is_xen) ) 1.67 + { 1.68 + rc = -EINVAL; 1.69 + goto out; 1.70 + } 1.71 + 1.72 switch ( chn->state ) 1.73 { 1.74 case ECS_VIRQ: 1.75 @@ -804,6 +840,71 @@ long do_event_channel_op(int cmd, XEN_GU 1.76 } 1.77 1.78 1.79 +int alloc_unbound_xen_event_channel( 1.80 + struct vcpu *local_vcpu, domid_t remote_domid) 1.81 +{ 1.82 + struct evtchn *chn; 1.83 + struct domain *d = local_vcpu->domain; 1.84 + int port; 1.85 + 1.86 + spin_lock(&d->evtchn_lock); 1.87 + 1.88 + if ( (port = get_free_port(d)) < 0 ) 1.89 + goto out; 1.90 + chn = evtchn_from_port(d, port); 1.91 + 1.92 + chn->state = ECS_UNBOUND; 1.93 + chn->consumer_is_xen = 1; 1.94 + chn->notify_vcpu_id = local_vcpu->vcpu_id; 1.95 + chn->u.unbound.remote_domid = remote_domid; 1.96 + 1.97 + out: 1.98 + spin_unlock(&d->evtchn_lock); 1.99 + 1.100 + return port; 1.101 +} 1.102 + 1.103 + 1.104 +void free_xen_event_channel( 1.105 + struct vcpu *local_vcpu, int port) 1.106 +{ 1.107 + struct evtchn *chn; 1.108 + struct domain *d = local_vcpu->domain; 1.109 + 1.110 + spin_lock(&d->evtchn_lock); 1.111 + chn = evtchn_from_port(d, port); 1.112 + BUG_ON(!chn->consumer_is_xen); 1.113 + chn->consumer_is_xen = 0; 1.114 + spin_unlock(&d->evtchn_lock); 1.115 + 1.116 + (void)__evtchn_close(d, port); 1.117 +} 1.118 + 1.119 + 1.120 +void notify_via_xen_event_channel(int lport) 1.121 +{ 1.122 + struct evtchn *lchn, *rchn; 1.123 + struct domain *ld = current->domain, *rd; 1.124 + int rport; 1.125 + 1.126 + spin_lock(&ld->evtchn_lock); 1.127 + 1.128 + ASSERT(port_is_valid(ld, lport)); 1.129 + lchn = evtchn_from_port(ld, lport); 1.130 + ASSERT(lchn->consumer_is_xen); 1.131 + 1.132 + if ( likely(lchn->state == ECS_INTERDOMAIN) ) 1.133 + { 1.134 + rd = lchn->u.interdomain.remote_dom; 1.135 + rport = lchn->u.interdomain.remote_port; 1.136 + rchn = evtchn_from_port(rd, rport); 1.137 + evtchn_set_pending(rd->vcpu[rchn->notify_vcpu_id], rport); 1.138 + } 1.139 + 1.140 + spin_unlock(&ld->evtchn_lock); 1.141 +} 1.142 + 1.143 + 1.144 int evtchn_init(struct domain *d) 1.145 { 1.146 spin_lock_init(&d->evtchn_lock); 1.147 @@ -819,7 +920,10 @@ void evtchn_destroy(struct domain *d) 1.148 int i; 1.149 1.150 for ( i = 0; port_is_valid(d, i); i++ ) 1.151 - (void)__evtchn_close(d, i); 1.152 + { 1.153 + evtchn_from_port(d, i)->consumer_is_xen = 0; 1.154 + (void)__evtchn_close(d, i); 1.155 + } 1.156 1.157 for ( i = 0; i < NR_EVTCHN_BUCKETS; i++ ) 1.158 xfree(d->evtchn[i]);
2.1 --- a/xen/include/xen/event.h Fri Aug 04 20:30:12 2006 +0100 2.2 +++ b/xen/include/xen/event.h Fri Aug 04 20:34:44 2006 +0100 2.3 @@ -15,33 +15,58 @@ 2.4 #include <asm/bitops.h> 2.5 #include <asm/event.h> 2.6 2.7 -extern void evtchn_set_pending(struct vcpu *v, int port); 2.8 +void evtchn_set_pending(struct vcpu *v, int port); 2.9 2.10 /* 2.11 * send_guest_vcpu_virq: Notify guest via a per-VCPU VIRQ. 2.12 * @v: VCPU to which virtual IRQ should be sent 2.13 * @virq: Virtual IRQ number (VIRQ_*) 2.14 */ 2.15 -extern void send_guest_vcpu_virq(struct vcpu *v, int virq); 2.16 +void send_guest_vcpu_virq(struct vcpu *v, int virq); 2.17 2.18 /* 2.19 * send_guest_global_virq: Notify guest via a global VIRQ. 2.20 * @d: Domain to which virtual IRQ should be sent 2.21 * @virq: Virtual IRQ number (VIRQ_*) 2.22 */ 2.23 -extern void send_guest_global_virq(struct domain *d, int virq); 2.24 +void send_guest_global_virq(struct domain *d, int virq); 2.25 2.26 /* 2.27 * send_guest_pirq: 2.28 * @d: Domain to which physical IRQ should be sent 2.29 * @pirq: Physical IRQ number 2.30 */ 2.31 -extern void send_guest_pirq(struct domain *d, int pirq); 2.32 +void send_guest_pirq(struct domain *d, int pirq); 2.33 2.34 /* Send a notification from a local event-channel port. */ 2.35 -extern long evtchn_send(unsigned int lport); 2.36 +long evtchn_send(unsigned int lport); 2.37 2.38 /* Bind a local event-channel port to the specified VCPU. */ 2.39 -extern long evtchn_bind_vcpu(unsigned int port, unsigned int vcpu_id); 2.40 +long evtchn_bind_vcpu(unsigned int port, unsigned int vcpu_id); 2.41 + 2.42 +/* Allocate/free a Xen-attached event channel port. */ 2.43 +int alloc_unbound_xen_event_channel( 2.44 + struct vcpu *local_vcpu, domid_t remote_domid); 2.45 +void free_xen_event_channel( 2.46 + struct vcpu *local_vcpu, int port); 2.47 + 2.48 +/* Notify remote end of a Xen-attached event channel.*/ 2.49 +void notify_via_xen_event_channel(int lport); 2.50 + 2.51 +/* Wait on a Xen-attached event channel. */ 2.52 +#define wait_on_xen_event_channel(port, condition) \ 2.53 + do { \ 2.54 + if ( condition ) \ 2.55 + break; \ 2.56 + set_bit(_VCPUF_blocked_in_xen, ¤t->vcpu_flags); \ 2.57 + mb(); /* set blocked status /then/ re-evaluate condition */ \ 2.58 + if ( condition ) \ 2.59 + { \ 2.60 + clear_bit(_VCPUF_blocked_in_xen, ¤t->vcpu_flags); \ 2.61 + break; \ 2.62 + } \ 2.63 + raise_softirq(SCHEDULE_SOFTIRQ); \ 2.64 + do_softirq(); \ 2.65 + } while ( 0 ) 2.66 2.67 #endif /* __XEN_EVENT_H__ */
3.1 --- a/xen/include/xen/sched.h Fri Aug 04 20:30:12 2006 +0100 3.2 +++ b/xen/include/xen/sched.h Fri Aug 04 20:34:44 2006 +0100 3.3 @@ -36,7 +36,8 @@ struct evtchn 3.4 #define ECS_PIRQ 4 /* Channel is bound to a physical IRQ line. */ 3.5 #define ECS_VIRQ 5 /* Channel is bound to a virtual IRQ line. */ 3.6 #define ECS_IPI 6 /* Channel is bound to a virtual IPI line. */ 3.7 - u16 state; /* ECS_* */ 3.8 + u8 state; /* ECS_* */ 3.9 + u8 consumer_is_xen; /* Consumed by Xen or by guest? */ 3.10 u16 notify_vcpu_id; /* VCPU for local delivery notification */ 3.11 union { 3.12 struct { 3.13 @@ -375,6 +376,9 @@ extern struct domain *domain_list; 3.14 /* VCPU is paused by the hypervisor? */ 3.15 #define _VCPUF_paused 11 3.16 #define VCPUF_paused (1UL<<_VCPUF_paused) 3.17 + /* VCPU is blocked awaiting an event to be consumed by Xen. */ 3.18 +#define _VCPUF_blocked_in_xen 12 3.19 +#define VCPUF_blocked_in_xen (1UL<<_VCPUF_blocked_in_xen) 3.20 3.21 /* 3.22 * Per-domain flags (domain_flags). 3.23 @@ -404,7 +408,7 @@ extern struct domain *domain_list; 3.24 static inline int vcpu_runnable(struct vcpu *v) 3.25 { 3.26 return ( !(v->vcpu_flags & 3.27 - (VCPUF_blocked|VCPUF_down|VCPUF_paused)) && 3.28 + (VCPUF_blocked|VCPUF_down|VCPUF_paused|VCPUF_blocked_in_xen)) && 3.29 !(v->domain->domain_flags & 3.30 (DOMF_shutdown|DOMF_ctrl_pause|DOMF_paused)) ); 3.31 }