diff options
Diffstat (limited to 'arch/x86/kernel/cpu/resctrl/monitor.c')
| -rw-r--r-- | arch/x86/kernel/cpu/resctrl/monitor.c | 79 | 
1 files changed, 62 insertions, 17 deletions
diff --git a/arch/x86/kernel/cpu/resctrl/monitor.c b/arch/x86/kernel/cpu/resctrl/monitor.c index efe0c30d3a12..7fe51488e136 100644 --- a/arch/x86/kernel/cpu/resctrl/monitor.c +++ b/arch/x86/kernel/cpu/resctrl/monitor.c @@ -146,6 +146,30 @@ static inline struct rmid_entry *__rmid_entry(u32 rmid)  	return entry;  } +static int __rmid_read(u32 rmid, enum resctrl_event_id eventid, u64 *val) +{ +	u64 msr_val; + +	/* +	 * As per the SDM, when IA32_QM_EVTSEL.EvtID (bits 7:0) is configured +	 * with a valid event code for supported resource type and the bits +	 * IA32_QM_EVTSEL.RMID (bits 41:32) are configured with valid RMID, +	 * IA32_QM_CTR.data (bits 61:0) reports the monitored data. +	 * IA32_QM_CTR.Error (bit 63) and IA32_QM_CTR.Unavailable (bit 62) +	 * are error bits. +	 */ +	wrmsr(MSR_IA32_QM_EVTSEL, eventid, rmid); +	rdmsrl(MSR_IA32_QM_CTR, msr_val); + +	if (msr_val & RMID_VAL_ERROR) +		return -EIO; +	if (msr_val & RMID_VAL_UNAVAIL) +		return -EINVAL; + +	*val = msr_val; +	return 0; +} +  static struct arch_mbm_state *get_arch_mbm_state(struct rdt_hw_domain *hw_dom,  						 u32 rmid,  						 enum resctrl_event_id eventid) @@ -172,8 +196,29 @@ void resctrl_arch_reset_rmid(struct rdt_resource *r, struct rdt_domain *d,  	struct arch_mbm_state *am;  	am = get_arch_mbm_state(hw_dom, rmid, eventid); -	if (am) +	if (am) {  		memset(am, 0, sizeof(*am)); + +		/* Record any initial, non-zero count value. */ +		__rmid_read(rmid, eventid, &am->prev_msr); +	} +} + +/* + * Assumes that hardware counters are also reset and thus that there is + * no need to record initial non-zero counts. + */ +void resctrl_arch_reset_rmid_all(struct rdt_resource *r, struct rdt_domain *d) +{ +	struct rdt_hw_domain *hw_dom = resctrl_to_arch_dom(d); + +	if (is_mbm_total_enabled()) +		memset(hw_dom->arch_mbm_total, 0, +		       sizeof(*hw_dom->arch_mbm_total) * r->num_rmid); + +	if (is_mbm_local_enabled()) +		memset(hw_dom->arch_mbm_local, 0, +		       sizeof(*hw_dom->arch_mbm_local) * r->num_rmid);  }  static u64 mbm_overflow_count(u64 prev_msr, u64 cur_msr, unsigned int width) @@ -191,25 +236,14 @@ int resctrl_arch_rmid_read(struct rdt_resource *r, struct rdt_domain *d,  	struct rdt_hw_domain *hw_dom = resctrl_to_arch_dom(d);  	struct arch_mbm_state *am;  	u64 msr_val, chunks; +	int ret;  	if (!cpumask_test_cpu(smp_processor_id(), &d->cpu_mask))  		return -EINVAL; -	/* -	 * As per the SDM, when IA32_QM_EVTSEL.EvtID (bits 7:0) is configured -	 * with a valid event code for supported resource type and the bits -	 * IA32_QM_EVTSEL.RMID (bits 41:32) are configured with valid RMID, -	 * IA32_QM_CTR.data (bits 61:0) reports the monitored data. -	 * IA32_QM_CTR.Error (bit 63) and IA32_QM_CTR.Unavailable (bit 62) -	 * are error bits. -	 */ -	wrmsr(MSR_IA32_QM_EVTSEL, eventid, rmid); -	rdmsrl(MSR_IA32_QM_CTR, msr_val); - -	if (msr_val & RMID_VAL_ERROR) -		return -EIO; -	if (msr_val & RMID_VAL_UNAVAIL) -		return -EINVAL; +	ret = __rmid_read(rmid, eventid, &msr_val); +	if (ret) +		return ret;  	am = get_arch_mbm_state(hw_dom, rmid, eventid);  	if (am) { @@ -746,7 +780,7 @@ static void l3_mon_evt_init(struct rdt_resource *r)  		list_add_tail(&mbm_local_event.list, &r->evt_list);  } -int rdt_get_mon_l3_config(struct rdt_resource *r) +int __init rdt_get_mon_l3_config(struct rdt_resource *r)  {  	unsigned int mbm_offset = boot_cpu_data.x86_cache_mbm_width_offset;  	struct rdt_hw_resource *hw_res = resctrl_to_arch_res(r); @@ -783,6 +817,17 @@ int rdt_get_mon_l3_config(struct rdt_resource *r)  	if (ret)  		return ret; +	if (rdt_cpu_has(X86_FEATURE_BMEC)) { +		if (rdt_cpu_has(X86_FEATURE_CQM_MBM_TOTAL)) { +			mbm_total_event.configurable = true; +			mbm_config_rftype_init("mbm_total_bytes_config"); +		} +		if (rdt_cpu_has(X86_FEATURE_CQM_MBM_LOCAL)) { +			mbm_local_event.configurable = true; +			mbm_config_rftype_init("mbm_local_bytes_config"); +		} +	} +  	l3_mon_evt_init(r);  	r->mon_capable = true;  |