]>
git.proxmox.com Git - ceph.git/blob - 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
9 #include "oob_monitor.h"
10 #include "power_manager.h"
11 #include "channel_manager.h"
13 static volatile unsigned run_loop
= 1;
14 static uint64_t g_branches
, g_branch_misses
;
17 void branch_monitor_exit(void)
22 /* Number of microseconds between each poll */
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
33 apply_policy(int core
)
37 uint64_t branches
, branch_misses
;
38 uint32_t last_branches
, last_branch_misses
;
39 int hits_diff
, miss_diff
;
46 last_branches
= ci
->cd
[core
].last_branches
;
47 last_branch_misses
= ci
->cd
[core
].last_branch_misses
;
49 ret
= pread(ci
->cd
[core
].msr_fd
, &counter
,
50 sizeof(counter
), IA32_PERFCTR0
);
52 RTE_LOG(ERR
, POWER_MANAGER
,
53 "unable to read counter for core %u\n",
57 ret
= pread(ci
->cd
[core
].msr_fd
, &counter
,
58 sizeof(counter
), IA32_PERFCTR1
);
60 RTE_LOG(ERR
, POWER_MANAGER
,
61 "unable to read counter for core %u\n",
63 branch_misses
= counter
;
66 ci
->cd
[core
].last_branches
= branches
;
67 ci
->cd
[core
].last_branch_misses
= branch_misses
;
69 hits_diff
= (int)branches
- (int)last_branches
;
71 /* Likely a counter overflow condition, skip this round */
75 miss_diff
= (int)branch_misses
- (int)last_branch_misses
;
77 /* Likely a counter overflow condition, skip this round */
81 g_branches
= hits_diff
;
82 g_branch_misses
= miss_diff
;
84 if (hits_diff
< (INTERVAL
*100)) {
85 /* Likely no workload running on this core. Skip. */
89 ratio
= (float)miss_diff
* (float)100 / (float)hits_diff
;
91 if (ratio
< ci
->branch_ratio_threshold
)
92 power_manager_scale_core_min(core
);
94 power_manager_scale_core_max(core
);
101 add_core_to_monitor(int core
)
103 struct core_info
*ci
;
104 char proc_file
[UNIX_PATH_MAX
];
107 ci
= get_core_info();
109 if (core
< ci
->core_count
) {
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",
122 * Set up branch counters
124 setup
= IA32_PERFEVT_BRANCH_HITS
;
125 ret
= pwrite(ci
->cd
[core
].msr_fd
, &setup
,
126 sizeof(setup
), IA32_PERFEVTSEL0
);
128 RTE_LOG(ERR
, POWER_MANAGER
,
129 "unable to set counter for core %u\n",
133 setup
= IA32_PERFEVT_BRANCH_MISS
;
134 ret
= pwrite(ci
->cd
[core
].msr_fd
, &setup
,
135 sizeof(setup
), IA32_PERFEVTSEL1
);
137 RTE_LOG(ERR
, POWER_MANAGER
,
138 "unable to set counter for core %u\n",
143 * Close the file and re-open as read only so
144 * as not to hog the resource
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",
155 ci
->cd
[core
].oob_enabled
= 1;
161 remove_core_from_monitor(int core
)
163 struct core_info
*ci
;
164 char proc_file
[UNIX_PATH_MAX
];
167 ci
= get_core_info();
169 if (ci
->cd
[core
].oob_enabled
) {
173 * close the msr file, then reopen rw so we can
174 * disable the counters
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",
187 setup
= 0x0; /* clear event */
188 ret
= pwrite(ci
->cd
[core
].msr_fd
, &setup
,
189 sizeof(setup
), IA32_PERFEVTSEL0
);
191 RTE_LOG(ERR
, POWER_MANAGER
,
192 "unable to set counter for core %u\n",
196 setup
= 0x0; /* clear event */
197 ret
= pwrite(ci
->cd
[core
].msr_fd
, &setup
,
198 sizeof(setup
), IA32_PERFEVTSEL1
);
200 RTE_LOG(ERR
, POWER_MANAGER
,
201 "unable to set counter for core %u\n",
206 close(ci
->cd
[core
].msr_fd
);
207 ci
->cd
[core
].msr_fd
= 0;
208 ci
->cd
[core
].oob_enabled
= 0;
214 branch_monitor_init(void)
220 run_branch_monitor(void)
222 struct core_info
*ci
;
228 ci
= get_core_info();
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
,
252 if (print
> PRINT_LOOP_COUNT
) {