ia64/xen-unstable

changeset 15948:2477e94450aa

cpufreq: Support cpufreq updates on AMD hardware by dom0 kernel.
Signed-off-by: Mark Langsdorf <mark.langsdorf@amd.com>
Signed-off-by: Keir Fraser <keir@xensource.com>
author Keir Fraser <keir@xensource.com>
date Thu Sep 20 14:15:45 2007 +0100 (2007-09-20)
parents 00040cd1b34f
children 7bd5b1f55308
files xen/arch/x86/domain.c xen/arch/x86/platform_hypercall.c xen/arch/x86/time.c xen/arch/x86/traps.c xen/common/schedule.c xen/include/asm-x86/msr.h xen/include/asm-x86/time.h xen/include/public/platform.h xen/include/xen/sched.h xen/include/xen/time.h
line diff
     1.1 --- a/xen/arch/x86/domain.c	Thu Sep 20 13:30:14 2007 +0100
     1.2 +++ b/xen/arch/x86/domain.c	Thu Sep 20 14:15:45 2007 +0100
     1.3 @@ -1378,10 +1378,9 @@ static void continue_hypercall_on_cpu_he
     1.4      regs->eax = info->func(info->data);
     1.5  
     1.6      v->arch.schedule_tail = info->saved_schedule_tail;
     1.7 -    v->cpu_affinity = info->saved_affinity;
     1.8 +    v->arch.continue_info = NULL;
     1.9  
    1.10      xfree(info);
    1.11 -    v->arch.continue_info = NULL;
    1.12  
    1.13      vcpu_set_affinity(v, &v->cpu_affinity);
    1.14      schedule_tail(v);
    1.15 @@ -1392,6 +1391,7 @@ int continue_hypercall_on_cpu(int cpu, l
    1.16      struct vcpu *v = current;
    1.17      struct migrate_info *info;
    1.18      cpumask_t mask = cpumask_of_cpu(cpu);
    1.19 +    int rc;
    1.20  
    1.21      if ( cpu == smp_processor_id() )
    1.22          return func(data);
    1.23 @@ -1403,12 +1403,19 @@ int continue_hypercall_on_cpu(int cpu, l
    1.24      info->func = func;
    1.25      info->data = data;
    1.26      info->saved_schedule_tail = v->arch.schedule_tail;
    1.27 +    info->saved_affinity = v->cpu_affinity;
    1.28 +
    1.29      v->arch.schedule_tail = continue_hypercall_on_cpu_helper;
    1.30 -
    1.31 -    info->saved_affinity = v->cpu_affinity;
    1.32      v->arch.continue_info = info;
    1.33  
    1.34 -    vcpu_set_affinity(v, &mask);
    1.35 +    rc = vcpu_set_affinity(v, &mask);
    1.36 +    if ( rc )
    1.37 +    {
    1.38 +        v->arch.schedule_tail = info->saved_schedule_tail;
    1.39 +        v->arch.continue_info = NULL;
    1.40 +        xfree(info);
    1.41 +        return rc;
    1.42 +    }
    1.43  
    1.44      /* Dummy return value will be overwritten by new schedule_tail. */
    1.45      BUG_ON(!test_bit(SCHEDULE_SOFTIRQ, &softirq_pending(smp_processor_id())));
     2.1 --- a/xen/arch/x86/platform_hypercall.c	Thu Sep 20 13:30:14 2007 +0100
     2.2 +++ b/xen/arch/x86/platform_hypercall.c	Thu Sep 20 14:15:45 2007 +0100
     2.3 @@ -40,6 +40,11 @@ DEFINE_SPINLOCK(xenpf_lock);
     2.4  extern spinlock_t xenpf_lock;
     2.5  #endif
     2.6  
     2.7 +static long cpu_frequency_change_helper(void *data)
     2.8 +{
     2.9 +    return cpu_frequency_change(*(uint64_t *)data);
    2.10 +}
    2.11 +
    2.12  ret_t do_platform_op(XEN_GUEST_HANDLE(xen_platform_op_t) u_xenpf_op)
    2.13  {
    2.14      ret_t ret = 0;
    2.15 @@ -280,6 +285,15 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xe
    2.16          ret = acpi_enter_sleep(&op->u.enter_acpi_sleep);
    2.17          break;
    2.18  
    2.19 +    case XENPF_change_freq:
    2.20 +        ret = -EINVAL;
    2.21 +        if ( op->u.change_freq.flags != 0 )
    2.22 +            break;
    2.23 +        ret = continue_hypercall_on_cpu(op->u.change_freq.cpu,
    2.24 +                                        cpu_frequency_change_helper,
    2.25 +                                        &op->u.change_freq.freq);
    2.26 +        break;
    2.27 +
    2.28      default:
    2.29          ret = -ENOSYS;
    2.30          break;
     3.1 --- a/xen/arch/x86/time.c	Thu Sep 20 13:30:14 2007 +0100
     3.2 +++ b/xen/arch/x86/time.c	Thu Sep 20 14:15:45 2007 +0100
     3.3 @@ -722,6 +722,27 @@ void update_domain_wallclock_time(struct
     3.4      spin_unlock(&wc_lock);
     3.5  }
     3.6  
     3.7 +int cpu_frequency_change(u64 freq)
     3.8 +{
     3.9 +    struct cpu_time *t = &this_cpu(cpu_time);
    3.10 +    u64 curr_tsc;
    3.11 +
    3.12 +    local_irq_disable();
    3.13 +    set_time_scale(&t->tsc_scale, freq);
    3.14 +    rdtscll(curr_tsc);
    3.15 +    t->local_tsc_stamp = curr_tsc;
    3.16 +    t->stime_local_stamp = get_s_time();
    3.17 +    t->stime_master_stamp = read_platform_stime();
    3.18 +    local_irq_enable();
    3.19 +
    3.20 +    /* A full epoch should pass before we check for deviation. */
    3.21 +    set_timer(&t->calibration_timer, NOW() + EPOCH);
    3.22 +    if ( smp_processor_id() == 0 )
    3.23 +        platform_time_calibration();
    3.24 +
    3.25 +    return 0;
    3.26 +}
    3.27 +
    3.28  /* Set clock to <secs,usecs> after 00:00:00 UTC, 1 January, 1970. */
    3.29  void do_settime(unsigned long secs, unsigned long nsecs, u64 system_time_base)
    3.30  {
    3.31 @@ -866,12 +887,14 @@ static void local_time_calibration(void 
    3.32             error_factor, calibration_mul_frac, tsc_shift);
    3.33  #endif
    3.34  
    3.35 -    /* Record new timestamp information. */
    3.36 +    /* Record new timestamp information, atomically w.r.t. interrupts. */
    3.37 +    local_irq_disable();
    3.38      t->tsc_scale.mul_frac = calibration_mul_frac;
    3.39      t->tsc_scale.shift    = tsc_shift;
    3.40      t->local_tsc_stamp    = curr_tsc;
    3.41      t->stime_local_stamp  = curr_local_stime;
    3.42      t->stime_master_stamp = curr_master_stime;
    3.43 +    local_irq_enable();
    3.44  
    3.45      update_vcpu_system_time(current);
    3.46  
     4.1 --- a/xen/arch/x86/traps.c	Thu Sep 20 13:30:14 2007 +0100
     4.2 +++ b/xen/arch/x86/traps.c	Thu Sep 20 14:15:45 2007 +0100
     4.3 @@ -1728,10 +1728,16 @@ static int emulate_privileged_op(struct 
     4.4              v->arch.guest_context.gs_base_user = res;
     4.5              break;
     4.6  #endif
     4.7 +        case MSR_K8_FIDVID_STATUS:
     4.8 +        case MSR_K8_FIDVID_CTL:
     4.9 +            if ( (cpufreq_controller != FREQCTL_dom0_kernel) ||
    4.10 +                 (boot_cpu_data.x86_vendor != X86_VENDOR_AMD) ||
    4.11 +                 wrmsr_safe(regs->ecx, eax, edx) )
    4.12 +                goto fail;
    4.13 +            break;
    4.14          default:
    4.15              if ( wrmsr_hypervisor_regs(regs->ecx, eax, edx) )
    4.16                  break;
    4.17 -
    4.18              if ( (rdmsr_safe(regs->ecx, l, h) != 0) ||
    4.19                   (eax != l) || (edx != h) )
    4.20                  gdprintk(XENLOG_WARNING, "Domain attempted WRMSR %p from "
    4.21 @@ -1764,6 +1770,13 @@ static int emulate_privileged_op(struct 
    4.22              regs->edx = v->arch.guest_context.gs_base_user >> 32;
    4.23              break;
    4.24  #endif
    4.25 +        case MSR_K8_FIDVID_CTL:
    4.26 +        case MSR_K8_FIDVID_STATUS:
    4.27 +            if ( (cpufreq_controller != FREQCTL_dom0_kernel) ||
    4.28 +                 (boot_cpu_data.x86_vendor != X86_VENDOR_AMD) ||
    4.29 +                 rdmsr_safe(regs->ecx, regs->eax, regs->edx) )
    4.30 +                goto fail;
    4.31 +            break;
    4.32          case MSR_EFER:
    4.33              if ( rdmsr_safe(regs->ecx, regs->eax, regs->edx) )
    4.34                  goto fail;
     5.1 --- a/xen/common/schedule.c	Thu Sep 20 13:30:14 2007 +0100
     5.2 +++ b/xen/common/schedule.c	Thu Sep 20 14:15:45 2007 +0100
     5.3 @@ -42,6 +42,17 @@ string_param("sched", opt_sched);
     5.4  static unsigned int opt_dom0_vcpus_pin;
     5.5  boolean_param("dom0_vcpus_pin", opt_dom0_vcpus_pin);
     5.6  
     5.7 +enum cpufreq_controller cpufreq_controller;
     5.8 +static void __init setup_cpufreq_option(char *str)
     5.9 +{
    5.10 +    if ( !strcmp(str, "dom0-kernel") )
    5.11 +    {
    5.12 +        cpufreq_controller = FREQCTL_dom0_kernel;
    5.13 +        opt_dom0_vcpus_pin = 1;
    5.14 +    }
    5.15 +}
    5.16 +custom_param("cpufreq", setup_cpufreq_option);
    5.17 +
    5.18  #define TIME_SLOP      (s32)MICROSECS(50)     /* allow time to slip a bit */
    5.19  
    5.20  /* Various timer handlers. */
     6.1 --- a/xen/include/asm-x86/msr.h	Thu Sep 20 13:30:14 2007 +0100
     6.2 +++ b/xen/include/asm-x86/msr.h	Thu Sep 20 14:15:45 2007 +0100
     6.3 @@ -360,6 +360,9 @@ static inline void write_efer(__u64 val)
     6.4  #define MSR_K8_VM_CR			0xC0010114
     6.5  #define MSR_K8_VM_HSAVE_PA		0xC0010117
     6.6  
     6.7 +#define MSR_K8_FIDVID_CTL		0xC0010041
     6.8 +#define MSR_K8_FIDVID_STATUS		0xC0010042
     6.9 +
    6.10  /* MSR_K8_VM_CR bits: */
    6.11  #define _K8_VMCR_SVME_DISABLE		4
    6.12  #define K8_VMCR_SVME_DISABLE		(1 << _K8_VMCR_SVME_DISABLE)
     7.1 --- a/xen/include/asm-x86/time.h	Thu Sep 20 13:30:14 2007 +0100
     7.2 +++ b/xen/include/asm-x86/time.h	Thu Sep 20 14:15:45 2007 +0100
     7.3 @@ -29,4 +29,6 @@ void init_percpu_time(void);
     7.4  struct ioreq;
     7.5  int dom0_pit_access(struct ioreq *ioreq);
     7.6  
     7.7 +int cpu_frequency_change(u64 freq);
     7.8 +
     7.9  #endif /* __X86_TIME_H__ */
     8.1 --- a/xen/include/public/platform.h	Thu Sep 20 13:30:14 2007 +0100
     8.2 +++ b/xen/include/public/platform.h	Thu Sep 20 14:15:45 2007 +0100
     8.3 @@ -164,6 +164,16 @@ struct xenpf_enter_acpi_sleep {
     8.4  typedef struct xenpf_enter_acpi_sleep xenpf_enter_acpi_sleep_t;
     8.5  DEFINE_XEN_GUEST_HANDLE(xenpf_enter_acpi_sleep_t);
     8.6  
     8.7 +#define XENPF_change_freq       52
     8.8 +struct xenpf_change_freq {
     8.9 +    /* IN variables */
    8.10 +    uint32_t flags; /* Must be zero. */
    8.11 +    uint32_t cpu;   /* Physical cpu. */
    8.12 +    uint64_t freq;  /* New frequency (Hz). */
    8.13 +};
    8.14 +typedef struct xenpf_change_freq xenpf_change_freq_t;
    8.15 +DEFINE_XEN_GUEST_HANDLE(xenpf_change_freq_t);
    8.16 +
    8.17  struct xen_platform_op {
    8.18      uint32_t cmd;
    8.19      uint32_t interface_version; /* XENPF_INTERFACE_VERSION */
    8.20 @@ -176,6 +186,7 @@ struct xen_platform_op {
    8.21          struct xenpf_platform_quirk    platform_quirk;
    8.22          struct xenpf_firmware_info     firmware_info;
    8.23          struct xenpf_enter_acpi_sleep  enter_acpi_sleep;
    8.24 +        struct xenpf_change_freq       change_freq;
    8.25          uint8_t                        pad[128];
    8.26      } u;
    8.27  };
     9.1 --- a/xen/include/xen/sched.h	Thu Sep 20 13:30:14 2007 +0100
     9.2 +++ b/xen/include/xen/sched.h	Thu Sep 20 14:15:45 2007 +0100
     9.3 @@ -499,6 +499,10 @@ static inline void vcpu_unblock(struct v
     9.4  #define is_hvm_domain(d) ((d)->is_hvm)
     9.5  #define is_hvm_vcpu(v)   (is_hvm_domain(v->domain))
     9.6  
     9.7 +extern enum cpufreq_controller {
     9.8 +    FREQCTL_none, FREQCTL_dom0_kernel
     9.9 +} cpufreq_controller;
    9.10 +
    9.11  #endif /* __SCHED_H__ */
    9.12  
    9.13  /*
    10.1 --- a/xen/include/xen/time.h	Thu Sep 20 13:30:14 2007 +0100
    10.2 +++ b/xen/include/xen/time.h	Thu Sep 20 14:15:45 2007 +0100
    10.3 @@ -1,28 +1,10 @@
    10.4 -/****************************************************************************
    10.5 - * (C) 2002 - Rolf Neugebauer - Intel Research Cambridge
    10.6 - ****************************************************************************
    10.7 - *
    10.8 - *        File: time.h
    10.9 - *      Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk)
   10.10 - *     Changes: 
   10.11 - *              
   10.12 - *        Date: Nov 2002
   10.13 +/******************************************************************************
   10.14 + * time.h
   10.15   * 
   10.16 - * Environment: Xen Hypervisor
   10.17 - * Description: This file provides a one stop shop for all time related
   10.18 - *              issues within the hypervisor. 
   10.19 - * 
   10.20 - *              The Hypervisor provides the following notions of time:
   10.21 - *              Cycle Counter Time, System Time, Wall Clock Time, and 
   10.22 - *              Domain Virtual Time.
   10.23 - *
   10.24 - ****************************************************************************
   10.25 - * $Id: h-insert.h,v 1.4 2002/11/08 16:03:55 rn Exp $
   10.26 - ****************************************************************************
   10.27 + * Copyright (c) 2002-2003 Rolf Neugebauer
   10.28 + * Copyright (c) 2002-2005 K A Fraser
   10.29   */
   10.30  
   10.31 -
   10.32 -
   10.33  #ifndef __XEN_TIME_H__
   10.34  #define __XEN_TIME_H__
   10.35