]> git.proxmox.com Git - ceph.git/blob - ceph/src/spdk/dpdk/examples/vm_power_manager/oob_monitor_x86.c
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / spdk / dpdk / examples / vm_power_manager / oob_monitor_x86.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2018 Intel Corporation
3 */
4
5 #include <unistd.h>
6 #include <fcntl.h>
7 #include <rte_log.h>
8
9 #include "oob_monitor.h"
10 #include "power_manager.h"
11 #include "channel_manager.h"
12
13 static volatile unsigned run_loop = 1;
14 static uint64_t g_branches, g_branch_misses;
15 static int g_active;
16
17 void branch_monitor_exit(void)
18 {
19 run_loop = 0;
20 }
21
22 /* Number of microseconds between each poll */
23 #define INTERVAL 100
24 #define PRINT_LOOP_COUNT (1000000/INTERVAL)
25 #define IA32_PERFEVTSEL0 0x186
26 #define IA32_PERFEVTSEL1 0x187
27 #define IA32_PERFCTR0 0xc1
28 #define IA32_PERFCTR1 0xc2
29 #define IA32_PERFEVT_BRANCH_HITS 0x05300c4
30 #define IA32_PERFEVT_BRANCH_MISS 0x05300c5
31
32 static float
33 apply_policy(int core)
34 {
35 struct core_info *ci;
36 uint64_t counter;
37 uint64_t branches, branch_misses;
38 uint32_t last_branches, last_branch_misses;
39 int hits_diff, miss_diff;
40 float ratio;
41 int ret;
42
43 g_active = 0;
44 ci = get_core_info();
45
46 last_branches = ci->cd[core].last_branches;
47 last_branch_misses = ci->cd[core].last_branch_misses;
48
49 ret = pread(ci->cd[core].msr_fd, &counter,
50 sizeof(counter), IA32_PERFCTR0);
51 if (ret < 0)
52 RTE_LOG(ERR, POWER_MANAGER,
53 "unable to read counter for core %u\n",
54 core);
55 branches = counter;
56
57 ret = pread(ci->cd[core].msr_fd, &counter,
58 sizeof(counter), IA32_PERFCTR1);
59 if (ret < 0)
60 RTE_LOG(ERR, POWER_MANAGER,
61 "unable to read counter for core %u\n",
62 core);
63 branch_misses = counter;
64
65
66 ci->cd[core].last_branches = branches;
67 ci->cd[core].last_branch_misses = branch_misses;
68
69 hits_diff = (int)branches - (int)last_branches;
70 if (hits_diff <= 0) {
71 /* Likely a counter overflow condition, skip this round */
72 return -1.0;
73 }
74
75 miss_diff = (int)branch_misses - (int)last_branch_misses;
76 if (miss_diff <= 0) {
77 /* Likely a counter overflow condition, skip this round */
78 return -1.0;
79 }
80
81 g_branches = hits_diff;
82 g_branch_misses = miss_diff;
83
84 if (hits_diff < (INTERVAL*100)) {
85 /* Likely no workload running on this core. Skip. */
86 return -1.0;
87 }
88
89 ratio = (float)miss_diff * (float)100 / (float)hits_diff;
90
91 if (ratio < ci->branch_ratio_threshold)
92 power_manager_scale_core_min(core);
93 else
94 power_manager_scale_core_max(core);
95
96 g_active = 1;
97 return ratio;
98 }
99
100 int
101 add_core_to_monitor(int core)
102 {
103 struct core_info *ci;
104 char proc_file[UNIX_PATH_MAX];
105 int ret;
106
107 ci = get_core_info();
108
109 if (core < ci->core_count) {
110 long setup;
111
112 snprintf(proc_file, UNIX_PATH_MAX, "/dev/cpu/%d/msr", core);
113 ci->cd[core].msr_fd = open(proc_file, O_RDWR | O_SYNC);
114 if (ci->cd[core].msr_fd < 0) {
115 RTE_LOG(ERR, POWER_MANAGER,
116 "Error opening MSR file for core %d "
117 "(is msr kernel module loaded?)\n",
118 core);
119 return -1;
120 }
121 /*
122 * Set up branch counters
123 */
124 setup = IA32_PERFEVT_BRANCH_HITS;
125 ret = pwrite(ci->cd[core].msr_fd, &setup,
126 sizeof(setup), IA32_PERFEVTSEL0);
127 if (ret < 0) {
128 RTE_LOG(ERR, POWER_MANAGER,
129 "unable to set counter for core %u\n",
130 core);
131 return ret;
132 }
133 setup = IA32_PERFEVT_BRANCH_MISS;
134 ret = pwrite(ci->cd[core].msr_fd, &setup,
135 sizeof(setup), IA32_PERFEVTSEL1);
136 if (ret < 0) {
137 RTE_LOG(ERR, POWER_MANAGER,
138 "unable to set counter for core %u\n",
139 core);
140 return ret;
141 }
142 /*
143 * Close the file and re-open as read only so
144 * as not to hog the resource
145 */
146 close(ci->cd[core].msr_fd);
147 ci->cd[core].msr_fd = open(proc_file, O_RDONLY);
148 if (ci->cd[core].msr_fd < 0) {
149 RTE_LOG(ERR, POWER_MANAGER,
150 "Error opening MSR file for core %d "
151 "(is msr kernel module loaded?)\n",
152 core);
153 return -1;
154 }
155 ci->cd[core].oob_enabled = 1;
156 }
157 return 0;
158 }
159
160 int
161 remove_core_from_monitor(int core)
162 {
163 struct core_info *ci;
164 char proc_file[UNIX_PATH_MAX];
165 int ret;
166
167 ci = get_core_info();
168
169 if (ci->cd[core].oob_enabled) {
170 long setup;
171
172 /*
173 * close the msr file, then reopen rw so we can
174 * disable the counters
175 */
176 if (ci->cd[core].msr_fd != 0)
177 close(ci->cd[core].msr_fd);
178 snprintf(proc_file, UNIX_PATH_MAX, "/dev/cpu/%d/msr", core);
179 ci->cd[core].msr_fd = open(proc_file, O_RDWR | O_SYNC);
180 if (ci->cd[core].msr_fd < 0) {
181 RTE_LOG(ERR, POWER_MANAGER,
182 "Error opening MSR file for core %d "
183 "(is msr kernel module loaded?)\n",
184 core);
185 return -1;
186 }
187 setup = 0x0; /* clear event */
188 ret = pwrite(ci->cd[core].msr_fd, &setup,
189 sizeof(setup), IA32_PERFEVTSEL0);
190 if (ret < 0) {
191 RTE_LOG(ERR, POWER_MANAGER,
192 "unable to set counter for core %u\n",
193 core);
194 return ret;
195 }
196 setup = 0x0; /* clear event */
197 ret = pwrite(ci->cd[core].msr_fd, &setup,
198 sizeof(setup), IA32_PERFEVTSEL1);
199 if (ret < 0) {
200 RTE_LOG(ERR, POWER_MANAGER,
201 "unable to set counter for core %u\n",
202 core);
203 return ret;
204 }
205
206 close(ci->cd[core].msr_fd);
207 ci->cd[core].msr_fd = 0;
208 ci->cd[core].oob_enabled = 0;
209 }
210 return 0;
211 }
212
213 int
214 branch_monitor_init(void)
215 {
216 return 0;
217 }
218
219 void
220 run_branch_monitor(void)
221 {
222 struct core_info *ci;
223 int print = 0;
224 float ratio;
225 int printed;
226 int reads = 0;
227
228 ci = get_core_info();
229
230 while (run_loop) {
231
232 if (!run_loop)
233 break;
234 usleep(INTERVAL);
235 int j;
236 print++;
237 printed = 0;
238 for (j = 0; j < ci->core_count; j++) {
239 if (ci->cd[j].oob_enabled) {
240 ratio = apply_policy(j);
241 if ((print > PRINT_LOOP_COUNT) && (g_active)) {
242 printf(" %d: %.4f {%lu} {%d}", j,
243 ratio, g_branches,
244 reads);
245 printed = 1;
246 reads = 0;
247 } else {
248 reads++;
249 }
250 }
251 }
252 if (print > PRINT_LOOP_COUNT) {
253 if (printed)
254 printf("\n");
255 print = 0;
256 }
257 }
258 }