Commit 5186ba33 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'x86_cache_for_v6.10_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 resource control updates from Borislav Petkov:

 - Add a tracepoint to read out LLC occupancy of resource monitor IDs
   with the goal of freeing them sooner rather than later

 - Other code improvements and cleanups

* tag 'x86_cache_for_v6.10_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86/resctrl: Add tracepoint for llc_occupancy tracking
  x86/resctrl: Rename pseudo_lock_event.h to trace.h
  x86/resctrl: Simplify call convention for MSR update functions
  x86/resctrl: Pass domain to target CPU
parents 25c7cb05 931be446
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -446,6 +446,12 @@ during mkdir.
max_threshold_occupancy is a user configurable value to determine the
occupancy at which an RMID can be freed.

The mon_llc_occupancy_limbo tracepoint gives the precise occupancy in bytes
for a subset of RMID that are not immediately available for allocation.
This can't be relied on to produce output every second, it may be necessary
to attempt to create an empty monitor group to force an update. Output may
only be produced if creation of a control or monitor group fails.

Schemata files - general concepts
---------------------------------
Each line in the file describes one resource. The line starts with
+21 −34
Original line number Diff line number Diff line
@@ -56,14 +56,9 @@ int max_name_width, max_data_width;
 */
bool rdt_alloc_capable;

static void
mba_wrmsr_intel(struct rdt_domain *d, struct msr_param *m,
		struct rdt_resource *r);
static void
cat_wrmsr(struct rdt_domain *d, struct msr_param *m, struct rdt_resource *r);
static void
mba_wrmsr_amd(struct rdt_domain *d, struct msr_param *m,
	      struct rdt_resource *r);
static void mba_wrmsr_intel(struct msr_param *m);
static void cat_wrmsr(struct msr_param *m);
static void mba_wrmsr_amd(struct msr_param *m);

#define domain_init(id) LIST_HEAD_INIT(rdt_resources_all[id].r_resctrl.domains)

@@ -309,12 +304,11 @@ static void rdt_get_cdp_l2_config(void)
	rdt_get_cdp_config(RDT_RESOURCE_L2);
}

static void
mba_wrmsr_amd(struct rdt_domain *d, struct msr_param *m, struct rdt_resource *r)
static void mba_wrmsr_amd(struct msr_param *m)
{
	struct rdt_hw_resource *hw_res = resctrl_to_arch_res(m->res);
	struct rdt_hw_domain *hw_dom = resctrl_to_arch_dom(m->dom);
	unsigned int i;
	struct rdt_hw_domain *hw_dom = resctrl_to_arch_dom(d);
	struct rdt_hw_resource *hw_res = resctrl_to_arch_res(r);

	for (i = m->low; i < m->high; i++)
		wrmsrl(hw_res->msr_base + i, hw_dom->ctrl_val[i]);
@@ -334,25 +328,22 @@ static u32 delay_bw_map(unsigned long bw, struct rdt_resource *r)
	return r->default_ctrl;
}

static void
mba_wrmsr_intel(struct rdt_domain *d, struct msr_param *m,
		struct rdt_resource *r)
static void mba_wrmsr_intel(struct msr_param *m)
{
	struct rdt_hw_resource *hw_res = resctrl_to_arch_res(m->res);
	struct rdt_hw_domain *hw_dom = resctrl_to_arch_dom(m->dom);
	unsigned int i;
	struct rdt_hw_domain *hw_dom = resctrl_to_arch_dom(d);
	struct rdt_hw_resource *hw_res = resctrl_to_arch_res(r);

	/*  Write the delay values for mba. */
	for (i = m->low; i < m->high; i++)
		wrmsrl(hw_res->msr_base + i, delay_bw_map(hw_dom->ctrl_val[i], r));
		wrmsrl(hw_res->msr_base + i, delay_bw_map(hw_dom->ctrl_val[i], m->res));
}

static void
cat_wrmsr(struct rdt_domain *d, struct msr_param *m, struct rdt_resource *r)
static void cat_wrmsr(struct msr_param *m)
{
	struct rdt_hw_resource *hw_res = resctrl_to_arch_res(m->res);
	struct rdt_hw_domain *hw_dom = resctrl_to_arch_dom(m->dom);
	unsigned int i;
	struct rdt_hw_domain *hw_dom = resctrl_to_arch_dom(d);
	struct rdt_hw_resource *hw_res = resctrl_to_arch_res(r);

	for (i = m->low; i < m->high; i++)
		wrmsrl(hw_res->msr_base + i, hw_dom->ctrl_val[i]);
@@ -362,6 +353,8 @@ struct rdt_domain *get_domain_from_cpu(int cpu, struct rdt_resource *r)
{
	struct rdt_domain *d;

	lockdep_assert_cpus_held();

	list_for_each_entry(d, &r->domains, list) {
		/* Find the domain that contains this CPU */
		if (cpumask_test_cpu(cpu, &d->cpu_mask))
@@ -378,19 +371,11 @@ u32 resctrl_arch_get_num_closid(struct rdt_resource *r)

void rdt_ctrl_update(void *arg)
{
	struct rdt_hw_resource *hw_res;
	struct msr_param *m = arg;
	struct rdt_hw_resource *hw_res = resctrl_to_arch_res(m->res);
	struct rdt_resource *r = m->res;
	int cpu = smp_processor_id();
	struct rdt_domain *d;

	d = get_domain_from_cpu(cpu, r);
	if (d) {
		hw_res->msr_update(d, m, r);
		return;
	}
	pr_warn_once("cpu %d not found in any domain for resource %s\n",
		     cpu, r->name);
	hw_res = resctrl_to_arch_res(m->res);
	hw_res->msr_update(m);
}

/*
@@ -463,9 +448,11 @@ static int domain_setup_ctrlval(struct rdt_resource *r, struct rdt_domain *d)
	hw_dom->ctrl_val = dc;
	setup_default_ctrlval(r, dc);

	m.res = r;
	m.dom = d;
	m.low = 0;
	m.high = hw_res->num_closid;
	hw_res->msr_update(d, &m, r);
	hw_res->msr_update(&m);
	return 0;
}

+8 −32
Original line number Diff line number Diff line
@@ -272,22 +272,6 @@ static u32 get_config_index(u32 closid, enum resctrl_conf_type type)
	}
}

static bool apply_config(struct rdt_hw_domain *hw_dom,
			 struct resctrl_staged_config *cfg, u32 idx,
			 cpumask_var_t cpu_mask)
{
	struct rdt_domain *dom = &hw_dom->d_resctrl;

	if (cfg->new_ctrl != hw_dom->ctrl_val[idx]) {
		cpumask_set_cpu(cpumask_any(&dom->cpu_mask), cpu_mask);
		hw_dom->ctrl_val[idx] = cfg->new_ctrl;

		return true;
	}

	return false;
}

int resctrl_arch_update_one(struct rdt_resource *r, struct rdt_domain *d,
			    u32 closid, enum resctrl_conf_type t, u32 cfg_val)
{
@@ -302,9 +286,10 @@ int resctrl_arch_update_one(struct rdt_resource *r, struct rdt_domain *d,
	hw_dom->ctrl_val[idx] = cfg_val;

	msr_param.res = r;
	msr_param.dom = d;
	msr_param.low = idx;
	msr_param.high = idx + 1;
	hw_res->msr_update(d, &msr_param, r);
	hw_res->msr_update(&msr_param);

	return 0;
}
@@ -315,48 +300,39 @@ int resctrl_arch_update_domains(struct rdt_resource *r, u32 closid)
	struct rdt_hw_domain *hw_dom;
	struct msr_param msr_param;
	enum resctrl_conf_type t;
	cpumask_var_t cpu_mask;
	struct rdt_domain *d;
	u32 idx;

	/* Walking r->domains, ensure it can't race with cpuhp */
	lockdep_assert_cpus_held();

	if (!zalloc_cpumask_var(&cpu_mask, GFP_KERNEL))
		return -ENOMEM;

	msr_param.res = NULL;
	list_for_each_entry(d, &r->domains, list) {
		hw_dom = resctrl_to_arch_dom(d);
		msr_param.res = NULL;
		for (t = 0; t < CDP_NUM_TYPES; t++) {
			cfg = &hw_dom->d_resctrl.staged_config[t];
			if (!cfg->have_new_ctrl)
				continue;

			idx = get_config_index(closid, t);
			if (!apply_config(hw_dom, cfg, idx, cpu_mask))
			if (cfg->new_ctrl == hw_dom->ctrl_val[idx])
				continue;
			hw_dom->ctrl_val[idx] = cfg->new_ctrl;

			if (!msr_param.res) {
				msr_param.low = idx;
				msr_param.high = msr_param.low + 1;
				msr_param.res = r;
				msr_param.dom = d;
			} else {
				msr_param.low = min(msr_param.low, idx);
				msr_param.high = max(msr_param.high, idx + 1);
			}
		}
		if (msr_param.res)
			smp_call_function_any(&d->cpu_mask, rdt_ctrl_update, &msr_param, 1);
	}

	if (cpumask_empty(cpu_mask))
		goto done;

	/* Update resource control msr on all the CPUs. */
	on_each_cpu_mask(cpu_mask, rdt_ctrl_update, &msr_param, 1);

done:
	free_cpumask_var(cpu_mask);

	return 0;
}

+3 −2
Original line number Diff line number Diff line
@@ -379,11 +379,13 @@ static inline struct rdt_hw_domain *resctrl_to_arch_dom(struct rdt_domain *r)
/**
 * struct msr_param - set a range of MSRs from a domain
 * @res:       The resource to use
 * @dom:       The domain to update
 * @low:       Beginning index from base MSR
 * @high:      End index
 */
struct msr_param {
	struct rdt_resource	*res;
	struct rdt_domain	*dom;
	u32			low;
	u32			high;
};
@@ -443,8 +445,7 @@ struct rdt_hw_resource {
	struct rdt_resource	r_resctrl;
	u32			num_closid;
	unsigned int		msr_base;
	void (*msr_update)	(struct rdt_domain *d, struct msr_param *m,
				 struct rdt_resource *r);
	void			(*msr_update)(struct msr_param *m);
	unsigned int		mon_scale;
	unsigned int		mbm_width;
	unsigned int		mbm_cfg_mask;
+11 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@
#include <asm/resctrl.h>

#include "internal.h"
#include "trace.h"

/**
 * struct rmid_entry - dirty tracking for all RMID.
@@ -354,6 +355,16 @@ void __check_limbo(struct rdt_domain *d, bool force_free)
			rmid_dirty = true;
		} else {
			rmid_dirty = (val >= resctrl_rmid_realloc_threshold);

			/*
			 * x86's CLOSID and RMID are independent numbers, so the entry's
			 * CLOSID is an empty CLOSID (X86_RESCTRL_EMPTY_CLOSID). On Arm the
			 * RMID (PMG) extends the CLOSID (PARTID) space with bits that aren't
			 * used to select the configuration. It is thus necessary to track both
			 * CLOSID and RMID because there may be dependencies between them
			 * on some architectures.
			 */
			trace_mon_llc_occupancy_limbo(entry->closid, entry->rmid, d->id, val);
		}

		if (force_free || !rmid_dirty) {
Loading