[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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |