ia64/xen-unstable

changeset 15623:858b9bc8d0e6

SMP support for Xen PM.

Add SMP sleep support to Xen. One new utility is created
to allow vcpu continue previous running after migration
to new processor.

Signed-off-by: Kevin Tian <kevin.tian@intel.com>
Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Thu Jul 19 13:23:33 2007 +0100 (2007-07-19)
parents 0d291a7c8c1f
children c41dd7e841b1
files xen/arch/x86/acpi/power.c xen/arch/x86/cpu/intel_cacheinfo.c xen/arch/x86/domain.c xen/include/asm-x86/domain.h xen/include/asm-x86/smp.h
line diff
     1.1 --- a/xen/arch/x86/acpi/power.c	Thu Jul 19 12:53:32 2007 +0100
     1.2 +++ b/xen/arch/x86/acpi/power.c	Thu Jul 19 13:23:33 2007 +0100
     1.3 @@ -119,20 +119,26 @@ static int enter_state(u32 state)
     1.4      if (state <= ACPI_STATE_S0 || state > ACPI_S_STATES_MAX)
     1.5          return -EINVAL;
     1.6  
     1.7 -    /* Sync lazy state on ths cpu */
     1.8      __sync_lazy_execstate();
     1.9      pmprintk(XENLOG_INFO, "Flush lazy state\n");
    1.10  
    1.11      if (!spin_trylock(&pm_lock))
    1.12          return -EBUSY;
    1.13      
    1.14 +    pmprintk(XENLOG_INFO, "PM: Preparing system for %s sleep\n",
    1.15 +        acpi_states[state]);
    1.16 +
    1.17      freeze_domains();
    1.18  
    1.19 +    disable_nonboot_cpus();
    1.20 +    if (num_online_cpus() != 1)
    1.21 +    {
    1.22 +        error = -EBUSY;
    1.23 +        goto Enable_cpu;
    1.24 +    }
    1.25 +
    1.26      hvm_cpu_down();
    1.27  
    1.28 -    pmprintk(XENLOG_INFO, "PM: Preparing system for %s sleep\n",
    1.29 -        acpi_states[state]);
    1.30 -
    1.31      acpi_sleep_prepare(state);
    1.32  
    1.33      local_irq_save(flags);
    1.34 @@ -169,16 +175,31 @@ static int enter_state(u32 state)
    1.35      if ( !hvm_cpu_up() )
    1.36          BUG();
    1.37  
    1.38 + Enable_cpu:
    1.39 +    enable_nonboot_cpus();
    1.40 +
    1.41      thaw_domains();
    1.42      spin_unlock(&pm_lock);
    1.43      return error;
    1.44  }
    1.45  
    1.46 +static void acpi_power_off(void)
    1.47 +{
    1.48 +    pmprintk(XENLOG_INFO, "%s called\n", __FUNCTION__);
    1.49 +    local_irq_disable();
    1.50 +    /* Some SMP machines only can poweroff in boot CPU */
    1.51 +    acpi_enter_sleep_state(ACPI_STATE_S5);
    1.52 +}
    1.53 +
    1.54 +static long enter_state_helper(void *data)
    1.55 +{
    1.56 +    struct acpi_sleep_info *sinfo = (struct acpi_sleep_info *)data;
    1.57 +    return enter_state(sinfo->sleep_state);
    1.58 +}
    1.59 +
    1.60  /*
    1.61   * Dom0 issues this hypercall in place of writing pm1a_cnt. Xen then
    1.62   * takes over the control and put the system into sleep state really.
    1.63 - * Also video flags and mode are passed here, in case user may use
    1.64 - * "acpi_sleep=***" for video resume.
    1.65   *
    1.66   * Guest may issue a two-phases write to PM1x_CNT, to work
    1.67   * around poorly implemented hardware. It's better to keep
    1.68 @@ -216,7 +237,14 @@ int acpi_enter_sleep(struct xenpf_enter_
    1.69      acpi_sinfo.pm1b_cnt_val = sleep->pm1b_cnt_val;
    1.70      acpi_sinfo.sleep_state = sleep->sleep_state;
    1.71  
    1.72 -    return enter_state(acpi_sinfo.sleep_state);
    1.73 +    /* ACPI power-off method. */
    1.74 +    if ( acpi_sinfo.sleep_state == ACPI_STATE_S5 )
    1.75 +    {
    1.76 +        for ( ; ; )
    1.77 +            acpi_power_off();
    1.78 +    }
    1.79 +
    1.80 +    return continue_hypercall_on_cpu(0, enter_state_helper, &acpi_sinfo);
    1.81  }
    1.82  
    1.83  static int acpi_get_wake_status(void)
     2.1 --- a/xen/arch/x86/cpu/intel_cacheinfo.c	Thu Jul 19 12:53:32 2007 +0100
     2.2 +++ b/xen/arch/x86/cpu/intel_cacheinfo.c	Thu Jul 19 13:23:33 2007 +0100
     2.3 @@ -17,7 +17,7 @@ struct _cache_table
     2.4  };
     2.5  
     2.6  /* all the cache descriptor types we care about (no TLB or trace cache entries) */
     2.7 -static struct _cache_table cache_table[] __initdata =
     2.8 +static struct _cache_table cache_table[] __devinitdata =
     2.9  {
    2.10  	{ 0x06, LVL_1_INST, 8 },	/* 4-way set assoc, 32 byte line size */
    2.11  	{ 0x08, LVL_1_INST, 16 },	/* 4-way set assoc, 32 byte line size */
    2.12 @@ -60,7 +60,7 @@ static struct _cache_table cache_table[]
    2.13  	{ 0x00, 0, 0}
    2.14  };
    2.15  
    2.16 -unsigned int __init init_intel_cacheinfo(struct cpuinfo_x86 *c)
    2.17 +unsigned int __devinit init_intel_cacheinfo(struct cpuinfo_x86 *c)
    2.18  {
    2.19  	unsigned int trace = 0, l1i = 0, l1d = 0, l2 = 0, l3 = 0; /* Cache sizes */
    2.20  
     3.1 --- a/xen/arch/x86/domain.c	Thu Jul 19 12:53:32 2007 +0100
     3.2 +++ b/xen/arch/x86/domain.c	Thu Jul 19 13:23:33 2007 +0100
     3.3 @@ -82,6 +82,7 @@ static void play_dead(void)
     3.4      __cpu_disable();
     3.5      /* This must be done before dead CPU ack */
     3.6      cpu_exit_clear();
     3.7 +    hvm_cpu_down();
     3.8      wbinvd();
     3.9      mb();
    3.10      /* Ack it */
    3.11 @@ -1363,6 +1364,54 @@ void sync_vcpu_execstate(struct vcpu *v)
    3.12      flush_tlb_mask(v->vcpu_dirty_cpumask);
    3.13  }
    3.14  
    3.15 +struct migrate_info {
    3.16 +    long (*func)(void *data);
    3.17 +    void *data;
    3.18 +    void (*saved_schedule_tail)(struct vcpu *);
    3.19 +    cpumask_t saved_affinity;
    3.20 +};
    3.21 +
    3.22 +static void continue_hypercall_on_cpu_helper(struct vcpu *v)
    3.23 +{
    3.24 +    struct cpu_user_regs *regs = guest_cpu_user_regs();
    3.25 +    struct migrate_info *info = v->arch.continue_info;
    3.26 +
    3.27 +    regs->eax = info->func(info->data);
    3.28 +
    3.29 +    v->arch.schedule_tail = info->saved_schedule_tail;
    3.30 +    v->cpu_affinity = info->saved_affinity;
    3.31 +
    3.32 +    xfree(info);
    3.33 +    v->arch.continue_info = NULL;
    3.34 +
    3.35 +    vcpu_set_affinity(v, &v->cpu_affinity);
    3.36 +    schedule_tail(v);
    3.37 +}
    3.38 +
    3.39 +int continue_hypercall_on_cpu(int cpu, long (*func)(void *data), void *data)
    3.40 +{
    3.41 +    struct vcpu *v = current;
    3.42 +    struct migrate_info *info;
    3.43 +    cpumask_t mask = cpumask_of_cpu(cpu);
    3.44 +
    3.45 +    info = xmalloc(struct migrate_info);
    3.46 +    if ( info == NULL )
    3.47 +        return -ENOMEM;
    3.48 +
    3.49 +    info->func = func;
    3.50 +    info->data = data;
    3.51 +    info->saved_schedule_tail = v->arch.schedule_tail;
    3.52 +    v->arch.schedule_tail = continue_hypercall_on_cpu_helper;
    3.53 +
    3.54 +    info->saved_affinity = v->cpu_affinity;
    3.55 +    v->arch.continue_info = info;
    3.56 +
    3.57 +    vcpu_set_affinity(v, &mask);
    3.58 +    schedule_tail(v);
    3.59 +
    3.60 +    return 0;
    3.61 +}
    3.62 +
    3.63  #define next_arg(fmt, args) ({                                              \
    3.64      unsigned long __arg;                                                    \
    3.65      switch ( *(fmt)++ )                                                     \
     4.1 --- a/xen/include/asm-x86/domain.h	Thu Jul 19 12:53:32 2007 +0100
     4.2 +++ b/xen/include/asm-x86/domain.h	Thu Jul 19 13:23:33 2007 +0100
     4.3 @@ -268,6 +268,9 @@ struct arch_vcpu
     4.4      void (*ctxt_switch_from) (struct vcpu *);
     4.5      void (*ctxt_switch_to) (struct vcpu *);
     4.6  
     4.7 +    /* Record information required to continue execution after migration */
     4.8 +    void *continue_info;
     4.9 +
    4.10      /* Bounce information for propagating an exception to guest OS. */
    4.11      struct trap_bounce trap_bounce;
    4.12  
    4.13 @@ -311,10 +314,13 @@ struct arch_vcpu
    4.14      unsigned long vcpu_info_mfn;
    4.15  } __cacheline_aligned;
    4.16  
    4.17 -/* shorthands to improve code legibility */
    4.18 +/* Shorthands to improve code legibility. */
    4.19  #define hvm_vmx         hvm_vcpu.u.vmx
    4.20  #define hvm_svm         hvm_vcpu.u.svm
    4.21  
    4.22 +/* Continue the current hypercall via func(data) on specified cpu. */
    4.23 +int continue_hypercall_on_cpu(int cpu, long (*func)(void *data), void *data);
    4.24 +
    4.25  #endif /* __ASM_DOMAIN_H__ */
    4.26  
    4.27  /*
     5.1 --- a/xen/include/asm-x86/smp.h	Thu Jul 19 12:53:32 2007 +0100
     5.2 +++ b/xen/include/asm-x86/smp.h	Thu Jul 19 13:23:33 2007 +0100
     5.3 @@ -66,6 +66,8 @@ extern void disable_nonboot_cpus(void);
     5.4  extern void enable_nonboot_cpus(void);
     5.5  #else
     5.6  static inline int cpu_is_offline(int cpu) {return 0;}
     5.7 +static inline void disable_nonboot_cpus(void) {}
     5.8 +static inline void enable_nonboot_cpus(void) {}
     5.9  #endif
    5.10  
    5.11  /*