[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] cpufreq: Support cpufreq updates on AMD hardware by dom0 kernel.



# HG changeset patch
# User Keir Fraser <keir@xxxxxxxxxxxxx>
# Date 1190294145 -3600
# Node ID 2477e94450aa11bdaa55d80dee05f6d0bc67f957
# Parent  00040cd1b34fc8db00b665e11c07dade80af0507
cpufreq: Support cpufreq updates on AMD hardware by dom0 kernel.
Signed-off-by: Mark Langsdorf <mark.langsdorf@xxxxxxx>
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
 xen/arch/x86/domain.c             |   17 ++++++++++++-----
 xen/arch/x86/platform_hypercall.c |   14 ++++++++++++++
 xen/arch/x86/time.c               |   25 ++++++++++++++++++++++++-
 xen/arch/x86/traps.c              |   15 ++++++++++++++-
 xen/common/schedule.c             |   11 +++++++++++
 xen/include/asm-x86/msr.h         |    3 +++
 xen/include/asm-x86/time.h        |    2 ++
 xen/include/public/platform.h     |   11 +++++++++++
 xen/include/xen/sched.h           |    4 ++++
 xen/include/xen/time.h            |   26 ++++----------------------
 10 files changed, 99 insertions(+), 29 deletions(-)

diff -r 00040cd1b34f -r 2477e94450aa xen/arch/x86/domain.c
--- a/xen/arch/x86/domain.c     Thu Sep 20 13:30:14 2007 +0100
+++ b/xen/arch/x86/domain.c     Thu Sep 20 14:15:45 2007 +0100
@@ -1378,10 +1378,9 @@ static void continue_hypercall_on_cpu_he
     regs->eax = info->func(info->data);
 
     v->arch.schedule_tail = info->saved_schedule_tail;
-    v->cpu_affinity = info->saved_affinity;
+    v->arch.continue_info = NULL;
 
     xfree(info);
-    v->arch.continue_info = NULL;
 
     vcpu_set_affinity(v, &v->cpu_affinity);
     schedule_tail(v);
@@ -1392,6 +1391,7 @@ int continue_hypercall_on_cpu(int cpu, l
     struct vcpu *v = current;
     struct migrate_info *info;
     cpumask_t mask = cpumask_of_cpu(cpu);
+    int rc;
 
     if ( cpu == smp_processor_id() )
         return func(data);
@@ -1403,12 +1403,19 @@ int continue_hypercall_on_cpu(int cpu, l
     info->func = func;
     info->data = data;
     info->saved_schedule_tail = v->arch.schedule_tail;
+    info->saved_affinity = v->cpu_affinity;
+
     v->arch.schedule_tail = continue_hypercall_on_cpu_helper;
-
-    info->saved_affinity = v->cpu_affinity;
     v->arch.continue_info = info;
 
-    vcpu_set_affinity(v, &mask);
+    rc = vcpu_set_affinity(v, &mask);
+    if ( rc )
+    {
+        v->arch.schedule_tail = info->saved_schedule_tail;
+        v->arch.continue_info = NULL;
+        xfree(info);
+        return rc;
+    }
 
     /* Dummy return value will be overwritten by new schedule_tail. */
     BUG_ON(!test_bit(SCHEDULE_SOFTIRQ, &softirq_pending(smp_processor_id())));
diff -r 00040cd1b34f -r 2477e94450aa xen/arch/x86/platform_hypercall.c
--- a/xen/arch/x86/platform_hypercall.c Thu Sep 20 13:30:14 2007 +0100
+++ b/xen/arch/x86/platform_hypercall.c Thu Sep 20 14:15:45 2007 +0100
@@ -40,6 +40,11 @@ extern spinlock_t xenpf_lock;
 extern spinlock_t xenpf_lock;
 #endif
 
+static long cpu_frequency_change_helper(void *data)
+{
+    return cpu_frequency_change(*(uint64_t *)data);
+}
+
 ret_t do_platform_op(XEN_GUEST_HANDLE(xen_platform_op_t) u_xenpf_op)
 {
     ret_t ret = 0;
@@ -280,6 +285,15 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xe
         ret = acpi_enter_sleep(&op->u.enter_acpi_sleep);
         break;
 
+    case XENPF_change_freq:
+        ret = -EINVAL;
+        if ( op->u.change_freq.flags != 0 )
+            break;
+        ret = continue_hypercall_on_cpu(op->u.change_freq.cpu,
+                                        cpu_frequency_change_helper,
+                                        &op->u.change_freq.freq);
+        break;
+
     default:
         ret = -ENOSYS;
         break;
diff -r 00040cd1b34f -r 2477e94450aa xen/arch/x86/time.c
--- a/xen/arch/x86/time.c       Thu Sep 20 13:30:14 2007 +0100
+++ b/xen/arch/x86/time.c       Thu Sep 20 14:15:45 2007 +0100
@@ -722,6 +722,27 @@ void update_domain_wallclock_time(struct
     spin_unlock(&wc_lock);
 }
 
+int cpu_frequency_change(u64 freq)
+{
+    struct cpu_time *t = &this_cpu(cpu_time);
+    u64 curr_tsc;
+
+    local_irq_disable();
+    set_time_scale(&t->tsc_scale, freq);
+    rdtscll(curr_tsc);
+    t->local_tsc_stamp = curr_tsc;
+    t->stime_local_stamp = get_s_time();
+    t->stime_master_stamp = read_platform_stime();
+    local_irq_enable();
+
+    /* A full epoch should pass before we check for deviation. */
+    set_timer(&t->calibration_timer, NOW() + EPOCH);
+    if ( smp_processor_id() == 0 )
+        platform_time_calibration();
+
+    return 0;
+}
+
 /* Set clock to <secs,usecs> after 00:00:00 UTC, 1 January, 1970. */
 void do_settime(unsigned long secs, unsigned long nsecs, u64 system_time_base)
 {
@@ -866,12 +887,14 @@ static void local_time_calibration(void 
            error_factor, calibration_mul_frac, tsc_shift);
 #endif
 
-    /* Record new timestamp information. */
+    /* Record new timestamp information, atomically w.r.t. interrupts. */
+    local_irq_disable();
     t->tsc_scale.mul_frac = calibration_mul_frac;
     t->tsc_scale.shift    = tsc_shift;
     t->local_tsc_stamp    = curr_tsc;
     t->stime_local_stamp  = curr_local_stime;
     t->stime_master_stamp = curr_master_stime;
+    local_irq_enable();
 
     update_vcpu_system_time(current);
 
diff -r 00040cd1b34f -r 2477e94450aa xen/arch/x86/traps.c
--- a/xen/arch/x86/traps.c      Thu Sep 20 13:30:14 2007 +0100
+++ b/xen/arch/x86/traps.c      Thu Sep 20 14:15:45 2007 +0100
@@ -1728,10 +1728,16 @@ static int emulate_privileged_op(struct 
             v->arch.guest_context.gs_base_user = res;
             break;
 #endif
+        case MSR_K8_FIDVID_STATUS:
+        case MSR_K8_FIDVID_CTL:
+            if ( (cpufreq_controller != FREQCTL_dom0_kernel) ||
+                 (boot_cpu_data.x86_vendor != X86_VENDOR_AMD) ||
+                 wrmsr_safe(regs->ecx, eax, edx) )
+                goto fail;
+            break;
         default:
             if ( wrmsr_hypervisor_regs(regs->ecx, eax, edx) )
                 break;
-
             if ( (rdmsr_safe(regs->ecx, l, h) != 0) ||
                  (eax != l) || (edx != h) )
                 gdprintk(XENLOG_WARNING, "Domain attempted WRMSR %p from "
@@ -1764,6 +1770,13 @@ static int emulate_privileged_op(struct 
             regs->edx = v->arch.guest_context.gs_base_user >> 32;
             break;
 #endif
+        case MSR_K8_FIDVID_CTL:
+        case MSR_K8_FIDVID_STATUS:
+            if ( (cpufreq_controller != FREQCTL_dom0_kernel) ||
+                 (boot_cpu_data.x86_vendor != X86_VENDOR_AMD) ||
+                 rdmsr_safe(regs->ecx, regs->eax, regs->edx) )
+                goto fail;
+            break;
         case MSR_EFER:
             if ( rdmsr_safe(regs->ecx, regs->eax, regs->edx) )
                 goto fail;
diff -r 00040cd1b34f -r 2477e94450aa xen/common/schedule.c
--- a/xen/common/schedule.c     Thu Sep 20 13:30:14 2007 +0100
+++ b/xen/common/schedule.c     Thu Sep 20 14:15:45 2007 +0100
@@ -42,6 +42,17 @@ static unsigned int opt_dom0_vcpus_pin;
 static unsigned int opt_dom0_vcpus_pin;
 boolean_param("dom0_vcpus_pin", opt_dom0_vcpus_pin);
 
+enum cpufreq_controller cpufreq_controller;
+static void __init setup_cpufreq_option(char *str)
+{
+    if ( !strcmp(str, "dom0-kernel") )
+    {
+        cpufreq_controller = FREQCTL_dom0_kernel;
+        opt_dom0_vcpus_pin = 1;
+    }
+}
+custom_param("cpufreq", setup_cpufreq_option);
+
 #define TIME_SLOP      (s32)MICROSECS(50)     /* allow time to slip a bit */
 
 /* Various timer handlers. */
diff -r 00040cd1b34f -r 2477e94450aa xen/include/asm-x86/msr.h
--- a/xen/include/asm-x86/msr.h Thu Sep 20 13:30:14 2007 +0100
+++ b/xen/include/asm-x86/msr.h Thu Sep 20 14:15:45 2007 +0100
@@ -360,6 +360,9 @@ static inline void write_efer(__u64 val)
 #define MSR_K8_VM_CR                   0xC0010114
 #define MSR_K8_VM_HSAVE_PA             0xC0010117
 
+#define MSR_K8_FIDVID_CTL              0xC0010041
+#define MSR_K8_FIDVID_STATUS           0xC0010042
+
 /* MSR_K8_VM_CR bits: */
 #define _K8_VMCR_SVME_DISABLE          4
 #define K8_VMCR_SVME_DISABLE           (1 << _K8_VMCR_SVME_DISABLE)
diff -r 00040cd1b34f -r 2477e94450aa xen/include/asm-x86/time.h
--- a/xen/include/asm-x86/time.h        Thu Sep 20 13:30:14 2007 +0100
+++ b/xen/include/asm-x86/time.h        Thu Sep 20 14:15:45 2007 +0100
@@ -29,4 +29,6 @@ struct ioreq;
 struct ioreq;
 int dom0_pit_access(struct ioreq *ioreq);
 
+int cpu_frequency_change(u64 freq);
+
 #endif /* __X86_TIME_H__ */
diff -r 00040cd1b34f -r 2477e94450aa xen/include/public/platform.h
--- a/xen/include/public/platform.h     Thu Sep 20 13:30:14 2007 +0100
+++ b/xen/include/public/platform.h     Thu Sep 20 14:15:45 2007 +0100
@@ -164,6 +164,16 @@ typedef struct xenpf_enter_acpi_sleep xe
 typedef struct xenpf_enter_acpi_sleep xenpf_enter_acpi_sleep_t;
 DEFINE_XEN_GUEST_HANDLE(xenpf_enter_acpi_sleep_t);
 
+#define XENPF_change_freq       52
+struct xenpf_change_freq {
+    /* IN variables */
+    uint32_t flags; /* Must be zero. */
+    uint32_t cpu;   /* Physical cpu. */
+    uint64_t freq;  /* New frequency (Hz). */
+};
+typedef struct xenpf_change_freq xenpf_change_freq_t;
+DEFINE_XEN_GUEST_HANDLE(xenpf_change_freq_t);
+
 struct xen_platform_op {
     uint32_t cmd;
     uint32_t interface_version; /* XENPF_INTERFACE_VERSION */
@@ -176,6 +186,7 @@ struct xen_platform_op {
         struct xenpf_platform_quirk    platform_quirk;
         struct xenpf_firmware_info     firmware_info;
         struct xenpf_enter_acpi_sleep  enter_acpi_sleep;
+        struct xenpf_change_freq       change_freq;
         uint8_t                        pad[128];
     } u;
 };
diff -r 00040cd1b34f -r 2477e94450aa xen/include/xen/sched.h
--- a/xen/include/xen/sched.h   Thu Sep 20 13:30:14 2007 +0100
+++ b/xen/include/xen/sched.h   Thu Sep 20 14:15:45 2007 +0100
@@ -499,6 +499,10 @@ static inline void vcpu_unblock(struct v
 #define is_hvm_domain(d) ((d)->is_hvm)
 #define is_hvm_vcpu(v)   (is_hvm_domain(v->domain))
 
+extern enum cpufreq_controller {
+    FREQCTL_none, FREQCTL_dom0_kernel
+} cpufreq_controller;
+
 #endif /* __SCHED_H__ */
 
 /*
diff -r 00040cd1b34f -r 2477e94450aa xen/include/xen/time.h
--- a/xen/include/xen/time.h    Thu Sep 20 13:30:14 2007 +0100
+++ b/xen/include/xen/time.h    Thu Sep 20 14:15:45 2007 +0100
@@ -1,27 +1,9 @@
-/****************************************************************************
- * (C) 2002 - Rolf Neugebauer - Intel Research Cambridge
- ****************************************************************************
- *
- *        File: time.h
- *      Author: Rolf Neugebauer (neugebar@xxxxxxxxxxxxx)
- *     Changes: 
- *              
- *        Date: Nov 2002
+/******************************************************************************
+ * time.h
  * 
- * Environment: Xen Hypervisor
- * Description: This file provides a one stop shop for all time related
- *              issues within the hypervisor. 
- * 
- *              The Hypervisor provides the following notions of time:
- *              Cycle Counter Time, System Time, Wall Clock Time, and 
- *              Domain Virtual Time.
- *
- ****************************************************************************
- * $Id: h-insert.h,v 1.4 2002/11/08 16:03:55 rn Exp $
- ****************************************************************************
+ * Copyright (c) 2002-2003 Rolf Neugebauer
+ * Copyright (c) 2002-2005 K A Fraser
  */
-
-
 
 #ifndef __XEN_TIME_H__
 #define __XEN_TIME_H__

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.