Don't require a separate domctl to notify the memevent interface that an event has occured. This domctl can be taxing, particularly when you are scaling events and paging to many domains across a single system. Instead, we use the existing event channel to signal when we place something in the ring (as per normal ring operation). Signed-off-by: Adin Scannell diff -r e581ed816224 xen/arch/ia64/xen/Makefile --- a/xen/arch/ia64/xen/Makefile +++ b/xen/arch/ia64/xen/Makefile @@ -38,6 +38,7 @@ obj-y += flushd.o obj-y += privop_stat.o obj-y += xenpatch.o obj-y += pci.o +obj-y += events.o obj-$(crash_debug) += gdbstub.o obj-$(xen_ia64_tlb_track) += tlb_track.o diff -r e581ed816224 xen/arch/ia64/xen/events.c --- /dev/null +++ b/xen/arch/ia64/xen/events.c @@ -0,0 +1,27 @@ +/****************************************************************************** + * events.c + * + * Arch-specific event channels. + */ + +#include +#include +#include +#include + +int arch_event_notify(struct vcpu *v, int port) +{ + int ret = 0; + + if( port == v->arch.hvm_vcpu.xen_port ) + { + if( test_and_clear_bit(_VPF_blocked_in_xen, &v->pause_flags) ) + vcpu_wake(v); + } + else + { + ret = -EINVAL; + } + + return ret; +} diff -r e581ed816224 xen/arch/x86/Makefile --- a/xen/arch/x86/Makefile +++ b/xen/arch/x86/Makefile @@ -57,6 +57,7 @@ obj-y += crash.o obj-y += tboot.o obj-y += hpet.o obj-y += xstate.o +obj-y += events.o obj-$(crash_debug) += gdbstub.o diff -r e581ed816224 xen/arch/x86/events.c --- /dev/null +++ b/xen/arch/x86/events.c @@ -0,0 +1,41 @@ +/****************************************************************************** + * events.c + * + * Arch-specific event channels. + */ + +#include +#include +#include +#include +#include +#include + +int arch_event_notify(struct vcpu *v, int port) +{ + int ret = 0; + + if( port == v->arch.hvm_vcpu.xen_port ) + { + if( test_and_clear_bit(_VPF_blocked_in_xen, &v->pause_flags) ) + vcpu_wake(v); + } + else if ( port == v->domain->mem_paging.xen_port ) + { + ret = p2m_mem_paging_resume(v->domain); + } + else if ( port == v->domain->mem_access.xen_port ) + { + ret = p2m_mem_access_resume(v->domain); + } + else if ( port == v->domain->mem_share.xen_port ) + { + ret = mem_sharing_sharing_resume(v->domain); + } + else + { + ret = -EINVAL; + } + + return ret; +} diff -r e581ed816224 xen/arch/x86/mm/mem_access.c --- a/xen/arch/x86/mm/mem_access.c +++ b/xen/arch/x86/mm/mem_access.c @@ -29,13 +29,12 @@ int mem_access_domctl(struct domain *d, XEN_GUEST_HANDLE(void) u_domctl) { int rc; - struct p2m_domain *p2m = p2m_get_hostp2m(d); switch( mec->op ) { case XEN_DOMCTL_MEM_EVENT_OP_ACCESS_RESUME: { - p2m_mem_access_resume(p2m); + p2m_mem_access_resume(d); rc = 0; } break; diff -r e581ed816224 xen/arch/x86/mm/mem_paging.c --- a/xen/arch/x86/mm/mem_paging.c +++ b/xen/arch/x86/mm/mem_paging.c @@ -64,7 +64,6 @@ int mem_paging_domctl(struct domain *d, } } - /* * Local variables: * mode: C diff -r e581ed816224 xen/arch/x86/mm/p2m.c --- a/xen/arch/x86/mm/p2m.c +++ b/xen/arch/x86/mm/p2m.c @@ -833,7 +833,7 @@ int p2m_mem_paging_prep(struct domain *d return 0; } -void p2m_mem_paging_resume(struct domain *d) +int p2m_mem_paging_resume(struct domain *d) { struct p2m_domain *p2m = p2m_get_hostp2m(d); mem_event_response_t rsp; @@ -861,6 +861,8 @@ void p2m_mem_paging_resume(struct domain /* Unpause any domains that were paused because the ring was full */ mem_event_unpause_vcpus(d, &d->mem_paging); + + return 0; } void p2m_mem_access_check(unsigned long gpa, bool_t gla_valid, unsigned long gla, @@ -936,9 +938,8 @@ void p2m_mem_access_check(unsigned long /* VCPU paused, mem event request sent */ } -void p2m_mem_access_resume(struct p2m_domain *p2m) +int p2m_mem_access_resume(struct domain *d) { - struct domain *d = p2m->domain; mem_event_response_t rsp; /* Pull all responses off the ring */ @@ -952,6 +953,8 @@ void p2m_mem_access_resume(struct p2m_do /* Unpause any domains that were paused because the ring was full or no listener * was available */ mem_event_unpause_vcpus(d, &d->mem_access); + + return 0; } diff -r e581ed816224 xen/common/event_channel.c --- a/xen/common/event_channel.c +++ b/xen/common/event_channel.c @@ -57,6 +57,8 @@ goto out; \ } while ( 0 ) +extern int arch_event_notify(struct vcpu *v, int port); + static int evtchn_set_pending(struct vcpu *v, int port); static int virq_is_global(int virq) @@ -553,10 +555,7 @@ int evtchn_send(struct domain *d, unsign rvcpu = rd->vcpu[rchn->notify_vcpu_id]; if ( rchn->consumer_is_xen ) { - /* Xen consumers need notification only if they are blocked. */ - if ( test_and_clear_bit(_VPF_blocked_in_xen, - &rvcpu->pause_flags) ) - vcpu_wake(rvcpu); + ret = arch_event_notify(rvcpu, rport); } else { diff -r e581ed816224 xen/include/asm-x86/mem_event.h --- a/xen/include/asm-x86/mem_event.h +++ b/xen/include/asm-x86/mem_event.h @@ -24,6 +24,8 @@ #ifndef __MEM_EVENT_H__ #define __MEM_EVENT_H__ +#include + /* Pauses VCPU while marking pause flag for mem event */ void mem_event_mark_and_pause(struct vcpu *v, struct mem_event_domain *med); int mem_event_check_ring(struct domain *d, struct mem_event_domain *med); diff -r e581ed816224 xen/include/asm-x86/mem_sharing.h --- a/xen/include/asm-x86/mem_sharing.h +++ b/xen/include/asm-x86/mem_sharing.h @@ -47,6 +47,9 @@ void mem_sharing_init(void); #define mem_sharing_init() do { } while (0) +static inline int mem_sharing_sharing_resume(struct domain *d) +{ return -EINVAL; } + #endif /* __x86_64__ */ #endif /* __MEM_SHARING_H__ */ diff -r e581ed816224 xen/include/asm-x86/p2m.h --- a/xen/include/asm-x86/p2m.h +++ b/xen/include/asm-x86/p2m.h @@ -489,12 +489,14 @@ void p2m_mem_paging_populate(struct doma /* Prepare the p2m for paging a frame in */ int p2m_mem_paging_prep(struct domain *d, unsigned long gfn); /* Resume normal operation (in case a domain was paused) */ -void p2m_mem_paging_resume(struct domain *d); +int p2m_mem_paging_resume(struct domain *d); #else static inline void p2m_mem_paging_drop_page(struct domain *d, unsigned long gfn) { } static inline void p2m_mem_paging_populate(struct domain *d, unsigned long gfn) { } +static inline int p2m_mem_paging_resume(struct domain *d) +{ return -EINVAL; } #endif #ifdef __x86_64__ @@ -503,7 +505,7 @@ static inline void p2m_mem_paging_popula void p2m_mem_access_check(unsigned long gpa, bool_t gla_valid, unsigned long gla, bool_t access_r, bool_t access_w, bool_t access_x); /* Resumes the running of the VCPU, restarting the last instruction */ -void p2m_mem_access_resume(struct p2m_domain *p2m); +int p2m_mem_access_resume(struct domain *d); /* Set access type for a region of pfns. * If start_pfn == -1ul, sets the default access type */ @@ -527,6 +529,8 @@ static inline int p2m_set_mem_access(str static inline int p2m_get_mem_access(struct domain *d, unsigned long pfn, hvmmem_access_t *access) { return -EINVAL; } +static inline int p2m_mem_access_resume(struct domain *d) +{ return -EINVAL; } #endif /*