Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ba0f26d8 authored by Vikas Shivappa's avatar Vikas Shivappa Committed by Thomas Gleixner
Browse files

x86/intel_rdt/mba_sc: Prepare for feedback loop



This is a preparatory patch for the mba feedback loop. Add support to
measure the "bandwidth in MBps" and the "delta bandwidth". Measure it by
reading the MBM IA32_QM_CTR MSRs and calculating the amount of "bytes"
moved. There is no user space interface for this and will only be used by
the feedback loop patch.

Signed-off-by: default avatarVikas Shivappa <vikas.shivappa@linux.intel.com>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Cc: ravi.v.shankar@intel.com
Cc: tony.luck@intel.com
Cc: fenghua.yu@intel.com
Cc: vikas.shivappa@intel.com
Cc: ak@linux.intel.com
Cc: hpa@zytor.com
Link: https://lkml.kernel.org/r/1524263781-14267-6-git-send-email-vikas.shivappa@linux.intel.com
parent 8205a078
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -180,10 +180,20 @@ struct rftype {
 * struct mbm_state - status for each MBM counter in each domain
 * @chunks:	Total data moved (multiply by rdt_group.mon_scale to get bytes)
 * @prev_msr	Value of IA32_QM_CTR for this RMID last time we read it
 * @chunks_bw	Total local data moved. Used for bandwidth calculation
 * @prev_bw_msr:Value of previous IA32_QM_CTR for bandwidth counting
 * @prev_bw	The most recent bandwidth in MBps
 * @delta_bw	Difference between the current and previous bandwidth
 * @delta_comp	Indicates whether to compute the delta_bw
 */
struct mbm_state {
	u64	chunks;
	u64	prev_msr;
	u64	chunks_bw;
	u64	prev_bw_msr;
	u32	prev_bw;
	u32	delta_bw;
	bool	delta_comp;
};

/**
+38 −6
Original line number Diff line number Diff line
@@ -225,10 +225,18 @@ void free_rmid(u32 rmid)
		list_add_tail(&entry->list, &rmid_free_lru);
}

static u64 mbm_overflow_count(u64 prev_msr, u64 cur_msr)
{
	u64 shift = 64 - MBM_CNTR_WIDTH, chunks;

	chunks = (cur_msr << shift) - (prev_msr << shift);
	return chunks >>= shift;
}

static int __mon_event_count(u32 rmid, struct rmid_read *rr)
{
	u64 chunks, shift, tval;
	struct mbm_state *m;
	u64 chunks, tval;

	tval = __rmid_read(rmid, rr->evtid);
	if (tval & (RMID_VAL_ERROR | RMID_VAL_UNAVAIL)) {
@@ -254,14 +262,12 @@ static int __mon_event_count(u32 rmid, struct rmid_read *rr)
	}

	if (rr->first) {
		m->prev_msr = tval;
		m->chunks = 0;
		memset(m, 0, sizeof(struct mbm_state));
		m->prev_bw_msr = m->prev_msr = tval;
		return 0;
	}

	shift = 64 - MBM_CNTR_WIDTH;
	chunks = (tval << shift) - (m->prev_msr << shift);
	chunks >>= shift;
	chunks = mbm_overflow_count(m->prev_msr, tval);
	m->chunks += chunks;
	m->prev_msr = tval;

@@ -269,6 +275,32 @@ static int __mon_event_count(u32 rmid, struct rmid_read *rr)
	return 0;
}

/*
 * Supporting function to calculate the memory bandwidth
 * and delta bandwidth in MBps.
 */
static void mbm_bw_count(u32 rmid, struct rmid_read *rr)
{
	struct rdt_resource *r = &rdt_resources_all[RDT_RESOURCE_L3];
	struct mbm_state *m = &rr->d->mbm_local[rmid];
	u64 tval, cur_bw, chunks;

	tval = __rmid_read(rmid, rr->evtid);
	if (tval & (RMID_VAL_ERROR | RMID_VAL_UNAVAIL))
		return;

	chunks = mbm_overflow_count(m->prev_bw_msr, tval);
	m->chunks_bw += chunks;
	m->chunks = m->chunks_bw;
	cur_bw = (chunks * r->mon_scale) >> 20;

	if (m->delta_comp)
		m->delta_bw = abs(cur_bw - m->prev_bw);
	m->delta_comp = false;
	m->prev_bw = cur_bw;
	m->prev_bw_msr = tval;
}

/*
 * This is called via IPI to read the CQM/MBM counters
 * on a domain.