This source file includes following definitions.
- __rmid_entry
- __rmid_read
- rmid_dirty
- __check_limbo
- has_busy_rmid
- alloc_rmid
- add_rmid_to_limbo
- free_rmid
- mbm_overflow_count
- __mon_event_count
- mbm_bw_count
- mon_event_count
- update_mba_bw
- mbm_update
- cqm_handle_limbo
- cqm_setup_limbo_handler
- mbm_handle_overflow
- mbm_setup_overflow_handler
- dom_data_init
- l3_mon_evt_init
- rdt_get_mon_l3_config
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 
  12 
  13 
  14 
  15 
  16 
  17 
  18 #include <linux/module.h>
  19 #include <linux/slab.h>
  20 #include <asm/cpu_device_id.h>
  21 #include "internal.h"
  22 
  23 struct rmid_entry {
  24         u32                             rmid;
  25         int                             busy;
  26         struct list_head                list;
  27 };
  28 
  29 
  30 
  31 
  32 
  33 
  34 static LIST_HEAD(rmid_free_lru);
  35 
  36 
  37 
  38 
  39 
  40 
  41 
  42 
  43 static unsigned int rmid_limbo_count;
  44 
  45 
  46 
  47 
  48 static struct rmid_entry        *rmid_ptrs;
  49 
  50 
  51 
  52 
  53 
  54 bool rdt_mon_capable;
  55 
  56 
  57 
  58 
  59 unsigned int rdt_mon_features;
  60 
  61 
  62 
  63 
  64 
  65 unsigned int resctrl_cqm_threshold;
  66 
  67 static inline struct rmid_entry *__rmid_entry(u32 rmid)
  68 {
  69         struct rmid_entry *entry;
  70 
  71         entry = &rmid_ptrs[rmid];
  72         WARN_ON(entry->rmid != rmid);
  73 
  74         return entry;
  75 }
  76 
  77 static u64 __rmid_read(u32 rmid, u32 eventid)
  78 {
  79         u64 val;
  80 
  81         
  82 
  83 
  84 
  85 
  86 
  87 
  88 
  89         wrmsr(MSR_IA32_QM_EVTSEL, eventid, rmid);
  90         rdmsrl(MSR_IA32_QM_CTR, val);
  91 
  92         return val;
  93 }
  94 
  95 static bool rmid_dirty(struct rmid_entry *entry)
  96 {
  97         u64 val = __rmid_read(entry->rmid, QOS_L3_OCCUP_EVENT_ID);
  98 
  99         return val >= resctrl_cqm_threshold;
 100 }
 101 
 102 
 103 
 104 
 105 
 106 
 107 
 108 void __check_limbo(struct rdt_domain *d, bool force_free)
 109 {
 110         struct rmid_entry *entry;
 111         struct rdt_resource *r;
 112         u32 crmid = 1, nrmid;
 113 
 114         r = &rdt_resources_all[RDT_RESOURCE_L3];
 115 
 116         
 117 
 118 
 119 
 120 
 121 
 122         for (;;) {
 123                 nrmid = find_next_bit(d->rmid_busy_llc, r->num_rmid, crmid);
 124                 if (nrmid >= r->num_rmid)
 125                         break;
 126 
 127                 entry = __rmid_entry(nrmid);
 128                 if (force_free || !rmid_dirty(entry)) {
 129                         clear_bit(entry->rmid, d->rmid_busy_llc);
 130                         if (!--entry->busy) {
 131                                 rmid_limbo_count--;
 132                                 list_add_tail(&entry->list, &rmid_free_lru);
 133                         }
 134                 }
 135                 crmid = nrmid + 1;
 136         }
 137 }
 138 
 139 bool has_busy_rmid(struct rdt_resource *r, struct rdt_domain *d)
 140 {
 141         return find_first_bit(d->rmid_busy_llc, r->num_rmid) != r->num_rmid;
 142 }
 143 
 144 
 145 
 146 
 147 
 148 
 149 int alloc_rmid(void)
 150 {
 151         struct rmid_entry *entry;
 152 
 153         lockdep_assert_held(&rdtgroup_mutex);
 154 
 155         if (list_empty(&rmid_free_lru))
 156                 return rmid_limbo_count ? -EBUSY : -ENOSPC;
 157 
 158         entry = list_first_entry(&rmid_free_lru,
 159                                  struct rmid_entry, list);
 160         list_del(&entry->list);
 161 
 162         return entry->rmid;
 163 }
 164 
 165 static void add_rmid_to_limbo(struct rmid_entry *entry)
 166 {
 167         struct rdt_resource *r;
 168         struct rdt_domain *d;
 169         int cpu;
 170         u64 val;
 171 
 172         r = &rdt_resources_all[RDT_RESOURCE_L3];
 173 
 174         entry->busy = 0;
 175         cpu = get_cpu();
 176         list_for_each_entry(d, &r->domains, list) {
 177                 if (cpumask_test_cpu(cpu, &d->cpu_mask)) {
 178                         val = __rmid_read(entry->rmid, QOS_L3_OCCUP_EVENT_ID);
 179                         if (val <= resctrl_cqm_threshold)
 180                                 continue;
 181                 }
 182 
 183                 
 184 
 185 
 186 
 187                 if (!has_busy_rmid(r, d))
 188                         cqm_setup_limbo_handler(d, CQM_LIMBOCHECK_INTERVAL);
 189                 set_bit(entry->rmid, d->rmid_busy_llc);
 190                 entry->busy++;
 191         }
 192         put_cpu();
 193 
 194         if (entry->busy)
 195                 rmid_limbo_count++;
 196         else
 197                 list_add_tail(&entry->list, &rmid_free_lru);
 198 }
 199 
 200 void free_rmid(u32 rmid)
 201 {
 202         struct rmid_entry *entry;
 203 
 204         if (!rmid)
 205                 return;
 206 
 207         lockdep_assert_held(&rdtgroup_mutex);
 208 
 209         entry = __rmid_entry(rmid);
 210 
 211         if (is_llc_occupancy_enabled())
 212                 add_rmid_to_limbo(entry);
 213         else
 214                 list_add_tail(&entry->list, &rmid_free_lru);
 215 }
 216 
 217 static u64 mbm_overflow_count(u64 prev_msr, u64 cur_msr)
 218 {
 219         u64 shift = 64 - MBM_CNTR_WIDTH, chunks;
 220 
 221         chunks = (cur_msr << shift) - (prev_msr << shift);
 222         return chunks >>= shift;
 223 }
 224 
 225 static int __mon_event_count(u32 rmid, struct rmid_read *rr)
 226 {
 227         struct mbm_state *m;
 228         u64 chunks, tval;
 229 
 230         tval = __rmid_read(rmid, rr->evtid);
 231         if (tval & (RMID_VAL_ERROR | RMID_VAL_UNAVAIL)) {
 232                 rr->val = tval;
 233                 return -EINVAL;
 234         }
 235         switch (rr->evtid) {
 236         case QOS_L3_OCCUP_EVENT_ID:
 237                 rr->val += tval;
 238                 return 0;
 239         case QOS_L3_MBM_TOTAL_EVENT_ID:
 240                 m = &rr->d->mbm_total[rmid];
 241                 break;
 242         case QOS_L3_MBM_LOCAL_EVENT_ID:
 243                 m = &rr->d->mbm_local[rmid];
 244                 break;
 245         default:
 246                 
 247 
 248 
 249 
 250                 return -EINVAL;
 251         }
 252 
 253         if (rr->first) {
 254                 memset(m, 0, sizeof(struct mbm_state));
 255                 m->prev_bw_msr = m->prev_msr = tval;
 256                 return 0;
 257         }
 258 
 259         chunks = mbm_overflow_count(m->prev_msr, tval);
 260         m->chunks += chunks;
 261         m->prev_msr = tval;
 262 
 263         rr->val += m->chunks;
 264         return 0;
 265 }
 266 
 267 
 268 
 269 
 270 
 271 static void mbm_bw_count(u32 rmid, struct rmid_read *rr)
 272 {
 273         struct rdt_resource *r = &rdt_resources_all[RDT_RESOURCE_L3];
 274         struct mbm_state *m = &rr->d->mbm_local[rmid];
 275         u64 tval, cur_bw, chunks;
 276 
 277         tval = __rmid_read(rmid, rr->evtid);
 278         if (tval & (RMID_VAL_ERROR | RMID_VAL_UNAVAIL))
 279                 return;
 280 
 281         chunks = mbm_overflow_count(m->prev_bw_msr, tval);
 282         m->chunks_bw += chunks;
 283         m->chunks = m->chunks_bw;
 284         cur_bw = (chunks * r->mon_scale) >> 20;
 285 
 286         if (m->delta_comp)
 287                 m->delta_bw = abs(cur_bw - m->prev_bw);
 288         m->delta_comp = false;
 289         m->prev_bw = cur_bw;
 290         m->prev_bw_msr = tval;
 291 }
 292 
 293 
 294 
 295 
 296 
 297 void mon_event_count(void *info)
 298 {
 299         struct rdtgroup *rdtgrp, *entry;
 300         struct rmid_read *rr = info;
 301         struct list_head *head;
 302 
 303         rdtgrp = rr->rgrp;
 304 
 305         if (__mon_event_count(rdtgrp->mon.rmid, rr))
 306                 return;
 307 
 308         
 309 
 310 
 311         head = &rdtgrp->mon.crdtgrp_list;
 312 
 313         if (rdtgrp->type == RDTCTRL_GROUP) {
 314                 list_for_each_entry(entry, head, mon.crdtgrp_list) {
 315                         if (__mon_event_count(entry->mon.rmid, rr))
 316                                 return;
 317                 }
 318         }
 319 }
 320 
 321 
 322 
 323 
 324 
 325 
 326 
 327 
 328 
 329 
 330 
 331 
 332 
 333 
 334 
 335 
 336 
 337 
 338 
 339 
 340 
 341 
 342 
 343 
 344 
 345 
 346 
 347 
 348 
 349 
 350 
 351 
 352 
 353 static void update_mba_bw(struct rdtgroup *rgrp, struct rdt_domain *dom_mbm)
 354 {
 355         u32 closid, rmid, cur_msr, cur_msr_val, new_msr_val;
 356         struct mbm_state *pmbm_data, *cmbm_data;
 357         u32 cur_bw, delta_bw, user_bw;
 358         struct rdt_resource *r_mba;
 359         struct rdt_domain *dom_mba;
 360         struct list_head *head;
 361         struct rdtgroup *entry;
 362 
 363         if (!is_mbm_local_enabled())
 364                 return;
 365 
 366         r_mba = &rdt_resources_all[RDT_RESOURCE_MBA];
 367         closid = rgrp->closid;
 368         rmid = rgrp->mon.rmid;
 369         pmbm_data = &dom_mbm->mbm_local[rmid];
 370 
 371         dom_mba = get_domain_from_cpu(smp_processor_id(), r_mba);
 372         if (!dom_mba) {
 373                 pr_warn_once("Failure to get domain for MBA update\n");
 374                 return;
 375         }
 376 
 377         cur_bw = pmbm_data->prev_bw;
 378         user_bw = dom_mba->mbps_val[closid];
 379         delta_bw = pmbm_data->delta_bw;
 380         cur_msr_val = dom_mba->ctrl_val[closid];
 381 
 382         
 383 
 384 
 385         head = &rgrp->mon.crdtgrp_list;
 386         list_for_each_entry(entry, head, mon.crdtgrp_list) {
 387                 cmbm_data = &dom_mbm->mbm_local[entry->mon.rmid];
 388                 cur_bw += cmbm_data->prev_bw;
 389                 delta_bw += cmbm_data->delta_bw;
 390         }
 391 
 392         
 393 
 394 
 395 
 396 
 397 
 398 
 399 
 400 
 401 
 402 
 403 
 404 
 405 
 406         if (cur_msr_val > r_mba->membw.min_bw && user_bw < cur_bw) {
 407                 new_msr_val = cur_msr_val - r_mba->membw.bw_gran;
 408         } else if (cur_msr_val < MAX_MBA_BW &&
 409                    (user_bw > (cur_bw + delta_bw))) {
 410                 new_msr_val = cur_msr_val + r_mba->membw.bw_gran;
 411         } else {
 412                 return;
 413         }
 414 
 415         cur_msr = r_mba->msr_base + closid;
 416         wrmsrl(cur_msr, delay_bw_map(new_msr_val, r_mba));
 417         dom_mba->ctrl_val[closid] = new_msr_val;
 418 
 419         
 420 
 421 
 422 
 423 
 424 
 425 
 426 
 427 
 428 
 429         pmbm_data->delta_comp = true;
 430         list_for_each_entry(entry, head, mon.crdtgrp_list) {
 431                 cmbm_data = &dom_mbm->mbm_local[entry->mon.rmid];
 432                 cmbm_data->delta_comp = true;
 433         }
 434 }
 435 
 436 static void mbm_update(struct rdt_domain *d, int rmid)
 437 {
 438         struct rmid_read rr;
 439 
 440         rr.first = false;
 441         rr.d = d;
 442 
 443         
 444 
 445 
 446 
 447         if (is_mbm_total_enabled()) {
 448                 rr.evtid = QOS_L3_MBM_TOTAL_EVENT_ID;
 449                 __mon_event_count(rmid, &rr);
 450         }
 451         if (is_mbm_local_enabled()) {
 452                 rr.evtid = QOS_L3_MBM_LOCAL_EVENT_ID;
 453 
 454                 
 455 
 456 
 457 
 458 
 459                 if (!is_mba_sc(NULL))
 460                         __mon_event_count(rmid, &rr);
 461                 else
 462                         mbm_bw_count(rmid, &rr);
 463         }
 464 }
 465 
 466 
 467 
 468 
 469 
 470 void cqm_handle_limbo(struct work_struct *work)
 471 {
 472         unsigned long delay = msecs_to_jiffies(CQM_LIMBOCHECK_INTERVAL);
 473         int cpu = smp_processor_id();
 474         struct rdt_resource *r;
 475         struct rdt_domain *d;
 476 
 477         mutex_lock(&rdtgroup_mutex);
 478 
 479         r = &rdt_resources_all[RDT_RESOURCE_L3];
 480         d = get_domain_from_cpu(cpu, r);
 481 
 482         if (!d) {
 483                 pr_warn_once("Failure to get domain for limbo worker\n");
 484                 goto out_unlock;
 485         }
 486 
 487         __check_limbo(d, false);
 488 
 489         if (has_busy_rmid(r, d))
 490                 schedule_delayed_work_on(cpu, &d->cqm_limbo, delay);
 491 
 492 out_unlock:
 493         mutex_unlock(&rdtgroup_mutex);
 494 }
 495 
 496 void cqm_setup_limbo_handler(struct rdt_domain *dom, unsigned long delay_ms)
 497 {
 498         unsigned long delay = msecs_to_jiffies(delay_ms);
 499         int cpu;
 500 
 501         cpu = cpumask_any(&dom->cpu_mask);
 502         dom->cqm_work_cpu = cpu;
 503 
 504         schedule_delayed_work_on(cpu, &dom->cqm_limbo, delay);
 505 }
 506 
 507 void mbm_handle_overflow(struct work_struct *work)
 508 {
 509         unsigned long delay = msecs_to_jiffies(MBM_OVERFLOW_INTERVAL);
 510         struct rdtgroup *prgrp, *crgrp;
 511         int cpu = smp_processor_id();
 512         struct list_head *head;
 513         struct rdt_domain *d;
 514 
 515         mutex_lock(&rdtgroup_mutex);
 516 
 517         if (!static_branch_likely(&rdt_mon_enable_key))
 518                 goto out_unlock;
 519 
 520         d = get_domain_from_cpu(cpu, &rdt_resources_all[RDT_RESOURCE_L3]);
 521         if (!d)
 522                 goto out_unlock;
 523 
 524         list_for_each_entry(prgrp, &rdt_all_groups, rdtgroup_list) {
 525                 mbm_update(d, prgrp->mon.rmid);
 526 
 527                 head = &prgrp->mon.crdtgrp_list;
 528                 list_for_each_entry(crgrp, head, mon.crdtgrp_list)
 529                         mbm_update(d, crgrp->mon.rmid);
 530 
 531                 if (is_mba_sc(NULL))
 532                         update_mba_bw(prgrp, d);
 533         }
 534 
 535         schedule_delayed_work_on(cpu, &d->mbm_over, delay);
 536 
 537 out_unlock:
 538         mutex_unlock(&rdtgroup_mutex);
 539 }
 540 
 541 void mbm_setup_overflow_handler(struct rdt_domain *dom, unsigned long delay_ms)
 542 {
 543         unsigned long delay = msecs_to_jiffies(delay_ms);
 544         int cpu;
 545 
 546         if (!static_branch_likely(&rdt_mon_enable_key))
 547                 return;
 548         cpu = cpumask_any(&dom->cpu_mask);
 549         dom->mbm_work_cpu = cpu;
 550         schedule_delayed_work_on(cpu, &dom->mbm_over, delay);
 551 }
 552 
 553 static int dom_data_init(struct rdt_resource *r)
 554 {
 555         struct rmid_entry *entry = NULL;
 556         int i, nr_rmids;
 557 
 558         nr_rmids = r->num_rmid;
 559         rmid_ptrs = kcalloc(nr_rmids, sizeof(struct rmid_entry), GFP_KERNEL);
 560         if (!rmid_ptrs)
 561                 return -ENOMEM;
 562 
 563         for (i = 0; i < nr_rmids; i++) {
 564                 entry = &rmid_ptrs[i];
 565                 INIT_LIST_HEAD(&entry->list);
 566 
 567                 entry->rmid = i;
 568                 list_add_tail(&entry->list, &rmid_free_lru);
 569         }
 570 
 571         
 572 
 573 
 574 
 575         entry = __rmid_entry(0);
 576         list_del(&entry->list);
 577 
 578         return 0;
 579 }
 580 
 581 static struct mon_evt llc_occupancy_event = {
 582         .name           = "llc_occupancy",
 583         .evtid          = QOS_L3_OCCUP_EVENT_ID,
 584 };
 585 
 586 static struct mon_evt mbm_total_event = {
 587         .name           = "mbm_total_bytes",
 588         .evtid          = QOS_L3_MBM_TOTAL_EVENT_ID,
 589 };
 590 
 591 static struct mon_evt mbm_local_event = {
 592         .name           = "mbm_local_bytes",
 593         .evtid          = QOS_L3_MBM_LOCAL_EVENT_ID,
 594 };
 595 
 596 
 597 
 598 
 599 
 600 
 601 
 602 
 603 static void l3_mon_evt_init(struct rdt_resource *r)
 604 {
 605         INIT_LIST_HEAD(&r->evt_list);
 606 
 607         if (is_llc_occupancy_enabled())
 608                 list_add_tail(&llc_occupancy_event.list, &r->evt_list);
 609         if (is_mbm_total_enabled())
 610                 list_add_tail(&mbm_total_event.list, &r->evt_list);
 611         if (is_mbm_local_enabled())
 612                 list_add_tail(&mbm_local_event.list, &r->evt_list);
 613 }
 614 
 615 int rdt_get_mon_l3_config(struct rdt_resource *r)
 616 {
 617         unsigned int cl_size = boot_cpu_data.x86_cache_size;
 618         int ret;
 619 
 620         r->mon_scale = boot_cpu_data.x86_cache_occ_scale;
 621         r->num_rmid = boot_cpu_data.x86_cache_max_rmid + 1;
 622 
 623         
 624 
 625 
 626 
 627 
 628 
 629 
 630         resctrl_cqm_threshold = cl_size * 1024 / r->num_rmid;
 631 
 632         
 633         resctrl_cqm_threshold /= r->mon_scale;
 634 
 635         ret = dom_data_init(r);
 636         if (ret)
 637                 return ret;
 638 
 639         l3_mon_evt_init(r);
 640 
 641         r->mon_capable = true;
 642         r->mon_enabled = true;
 643 
 644         return 0;
 645 }