debuggers.hg

changeset 22826:97ab84aca65c

PoD: Allow pod_set_cache_target hypercall to be preempted

For very large VMs, setting the cache target can take long enough that
dom0 complains of soft lockups. Allow the hypercall to be preempted.

Signed-off-by: George Dunlap <george.dunlap@eu.citrix.com>
Acked-by: Tim Deegan <Tim.Deegan@citrix.com>
author George Dunlap <george.dunlap@eu.citrix.com>
date Mon Jan 17 14:24:13 2011 +0000 (2011-01-17)
parents d1631540bcc4
children 3decd02e0b18
files xen/arch/x86/domain.c xen/arch/x86/mm.c xen/arch/x86/mm/p2m.c xen/arch/x86/x86_64/compat/mm.c
line diff
     1.1 --- a/xen/arch/x86/domain.c	Tue Jan 18 17:23:24 2011 +0000
     1.2 +++ b/xen/arch/x86/domain.c	Mon Jan 17 14:24:13 2011 +0000
     1.3 @@ -1653,8 +1653,8 @@ int hypercall_xlat_continuation(unsigned
     1.4      unsigned long nval = 0;
     1.5      va_list args;
     1.6  
     1.7 -    BUG_ON(*id > 5);
     1.8 -    BUG_ON(mask & (1U << *id));
     1.9 +    BUG_ON(id && *id > 5);
    1.10 +    BUG_ON(id && (mask & (1U << *id)));
    1.11  
    1.12      va_start(args, mask);
    1.13  
     2.1 --- a/xen/arch/x86/mm.c	Tue Jan 18 17:23:24 2011 +0000
     2.2 +++ b/xen/arch/x86/mm.c	Mon Jan 17 14:24:13 2011 +0000
     2.3 @@ -4799,15 +4799,23 @@ long arch_memory_op(int op, XEN_GUEST_HA
     2.4              rc = p2m_pod_set_mem_target(d, target.target_pages);
     2.5          }
     2.6  
     2.7 -        p2m = p2m_get_hostp2m(d);
     2.8 -        target.tot_pages       = d->tot_pages;
     2.9 -        target.pod_cache_pages = p2m->pod.count;
    2.10 -        target.pod_entries     = p2m->pod.entry_count;
    2.11 -
    2.12 -        if ( copy_to_guest(arg, &target, 1) )
    2.13 +        if ( rc == -EAGAIN )
    2.14 +        {
    2.15 +            rc = hypercall_create_continuation(
    2.16 +                __HYPERVISOR_memory_op, "lh", op, arg);
    2.17 +        }
    2.18 +        else if ( rc >= 0 )
    2.19          {
    2.20 -            rc= -EFAULT;
    2.21 -            goto pod_target_out_unlock;
    2.22 +            p2m = p2m_get_hostp2m(d);
    2.23 +            target.tot_pages       = d->tot_pages;
    2.24 +            target.pod_cache_pages = p2m->pod.count;
    2.25 +            target.pod_entries     = p2m->pod.entry_count;
    2.26 +
    2.27 +            if ( copy_to_guest(arg, &target, 1) )
    2.28 +            {
    2.29 +                rc= -EFAULT;
    2.30 +                goto pod_target_out_unlock;
    2.31 +            }
    2.32          }
    2.33          
    2.34      pod_target_out_unlock:
     3.1 --- a/xen/arch/x86/mm/p2m.c	Tue Jan 18 17:23:24 2011 +0000
     3.2 +++ b/xen/arch/x86/mm/p2m.c	Mon Jan 17 14:24:13 2011 +0000
     3.3 @@ -435,7 +435,7 @@ static struct page_info * p2m_pod_cache_
     3.4  
     3.5  /* Set the size of the cache, allocating or freeing as necessary. */
     3.6  static int
     3.7 -p2m_pod_set_cache_target(struct p2m_domain *p2m, unsigned long pod_target)
     3.8 +p2m_pod_set_cache_target(struct p2m_domain *p2m, unsigned long pod_target, int preemptible)
     3.9  {
    3.10      struct domain *d = p2m->domain;
    3.11      int ret = 0;
    3.12 @@ -468,6 +468,12 @@ p2m_pod_set_cache_target(struct p2m_doma
    3.13          }
    3.14  
    3.15          p2m_pod_cache_add(p2m, page, order);
    3.16 +
    3.17 +        if ( hypercall_preempt_check() && preemptible )
    3.18 +        {
    3.19 +            ret = -EAGAIN;
    3.20 +            goto out;
    3.21 +        }
    3.22      }
    3.23  
    3.24      /* Decreasing the target */
    3.25 @@ -512,6 +518,12 @@ p2m_pod_set_cache_target(struct p2m_doma
    3.26                  put_page(page+i);
    3.27  
    3.28              put_page(page+i);
    3.29 +
    3.30 +            if ( hypercall_preempt_check() && preemptible )
    3.31 +            {
    3.32 +                ret = -EAGAIN;
    3.33 +                goto out;
    3.34 +            }
    3.35          }
    3.36      }
    3.37  
    3.38 @@ -589,7 +601,7 @@ p2m_pod_set_mem_target(struct domain *d,
    3.39  
    3.40      ASSERT( pod_target >= p2m->pod.count );
    3.41  
    3.42 -    ret = p2m_pod_set_cache_target(p2m, pod_target);
    3.43 +    ret = p2m_pod_set_cache_target(p2m, pod_target, 1/*preemptible*/);
    3.44  
    3.45  out:
    3.46      p2m_unlock(p2m);
    3.47 @@ -753,7 +765,7 @@ out_entry_check:
    3.48      /* If we've reduced our "liabilities" beyond our "assets", free some */
    3.49      if ( p2m->pod.entry_count < p2m->pod.count )
    3.50      {
    3.51 -        p2m_pod_set_cache_target(p2m, p2m->pod.entry_count);
    3.52 +        p2m_pod_set_cache_target(p2m, p2m->pod.entry_count, 0/*can't preempt*/);
    3.53      }
    3.54  
    3.55  out_unlock:
     4.1 --- a/xen/arch/x86/x86_64/compat/mm.c	Tue Jan 18 17:23:24 2011 +0000
     4.2 +++ b/xen/arch/x86/x86_64/compat/mm.c	Mon Jan 17 14:24:13 2011 +0000
     4.3 @@ -127,6 +127,9 @@ int compat_arch_memory_op(int op, XEN_GU
     4.4          if ( rc < 0 )
     4.5              break;
     4.6  
     4.7 +        if ( rc == __HYPERVISOR_memory_op )
     4.8 +            hypercall_xlat_continuation(NULL, 0x2, nat, arg);
     4.9 +
    4.10          XLAT_pod_target(&cmp, nat);
    4.11  
    4.12          if ( copy_to_guest(arg, &cmp, 1) )