/****************************************************************************** * event.h * * A nice interface for passing asynchronous events to guest OSes. * * Copyright (c) 2002-2006, K A Fraser */ #ifndef __XEN_EVENT_H__ #define __XEN_EVENT_H__ #include #include #include #include #include /* * send_guest_vcpu_virq: Notify guest via a per-VCPU VIRQ. * @v: VCPU to which virtual IRQ should be sent * @virq: Virtual IRQ number (VIRQ_*) */ void send_guest_vcpu_virq(struct vcpu *v, uint32_t virq); /* * send_global_virq: Notify the domain handling a global VIRQ. * @virq: Virtual IRQ number (VIRQ_*) */ void send_global_virq(uint32_t virq); /* * sent_global_virq_handler: Set a global VIRQ handler. * @d: New target domain for this VIRQ * @virq: Virtual IRQ number (VIRQ_*), must be global */ int set_global_virq_handler(struct domain *d, uint32_t virq); /* * send_guest_pirq: * @d: Domain to which physical IRQ should be sent * @pirq: Physical IRQ number */ void send_guest_pirq(struct domain *, const struct pirq *); /* Send a notification from a given domain's event-channel port. */ int evtchn_send(struct domain *d, unsigned int lport); /* Bind a local event-channel port to the specified VCPU. */ long evtchn_bind_vcpu(unsigned int port, unsigned int vcpu_id); /* Unmask a local event-channel port. */ int evtchn_unmask(unsigned int port); /* Move all PIRQs after a vCPU was moved to another pCPU. */ void evtchn_move_pirqs(struct vcpu *v); /* Allocate/free a Xen-attached event channel port. */ typedef void (*xen_event_channel_notification_t)( struct vcpu *v, unsigned int port); int alloc_unbound_xen_event_channel( struct vcpu *local_vcpu, domid_t remote_domid, xen_event_channel_notification_t notification_fn); void free_xen_event_channel( struct vcpu *local_vcpu, int port); /* Query if event channel is in use by the guest */ int guest_enabled_event(struct vcpu *v, uint32_t virq); /* Notify remote end of a Xen-attached event channel.*/ void notify_via_xen_event_channel(struct domain *ld, int lport); /* Internal event channel object accessors */ #define bucket_from_port(d,p) \ ((d)->evtchn[(p)/EVTCHNS_PER_BUCKET]) #define port_is_valid(d,p) \ (((p) >= 0) && ((p) < MAX_EVTCHNS(d)) && \ (bucket_from_port(d,p) != NULL)) #define evtchn_from_port(d,p) \ (&(bucket_from_port(d,p))[(p)&(EVTCHNS_PER_BUCKET-1)]) /* Wait on a Xen-attached event channel. */ #define wait_on_xen_event_channel(port, condition) \ do { \ if ( condition ) \ break; \ set_bit(_VPF_blocked_in_xen, ¤t->pause_flags); \ smp_mb(); /* set blocked status /then/ re-evaluate condition */ \ if ( condition ) \ { \ clear_bit(_VPF_blocked_in_xen, ¤t->pause_flags); \ break; \ } \ raise_softirq(SCHEDULE_SOFTIRQ); \ do_softirq(); \ } while ( 0 ) #define prepare_wait_on_xen_event_channel(port) \ do { \ set_bit(_VPF_blocked_in_xen, ¤t->pause_flags); \ raise_softirq(SCHEDULE_SOFTIRQ); \ smp_mb(); /* set blocked status /then/ caller does his work */ \ } while ( 0 ) void evtchn_check_pollers(struct domain *d, unsigned int port); void evtchn_2l_init(struct domain *d); /* * Low-level event channel port ops. */ struct evtchn_port_ops { void (*set_pending)(struct vcpu *v, struct evtchn *evtchn); void (*clear_pending)(struct domain *d, struct evtchn *evtchn); void (*unmask)(struct domain *d, struct evtchn *evtchn); bool_t (*is_pending)(struct domain *d, const struct evtchn *evtchn); bool_t (*is_masked)(struct domain *d, const struct evtchn *evtchn); }; static inline void evtchn_port_set_pending(struct vcpu *v, struct evtchn *evtchn) { v->domain->evtchn_port_ops->set_pending(v, evtchn); } static inline void evtchn_port_clear_pending(struct domain *d, struct evtchn *evtchn) { d->evtchn_port_ops->clear_pending(d, evtchn); } static inline void evtchn_port_unmask(struct domain *d, struct evtchn *evtchn) { d->evtchn_port_ops->unmask(d, evtchn); } static inline bool_t evtchn_port_is_pending(struct domain *d, const struct evtchn *evtchn) { return d->evtchn_port_ops->is_pending(d, evtchn); } static inline bool_t evtchn_port_is_masked(struct domain *d, const struct evtchn *evtchn) { return d->evtchn_port_ops->is_masked(d, evtchn); } #endif /* __XEN_EVENT_H__ */