ia64/xen-unstable

changeset 8837:4a9a39d08a06

Rework hvm_wait_io() -- now tries to be a polite user of
event channels by re-setting the selector and master
pending flags when it exits. Should make for better
behaviour when there are others using the event channels.

This needs some testing to be sure it doesn't break
anything or trigger latent bugs.

Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Sat Feb 11 13:06:49 2006 +0100 (2006-02-11)
parents 0828f5f18b56
children 6ff2db607256
files xen/arch/x86/hvm/io.c xen/arch/x86/hvm/svm/vmcb.c xen/arch/x86/hvm/vmx/io.c xen/include/asm-x86/hvm/support.h
line diff
     1.1 --- a/xen/arch/x86/hvm/io.c	Fri Feb 10 17:57:13 2006 +0100
     1.2 +++ b/xen/arch/x86/hvm/io.c	Sat Feb 11 13:06:49 2006 +0100
     1.3 @@ -690,62 +690,41 @@ void hvm_io_assist(struct vcpu *v)
     1.4      }
     1.5  }
     1.6  
     1.7 -int hvm_clear_pending_io_event(struct vcpu *v)
     1.8 -{
     1.9 -    struct domain *d = v->domain;
    1.10 -    int port = iopacket_port(d);
    1.11 -
    1.12 -    /* evtchn_pending_sel bit is shared by other event channels. */
    1.13 -    if (!d->shared_info->evtchn_pending[port/BITS_PER_LONG])
    1.14 -        clear_bit(port/BITS_PER_LONG, &v->vcpu_info->evtchn_pending_sel);
    1.15 -
    1.16 -    /* Note: HVM domains may need upcalls as well. */
    1.17 -    if (!v->vcpu_info->evtchn_pending_sel)
    1.18 -        clear_bit(0, &v->vcpu_info->evtchn_upcall_pending);
    1.19 -
    1.20 -    /* Clear the pending bit for port. */
    1.21 -    return test_and_clear_bit(port, &d->shared_info->evtchn_pending[0]);
    1.22 -}
    1.23 -
    1.24  /*
    1.25 - * Because we've cleared the pending events first, we need to guarantee that
    1.26 - * all events to be handled by xen for HVM domains are taken care of here.
    1.27 - *
    1.28 - * interrupts are guaranteed to be checked before resuming guest.
    1.29 - * HVM upcalls have been already arranged for if necessary.
    1.30 - */
    1.31 -void hvm_check_events(struct vcpu *v)
    1.32 -{
    1.33 -    /*
    1.34 -     * Clear the event *before* checking for work. This should
    1.35 -     * avoid the set-and-check races
    1.36 -     */
    1.37 -    if (hvm_clear_pending_io_event(current))
    1.38 -        hvm_io_assist(v);
    1.39 -}
    1.40 -
    1.41 -/*
    1.42 - * On exit from hvm_wait_io, we're guaranteed to have a I/O response
    1.43 - * from the device model.
    1.44 + * On exit from hvm_wait_io, we're guaranteed not to be waiting on
    1.45 + * I/O response from the device model.
    1.46   */
    1.47  void hvm_wait_io(void)
    1.48  {
    1.49 -    int port = iopacket_port(current->domain);
    1.50 -
    1.51 -    do {
    1.52 -        if (!test_bit(port, &current->domain->shared_info->evtchn_pending[0]))
    1.53 -	    do_sched_op(SCHEDOP_block, 0);
    1.54 +    struct vcpu *v = current;
    1.55 +    struct domain *d = v->domain;    
    1.56 +    int port = iopacket_port(d);
    1.57  
    1.58 -        hvm_check_events(current);
    1.59 -        if (!test_bit(ARCH_HVM_IO_WAIT, &current->arch.hvm_vcpu.ioflags))
    1.60 +    for ( ; ; )
    1.61 +    {
    1.62 +        /* Clear master flag, selector flag, event flag each in turn. */
    1.63 +        v->vcpu_info->evtchn_upcall_pending = 0;
    1.64 +        smp_mb__before_clear_bit();
    1.65 +        clear_bit(port/BITS_PER_LONG, &v->vcpu_info->evtchn_pending_sel);
    1.66 +        smp_mb__after_clear_bit();
    1.67 +        if ( test_and_clear_bit(port, &d->shared_info->evtchn_pending[0]) )
    1.68 +            hvm_io_assist(v);
    1.69 +
    1.70 +        /* Need to wait for I/O responses? */
    1.71 +        if ( !test_bit(ARCH_HVM_IO_WAIT, &v->arch.hvm_vcpu.ioflags) )
    1.72              break;
    1.73 -        /*
    1.74 -	 * Events other than IOPACKET_PORT might have woken us up.
    1.75 -	 * In that case, safely go back to sleep.
    1.76 -	 */
    1.77 -        clear_bit(port/BITS_PER_LONG, &current->vcpu_info->evtchn_pending_sel);
    1.78 -        clear_bit(0, &current->vcpu_info->evtchn_upcall_pending);
    1.79 -    } while(1);
    1.80 +
    1.81 +        do_sched_op(SCHEDOP_block, 0);
    1.82 +    }
    1.83 +
    1.84 +    /*
    1.85 +     * Re-set the selector and master flags in case any other notifications
    1.86 +     * are pending.
    1.87 +     */
    1.88 +    if ( d->shared_info->evtchn_pending[port/BITS_PER_LONG] )
    1.89 +        set_bit(port/BITS_PER_LONG, &v->vcpu_info->evtchn_pending_sel);
    1.90 +    if ( v->vcpu_info->evtchn_pending_sel )
    1.91 +        v->vcpu_info->evtchn_upcall_pending = 1;
    1.92  }
    1.93  
    1.94  /*
     2.1 --- a/xen/arch/x86/hvm/svm/vmcb.c	Fri Feb 10 17:57:13 2006 +0100
     2.2 +++ b/xen/arch/x86/hvm/svm/vmcb.c	Sat Feb 11 13:06:49 2006 +0100
     2.3 @@ -489,13 +489,8 @@ void svm_do_resume(struct vcpu *v)
     2.4  {
     2.5      struct hvm_virpit *vpit = &v->domain->arch.hvm_domain.vpit;
     2.6      
     2.7 -    if (event_pending(v)) 
     2.8 -    {
     2.9 -        hvm_check_events(v);
    2.10 -
    2.11 -        if (test_bit(ARCH_HVM_IO_WAIT, &v->arch.hvm_vcpu.ioflags))
    2.12 -            hvm_wait_io();
    2.13 -    }
    2.14 +    if ( event_pending(v) )
    2.15 +        hvm_wait_io();
    2.16  
    2.17      /* pick up the elapsed PIT ticks and re-enable pit_timer */
    2.18      if ( vpit->first_injected ) {
     3.1 --- a/xen/arch/x86/hvm/vmx/io.c	Fri Feb 10 17:57:13 2006 +0100
     3.2 +++ b/xen/arch/x86/hvm/vmx/io.c	Sat Feb 11 13:06:49 2006 +0100
     3.3 @@ -177,17 +177,13 @@ void vmx_do_resume(struct vcpu *v)
     3.4  
     3.5      vmx_stts();
     3.6  
     3.7 -    if (event_pending(v)) {
     3.8 -        hvm_check_events(v);
     3.9 +    if ( event_pending(v) )
    3.10 +        hvm_wait_io();
    3.11  
    3.12 -        if (test_bit(ARCH_HVM_IO_WAIT, &v->arch.hvm_vcpu.ioflags))
    3.13 -            hvm_wait_io();
    3.14 -    }
    3.15      /* pick up the elapsed PIT ticks and re-enable pit_timer */
    3.16 -    if ( vpit->first_injected ) {
    3.17 +    if ( vpit->first_injected )
    3.18          pickup_deactive_ticks(vpit);
    3.19 -    }
    3.20 -    vmx_set_tsc_shift(v,vpit);
    3.21 +    vmx_set_tsc_shift(v, vpit);
    3.22  
    3.23      /* We can't resume the guest if we're waiting on I/O */
    3.24      ASSERT(!test_bit(ARCH_HVM_IO_WAIT, &v->arch.hvm_vcpu.ioflags));
     4.1 --- a/xen/include/asm-x86/hvm/support.h	Fri Feb 10 17:57:13 2006 +0100
     4.2 +++ b/xen/include/asm-x86/hvm/support.h	Sat Feb 11 13:06:49 2006 +0100
     4.3 @@ -141,7 +141,6 @@ extern int hvm_copy(void *buf, unsigned 
     4.4  extern void hvm_setup_platform(struct domain* d);
     4.5  extern int hvm_mmio_intercept(ioreq_t *p);
     4.6  extern int hvm_io_intercept(ioreq_t *p, int type);
     4.7 -extern void hvm_check_events(struct vcpu *v);
     4.8  extern void hvm_hooks_assist(struct vcpu *v);
     4.9  extern void hvm_print_line(struct vcpu *v, const char c);
    4.10  extern void hlt_timer_fn(void *data);