Commit 9d672495 authored by Zeng Heng's avatar Zeng Heng
Browse files

fs/resctrl: Adapt to the hardware topology structures of RDT and MPAM

hulk inclusion
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I8T2RT



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

When attempting to enable the MPAM memory bandwidth monitoring feature, we
found that MPAM differs from x86 RDT in hardware topology implementation.
To maintain compatibility with the interface of version, a small amount of
public code needs to be split.

According to the x86 SDM, both total memory bandwidth and local memory
bandwidth are classified as part of L3 cache monitoring:
~~~
  mon_data
  ├── mon_L3_00
  │   ├── llc_occupancy
  │   ├── mbm_local_bytes
  │   └── mbm_total_bytes
  └── mon_L3_01
      ├── llc_occupancy
      ├── mbm_local_bytes
      └── mbm_total_bytes
~~~

In contrast, for ARM64 MPAM, L3/memory monitoring is implemented using
separate L3/MATA resources:
~~~
  mon_data
  ├── mon_L3_01
  │   ├── llc_occupancy
  │   └── mbm_local_bytes
  ├── mon_L3_195
  │   ├── llc_occupancy
  │   └── mbm_local_bytes
  ├── mon_MB_00
  │   └── mbm_total_bytes
  └── mon_MB_01
      └── mbm_total_bytes
~~~

The public code file fs/resctrl/monitor.c has added a reference to
resctrl_arch_mon_resource_init() and removed l3_mon_evt_init(). Both x86
RDT and ARM64 MPAM implement their own versions of
resctrl_arch_mon_resource_init() and l3_mon_evt_init(), with the x86 part
retaining its original logic unchanged.

Fixes: 13e249bf ("x86/resctrl: Move the filesystem portions of resctrl to live in '/fs/'")
Signed-off-by: default avatarZeng Heng <zengheng4@huawei.com>
parent 97a32f07
Loading
Loading
Loading
Loading
+52 −0
Original line number Diff line number Diff line
@@ -267,3 +267,55 @@ void __init intel_rdt_mbm_apply_quirk(void)
	mbm_cf_rmidthreshold = mbm_cf_table[cf_index].rmidthreshold;
	mbm_cf = mbm_cf_table[cf_index].cf;
}

static struct mon_evt llc_occupancy_event = {
	.name		= "llc_occupancy",
	.evtid		= QOS_L3_OCCUP_EVENT_ID,
};

static struct mon_evt mbm_total_event = {
	.name		= "mbm_total_bytes",
	.evtid		= QOS_L3_MBM_TOTAL_EVENT_ID,
};

static struct mon_evt mbm_local_event = {
	.name		= "mbm_local_bytes",
	.evtid		= QOS_L3_MBM_LOCAL_EVENT_ID,
};

/*
 * Initialize the event list for the resource.
 *
 * Note that MBM events are also part of RDT_RESOURCE_L3 resource
 * because as per the SDM the total and local memory bandwidth
 * are enumerated as part of L3 monitoring.
 */
static void l3_mon_evt_init(struct rdt_resource *r)
{
	INIT_LIST_HEAD(&r->evt_list);

	if (resctrl_arch_is_llc_occupancy_enabled())
		list_add_tail(&llc_occupancy_event.list, &r->evt_list);
	if (resctrl_arch_is_mbm_total_enabled())
		list_add_tail(&mbm_total_event.list, &r->evt_list);
	if (resctrl_arch_is_mbm_local_enabled())
		list_add_tail(&mbm_local_event.list, &r->evt_list);
}

int resctrl_arch_mon_resource_init(void)
{
	struct rdt_resource *r = resctrl_arch_get_resource(RDT_RESOURCE_L3);

	l3_mon_evt_init(r);

	if (resctrl_arch_is_evt_configurable(QOS_L3_MBM_TOTAL_EVENT_ID)) {
		mbm_total_event.configurable = true;
		mbm_config_rftype_init("mbm_total_bytes_config");
	}
	if (resctrl_arch_is_evt_configurable(QOS_L3_MBM_LOCAL_EVENT_ID)) {
		mbm_local_event.configurable = true;
		mbm_config_rftype_init("mbm_local_bytes_config");
	}

	return 0;
}
+59 −0
Original line number Diff line number Diff line
@@ -1199,6 +1199,65 @@ int mpam_resctrl_offline_cpu(unsigned int cpu)
	return 0;
}

static struct mon_evt llc_occupancy_event = {
	.name		= "llc_occupancy",
	.evtid		= QOS_L3_OCCUP_EVENT_ID,
};

static struct mon_evt mbm_total_event = {
	.name		= "mbm_total_bytes",
	.evtid		= QOS_L3_MBM_TOTAL_EVENT_ID,
};

static struct mon_evt mbm_local_event = {
	.name		= "mbm_local_bytes",
	.evtid		= QOS_L3_MBM_LOCAL_EVENT_ID,
};

/*
 * Initialize the event list for the resource.
 *
 * Note that MBM events are also part of RDT_RESOURCE_L3 resource
 * because as per the SDM the total and local memory bandwidth
 * are enumerated as part of L3 monitoring.
 */
static void l3_mon_evt_init(struct rdt_resource *r)
{
	INIT_LIST_HEAD(&r->evt_list);

	if (!r->mon_capable)
		return;

	if (r->rid == RDT_RESOURCE_L3) {
		if (resctrl_arch_is_llc_occupancy_enabled())
			list_add_tail(&llc_occupancy_event.list, &r->evt_list);

		if (resctrl_arch_is_mbm_local_enabled())
			list_add_tail(&mbm_local_event.list, &r->evt_list);
	}

	if ((r->rid == RDT_RESOURCE_MBA) &&
	     resctrl_arch_is_mbm_total_enabled())
		list_add_tail(&mbm_total_event.list, &r->evt_list);
}

int resctrl_arch_mon_resource_init(void)
{
	l3_mon_evt_init(resctrl_arch_get_resource(RDT_RESOURCE_L3));
	l3_mon_evt_init(resctrl_arch_get_resource(RDT_RESOURCE_MBA));

	if (resctrl_arch_is_evt_configurable(QOS_L3_MBM_TOTAL_EVENT_ID)) {
		mbm_total_event.configurable = true;
		mbm_config_rftype_init("mbm_total_bytes_config");
	}
	if (resctrl_arch_is_evt_configurable(QOS_L3_MBM_LOCAL_EVENT_ID)) {
		mbm_local_event.configurable = true;
		mbm_config_rftype_init("mbm_local_bytes_config");
	}

	return 0;
}

static int __init __cacheinfo_ready(void)
{
	cacheinfo_ready = true;
+0 −15
Original line number Diff line number Diff line
@@ -66,20 +66,6 @@ static inline struct rdt_fs_context *rdt_fc2context(struct fs_context *fc)
	return container_of(kfc, struct rdt_fs_context, kfc);
}

/**
 * struct mon_evt - Entry in the event list of a resource
 * @evtid:		event id
 * @name:		name of the event
 * @configurable:	true if the event is configurable
 * @list:		entry in &rdt_resource->evt_list
 */
struct mon_evt {
	enum resctrl_event_id	evtid;
	char			*name;
	bool			configurable;
	struct list_head	list;
};

/**
 * union mon_data_bits - Monitoring details for each event file
 * @priv:              Used to store monitoring event data in @u
@@ -306,7 +292,6 @@ void cqm_setup_limbo_handler(struct rdt_domain *dom, unsigned long delay_ms,
void cqm_handle_limbo(struct work_struct *work);
bool has_busy_rmid(struct rdt_domain *d);
void __check_limbo(struct rdt_domain *d, bool force_free);
void mbm_config_rftype_init(const char *config);
void rdt_staged_configs_clear(void);
int resctrl_find_cleanest_closid(void);

+1 −46
Original line number Diff line number Diff line
@@ -791,40 +791,6 @@ static void dom_data_exit(struct rdt_resource *r)
	mutex_unlock(&rdtgroup_mutex);
}

static struct mon_evt llc_occupancy_event = {
	.name		= "llc_occupancy",
	.evtid		= QOS_L3_OCCUP_EVENT_ID,
};

static struct mon_evt mbm_total_event = {
	.name		= "mbm_total_bytes",
	.evtid		= QOS_L3_MBM_TOTAL_EVENT_ID,
};

static struct mon_evt mbm_local_event = {
	.name		= "mbm_local_bytes",
	.evtid		= QOS_L3_MBM_LOCAL_EVENT_ID,
};

/*
 * Initialize the event list for the resource.
 *
 * Note that MBM events are also part of RDT_RESOURCE_L3 resource
 * because as per the SDM the total and local memory bandwidth
 * are enumerated as part of L3 monitoring.
 */
static void l3_mon_evt_init(struct rdt_resource *r)
{
	INIT_LIST_HEAD(&r->evt_list);

	if (resctrl_arch_is_llc_occupancy_enabled())
		list_add_tail(&llc_occupancy_event.list, &r->evt_list);
	if (resctrl_arch_is_mbm_total_enabled())
		list_add_tail(&mbm_total_event.list, &r->evt_list);
	if (resctrl_arch_is_mbm_local_enabled())
		list_add_tail(&mbm_local_event.list, &r->evt_list);
}

int resctrl_mon_resource_init(void)
{
	struct rdt_resource *r = resctrl_arch_get_resource(RDT_RESOURCE_L3);
@@ -837,18 +803,7 @@ int resctrl_mon_resource_init(void)
	if (ret)
		return ret;

	l3_mon_evt_init(r);

	if (resctrl_arch_is_evt_configurable(QOS_L3_MBM_TOTAL_EVENT_ID)) {
		mbm_total_event.configurable = true;
		mbm_config_rftype_init("mbm_total_bytes_config");
	}
	if (resctrl_arch_is_evt_configurable(QOS_L3_MBM_LOCAL_EVENT_ID)) {
		mbm_local_event.configurable = true;
		mbm_config_rftype_init("mbm_local_bytes_config");
	}

	return 0;
	return resctrl_arch_mon_resource_init();
}

void resctrl_mon_resource_exit(void)
+17 −0
Original line number Diff line number Diff line
@@ -254,6 +254,20 @@ struct resctrl_mon_config_info {
	int                  err;
};

/**
 * struct mon_evt - Entry in the event list of a resource
 * @evtid:		event id
 * @name:		name of the event
 * @configurable:	true if the event is configurable
 * @list:		entry in &rdt_resource->evt_list
 */
struct mon_evt {
	enum resctrl_event_id	evtid;
	char			*name;
	bool			configurable;
	struct list_head	list;
};

/*
 * Update and re-load this CPUs defaults. Called via IPI, takes a pointer to
 * struct resctrl_cpu_sync, or NULL.
@@ -405,4 +419,7 @@ extern unsigned int resctrl_rmid_realloc_limit;
int resctrl_init(void);
void resctrl_exit(void);

int resctrl_arch_mon_resource_init(void);
void mbm_config_rftype_init(const char *config);

#endif /* _RESCTRL_H */