Commit 9854842c authored by Babu Moger's avatar Babu Moger Committed by Wenkuan Wang
Browse files

x86/resctrl: Read supported bandwidth sources from CPUID

mainline inclusion
from mainline-v6.9-rc1
commit 54e35eb8611cce5550d3d7689679b1a91c864f28
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I9U2JC


CVE: NA

--------------------------------

If the BMEC (Bandwidth Monitoring Event Configuration) feature is
supported, the bandwidth events can be configured. The maximum supported
bandwidth bitmask can be read from CPUID:

  CPUID_Fn80000020_ECX_x03 [Platform QoS Monitoring Bandwidth Event Configuration]
  Bits    Description
  31:7    Reserved
   6:0    Identifies the bandwidth sources that can be tracked.

While at it, move the mask checking to mon_config_write() before
iterating over all the domains. Also, print the valid bitmask when the
user tries to configure invalid event configuration value.

The CPUID details are documented in the Processor Programming Reference
(PPR) Vol 1.1 for AMD Family 19h Model 11h B1 - 55901 Rev 0.25 in the
Link tag.

Fixes: dc2a3e85 ("x86/resctrl: Add interface to read mbm_total_bytes_config")
Signed-off-by: default avatarBabu Moger <babu.moger@amd.com>
Signed-off-by: default avatarBorislav Petkov (AMD) <bp@alien8.de>
Reviewed-by: default avatarReinette Chatre <reinette.chatre@intel.com>
Link: https://bugzilla.kernel.org/show_bug.cgi?id=206537
Link: https://lore.kernel.org/r/669896fa512c7451319fa5ca2fdb6f7e015b5635.1705359148.git.babu.moger@amd.com


Signed-off-by: default avatarWenkuan Wang <Wenkuan.Wang@amd.com>
parent fc7fe795
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -403,6 +403,9 @@ struct rdt_parse_data {
 * @msr_update:		Function pointer to update QOS MSRs
 * @mon_scale:		cqm counter * mon_scale = occupancy in bytes
 * @mbm_width:		Monitor width, to detect and correct for overflow.
 * @mbm_cfg_mask:	Bandwidth sources that can be tracked when Bandwidth
 *			Monitoring Event Configuration (BMEC) is supported.

 *
 * Members of this structure are either private to the architecture
 * e.g. mbm_width, or accessed via helpers that provide abstraction. e.g.
@@ -416,6 +419,7 @@ struct rdt_hw_resource {
				 struct rdt_resource *r);
	unsigned int		mon_scale;
	unsigned int		mbm_width;
	unsigned int		mbm_cfg_mask;
};

static inline struct rdt_hw_resource *resctrl_to_arch_res(struct rdt_resource *r)
+6 −0
Original line number Diff line number Diff line
@@ -728,6 +728,12 @@ int __init rdt_get_mon_l3_config(struct rdt_resource *r)
		return ret;

	if (rdt_cpu_has(X86_FEATURE_BMEC)) {
		u32 eax, ebx, ecx, edx;

		/* Detect list of bandwidth sources that can be tracked */
		cpuid_count(0x80000020, 3, &eax, &ebx, &ecx, &edx);
		hw_res->mbm_cfg_mask = ecx & MAX_EVT_CONFIG_BITS;

		if (rdt_cpu_has(X86_FEATURE_CQM_MBM_TOTAL)) {
			mbm_total_event.configurable = true;
			mbm_config_rftype_init("mbm_total_bytes_config");
+8 −6
Original line number Diff line number Diff line
@@ -1587,12 +1587,6 @@ static void mbm_config_write_domain(struct rdt_resource *r,
{
	struct mon_config_info mon_info = {0};

	/* mon_config cannot be more than the supported set of events */
	if (val > MAX_EVT_CONFIG_BITS) {
		rdt_last_cmd_puts("Invalid event configuration\n");
		return -EINVAL;
	}

	/*
	 * Read the current config value first. If both are the same then
	 * no need to write it again.
@@ -1627,6 +1621,7 @@ static void mbm_config_write_domain(struct rdt_resource *r,

static int mon_config_write(struct rdt_resource *r, char *tok, u32 evtid)
{
	struct rdt_hw_resource *hw_res = resctrl_to_arch_res(r);
	char *dom_str = NULL, *id_str;
	unsigned long dom_id, val;
	struct rdt_domain *d;
@@ -1649,6 +1644,13 @@ static int mon_config_write(struct rdt_resource *r, char *tok, u32 evtid)
		return -EINVAL;
	}

	/* Value from user cannot be more than the supported set of events */
	if ((val & hw_res->mbm_cfg_mask) != val) {
		rdt_last_cmd_printf("Invalid event configuration: max valid mask is 0x%02x\n",
				    hw_res->mbm_cfg_mask);
		return -EINVAL;
	}

	list_for_each_entry(d, &r->domains, list) {
		if (d->id == dom_id) {
			mbm_config_write_domain(r, d, evtid, val);