Coverage Report

Created: 2017-10-25 09:10

/root/src/xen/xen/common/core_parking.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 *  core_parking.c - implement core parking according to dom0 requirement
3
 *
4
 *  Copyright (C) 2012, Intel Corporation.
5
 *     Author: Liu, Jinsong <jinsong.liu@intel.com>
6
 *
7
 *  This program is free software; you can redistribute it and/or modify
8
 *  it under the terms of the GNU General Public License as published by
9
 *  the Free Software Foundation; either version 2 of the License, or (at
10
 *  your option) any later version.
11
 *
12
 *  This program is distributed in the hope that it will be useful, but
13
 *  WITHOUT ANY WARRANTY; without even the implied warranty of
14
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 *  General Public License for more details.
16
 */
17
18
#include <xen/types.h>
19
#include <xen/cpu.h>
20
#include <xen/init.h>
21
#include <xen/cpumask.h>
22
#include <asm/percpu.h>
23
#include <asm/smp.h>
24
25
0
#define CORE_PARKING_INCREMENT 1
26
0
#define CORE_PARKING_DECREMENT 2
27
28
static unsigned int core_parking_power(unsigned int event);
29
static unsigned int core_parking_performance(unsigned int event);
30
31
static uint32_t cur_idle_nums;
32
static unsigned int core_parking_cpunum[NR_CPUS] = {[0 ... NR_CPUS-1] = -1};
33
34
static struct core_parking_policy {
35
    char name[30];
36
    unsigned int (*next)(unsigned int event);
37
} *core_parking_policy;
38
39
static enum core_parking_controller {
40
    POWER_FIRST,
41
    PERFORMANCE_FIRST
42
} core_parking_controller = POWER_FIRST;
43
44
static int __init setup_core_parking_option(const char *str)
45
0
{
46
0
    if ( !strcmp(str, "power") )
47
0
        core_parking_controller = POWER_FIRST;
48
0
    else if ( !strcmp(str, "performance") )
49
0
        core_parking_controller = PERFORMANCE_FIRST;
50
0
    else
51
0
        return -EINVAL;
52
0
53
0
    return 0;
54
0
}
55
custom_param("core_parking", setup_core_parking_option);
56
57
static unsigned int core_parking_performance(unsigned int event)
58
0
{
59
0
    unsigned int cpu = -1;
60
0
61
0
    switch ( event )
62
0
    {
63
0
    case CORE_PARKING_INCREMENT:
64
0
    {
65
0
        int core_tmp, core_weight = -1;
66
0
        int sibling_tmp, sibling_weight = -1;
67
0
        cpumask_t core_candidate_map, sibling_candidate_map;
68
0
        cpumask_clear(&core_candidate_map);
69
0
        cpumask_clear(&sibling_candidate_map);
70
0
71
0
        for_each_cpu(cpu, &cpu_online_map)
72
0
        {
73
0
            if ( cpu == 0 )
74
0
                continue;
75
0
76
0
            core_tmp = cpumask_weight(per_cpu(cpu_core_mask, cpu));
77
0
            if ( core_weight < core_tmp )
78
0
            {
79
0
                core_weight = core_tmp;
80
0
                cpumask_copy(&core_candidate_map, cpumask_of(cpu));
81
0
            }
82
0
            else if ( core_weight == core_tmp )
83
0
                __cpumask_set_cpu(cpu, &core_candidate_map);
84
0
        }
85
0
86
0
        for_each_cpu(cpu, &core_candidate_map)
87
0
        {
88
0
            sibling_tmp = cpumask_weight(per_cpu(cpu_sibling_mask, cpu));
89
0
            if ( sibling_weight < sibling_tmp )
90
0
            {
91
0
                sibling_weight = sibling_tmp;
92
0
                cpumask_copy(&sibling_candidate_map, cpumask_of(cpu));
93
0
            }
94
0
            else if ( sibling_weight == sibling_tmp )
95
0
                __cpumask_set_cpu(cpu, &sibling_candidate_map);
96
0
        }
97
0
98
0
        cpu = cpumask_first(&sibling_candidate_map);
99
0
    }
100
0
    break;
101
0
102
0
    case CORE_PARKING_DECREMENT:
103
0
    {
104
0
        cpu = core_parking_cpunum[cur_idle_nums -1];
105
0
    }
106
0
    break;
107
0
108
0
    default:
109
0
        break;
110
0
    }
111
0
112
0
    return cpu;
113
0
}
114
115
static unsigned int core_parking_power(unsigned int event)
116
0
{
117
0
    unsigned int cpu = -1;
118
0
119
0
    switch ( event )
120
0
    {
121
0
    case CORE_PARKING_INCREMENT:
122
0
    {
123
0
        int core_tmp, core_weight = NR_CPUS + 1;
124
0
        int sibling_tmp, sibling_weight = NR_CPUS + 1;
125
0
        cpumask_t core_candidate_map, sibling_candidate_map;
126
0
        cpumask_clear(&core_candidate_map);
127
0
        cpumask_clear(&sibling_candidate_map);
128
0
129
0
        for_each_cpu(cpu, &cpu_online_map)
130
0
        {
131
0
            if ( cpu == 0 )
132
0
                continue;
133
0
134
0
            core_tmp = cpumask_weight(per_cpu(cpu_core_mask, cpu));
135
0
            if ( core_weight > core_tmp )
136
0
            {
137
0
                core_weight = core_tmp;
138
0
                cpumask_copy(&core_candidate_map, cpumask_of(cpu));
139
0
            }
140
0
            else if ( core_weight == core_tmp )
141
0
                __cpumask_set_cpu(cpu, &core_candidate_map);
142
0
        }
143
0
144
0
        for_each_cpu(cpu, &core_candidate_map)
145
0
        {
146
0
            sibling_tmp = cpumask_weight(per_cpu(cpu_sibling_mask, cpu));
147
0
            if ( sibling_weight > sibling_tmp )
148
0
            {
149
0
                sibling_weight = sibling_tmp;
150
0
                cpumask_copy(&sibling_candidate_map, cpumask_of(cpu));
151
0
            }
152
0
            else if ( sibling_weight == sibling_tmp )
153
0
                __cpumask_set_cpu(cpu, &sibling_candidate_map);
154
0
        }
155
0
156
0
        cpu = cpumask_first(&sibling_candidate_map);
157
0
    }
158
0
    break;
159
0
160
0
    case CORE_PARKING_DECREMENT:
161
0
    {
162
0
        cpu = core_parking_cpunum[cur_idle_nums -1];
163
0
    }
164
0
    break;
165
0
166
0
    default:
167
0
        break;
168
0
    }
169
0
170
0
    return cpu;
171
0
}
172
173
long core_parking_helper(void *data)
174
0
{
175
0
    uint32_t idle_nums = (unsigned long)data;
176
0
    unsigned int cpu;
177
0
    int ret = 0;
178
0
179
0
    if ( !core_parking_policy )
180
0
        return -EINVAL;
181
0
182
0
    while ( cur_idle_nums < idle_nums )
183
0
    {
184
0
        cpu = core_parking_policy->next(CORE_PARKING_INCREMENT);
185
0
        ret = cpu_down(cpu);
186
0
        if ( ret )
187
0
            return ret;
188
0
        core_parking_cpunum[cur_idle_nums++] = cpu;
189
0
    }
190
0
191
0
    while ( cur_idle_nums > idle_nums )
192
0
    {
193
0
        cpu = core_parking_policy->next(CORE_PARKING_DECREMENT);
194
0
        ret = cpu_up(cpu);
195
0
        if ( ret )
196
0
            return ret;
197
0
        core_parking_cpunum[--cur_idle_nums] = -1;
198
0
    }
199
0
200
0
    return ret;
201
0
}
202
203
uint32_t get_cur_idle_nums(void)
204
0
{
205
0
    return cur_idle_nums;
206
0
}
207
208
static struct core_parking_policy power_first = {
209
    .name = "power",
210
    .next = core_parking_power,
211
};
212
213
static struct core_parking_policy performance_first = {
214
    .name = "performance",
215
    .next = core_parking_performance,
216
};
217
218
static int register_core_parking_policy(struct core_parking_policy *policy)
219
1
{
220
1
    if ( !policy || !policy->next )
221
0
        return -EINVAL;
222
1
223
1
    core_parking_policy = policy;
224
1
    return 0;
225
1
}
226
227
static int __init core_parking_init(void)
228
1
{
229
1
    int ret = 0;
230
1
231
1
    if ( core_parking_controller == PERFORMANCE_FIRST )
232
0
        ret = register_core_parking_policy(&performance_first);
233
1
    else
234
1
        ret = register_core_parking_policy(&power_first);
235
1
236
1
    return ret;
237
1
}
238
__initcall(core_parking_init);