diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c index 88487644c7..cb37a45b24 100644 --- a/xen/arch/arm/traps.c +++ b/xen/arch/arm/traps.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -2269,12 +2270,23 @@ static void check_for_pcpu_work(void) * Process pending work for the vCPU. Any call should be fast or * implement preemption. */ -static void check_for_vcpu_work(void) +static bool check_for_vcpu_work(void) { struct vcpu *v = current; +#ifdef CONFIG_IOREQ_SERVER + bool handled; + + local_irq_enable(); + handled = vcpu_ioreq_handle_completion(v); + local_irq_disable(); + + if ( !handled ) + return true; +#endif + if ( likely(!v->arch.need_flush_to_ram) ) - return; + return false; /* * Give a chance for the pCPU to process work before handling the vCPU @@ -2285,6 +2297,8 @@ static void check_for_vcpu_work(void) local_irq_enable(); p2m_flush_vm(v); local_irq_disable(); + + return false; } /* @@ -2297,7 +2311,13 @@ void leave_hypervisor_to_guest(void) { local_irq_disable(); - check_for_vcpu_work(); + /* + * check_for_vcpu_work() may return true if there are more work to before + * the vCPU can safely resume. This gives us an opportunity to deschedule + * the vCPU if needed. + */ + while ( check_for_vcpu_work() ) + check_for_pcpu_work(); check_for_pcpu_work(); vgic_sync_to_lrs();