# 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
|