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

x86/resctrl: Add interface to read mbm_total_bytes_config

The event configuration can be viewed by the user by reading the
configuration file /sys/fs/resctrl/info/L3_MON/mbm_total_bytes_config. The
event configuration settings are domain specific and will affect all the CPUs in
the domain.

Following are the types of events supported:

==== ===========================================================
Bits Description
==== ===========================================================
6 Dirty Victims from the QOS domain to all types of memory
5 Reads to slow memory in the non-local NUMA domain
4 Reads to slow memory in the local NUMA domain
3 Non-temporal writes to non-local NUMA domain
2 Non-temporal writes to local NUMA domain
1 Reads to memory in the non-local NUMA domain
0 Reads to memory in the local NUMA domain
==== ===========================================================

By default, the mbm_total_bytes_config is set to 0x7f to count all the
event types.

For example:

$cat /sys/fs/resctrl/info/L3_MON/mbm_total_bytes_config
0=0x7f;1=0x7f;2=0x7f;3=0x7f

In this case, the event mbm_total_bytes is configured with 0x7f on
domains 0 to 3.

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/r/20230113152039.770054-10-babu.moger@amd.com

authored by

Babu Moger and committed by
Borislav Petkov (AMD)
dc2a3e85 d507f83c

+130 -1
+1
arch/x86/include/asm/msr-index.h
··· 1062 1062 /* - AMD: */ 1063 1063 #define MSR_IA32_MBA_BW_BASE 0xc0000200 1064 1064 #define MSR_IA32_SMBA_BW_BASE 0xc0000280 1065 + #define MSR_IA32_EVT_CFG_BASE 0xc0000400 1065 1066 1066 1067 /* MSR_IA32_VMX_MISC bits */ 1067 1068 #define MSR_IA32_VMX_MISC_INTEL_PT (1ULL << 14)
+24
arch/x86/kernel/cpu/resctrl/internal.h
··· 30 30 */ 31 31 #define MBM_CNTR_WIDTH_OFFSET_MAX (62 - MBM_CNTR_WIDTH_BASE) 32 32 33 + /* Reads to Local DRAM Memory */ 34 + #define READS_TO_LOCAL_MEM BIT(0) 35 + 36 + /* Reads to Remote DRAM Memory */ 37 + #define READS_TO_REMOTE_MEM BIT(1) 38 + 39 + /* Non-Temporal Writes to Local Memory */ 40 + #define NON_TEMP_WRITE_TO_LOCAL_MEM BIT(2) 41 + 42 + /* Non-Temporal Writes to Remote Memory */ 43 + #define NON_TEMP_WRITE_TO_REMOTE_MEM BIT(3) 44 + 45 + /* Reads to Local Memory the system identifies as "Slow Memory" */ 46 + #define READS_TO_LOCAL_S_MEM BIT(4) 47 + 48 + /* Reads to Remote Memory the system identifies as "Slow Memory" */ 49 + #define READS_TO_REMOTE_S_MEM BIT(5) 50 + 51 + /* Dirty Victims to All Types of Memory */ 52 + #define DIRTY_VICTIMS_TO_ALL_MEM BIT(6) 53 + 54 + /* Max event bits supported */ 55 + #define MAX_EVT_CONFIG_BITS GENMASK(6, 0) 33 56 34 57 struct rdt_fs_context { 35 58 struct kernfs_fs_context kfc; ··· 554 531 void __check_limbo(struct rdt_domain *d, bool force_free); 555 532 void rdt_domain_reconfigure_cdp(struct rdt_resource *r); 556 533 void __init thread_throttle_mode_init(void); 534 + void __init mbm_config_rftype_init(const char *config); 557 535 558 536 #endif /* _ASM_X86_RESCTRL_INTERNAL_H */
+3 -1
arch/x86/kernel/cpu/resctrl/monitor.c
··· 801 801 return ret; 802 802 803 803 if (rdt_cpu_has(X86_FEATURE_BMEC)) { 804 - if (rdt_cpu_has(X86_FEATURE_CQM_MBM_TOTAL)) 804 + if (rdt_cpu_has(X86_FEATURE_CQM_MBM_TOTAL)) { 805 805 mbm_total_event.configurable = true; 806 + mbm_config_rftype_init("mbm_total_bytes_config"); 807 + } 806 808 if (rdt_cpu_has(X86_FEATURE_CQM_MBM_LOCAL)) 807 809 mbm_local_event.configurable = true; 808 810 }
+102
arch/x86/kernel/cpu/resctrl/rdtgroup.c
··· 1420 1420 return ret; 1421 1421 } 1422 1422 1423 + struct mon_config_info { 1424 + u32 evtid; 1425 + u32 mon_config; 1426 + }; 1427 + 1428 + #define INVALID_CONFIG_INDEX UINT_MAX 1429 + 1430 + /** 1431 + * mon_event_config_index_get - get the hardware index for the 1432 + * configurable event 1433 + * @evtid: event id. 1434 + * 1435 + * Return: 0 for evtid == QOS_L3_MBM_TOTAL_EVENT_ID 1436 + * 1 for evtid == QOS_L3_MBM_LOCAL_EVENT_ID 1437 + * INVALID_CONFIG_INDEX for invalid evtid 1438 + */ 1439 + static inline unsigned int mon_event_config_index_get(u32 evtid) 1440 + { 1441 + switch (evtid) { 1442 + case QOS_L3_MBM_TOTAL_EVENT_ID: 1443 + return 0; 1444 + case QOS_L3_MBM_LOCAL_EVENT_ID: 1445 + return 1; 1446 + default: 1447 + /* Should never reach here */ 1448 + return INVALID_CONFIG_INDEX; 1449 + } 1450 + } 1451 + 1452 + static void mon_event_config_read(void *info) 1453 + { 1454 + struct mon_config_info *mon_info = info; 1455 + unsigned int index; 1456 + u32 h; 1457 + 1458 + index = mon_event_config_index_get(mon_info->evtid); 1459 + if (index == INVALID_CONFIG_INDEX) { 1460 + pr_warn_once("Invalid event id %d\n", mon_info->evtid); 1461 + return; 1462 + } 1463 + rdmsr(MSR_IA32_EVT_CFG_BASE + index, mon_info->mon_config, h); 1464 + 1465 + /* Report only the valid event configuration bits */ 1466 + mon_info->mon_config &= MAX_EVT_CONFIG_BITS; 1467 + } 1468 + 1469 + static void mondata_config_read(struct rdt_domain *d, struct mon_config_info *mon_info) 1470 + { 1471 + smp_call_function_any(&d->cpu_mask, mon_event_config_read, mon_info, 1); 1472 + } 1473 + 1474 + static int mbm_config_show(struct seq_file *s, struct rdt_resource *r, u32 evtid) 1475 + { 1476 + struct mon_config_info mon_info = {0}; 1477 + struct rdt_domain *dom; 1478 + bool sep = false; 1479 + 1480 + mutex_lock(&rdtgroup_mutex); 1481 + 1482 + list_for_each_entry(dom, &r->domains, list) { 1483 + if (sep) 1484 + seq_puts(s, ";"); 1485 + 1486 + memset(&mon_info, 0, sizeof(struct mon_config_info)); 1487 + mon_info.evtid = evtid; 1488 + mondata_config_read(dom, &mon_info); 1489 + 1490 + seq_printf(s, "%d=0x%02x", dom->id, mon_info.mon_config); 1491 + sep = true; 1492 + } 1493 + seq_puts(s, "\n"); 1494 + 1495 + mutex_unlock(&rdtgroup_mutex); 1496 + 1497 + return 0; 1498 + } 1499 + 1500 + static int mbm_total_bytes_config_show(struct kernfs_open_file *of, 1501 + struct seq_file *seq, void *v) 1502 + { 1503 + struct rdt_resource *r = of->kn->parent->priv; 1504 + 1505 + mbm_config_show(seq, r, QOS_L3_MBM_TOTAL_EVENT_ID); 1506 + 1507 + return 0; 1508 + } 1509 + 1423 1510 /* rdtgroup information files for one cache resource. */ 1424 1511 static struct rftype res_common_files[] = { 1425 1512 { ··· 1604 1517 .write = max_threshold_occ_write, 1605 1518 .seq_show = max_threshold_occ_show, 1606 1519 .fflags = RF_MON_INFO | RFTYPE_RES_CACHE, 1520 + }, 1521 + { 1522 + .name = "mbm_total_bytes_config", 1523 + .mode = 0444, 1524 + .kf_ops = &rdtgroup_kf_single_ops, 1525 + .seq_show = mbm_total_bytes_config_show, 1607 1526 }, 1608 1527 { 1609 1528 .name = "cpus", ··· 1715 1622 return; 1716 1623 1717 1624 rft->fflags = RF_CTRL_INFO | RFTYPE_RES_MB; 1625 + } 1626 + 1627 + void __init mbm_config_rftype_init(const char *config) 1628 + { 1629 + struct rftype *rft; 1630 + 1631 + rft = rdtgroup_get_rftype_by_name(config); 1632 + if (rft) 1633 + rft->fflags = RF_MON_INFO | RFTYPE_RES_CACHE; 1718 1634 } 1719 1635 1720 1636 /**