ia64/xen-unstable

changeset 16064:6903e3f3bdd6

hvm: Fix the flush-all-tlbs hypercall.
From: Peter Johnston <pjohnston@xensource.com>
Signed-off-by: Keir Fraser <keir@xensource.com>
author Keir Fraser <keir@xensource.com>
date Thu Oct 04 09:57:17 2007 +0100 (2007-10-04)
parents 4881f984e06e
children 671dcd08e806
files xen/arch/x86/hvm/hvm.c xen/common/domain.c xen/include/xen/sched.h
line diff
     1.1 --- a/xen/arch/x86/hvm/hvm.c	Thu Oct 04 09:40:31 2007 +0100
     1.2 +++ b/xen/arch/x86/hvm/hvm.c	Thu Oct 04 09:57:17 2007 +0100
     1.3 @@ -1661,14 +1661,38 @@ static int hvmop_set_pci_link_route(
     1.4  
     1.5  static int hvmop_flush_tlb_all(void)
     1.6  {
     1.7 +    struct domain *d = current->domain;
     1.8      struct vcpu *v;
     1.9  
    1.10 +    /* Avoid deadlock if more than one vcpu tries this at the same time. */
    1.11 +    if ( !spin_trylock(&d->hypercall_deadlock_mutex) )
    1.12 +        return -EAGAIN;
    1.13 +
    1.14 +    /* Pause all other vcpus. */
    1.15 +    for_each_vcpu ( d, v )
    1.16 +        if ( v != current )
    1.17 +            vcpu_pause_nosync(v);
    1.18 +
    1.19 +    /* Now that all VCPUs are signalled to deschedule, we wait... */
    1.20 +    for_each_vcpu ( d, v )
    1.21 +        if ( v != current )
    1.22 +            while ( !vcpu_runnable(v) && v->is_running )
    1.23 +                cpu_relax();
    1.24 +
    1.25 +    /* All other vcpus are paused, safe to unlock now. */
    1.26 +    spin_unlock(&d->hypercall_deadlock_mutex);
    1.27 +
    1.28      /* Flush paging-mode soft state (e.g., va->gfn cache; PAE PDPE cache). */
    1.29 -    for_each_vcpu ( current->domain, v )
    1.30 +    for_each_vcpu ( d, v )
    1.31          paging_update_cr3(v);
    1.32  
    1.33      /* Flush all dirty TLBs. */
    1.34 -    flush_tlb_mask(current->domain->domain_dirty_cpumask);
    1.35 +    flush_tlb_mask(d->domain_dirty_cpumask);
    1.36 +
    1.37 +    /* Done. */
    1.38 +    for_each_vcpu ( d, v )
    1.39 +        if ( v != current )
    1.40 +            vcpu_unpause(v);
    1.41  
    1.42      return 0;
    1.43  }
    1.44 @@ -1780,6 +1804,10 @@ long do_hvm_op(unsigned long op, XEN_GUE
    1.45      }
    1.46      }
    1.47  
    1.48 +    if ( rc == -EAGAIN )
    1.49 +        rc = hypercall_create_continuation(
    1.50 +            __HYPERVISOR_hvm_op, "lh", op, arg);
    1.51 +
    1.52      return rc;
    1.53  }
    1.54  
     2.1 --- a/xen/common/domain.c	Thu Oct 04 09:40:31 2007 +0100
     2.2 +++ b/xen/common/domain.c	Thu Oct 04 09:57:17 2007 +0100
     2.3 @@ -68,6 +68,7 @@ struct domain *alloc_domain(domid_t domi
     2.4      spin_lock_init(&d->big_lock);
     2.5      spin_lock_init(&d->page_alloc_lock);
     2.6      spin_lock_init(&d->shutdown_lock);
     2.7 +    spin_lock_init(&d->hypercall_deadlock_mutex);
     2.8      INIT_LIST_HEAD(&d->page_list);
     2.9      INIT_LIST_HEAD(&d->xenpage_list);
    2.10  
     3.1 --- a/xen/include/xen/sched.h	Thu Oct 04 09:40:31 2007 +0100
     3.2 +++ b/xen/include/xen/sched.h	Thu Oct 04 09:57:17 2007 +0100
     3.3 @@ -227,6 +227,12 @@ struct domain
     3.4      int32_t time_offset_seconds;
     3.5  
     3.6      struct rcu_head rcu;
     3.7 +
     3.8 +    /*
     3.9 +     * Hypercall deadlock avoidance lock. Used if a hypercall might
    3.10 +     * cause a deadlock. Acquirers don't spin waiting; they preempt.
    3.11 +     */
    3.12 +    spinlock_t hypercall_deadlock_mutex;
    3.13  };
    3.14  
    3.15  struct domain_setup_info