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

Configure Feed

Select the types of activity you want to include in your feed.

x86,fs/resctrl: Use struct rdt_domain_hdr when reading counters

Convert the whole call sequence from mon_event_read() to resctrl_arch_rmid_read() to
pass resource independent struct rdt_domain_hdr instead of an L3 specific domain
structure to prepare for monitoring events in other resources.

This additional layer of indirection obscures which aspects of event counting depend
on a valid domain. Event initialization, support for assignable counters, and normal
event counting implicitly depend on a valid domain while summing of domains does not.
Split summing domains from the core event counting handling to make their respective
dependencies obvious.

Signed-off-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
Reviewed-by: Reinette Chatre <reinette.chatre@intel.com>
Link: https://lore.kernel.org/20251217172121.12030-1-tony.luck@intel.com

authored by

Tony Luck and committed by
Borislav Petkov (AMD)
6b10cf7b ad5c2ff7

+78 -50
+9 -3
arch/x86/kernel/cpu/resctrl/monitor.c
··· 238 238 return chunks * hw_res->mon_scale; 239 239 } 240 240 241 - int resctrl_arch_rmid_read(struct rdt_resource *r, struct rdt_mon_domain *d, 241 + int resctrl_arch_rmid_read(struct rdt_resource *r, struct rdt_domain_hdr *hdr, 242 242 u32 unused, u32 rmid, enum resctrl_event_id eventid, 243 243 u64 *val, void *ignored) 244 244 { 245 - struct rdt_hw_mon_domain *hw_dom = resctrl_to_arch_mon_dom(d); 246 - int cpu = cpumask_any(&d->hdr.cpu_mask); 245 + struct rdt_hw_mon_domain *hw_dom; 247 246 struct arch_mbm_state *am; 247 + struct rdt_mon_domain *d; 248 248 u64 msr_val; 249 249 u32 prmid; 250 + int cpu; 250 251 int ret; 251 252 252 253 resctrl_arch_rmid_read_context_check(); 254 + if (!domain_header_is_valid(hdr, RESCTRL_MON_DOMAIN, RDT_RESOURCE_L3)) 255 + return -EINVAL; 253 256 257 + d = container_of(hdr, struct rdt_mon_domain, hdr); 258 + hw_dom = resctrl_to_arch_mon_dom(d); 259 + cpu = cpumask_any(&hdr->cpu_mask); 254 260 prmid = logical_rmid_to_physical_rmid(cpu, rmid); 255 261 ret = __rmid_read_phys(prmid, eventid, &msr_val); 256 262
+1 -8
fs/resctrl/ctrlmondata.c
··· 554 554 struct rdt_domain_hdr *hdr, struct rdtgroup *rdtgrp, 555 555 cpumask_t *cpumask, int evtid, int first) 556 556 { 557 - struct rdt_mon_domain *d = NULL; 558 557 int cpu; 559 558 560 559 /* When picking a CPU from cpu_mask, ensure it can't race with cpuhp */ 561 560 lockdep_assert_cpus_held(); 562 - 563 - if (hdr) { 564 - if (!domain_header_is_valid(hdr, RESCTRL_MON_DOMAIN, RDT_RESOURCE_L3)) 565 - return; 566 - d = container_of(hdr, struct rdt_mon_domain, hdr); 567 - } 568 561 569 562 /* 570 563 * Setup the parameters to pass to mon_event_count() to read the data. ··· 565 572 rr->rgrp = rdtgrp; 566 573 rr->evtid = evtid; 567 574 rr->r = r; 568 - rr->d = d; 575 + rr->hdr = hdr; 569 576 rr->first = first; 570 577 if (resctrl_arch_mbm_cntr_assign_enabled(r) && 571 578 resctrl_is_mbm_event(evtid)) {
+10 -8
fs/resctrl/internal.h
··· 106 106 * resource group then its event count is summed with the count from all 107 107 * its child resource groups. 108 108 * @r: Resource describing the properties of the event being read. 109 - * @d: Domain that the counter should be read from. If NULL then sum all 110 - * domains in @r sharing L3 @ci.id 109 + * @hdr: Header of domain that the counter should be read from. If NULL then 110 + * sum all domains in @r sharing L3 @ci.id 111 111 * @evtid: Which monitor event to read. 112 112 * @first: Initialize MBM counter when true. 113 - * @ci: Cacheinfo for L3. Only set when @d is NULL. Used when summing domains. 113 + * @ci: Cacheinfo for L3. Only set when @hdr is NULL. Used when summing 114 + * domains. 114 115 * @is_mbm_cntr: true if "mbm_event" counter assignment mode is enabled and it 115 116 * is an MBM event. 116 117 * @err: Error encountered when reading counter. 117 - * @val: Returned value of event counter. If @rgrp is a parent resource group, 118 - * @val includes the sum of event counts from its child resource groups. 119 - * If @d is NULL, @val includes the sum of all domains in @r sharing @ci.id, 120 - * (summed across child resource groups if @rgrp is a parent resource group). 118 + * @val: Returned value of event counter. If @rgrp is a parent resource 119 + * group, @val includes the sum of event counts from its child 120 + * resource groups. If @hdr is NULL, @val includes the sum of all 121 + * domains in @r sharing @ci.id, (summed across child resource groups 122 + * if @rgrp is a parent resource group). 121 123 * @arch_mon_ctx: Hardware monitor allocated for this read request (MPAM only). 122 124 */ 123 125 struct rmid_read { 124 126 struct rdtgroup *rgrp; 125 127 struct rdt_resource *r; 126 - struct rdt_mon_domain *d; 128 + struct rdt_domain_hdr *hdr; 127 129 enum resctrl_event_id evtid; 128 130 bool first; 129 131 struct cacheinfo *ci;
+56 -29
fs/resctrl/monitor.c
··· 159 159 break; 160 160 161 161 entry = __rmid_entry(idx); 162 - if (resctrl_arch_rmid_read(r, d, entry->closid, entry->rmid, 162 + if (resctrl_arch_rmid_read(r, &d->hdr, entry->closid, entry->rmid, 163 163 QOS_L3_OCCUP_EVENT_ID, &val, 164 164 arch_mon_ctx)) { 165 165 rmid_dirty = true; ··· 421 421 struct rdt_mon_domain *d; 422 422 int cntr_id = -ENOENT; 423 423 struct mbm_state *m; 424 - int err, ret; 425 424 u64 tval = 0; 426 425 426 + if (!domain_header_is_valid(rr->hdr, RESCTRL_MON_DOMAIN, RDT_RESOURCE_L3)) { 427 + rr->err = -EIO; 428 + return -EINVAL; 429 + } 430 + d = container_of(rr->hdr, struct rdt_mon_domain, hdr); 431 + 427 432 if (rr->is_mbm_cntr) { 428 - cntr_id = mbm_cntr_get(rr->r, rr->d, rdtgrp, rr->evtid); 433 + cntr_id = mbm_cntr_get(rr->r, d, rdtgrp, rr->evtid); 429 434 if (cntr_id < 0) { 430 435 rr->err = -ENOENT; 431 436 return -EINVAL; ··· 439 434 440 435 if (rr->first) { 441 436 if (rr->is_mbm_cntr) 442 - resctrl_arch_reset_cntr(rr->r, rr->d, closid, rmid, cntr_id, rr->evtid); 437 + resctrl_arch_reset_cntr(rr->r, d, closid, rmid, cntr_id, rr->evtid); 443 438 else 444 - resctrl_arch_reset_rmid(rr->r, rr->d, closid, rmid, rr->evtid); 445 - m = get_mbm_state(rr->d, closid, rmid, rr->evtid); 439 + resctrl_arch_reset_rmid(rr->r, d, closid, rmid, rr->evtid); 440 + m = get_mbm_state(d, closid, rmid, rr->evtid); 446 441 if (m) 447 442 memset(m, 0, sizeof(struct mbm_state)); 448 443 return 0; 449 444 } 450 445 451 - if (rr->d) { 452 - /* Reading a single domain, must be on a CPU in that domain. */ 453 - if (!cpumask_test_cpu(cpu, &rr->d->hdr.cpu_mask)) 454 - return -EINVAL; 455 - if (rr->is_mbm_cntr) 456 - rr->err = resctrl_arch_cntr_read(rr->r, rr->d, closid, rmid, cntr_id, 457 - rr->evtid, &tval); 458 - else 459 - rr->err = resctrl_arch_rmid_read(rr->r, rr->d, closid, rmid, 460 - rr->evtid, &tval, rr->arch_mon_ctx); 461 - if (rr->err) 462 - return rr->err; 446 + /* Reading a single domain, must be on a CPU in that domain. */ 447 + if (!cpumask_test_cpu(cpu, &d->hdr.cpu_mask)) 448 + return -EINVAL; 449 + if (rr->is_mbm_cntr) 450 + rr->err = resctrl_arch_cntr_read(rr->r, d, closid, rmid, cntr_id, 451 + rr->evtid, &tval); 452 + else 453 + rr->err = resctrl_arch_rmid_read(rr->r, rr->hdr, closid, rmid, 454 + rr->evtid, &tval, rr->arch_mon_ctx); 455 + if (rr->err) 456 + return rr->err; 463 457 464 - rr->val += tval; 458 + rr->val += tval; 465 459 466 - return 0; 460 + return 0; 461 + } 462 + 463 + static int __l3_mon_event_count_sum(struct rdtgroup *rdtgrp, struct rmid_read *rr) 464 + { 465 + int cpu = smp_processor_id(); 466 + u32 closid = rdtgrp->closid; 467 + u32 rmid = rdtgrp->mon.rmid; 468 + struct rdt_mon_domain *d; 469 + u64 tval = 0; 470 + int err, ret; 471 + 472 + /* 473 + * Summing across domains is only done for systems that implement 474 + * Sub-NUMA Cluster. There is no overlap with systems that support 475 + * assignable counters. 476 + */ 477 + if (rr->is_mbm_cntr) { 478 + pr_warn_once("Summing domains using assignable counters is not supported\n"); 479 + rr->err = -EINVAL; 480 + return -EINVAL; 467 481 } 468 482 469 483 /* Summing domains that share a cache, must be on a CPU for that cache. */ ··· 500 476 list_for_each_entry(d, &rr->r->mon_domains, hdr.list) { 501 477 if (d->ci_id != rr->ci->id) 502 478 continue; 503 - if (rr->is_mbm_cntr) 504 - err = resctrl_arch_cntr_read(rr->r, d, closid, rmid, cntr_id, 505 - rr->evtid, &tval); 506 - else 507 - err = resctrl_arch_rmid_read(rr->r, d, closid, rmid, 508 - rr->evtid, &tval, rr->arch_mon_ctx); 479 + err = resctrl_arch_rmid_read(rr->r, &d->hdr, closid, rmid, 480 + rr->evtid, &tval, rr->arch_mon_ctx); 509 481 if (!err) { 510 482 rr->val += tval; 511 483 ret = 0; ··· 518 498 { 519 499 switch (rr->r->rid) { 520 500 case RDT_RESOURCE_L3: 521 - return __l3_mon_event_count(rdtgrp, rr); 501 + if (rr->hdr) 502 + return __l3_mon_event_count(rdtgrp, rr); 503 + else 504 + return __l3_mon_event_count_sum(rdtgrp, rr); 522 505 default: 523 506 rr->err = -EINVAL; 524 507 return -EINVAL; ··· 545 522 u64 cur_bw, bytes, cur_bytes; 546 523 u32 closid = rdtgrp->closid; 547 524 u32 rmid = rdtgrp->mon.rmid; 525 + struct rdt_mon_domain *d; 548 526 struct mbm_state *m; 549 527 550 - m = get_mbm_state(rr->d, closid, rmid, rr->evtid); 528 + if (!domain_header_is_valid(rr->hdr, RESCTRL_MON_DOMAIN, RDT_RESOURCE_L3)) 529 + return; 530 + d = container_of(rr->hdr, struct rdt_mon_domain, hdr); 531 + m = get_mbm_state(d, closid, rmid, rr->evtid); 551 532 if (WARN_ON_ONCE(!m)) 552 533 return; 553 534 ··· 724 697 struct rmid_read rr = {0}; 725 698 726 699 rr.r = r; 727 - rr.d = d; 700 + rr.hdr = &d->hdr; 728 701 rr.evtid = evtid; 729 702 if (resctrl_arch_mbm_cntr_assign_enabled(r)) { 730 703 rr.is_mbm_cntr = true;
+2 -2
include/linux/resctrl.h
··· 517 517 * resctrl_arch_rmid_read() - Read the eventid counter corresponding to rmid 518 518 * for this resource and domain. 519 519 * @r: resource that the counter should be read from. 520 - * @d: domain that the counter should be read from. 520 + * @hdr: Header of domain that the counter should be read from. 521 521 * @closid: closid that matches the rmid. Depending on the architecture, the 522 522 * counter may match traffic of both @closid and @rmid, or @rmid 523 523 * only. ··· 538 538 * Return: 539 539 * 0 on success, or -EIO, -EINVAL etc on error. 540 540 */ 541 - int resctrl_arch_rmid_read(struct rdt_resource *r, struct rdt_mon_domain *d, 541 + int resctrl_arch_rmid_read(struct rdt_resource *r, struct rdt_domain_hdr *hdr, 542 542 u32 closid, u32 rmid, enum resctrl_event_id eventid, 543 543 u64 *val, void *arch_mon_ctx); 544 544