ia64/xen-unstable

changeset 18512:366c78ff361b

x86: Allow continue_hypercall_on_cpu() to be called from within an
existing continuation handler. This fix is needed for the new method
of microcode re-programming.

Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Sep 17 14:13:10 2008 +0100 (2008-09-17)
parents beb28a3975bd
children 694b7daa353c
files xen/arch/x86/domain.c xen/common/schedule.c xen/include/xen/sched.h
line diff
     1.1 --- a/xen/arch/x86/domain.c	Wed Sep 17 13:11:40 2008 +0100
     1.2 +++ b/xen/arch/x86/domain.c	Wed Sep 17 14:13:10 2008 +0100
     1.3 @@ -1356,6 +1356,7 @@ struct migrate_info {
     1.4      void *data;
     1.5      void (*saved_schedule_tail)(struct vcpu *);
     1.6      cpumask_t saved_affinity;
     1.7 +    unsigned int nest;
     1.8  };
     1.9  
    1.10  static void continue_hypercall_on_cpu_helper(struct vcpu *v)
    1.11 @@ -1363,47 +1364,63 @@ static void continue_hypercall_on_cpu_he
    1.12      struct cpu_user_regs *regs = guest_cpu_user_regs();
    1.13      struct migrate_info *info = v->arch.continue_info;
    1.14      cpumask_t mask = info->saved_affinity;
    1.15 +    void (*saved_schedule_tail)(struct vcpu *) = info->saved_schedule_tail;
    1.16  
    1.17      regs->eax = info->func(info->data);
    1.18  
    1.19 -    v->arch.schedule_tail = info->saved_schedule_tail;
    1.20 -    v->arch.continue_info = NULL;
    1.21 +    if ( info->nest-- == 0 )
    1.22 +    {
    1.23 +        xfree(info);
    1.24 +        v->arch.schedule_tail = saved_schedule_tail;
    1.25 +        v->arch.continue_info = NULL;
    1.26 +        vcpu_unlock_affinity(v, &mask);
    1.27 +    }
    1.28  
    1.29 -    xfree(info);
    1.30 -
    1.31 -    vcpu_unlock_affinity(v, &mask);
    1.32 -    schedule_tail(v);
    1.33 +    (*saved_schedule_tail)(v);
    1.34  }
    1.35  
    1.36  int continue_hypercall_on_cpu(int cpu, long (*func)(void *data), void *data)
    1.37  {
    1.38      struct vcpu *v = current;
    1.39      struct migrate_info *info;
    1.40 +    cpumask_t mask = cpumask_of_cpu(cpu);
    1.41      int rc;
    1.42  
    1.43      if ( cpu == smp_processor_id() )
    1.44          return func(data);
    1.45  
    1.46 -    info = xmalloc(struct migrate_info);
    1.47 +    info = v->arch.continue_info;
    1.48      if ( info == NULL )
    1.49 -        return -ENOMEM;
    1.50 +    {
    1.51 +        info = xmalloc(struct migrate_info);
    1.52 +        if ( info == NULL )
    1.53 +            return -ENOMEM;
    1.54 +
    1.55 +        rc = vcpu_lock_affinity(v, &mask);
    1.56 +        if ( rc )
    1.57 +        {
    1.58 +            xfree(info);
    1.59 +            return rc;
    1.60 +        }
    1.61 +
    1.62 +        info->saved_schedule_tail = v->arch.schedule_tail;
    1.63 +        info->saved_affinity = mask;
    1.64 +        info->nest = 0;
    1.65 +
    1.66 +        v->arch.schedule_tail = continue_hypercall_on_cpu_helper;
    1.67 +        v->arch.continue_info = info;
    1.68 +    }
    1.69 +    else
    1.70 +    {
    1.71 +        BUG_ON(info->nest != 0);
    1.72 +        rc = vcpu_locked_change_affinity(v, &mask);
    1.73 +        if ( rc )
    1.74 +            return rc;
    1.75 +        info->nest++;
    1.76 +    }
    1.77  
    1.78      info->func = func;
    1.79      info->data = data;
    1.80 -    info->saved_schedule_tail = v->arch.schedule_tail;
    1.81 -    info->saved_affinity = cpumask_of_cpu(cpu);
    1.82 -
    1.83 -    v->arch.schedule_tail = continue_hypercall_on_cpu_helper;
    1.84 -    v->arch.continue_info = info;
    1.85 -
    1.86 -    rc = vcpu_lock_affinity(v, &info->saved_affinity);
    1.87 -    if ( rc )
    1.88 -    {
    1.89 -        v->arch.schedule_tail = info->saved_schedule_tail;
    1.90 -        v->arch.continue_info = NULL;
    1.91 -        xfree(info);
    1.92 -        return rc;
    1.93 -    }
    1.94  
    1.95      /* Dummy return value will be overwritten by new schedule_tail. */
    1.96      BUG_ON(!test_bit(SCHEDULE_SOFTIRQ, &softirq_pending(smp_processor_id())));
     2.1 --- a/xen/common/schedule.c	Wed Sep 17 13:11:40 2008 +0100
     2.2 +++ b/xen/common/schedule.c	Wed Sep 17 14:13:10 2008 +0100
     2.3 @@ -380,6 +380,11 @@ int vcpu_lock_affinity(struct vcpu *v, c
     2.4      return __vcpu_set_affinity(v, affinity, 0, 1);
     2.5  }
     2.6  
     2.7 +int vcpu_locked_change_affinity(struct vcpu *v, cpumask_t *affinity)
     2.8 +{
     2.9 +    return __vcpu_set_affinity(v, affinity, 1, 1);
    2.10 +}
    2.11 +
    2.12  void vcpu_unlock_affinity(struct vcpu *v, cpumask_t *affinity)
    2.13  {
    2.14      cpumask_t online_affinity;
     3.1 --- a/xen/include/xen/sched.h	Wed Sep 17 13:11:40 2008 +0100
     3.2 +++ b/xen/include/xen/sched.h	Wed Sep 17 14:13:10 2008 +0100
     3.3 @@ -527,6 +527,7 @@ void vcpu_force_reschedule(struct vcpu *
     3.4  void cpu_disable_scheduler(void);
     3.5  int vcpu_set_affinity(struct vcpu *v, cpumask_t *affinity);
     3.6  int vcpu_lock_affinity(struct vcpu *v, cpumask_t *affinity);
     3.7 +int vcpu_locked_change_affinity(struct vcpu *v, cpumask_t *affinity);
     3.8  void vcpu_unlock_affinity(struct vcpu *v, cpumask_t *affinity);
     3.9  
    3.10  void vcpu_runstate_get(struct vcpu *v, struct vcpu_runstate_info *runstate);