diff options
| -rw-r--r-- | arch/x86/kernel/cpu/intel_rdt.h | 10 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/intel_rdt_monitor.c | 44 |
2 files changed, 48 insertions, 6 deletions
diff --git a/arch/x86/kernel/cpu/intel_rdt.h b/arch/x86/kernel/cpu/intel_rdt.h index 91cc31087e8a..66a0ba37a8a3 100644 --- a/arch/x86/kernel/cpu/intel_rdt.h +++ b/arch/x86/kernel/cpu/intel_rdt.h | |||
| @@ -180,10 +180,20 @@ struct rftype { | |||
| 180 | * struct mbm_state - status for each MBM counter in each domain | 180 | * struct mbm_state - status for each MBM counter in each domain |
| 181 | * @chunks: Total data moved (multiply by rdt_group.mon_scale to get bytes) | 181 | * @chunks: Total data moved (multiply by rdt_group.mon_scale to get bytes) |
| 182 | * @prev_msr Value of IA32_QM_CTR for this RMID last time we read it | 182 | * @prev_msr Value of IA32_QM_CTR for this RMID last time we read it |
| 183 | * @chunks_bw Total local data moved. Used for bandwidth calculation | ||
| 184 | * @prev_bw_msr:Value of previous IA32_QM_CTR for bandwidth counting | ||
| 185 | * @prev_bw The most recent bandwidth in MBps | ||
| 186 | * @delta_bw Difference between the current and previous bandwidth | ||
| 187 | * @delta_comp Indicates whether to compute the delta_bw | ||
| 183 | */ | 188 | */ |
| 184 | struct mbm_state { | 189 | struct mbm_state { |
| 185 | u64 chunks; | 190 | u64 chunks; |
| 186 | u64 prev_msr; | 191 | u64 prev_msr; |
| 192 | u64 chunks_bw; | ||
| 193 | u64 prev_bw_msr; | ||
| 194 | u32 prev_bw; | ||
| 195 | u32 delta_bw; | ||
| 196 | bool delta_comp; | ||
| 187 | }; | 197 | }; |
| 188 | 198 | ||
| 189 | /** | 199 | /** |
diff --git a/arch/x86/kernel/cpu/intel_rdt_monitor.c b/arch/x86/kernel/cpu/intel_rdt_monitor.c index 681450eee428..7690402c42b7 100644 --- a/arch/x86/kernel/cpu/intel_rdt_monitor.c +++ b/arch/x86/kernel/cpu/intel_rdt_monitor.c | |||
| @@ -225,10 +225,18 @@ void free_rmid(u32 rmid) | |||
| 225 | list_add_tail(&entry->list, &rmid_free_lru); | 225 | list_add_tail(&entry->list, &rmid_free_lru); |
| 226 | } | 226 | } |
| 227 | 227 | ||
| 228 | static u64 mbm_overflow_count(u64 prev_msr, u64 cur_msr) | ||
| 229 | { | ||
| 230 | u64 shift = 64 - MBM_CNTR_WIDTH, chunks; | ||
| 231 | |||
| 232 | chunks = (cur_msr << shift) - (prev_msr << shift); | ||
| 233 | return chunks >>= shift; | ||
| 234 | } | ||
| 235 | |||
| 228 | static int __mon_event_count(u32 rmid, struct rmid_read *rr) | 236 | static int __mon_event_count(u32 rmid, struct rmid_read *rr) |
| 229 | { | 237 | { |
| 230 | u64 chunks, shift, tval; | ||
| 231 | struct mbm_state *m; | 238 | struct mbm_state *m; |
| 239 | u64 chunks, tval; | ||
| 232 | 240 | ||
| 233 | tval = __rmid_read(rmid, rr->evtid); | 241 | tval = __rmid_read(rmid, rr->evtid); |
| 234 | if (tval & (RMID_VAL_ERROR | RMID_VAL_UNAVAIL)) { | 242 | if (tval & (RMID_VAL_ERROR | RMID_VAL_UNAVAIL)) { |
| @@ -254,14 +262,12 @@ static int __mon_event_count(u32 rmid, struct rmid_read *rr) | |||
| 254 | } | 262 | } |
| 255 | 263 | ||
| 256 | if (rr->first) { | 264 | if (rr->first) { |
| 257 | m->prev_msr = tval; | 265 | memset(m, 0, sizeof(struct mbm_state)); |
| 258 | m->chunks = 0; | 266 | m->prev_bw_msr = m->prev_msr = tval; |
| 259 | return 0; | 267 | return 0; |
| 260 | } | 268 | } |
| 261 | 269 | ||
| 262 | shift = 64 - MBM_CNTR_WIDTH; | 270 | chunks = mbm_overflow_count(m->prev_msr, tval); |
| 263 | chunks = (tval << shift) - (m->prev_msr << shift); | ||
| 264 | chunks >>= shift; | ||
| 265 | m->chunks += chunks; | 271 | m->chunks += chunks; |
| 266 | m->prev_msr = tval; | 272 | m->prev_msr = tval; |
| 267 | 273 | ||
| @@ -270,6 +276,32 @@ static int __mon_event_count(u32 rmid, struct rmid_read *rr) | |||
| 270 | } | 276 | } |
| 271 | 277 | ||
| 272 | /* | 278 | /* |
| 279 | * Supporting function to calculate the memory bandwidth | ||
| 280 | * and delta bandwidth in MBps. | ||
| 281 | */ | ||
| 282 | static void mbm_bw_count(u32 rmid, struct rmid_read *rr) | ||
| 283 | { | ||
| 284 | struct rdt_resource *r = &rdt_resources_all[RDT_RESOURCE_L3]; | ||
| 285 | struct mbm_state *m = &rr->d->mbm_local[rmid]; | ||
| 286 | u64 tval, cur_bw, chunks; | ||
| 287 | |||
| 288 | tval = __rmid_read(rmid, rr->evtid); | ||
| 289 | if (tval & (RMID_VAL_ERROR | RMID_VAL_UNAVAIL)) | ||
| 290 | return; | ||
| 291 | |||
| 292 | chunks = mbm_overflow_count(m->prev_bw_msr, tval); | ||
| 293 | m->chunks_bw += chunks; | ||
| 294 | m->chunks = m->chunks_bw; | ||
| 295 | cur_bw = (chunks * r->mon_scale) >> 20; | ||
| 296 | |||
| 297 | if (m->delta_comp) | ||
| 298 | m->delta_bw = abs(cur_bw - m->prev_bw); | ||
| 299 | m->delta_comp = false; | ||
| 300 | m->prev_bw = cur_bw; | ||
| 301 | m->prev_bw_msr = tval; | ||
| 302 | } | ||
| 303 | |||
| 304 | /* | ||
| 273 | * This is called via IPI to read the CQM/MBM counters | 305 | * This is called via IPI to read the CQM/MBM counters |
| 274 | * on a domain. | 306 | * on a domain. |
| 275 | */ | 307 | */ |
