WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] x86: Implement cpufreq ondemand policy

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] x86: Implement cpufreq ondemand policy
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Thu, 15 May 2008 04:40:22 -0700
Delivery-date: Thu, 15 May 2008 04:40:57 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1210769726 -3600
# Node ID c9ec94410137d9509a6ea8329e9c0a1f22a4378b
# Parent  50fb7620d05ad869f354619e9fdf72e316c0d2b5
x86: Implement cpufreq ondemand policy

Based on initialized cpufreq infrustructure, setup a timer on
each PSD domain, periodicly sample cpu load and driver cpu to
some Px state according to cpu load and cpu coordination.

Signed-off-by: Liu Jinsong <jinsong.liu@xxxxxxxxx>
---
 xen/arch/x86/acpi/cpufreq/cpufreq_ondemand.c |  231 +++++++++++++++++++++++++++
 1 files changed, 231 insertions(+)

diff -r 50fb7620d05a -r c9ec94410137 
xen/arch/x86/acpi/cpufreq/cpufreq_ondemand.c
--- a/xen/arch/x86/acpi/cpufreq/cpufreq_ondemand.c      Wed May 14 13:55:11 
2008 +0100
+++ b/xen/arch/x86/acpi/cpufreq/cpufreq_ondemand.c      Wed May 14 13:55:26 
2008 +0100
@@ -1,6 +1,237 @@
+/*
+ *  xen/arch/x86/acpi/cpufreq/cpufreq_ondemand.c
+ *
+ *  Copyright (C)  2001 Russell King
+ *            (C)  2003 Venkatesh Pallipadi <venkatesh.pallipadi@xxxxxxxxx>.
+ *                      Jun Nakajima <jun.nakajima@xxxxxxxxx>
+ *             Feb 2008 Liu Jinsong <jinsong.liu@xxxxxxxxx>
+ *             Porting cpufreq_ondemand.c from Liunx 2.6.23 to Xen hypervisor 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <xen/types.h>
+#include <xen/percpu.h>
+#include <xen/cpumask.h>
+#include <xen/types.h>
+#include <xen/sched.h>
+#include <xen/timer.h>
+#include <asm/config.h>
 #include <acpi/cpufreq/cpufreq.h>
 
+#define DEF_FREQUENCY_UP_THRESHOLD              (80)
+
+#define MIN_DBS_INTERVAL                        (MICROSECS(100))
+#define MIN_SAMPLING_MILLISECS                  (20)
+#define MIN_STAT_SAMPLING_RATE                   \
+    (MIN_SAMPLING_MILLISECS * MILLISECS(1))
+#define DEF_SAMPLING_RATE_LATENCY_MULTIPLIER    (1000)
+#define TRANSITION_LATENCY_LIMIT                (10 * 1000 )
+
+static uint64_t def_sampling_rate;
+
+/* Sampling types */
+enum {DBS_NORMAL_SAMPLE, DBS_SUB_SAMPLE};
+
+static DEFINE_PER_CPU(struct cpu_dbs_info_s, cpu_dbs_info);
+
+static unsigned int dbs_enable;    /* number of CPUs using this policy */
+
+static struct dbs_tuners {
+    uint64_t     sampling_rate;
+    unsigned int up_threshold;
+    unsigned int ignore_nice;
+    unsigned int powersave_bias;
+} dbs_tuners_ins = {
+    .up_threshold = DEF_FREQUENCY_UP_THRESHOLD,
+    .ignore_nice = 0,
+    .powersave_bias = 0,
+};
+
+static struct timer dbs_timer[NR_CPUS];
+
+static inline uint64_t get_cpu_idle_time(unsigned int cpu)
+{
+    uint64_t idle_ns;
+    struct vcpu *v;
+
+    if ((v = idle_vcpu[cpu]) == NULL)
+        return 0;
+
+    idle_ns = v->runstate.time[RUNSTATE_running];
+    if (v->is_running)
+        idle_ns += NOW() - v->runstate.state_entry_time;
+
+    return idle_ns;
+}
+
+static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)
+{
+    unsigned int load = 0;
+    uint64_t cur_ns, idle_ns, total_ns;
+
+    struct cpufreq_policy *policy;
+    unsigned int j;
+
+    if (!this_dbs_info->enable)
+        return;
+
+    policy = this_dbs_info->cur_policy;
+    cur_ns = NOW();
+    total_ns = cur_ns - this_dbs_info->prev_cpu_wall;
+    this_dbs_info->prev_cpu_wall = NOW();
+
+    if (total_ns < MIN_DBS_INTERVAL)
+        return;
+
+    /* Get Idle Time */
+    idle_ns = UINT_MAX;
+    for_each_cpu_mask(j, policy->cpus) {
+        uint64_t total_idle_ns;
+        unsigned int tmp_idle_ns;
+        struct cpu_dbs_info_s *j_dbs_info;
+
+        j_dbs_info = &per_cpu(cpu_dbs_info, j);
+        total_idle_ns = get_cpu_idle_time(j);
+        tmp_idle_ns = total_idle_ns - j_dbs_info->prev_cpu_idle;
+        j_dbs_info->prev_cpu_idle = total_idle_ns;
+
+        if (tmp_idle_ns < idle_ns)
+            idle_ns = tmp_idle_ns;
+    }
+
+    if (likely(total_ns > idle_ns))
+        load = (100 * (total_ns - idle_ns)) / total_ns;
+
+    /* Check for frequency increase */
+    if (load > dbs_tuners_ins.up_threshold) {
+        /* if we are already at full speed then break out early */
+        if (policy->cur == policy->max)
+            return;
+        __cpufreq_driver_target(policy, policy->max,CPUFREQ_RELATION_H);
+        return;
+    }
+
+    /* Check for frequency decrease */
+    /* if we cannot reduce the frequency anymore, break out early */
+    if (policy->cur == policy->min)
+        return;
+
+    /*
+     * The optimal frequency is the frequency that is the lowest that
+     * can support the current CPU usage without triggering the up
+     * policy. To be safe, we focus 10 points under the threshold.
+     */
+    if (load < (dbs_tuners_ins.up_threshold - 10)) {
+        unsigned int freq_next, freq_cur;
+
+        freq_cur = __cpufreq_driver_getavg(policy);
+        if (!freq_cur)
+            freq_cur = policy->cur;
+
+        freq_next = (freq_cur * load) / (dbs_tuners_ins.up_threshold - 10);
+
+        __cpufreq_driver_target(policy, freq_next, CPUFREQ_RELATION_L);
+    }
+}
+
+static void do_dbs_timer(void *dbs)
+{
+    struct cpu_dbs_info_s *dbs_info = (struct cpu_dbs_info_s *)dbs;
+
+    if (!dbs_info->enable)
+        return;
+
+    dbs_check_cpu(dbs_info);
+
+    set_timer(&dbs_timer[dbs_info->cpu], NOW()+dbs_tuners_ins.sampling_rate);
+}
+
+static void dbs_timer_init(struct cpu_dbs_info_s *dbs_info)
+{
+    dbs_info->enable = 1;
+
+    init_timer(&dbs_timer[dbs_info->cpu], do_dbs_timer, 
+        (void *)dbs_info, dbs_info->cpu);
+
+    set_timer(&dbs_timer[dbs_info->cpu], NOW()+dbs_tuners_ins.sampling_rate);
+}
+
+static void dbs_timer_exit(struct cpu_dbs_info_s *dbs_info)
+{
+    dbs_info->enable = 0;
+    stop_timer(&dbs_timer[dbs_info->cpu]);
+}
+
 int cpufreq_governor_dbs(struct cpufreq_policy *policy, unsigned int event)
 {
+    unsigned int cpu = policy->cpu;
+    struct cpu_dbs_info_s *this_dbs_info;
+    unsigned int j;
+
+    this_dbs_info = &per_cpu(cpu_dbs_info, cpu);
+
+    switch (event) {
+    case CPUFREQ_GOV_START:
+        if ((!cpu_online(cpu)) || (!policy->cur))
+            return -EINVAL;
+
+        if (policy->cpuinfo.transition_latency >
+            (TRANSITION_LATENCY_LIMIT * 1000)) {
+            printk(KERN_WARNING "ondemand governor failed to load "
+                "due to too long transition latency\n");
+            return -EINVAL;
+        }
+        if (this_dbs_info->enable)
+            /* Already enabled */
+            break;
+
+        dbs_enable++;
+
+        for_each_cpu_mask(j, policy->cpus) {
+            struct cpu_dbs_info_s *j_dbs_info;
+            j_dbs_info = &per_cpu(cpu_dbs_info, j);
+            j_dbs_info->cur_policy = policy;
+
+            j_dbs_info->prev_cpu_idle = get_cpu_idle_time(j);
+            j_dbs_info->prev_cpu_wall = NOW();
+        }
+        this_dbs_info->cpu = cpu;
+        /*
+         * Start the timerschedule work, when this governor
+         * is used for first time
+         */
+        if (dbs_enable == 1) {
+            def_sampling_rate = policy->cpuinfo.transition_latency *
+                DEF_SAMPLING_RATE_LATENCY_MULTIPLIER;
+
+            if (def_sampling_rate < MIN_STAT_SAMPLING_RATE)
+                def_sampling_rate = MIN_STAT_SAMPLING_RATE;
+
+            dbs_tuners_ins.sampling_rate = def_sampling_rate;
+        }
+        dbs_timer_init(this_dbs_info);
+
+        break;
+
+    case CPUFREQ_GOV_STOP:
+        if (this_dbs_info->enable)
+            dbs_timer_exit(this_dbs_info);
+        dbs_enable--;
+
+        break;
+
+    case CPUFREQ_GOV_LIMITS:
+        if (policy->max < this_dbs_info->cur_policy->cur)
+            __cpufreq_driver_target(this_dbs_info->cur_policy,
+                policy->max, CPUFREQ_RELATION_H);
+        else if (policy->min > this_dbs_info->cur_policy->cur)
+            __cpufreq_driver_target(this_dbs_info->cur_policy,
+                policy->min, CPUFREQ_RELATION_L);
+        break;
+    }
     return 0;
 }
+             

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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] x86: Implement cpufreq ondemand policy, Xen patchbot-unstable <=