direct-io.hg

changeset 10381:0fff4c07af18

[IA64] Fix network issue on VTI domain

Clean up event wait sequence in io emulation path, as a critical
fix to a severe issue where VTI domain may fall into block state
when doing bulk network transfer.

Signed-off-by Kevin Tian <kevin.tian@intel.com>
author awilliam@xenbuild.aw
date Tue Jun 06 09:01:38 2006 -0600 (2006-06-06)
parents f662f98d594b
children 6a49e02dc169
files xen/arch/ia64/vmx/vmx_support.c
line diff
     1.1 --- a/xen/arch/ia64/vmx/vmx_support.c	Mon Jun 05 14:28:39 2006 -0600
     1.2 +++ b/xen/arch/ia64/vmx/vmx_support.c	Tue Jun 06 09:01:38 2006 -0600
     1.3 @@ -32,7 +32,8 @@
     1.4   * when emulation code is waiting for I/O completion by blocking,
     1.5   * other events like DM interrupt, VBD, etc. may come and unblock
     1.6   * current exection flow. So we have to prepare for re-block if unblocked
     1.7 - * by non I/O completion event.
     1.8 + * by non I/O completion event. After io emulation is done, re-enable
     1.9 + * pending indicaion if other ports are pending
    1.10   */
    1.11  void vmx_wait_io(void)
    1.12  {
    1.13 @@ -40,39 +41,25 @@ void vmx_wait_io(void)
    1.14      struct domain *d = v->domain;
    1.15      int port = iopacket_port(v);
    1.16  
    1.17 -    do {
    1.18 -	if (!test_bit(port,
    1.19 -		&d->shared_info->evtchn_pending[0]))
    1.20 -            do_sched_op_compat(SCHEDOP_block, 0);
    1.21 +    for (;;) {
    1.22 +        if (test_and_clear_bit(0, &v->vcpu_info->evtchn_upcall_pending) &&
    1.23 +            test_and_clear_bit(port / BITS_PER_LONG,
    1.24 +                                     &v->vcpu_info->evtchn_pending_sel) &&
    1.25 +            test_and_clear_bit(port, &d->shared_info->evtchn_pending[0]))
    1.26 +            vmx_io_assist(v);
    1.27  
    1.28 -	/* Unblocked when some event is coming. Clear pending indication
    1.29 -	 * immediately if deciding to go for io assist
    1.30 -	  */
    1.31 -	if (test_and_clear_bit(port,
    1.32 -		&d->shared_info->evtchn_pending[0])) {
    1.33 -	    clear_bit(port/BITS_PER_LONG, &v->vcpu_info->evtchn_pending_sel);
    1.34 -	    clear_bit(0, &v->vcpu_info->evtchn_upcall_pending);
    1.35 -	    vmx_io_assist(v);
    1.36 -	}
    1.37 -
    1.38 +        if (!test_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags))
    1.39 +            break;
    1.40  
    1.41 -	if (test_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags)) {
    1.42 -	    /*
    1.43 -	     * Latest event is not I/O completion, so clear corresponding
    1.44 -	     * selector and pending indication, to allow real event coming
    1.45 -	     */
    1.46 -	    clear_bit(0, &v->vcpu_info->evtchn_upcall_pending);
    1.47 +        do_sched_op_compat(SCHEDOP_block, 0);
    1.48 +    }
    1.49  
    1.50 -	    /* Here atually one window is leaved before selector is cleared.
    1.51 -	     * However this window only delay the indication to coming event,
    1.52 -	     * nothing losed. Next loop will check I/O channel to fix this
    1.53 -	     * window.
    1.54 -	     */
    1.55 -	    clear_bit(port/BITS_PER_LONG, &v->vcpu_info->evtchn_pending_sel);
    1.56 -	}
    1.57 -	else
    1.58 -	    break;
    1.59 -    } while (test_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags));
    1.60 +    /* re-enable indication if other pending events */
    1.61 +    if (d->shared_info->evtchn_pending[port / BITS_PER_LONG])
    1.62 +        set_bit(port / BITS_PER_LONG, &v->vcpu_info->evtchn_pending_sel);
    1.63 +
    1.64 +    if (&v->vcpu_info->evtchn_pending_sel)
    1.65 +        set_bit(0, &v->vcpu_info->evtchn_upcall_pending);
    1.66  }
    1.67  
    1.68  /*
    1.69 @@ -110,8 +97,7 @@ void vmx_io_assist(struct vcpu *v)
    1.70  	    p->state = STATE_INVALID;
    1.71  
    1.72  	clear_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags);
    1.73 -    } else
    1.74 -	return; /* Spurous event? */
    1.75 +    }
    1.76  }
    1.77  
    1.78  /*
    1.79 @@ -131,22 +117,16 @@ void vmx_intr_assist(struct vcpu *v)
    1.80  					unsigned long *pend_irr);
    1.81      int port = iopacket_port(v);
    1.82  
    1.83 +    if (test_bit(port, &d->shared_info->evtchn_pending[0]) ||
    1.84 +	test_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags))
    1.85 +	vmx_wait_io();
    1.86 +
    1.87      /* I/O emulation is atomic, so it's impossible to see execution flow
    1.88       * out of vmx_wait_io, when guest is still waiting for response.
    1.89       */
    1.90      if (test_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags))
    1.91  	panic_domain(vcpu_regs(v),"!!!Bad resume to guest before I/O emulation is done.\n");
    1.92  
    1.93 -    /* Clear indicator specific to interrupt delivered from DM */
    1.94 -    if (test_and_clear_bit(port,
    1.95 -		&d->shared_info->evtchn_pending[0])) {
    1.96 -	if (!d->shared_info->evtchn_pending[port/BITS_PER_LONG])
    1.97 -	    clear_bit(port/BITS_PER_LONG, &v->vcpu_info->evtchn_pending_sel);
    1.98 -
    1.99 -	if (!v->vcpu_info->evtchn_pending_sel)
   1.100 -	    clear_bit(0, &v->vcpu_info->evtchn_upcall_pending);
   1.101 -    }
   1.102 -
   1.103      /* Even without event pending, we still need to sync pending bits
   1.104       * between DM and vlsapic. The reason is that interrupt delivery
   1.105       * shares same event channel as I/O emulation, with corresponding