Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

fs/resctrl: Support counter read/reset with mbm_event assignment mode

When "mbm_event" counter assignment mode is enabled, the architecture requires
a counter ID to read the event data.

Introduce an is_mbm_cntr field in struct rmid_read to indicate whether counter
assignment mode is in use.

Update the logic to call resctrl_arch_cntr_read() and resctrl_arch_reset_cntr()
when the assignment mode is active. Report 'Unassigned' in case the user attempts
to read an event without assigning a hardware counter.

Suggested-by: Reinette Chatre <reinette.chatre@intel.com>
Signed-off-by: Babu Moger <babu.moger@amd.com>
Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
Reviewed-by: Reinette Chatre <reinette.chatre@intel.com>
Link: https://lore.kernel.org/cover.1757108044.git.babu.moger@amd.com

authored by

Babu Moger and committed by
Borislav Petkov (AMD)
159f36cd 2a65b72c

+62 -16
+6
Documentation/filesystems/resctrl.rst
··· 434 434 for the L3 cache they occupy). These are named "mon_sub_L3_YY" 435 435 where "YY" is the node number. 436 436 437 + When the 'mbm_event' counter assignment mode is enabled, reading 438 + an MBM event of a MON group returns 'Unassigned' if no hardware 439 + counter is assigned to it. For CTRL_MON groups, 'Unassigned' is 440 + returned if the MBM event does not have an assigned counter in the 441 + CTRL_MON group nor in any of its associated MON groups. 442 + 437 443 "mon_hw_id": 438 444 Available only with debug option. The identifier used by hardware 439 445 for the monitor group. On x86 this is the RMID.
+17 -5
fs/resctrl/ctrlmondata.c
··· 563 563 rr->r = r; 564 564 rr->d = d; 565 565 rr->first = first; 566 - rr->arch_mon_ctx = resctrl_arch_mon_ctx_alloc(r, evtid); 567 - if (IS_ERR(rr->arch_mon_ctx)) { 568 - rr->err = -EINVAL; 569 - return; 566 + if (resctrl_arch_mbm_cntr_assign_enabled(r) && 567 + resctrl_is_mbm_event(evtid)) { 568 + rr->is_mbm_cntr = true; 569 + } else { 570 + rr->arch_mon_ctx = resctrl_arch_mon_ctx_alloc(r, evtid); 571 + if (IS_ERR(rr->arch_mon_ctx)) { 572 + rr->err = -EINVAL; 573 + return; 574 + } 570 575 } 571 576 572 577 cpu = cpumask_any_housekeeping(cpumask, RESCTRL_PICK_ANY_CPU); ··· 587 582 else 588 583 smp_call_on_cpu(cpu, smp_mon_event_count, rr, false); 589 584 590 - resctrl_arch_mon_ctx_free(r, evtid, rr->arch_mon_ctx); 585 + if (rr->arch_mon_ctx) 586 + resctrl_arch_mon_ctx_free(r, evtid, rr->arch_mon_ctx); 591 587 } 592 588 593 589 int rdtgroup_mondata_show(struct seq_file *m, void *arg) ··· 659 653 660 654 checkresult: 661 655 656 + /* 657 + * -ENOENT is a special case, set only when "mbm_event" counter assignment 658 + * mode is enabled and no counter has been assigned. 659 + */ 662 660 if (rr.err == -EIO) 663 661 seq_puts(m, "Error\n"); 664 662 else if (rr.err == -EINVAL) 665 663 seq_puts(m, "Unavailable\n"); 664 + else if (rr.err == -ENOENT) 665 + seq_puts(m, "Unassigned\n"); 666 666 else 667 667 seq_printf(m, "%llu\n", rr.val); 668 668
+3
fs/resctrl/internal.h
··· 111 111 * @evtid: Which monitor event to read. 112 112 * @first: Initialize MBM counter when true. 113 113 * @ci: Cacheinfo for L3. Only set when @d is NULL. Used when summing domains. 114 + * @is_mbm_cntr: true if "mbm_event" counter assignment mode is enabled and it 115 + * is an MBM event. 114 116 * @err: Error encountered when reading counter. 115 117 * @val: Returned value of event counter. If @rgrp is a parent resource group, 116 118 * @val includes the sum of event counts from its child resource groups. ··· 127 125 enum resctrl_event_id evtid; 128 126 bool first; 129 127 struct cacheinfo *ci; 128 + bool is_mbm_cntr; 130 129 int err; 131 130 u64 val; 132 131 void *arch_mon_ctx;
+36 -11
fs/resctrl/monitor.c
··· 419 419 u32 closid = rdtgrp->closid; 420 420 u32 rmid = rdtgrp->mon.rmid; 421 421 struct rdt_mon_domain *d; 422 + int cntr_id = -ENOENT; 422 423 struct mbm_state *m; 423 424 int err, ret; 424 425 u64 tval = 0; 425 426 427 + if (rr->is_mbm_cntr) { 428 + cntr_id = mbm_cntr_get(rr->r, rr->d, rdtgrp, rr->evtid); 429 + if (cntr_id < 0) { 430 + rr->err = -ENOENT; 431 + return -EINVAL; 432 + } 433 + } 434 + 426 435 if (rr->first) { 427 - resctrl_arch_reset_rmid(rr->r, rr->d, closid, rmid, rr->evtid); 436 + if (rr->is_mbm_cntr) 437 + resctrl_arch_reset_cntr(rr->r, rr->d, closid, rmid, cntr_id, rr->evtid); 438 + else 439 + resctrl_arch_reset_rmid(rr->r, rr->d, closid, rmid, rr->evtid); 428 440 m = get_mbm_state(rr->d, closid, rmid, rr->evtid); 429 441 if (m) 430 442 memset(m, 0, sizeof(struct mbm_state)); ··· 447 435 /* Reading a single domain, must be on a CPU in that domain. */ 448 436 if (!cpumask_test_cpu(cpu, &rr->d->hdr.cpu_mask)) 449 437 return -EINVAL; 450 - rr->err = resctrl_arch_rmid_read(rr->r, rr->d, closid, rmid, 451 - rr->evtid, &tval, rr->arch_mon_ctx); 438 + if (rr->is_mbm_cntr) 439 + rr->err = resctrl_arch_cntr_read(rr->r, rr->d, closid, rmid, cntr_id, 440 + rr->evtid, &tval); 441 + else 442 + rr->err = resctrl_arch_rmid_read(rr->r, rr->d, closid, rmid, 443 + rr->evtid, &tval, rr->arch_mon_ctx); 452 444 if (rr->err) 453 445 return rr->err; 454 446 ··· 476 460 list_for_each_entry(d, &rr->r->mon_domains, hdr.list) { 477 461 if (d->ci_id != rr->ci->id) 478 462 continue; 479 - err = resctrl_arch_rmid_read(rr->r, d, closid, rmid, 480 - rr->evtid, &tval, rr->arch_mon_ctx); 463 + if (rr->is_mbm_cntr) 464 + err = resctrl_arch_cntr_read(rr->r, d, closid, rmid, cntr_id, 465 + rr->evtid, &tval); 466 + else 467 + err = resctrl_arch_rmid_read(rr->r, d, closid, rmid, 468 + rr->evtid, &tval, rr->arch_mon_ctx); 481 469 if (!err) { 482 470 rr->val += tval; 483 471 ret = 0; ··· 688 668 rr.r = r; 689 669 rr.d = d; 690 670 rr.evtid = evtid; 691 - rr.arch_mon_ctx = resctrl_arch_mon_ctx_alloc(rr.r, rr.evtid); 692 - if (IS_ERR(rr.arch_mon_ctx)) { 693 - pr_warn_ratelimited("Failed to allocate monitor context: %ld", 694 - PTR_ERR(rr.arch_mon_ctx)); 695 - return; 671 + if (resctrl_arch_mbm_cntr_assign_enabled(r)) { 672 + rr.is_mbm_cntr = true; 673 + } else { 674 + rr.arch_mon_ctx = resctrl_arch_mon_ctx_alloc(rr.r, rr.evtid); 675 + if (IS_ERR(rr.arch_mon_ctx)) { 676 + pr_warn_ratelimited("Failed to allocate monitor context: %ld", 677 + PTR_ERR(rr.arch_mon_ctx)); 678 + return; 679 + } 696 680 } 697 681 698 682 __mon_event_count(rdtgrp, &rr); ··· 708 684 if (is_mba_sc(NULL)) 709 685 mbm_bw_count(rdtgrp, &rr); 710 686 711 - resctrl_arch_mon_ctx_free(rr.r, rr.evtid, rr.arch_mon_ctx); 687 + if (rr.arch_mon_ctx) 688 + resctrl_arch_mon_ctx_free(rr.r, rr.evtid, rr.arch_mon_ctx); 712 689 } 713 690 714 691 static void mbm_update(struct rdt_resource *r, struct rdt_mon_domain *d,