From bd56c5a3ccb42737cdb450de6ac2521ca2c9b31f Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Thu, 20 Sep 2007 14:17:12 +0100 Subject: [PATCH] Notify CPU frequency changes to Xen. Signed-off-by: Mark Langsdorf Signed-off-by: Keir Fraser --- arch/i386/kernel/time-xen.c | 40 ++++++++++++++++++++++++++++++++ include/xen/interface/platform.h | 11 +++++++++ 2 files changed, 51 insertions(+) diff --git a/arch/i386/kernel/time-xen.c b/arch/i386/kernel/time-xen.c index 686d35a6..8000f837 100644 --- a/arch/i386/kernel/time-xen.c +++ b/arch/i386/kernel/time-xen.c @@ -50,6 +50,7 @@ #include #include #include +#include #include #include @@ -1120,6 +1121,45 @@ void local_teardown_timer(unsigned int cpu) } #endif +#if CONFIG_CPU_FREQ +static int time_cpufreq_notifier(struct notifier_block *nb, unsigned long val, + void *data) +{ + struct cpufreq_freqs *freq = data; + struct xen_platform_op op; + + if (cpu_has(&cpu_data[freq->cpu], X86_FEATURE_CONSTANT_TSC)) + return 0; + + if (val == CPUFREQ_PRECHANGE) + return 0; + + op.cmd = XENPF_change_freq; + op.u.change_freq.flags = 0; + op.u.change_freq.cpu = freq->cpu; + op.u.change_freq.freq = (u64)freq->new * 1000; + HYPERVISOR_platform_op(&op); + + return 0; +} + +static struct notifier_block time_cpufreq_notifier_block = { + .notifier_call = time_cpufreq_notifier +}; + +static int __init cpufreq_time_setup(void) +{ + if (!cpufreq_register_notifier(&time_cpufreq_notifier_block, + CPUFREQ_TRANSITION_NOTIFIER)) { + printk(KERN_ERR "failed to set up cpufreq notifier\n"); + return -ENODEV; + } + return 0; +} + +core_initcall(cpufreq_time_setup); +#endif + /* * /proc/sys/xen: This really belongs in another file. It can stay here for * now however. diff --git a/include/xen/interface/platform.h b/include/xen/interface/platform.h index d1a44835..ad7847a9 100644 --- a/include/xen/interface/platform.h +++ b/include/xen/interface/platform.h @@ -164,6 +164,16 @@ struct xenpf_enter_acpi_sleep { 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; }; -- 2.39.5