debuggers.hg

changeset 21219:ecdc14634425

Improvements and bug fixes to continue_hypercall_on_cpu().

Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Apr 14 13:35:05 2010 +0100 (2010-04-14)
parents 3cdd4cf2c20e
children 373daaeb636e
files xen/common/domain.c xen/include/xen/sched.h
line diff
     1.1 --- a/xen/common/domain.c	Wed Apr 14 12:10:19 2010 +0100
     1.2 +++ b/xen/common/domain.c	Wed Apr 14 13:35:05 2010 +0100
     1.3 @@ -147,6 +147,8 @@ struct vcpu *alloc_vcpu(
     1.4  
     1.5      spin_lock_init(&v->virq_lock);
     1.6  
     1.7 +    tasklet_init(&v->continue_hypercall_tasklet, NULL, 0);
     1.8 +
     1.9      if ( is_idle_domain(d) )
    1.10      {
    1.11          v->runstate.state = RUNSTATE_running;
    1.12 @@ -587,6 +589,7 @@ static void complete_domain_destroy(stru
    1.13      {
    1.14          if ( (v = d->vcpu[i]) == NULL )
    1.15              continue;
    1.16 +        tasklet_kill(&v->continue_hypercall_tasklet);
    1.17          vcpu_destroy(v);
    1.18          sched_destroy_vcpu(v);
    1.19      }
    1.20 @@ -902,6 +905,7 @@ struct migrate_info {
    1.21      long (*func)(void *data);
    1.22      void *data;
    1.23      struct vcpu *vcpu;
    1.24 +    unsigned int cpu;
    1.25      unsigned int nest;
    1.26  };
    1.27  
    1.28 @@ -912,30 +916,48 @@ static void continue_hypercall_tasklet_h
    1.29      struct migrate_info *info = (struct migrate_info *)_info;
    1.30      struct vcpu *v = info->vcpu;
    1.31  
    1.32 -    vcpu_sleep_sync(v);
    1.33 +    /*
    1.34 +     * Wait for vcpu to be entirely descheduled. We re-schedule ourselves
    1.35 +     * meanwhile to allow other work to be done (e.g., descheduling the vcpu!).
    1.36 +     */
    1.37 +    BUG_ON(vcpu_runnable(v));
    1.38 +    if ( v->is_running )
    1.39 +    {
    1.40 +        tasklet_schedule(&v->continue_hypercall_tasklet);
    1.41 +        return;
    1.42 +    }
    1.43 +
    1.44 +    /* Once descheduled, we need to gain access to its register state. */
    1.45 +    sync_vcpu_execstate(v);
    1.46  
    1.47      this_cpu(continue_info) = info;
    1.48 -    return_reg(v) = info->func(info->data);
    1.49 +    return_reg(v) = (info->cpu == smp_processor_id())
    1.50 +        ? info->func(info->data) : -EINVAL;
    1.51      this_cpu(continue_info) = NULL;
    1.52  
    1.53      if ( info->nest-- == 0 )
    1.54      {
    1.55          xfree(info);
    1.56          vcpu_unpause(v);
    1.57 +        put_domain(v->domain);
    1.58      }
    1.59  }
    1.60  
    1.61  int continue_hypercall_on_cpu(int cpu, long (*func)(void *data), void *data)
    1.62  {
    1.63 -    struct vcpu *curr = current;
    1.64      struct migrate_info *info;
    1.65  
    1.66 +    if ( (cpu >= NR_CPUS) || !cpu_online(cpu) )
    1.67 +        return -EINVAL;
    1.68 +
    1.69      if ( cpu == smp_processor_id() )
    1.70          return func(data);
    1.71  
    1.72      info = this_cpu(continue_info);
    1.73      if ( info == NULL )
    1.74      {
    1.75 +        struct vcpu *curr = current;
    1.76 +
    1.77          info = xmalloc(struct migrate_info);
    1.78          if ( info == NULL )
    1.79              return -ENOMEM;
    1.80 @@ -943,11 +965,14 @@ int continue_hypercall_on_cpu(int cpu, l
    1.81          info->vcpu = curr;
    1.82          info->nest = 0;
    1.83  
    1.84 +        tasklet_kill(
    1.85 +            &curr->continue_hypercall_tasklet);
    1.86          tasklet_init(
    1.87              &curr->continue_hypercall_tasklet,
    1.88              continue_hypercall_tasklet_handler,
    1.89              (unsigned long)info);
    1.90  
    1.91 +        get_knownalive_domain(curr->domain);
    1.92          vcpu_pause_nosync(curr);
    1.93      }
    1.94      else
    1.95 @@ -958,8 +983,9 @@ int continue_hypercall_on_cpu(int cpu, l
    1.96  
    1.97      info->func = func;
    1.98      info->data = data;
    1.99 +    info->cpu  = cpu;
   1.100  
   1.101 -    tasklet_schedule_on_cpu(&curr->continue_hypercall_tasklet, cpu);
   1.102 +    tasklet_schedule_on_cpu(&info->vcpu->continue_hypercall_tasklet, cpu);
   1.103  
   1.104      /* Dummy return value will be overwritten by tasklet. */
   1.105      return 0;
     2.1 --- a/xen/include/xen/sched.h	Wed Apr 14 12:10:19 2010 +0100
     2.2 +++ b/xen/include/xen/sched.h	Wed Apr 14 13:35:05 2010 +0100
     2.3 @@ -375,14 +375,6 @@ static inline void get_knownalive_domain
     2.4      ASSERT(!(atomic_read(&d->refcnt) & DOMAIN_DESTROYED));
     2.5  }
     2.6  
     2.7 -/* Obtain a reference to the currently-running domain. */
     2.8 -static inline struct domain *get_current_domain(void)
     2.9 -{
    2.10 -    struct domain *d = current->domain;
    2.11 -    get_knownalive_domain(d);
    2.12 -    return d;
    2.13 -}
    2.14 -
    2.15  struct domain *domain_create(
    2.16      domid_t domid, unsigned int domcr_flags, ssidref_t ssidref);
    2.17   /* DOMCRF_hvm: Create an HVM domain, as opposed to a PV domain. */