Commit d43a6c0c authored by Wang ShaoBo's avatar Wang ShaoBo Committed by Zheng Zengkai
Browse files

MPAM / ACPI: Refactoring MPAM init process and set MPAM ACPI as entrance

hulk inclusion
category: feature
feature: ARM MPAM support
bugzilla: 48265
CVE: NA

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

Renaming mpam_late_init() in arch/arm64/kernel/mpam.c to mpam_init(),
traveling each MPAM ACPI cache / memory node and adding them to a list,
with that, we use the numa node id it belongs to label cache node and
proximity_domain to label memory node, once it ends, call mpam_init()
to initialize all like before.

Code was partially borrowed from James's:
http://www.linux-arm.org/git?p=linux-jm.git;a=commit;h=10fe7d6363ae96b


25f584d4a91f9d0f2fd5faf3b,"ACPI / MPAM: Parse the (draft) MPAM table
[dead]"

v3->v5: mpam.c in drivers/acpi/arm64 should not be compiled when MPAM
disabled, so we should add CONFIG_ACPI_MPAM macro and make CONFIG_MPAM
select it. Not only that, as mpam init procedure is strong correlated to
ACPI for Now (follow-up might be dependent on device tree), and CONFIG_
ACPI is not always selected under configuration, we should make CONFIG_
MPAM depends on CONFIG_ACPI before selecting CONFIG_ACPI_MPAM.

Signed-off-by: default avatarWang ShaoBo <bobo.shaobowang@huawei.com>
Reviewed-by: default avatarXie XiuQi <xiexiuqi@huawei.com>
Signed-off-by: default avatarYang Yingliang <yangyingliang@huawei.com>
Reviewed-by: default avatarCheng Jian <cj.chengjian@huawei.com>
Signed-off-by: default avatarZheng Zengkai <zhengzengkai@huawei.com>
parent 5c3d89e3
Loading
Loading
Loading
Loading
+2 −0
Original line number Original line Diff line number Diff line
@@ -993,7 +993,9 @@ config HOTPLUG_CPU
config MPAM
config MPAM
	bool "Support Memory Partitioning and Monitoring"
	bool "Support Memory Partitioning and Monitoring"
	default n
	default n
	depends on ACPI
	select RESCTRL
	select RESCTRL
	select ACPI_MPAM if ACPI
	help
	help
	  Memory Partitioning and Monitoring. More exactly Memory system
	  Memory Partitioning and Monitoring. More exactly Memory system
	  performance resource Partitioning and Monitoring
	  performance resource Partitioning and Monitoring
+14 −1
Original line number Original line Diff line number Diff line
@@ -95,6 +95,8 @@
 */
 */


struct mpam_node {
struct mpam_node {
	/* for label mpam_node instance*/
	u32 component_id;
	/* MPAM node header */
	/* MPAM node header */
	u8              type;   /* MPAM_SMMU, MPAM_CACHE, MPAM_MC */
	u8              type;   /* MPAM_SMMU, MPAM_CACHE, MPAM_MC */
	u64             addr;
	u64             addr;
@@ -105,8 +107,19 @@ struct mpam_node {
	/* for debug */
	/* for debug */
	char            *cpus_list;
	char            *cpus_list;
	char		*name;
	char		*name;
	struct list_head list;
};
};


int mpam_nodes_init(void);
int __init mpam_force_init(void);

int __init mpam_nodes_discovery_start(void);

void __init mpam_nodes_discovery_failed(void);

int __init mpam_nodes_discovery_complete(void);

int mpam_create_cache_node(u32 component_id, phys_addr_t hwpage_address);

int mpam_create_memory_node(u32 component_id, phys_addr_t hwpage_address);


#endif /* _ASM_ARM64_MPAM_RESOURCE_H */
#endif /* _ASM_ARM64_MPAM_RESOURCE_H */
+7 −1
Original line number Original line Diff line number Diff line
@@ -40,7 +40,13 @@ static inline void mpam_sched_in(void)
		__mpam_sched_in();
		__mpam_sched_in();
}
}


extern int __read_mostly mpam_enabled;
enum mpam_enable_type {
	enable_denied = 0,
	enable_default,
	enable_acpi,
};

extern enum mpam_enable_type __read_mostly mpam_enabled;


#else
#else


+192 −54
Original line number Original line Diff line number Diff line
@@ -62,12 +62,6 @@ int max_name_width, max_data_width;
 */
 */
bool rdt_alloc_capable;
bool rdt_alloc_capable;


char *mpam_types_str[] = {
	"MPAM_RESOURCE_SMMU",
	"MPAM_RESOURCE_CACHE",
	"MPAM_RESOURCE_MC",
};

/*
/*
 * Hi1620 2P Base Address Map
 * Hi1620 2P Base Address Map
 *
 *
@@ -81,35 +75,30 @@ char *mpam_types_str[] = {
 *   AFF2: MPIDR.AFF2
 *   AFF2: MPIDR.AFF2
 */
 */


#define MPAM_BASE(suffix, offset) ((suffix) << 24 | (offset) << 16)
static inline void mpam_node_assign_val(struct mpam_node *n,
#define MPAM_NODE(n, t, suffix, offset)			\
				char *name,
	{						\
				u8 type,
		.name	= #n,				\
				phys_addr_t hwpage_address,
		.type	= t,				\
				u32 component_id)
		.addr	= MPAM_BASE(suffix, (offset)),	\
{
		.cpus_list = "0",			\
	n->name = name;
	}
	n->type = type;

	n->addr = hwpage_address;
struct mpam_node mpam_node_all[] = {
	n->component_id = component_id;
	MPAM_NODE(L3TALL0, MPAM_RESOURCE_CACHE, 0x000098ULL, 0xB9),
	n->cpus_list = "0";
	MPAM_NODE(L3TALL1, MPAM_RESOURCE_CACHE, 0x000090ULL, 0xB9),
}
	MPAM_NODE(L3TALL2, MPAM_RESOURCE_CACHE, 0x200098ULL, 0xB9),

	MPAM_NODE(L3TALL3, MPAM_RESOURCE_CACHE, 0x200090ULL, 0xB9),
#define MPAM_NODE_NAME_SIZE (10)


	MPAM_NODE(HHAALL0, MPAM_RESOURCE_MC, 0x000098ULL, 0xC1),
struct mpam_node *mpam_nodes_ptr;
	MPAM_NODE(HHAALL1, MPAM_RESOURCE_MC, 0x000090ULL, 0xC1),
	MPAM_NODE(HHAALL2, MPAM_RESOURCE_MC, 0x200098ULL, 0xC1),
	MPAM_NODE(HHAALL3, MPAM_RESOURCE_MC, 0x200090ULL, 0xC1),
};


void mpam_nodes_unmap(void)
static int __init mpam_init(void);

static void mpam_nodes_unmap(void)
{
{
	int i;
	size_t num_nodes = ARRAY_SIZE(mpam_node_all);
	struct mpam_node *n;
	struct mpam_node *n;


	for (i = 0; i < num_nodes; i++) {
	list_for_each_entry(n, &mpam_nodes_ptr->list, list) {
		n = &mpam_node_all[i];
		if (n->base) {
		if (n->base) {
			iounmap(n->base);
			iounmap(n->base);
			n->base = NULL;
			n->base = NULL;
@@ -117,14 +106,12 @@ void mpam_nodes_unmap(void)
	}
	}
}
}


int mpam_nodes_init(void)
static int mpam_nodes_init(void)
{
{
	int i, ret = 0;
	int ret = 0;
	size_t num_nodes = ARRAY_SIZE(mpam_node_all);
	struct mpam_node *n;
	struct mpam_node *n;


	for (i = 0; i < num_nodes; i++) {
	list_for_each_entry(n, &mpam_nodes_ptr->list, list) {
		n = &mpam_node_all[i];
		ret |= cpulist_parse(n->cpus_list, &n->cpu_mask);
		ret |= cpulist_parse(n->cpus_list, &n->cpu_mask);
		n->base = ioremap(n->addr, 0x10000);
		n->base = ioremap(n->addr, 0x10000);
		if (!n->base) {
		if (!n->base) {
@@ -136,6 +123,160 @@ int mpam_nodes_init(void)
	return ret;
	return ret;
}
}


static void mpam_nodes_destroy(void)
{
	struct mpam_node *n, *tmp;

	if (!mpam_nodes_ptr)
		return;

	list_for_each_entry_safe(n, tmp, &mpam_nodes_ptr->list, list) {
		kfree(n->name);
		list_del(&n->list);
		kfree(n);
	}

	list_del(&mpam_nodes_ptr->list);
	kfree(mpam_nodes_ptr);
	mpam_nodes_ptr = NULL;
}

int __init mpam_nodes_discovery_start(void)
{
	if (!mpam_enabled)
		return -EINVAL;

	mpam_nodes_ptr = kzalloc(sizeof(struct mpam_node), GFP_KERNEL);
	if (!mpam_nodes_ptr)
		return -ENOMEM;

	INIT_LIST_HEAD(&mpam_nodes_ptr->list);

	return 0;
}

void __init mpam_nodes_discovery_failed(void)
{
	mpam_nodes_destroy();
}

int __init mpam_nodes_discovery_complete(void)
{
	return mpam_init();
}

static inline int validate_mpam_node(int type,
				int component_id)
{
	int ret = 0;
	struct mpam_node *n;

	list_for_each_entry(n, &mpam_nodes_ptr->list, list) {
		if (n->component_id == component_id &&
				n->type == type) {
			ret = -EINVAL;
			break;
		}
	}

	return ret;
}

int mpam_create_cache_node(u32 component_id,
			phys_addr_t hwpage_address)
{
	struct mpam_node *new;
	char *name;

	if (validate_mpam_node(MPAM_RESOURCE_CACHE, component_id))
		goto skip;

	new = kzalloc(sizeof(struct mpam_node), GFP_KERNEL);
	if (!new)
		return -ENOMEM;

	name = kzalloc(MPAM_NODE_NAME_SIZE, GFP_KERNEL);
	if (!name) {
		kfree(new);
		return -ENOMEM;
	}
	snprintf(name, MPAM_NODE_NAME_SIZE, "%s%d", "L3TALL", component_id);

	mpam_node_assign_val(new,
			name,
			MPAM_RESOURCE_CACHE,
			hwpage_address,
			component_id);
	list_add_tail(&new->list, &mpam_nodes_ptr->list);

skip:
	return 0;
}

int mpam_create_memory_node(u32 component_id,
			phys_addr_t hwpage_address)
{
	struct mpam_node *new;
	char *name;

	if (validate_mpam_node(MPAM_RESOURCE_MC, component_id))
		goto skip;

	new = kzalloc(sizeof(struct mpam_node), GFP_KERNEL);
	if (!new)
		return -ENOMEM;

	name = kzalloc(MPAM_NODE_NAME_SIZE, GFP_KERNEL);
	if (!name) {
		kfree(new);
		return -ENOMEM;
	}
	snprintf(name, MPAM_NODE_NAME_SIZE, "%s%d", "HHAALL", component_id);

	mpam_node_assign_val(new,
			name,
			MPAM_RESOURCE_MC,
			hwpage_address,
			component_id);
	list_add_tail(&new->list, &mpam_nodes_ptr->list);

skip:
	return 0;

}

int __init mpam_force_init(void)
{
	int ret;

	if (mpam_enabled != enable_default)
		return 0;

	ret = mpam_nodes_discovery_start();
	if (ret)
		return ret;

	ret |= mpam_create_cache_node(0, 0x000098b90000ULL);
	ret |= mpam_create_cache_node(1, 0x000090b90000ULL);
	ret |= mpam_create_cache_node(2, 0x200098b90000ULL);
	ret |= mpam_create_cache_node(3, 0x200090b90000ULL);
	ret |= mpam_create_memory_node(0, 0x000098c10000ULL);
	ret |= mpam_create_memory_node(1, 0x000090c10000ULL);
	ret |= mpam_create_memory_node(2, 0x200098c10000ULL);
	ret |= mpam_create_memory_node(3, 0x200090c10000ULL);
	if (ret) {
		mpam_nodes_discovery_failed();
		pr_err("Failed to force create mpam node\n");
		return -EINVAL;
	}

	ret = mpam_nodes_discovery_complete();
	if (!ret)
		pr_info("Successfully init mpam by hardcode.\n");

	return 1;
}

static void
static void
cat_wrmsr(struct rdt_domain *d, int partid);
cat_wrmsr(struct rdt_domain *d, int partid);
static void
static void
@@ -1137,16 +1278,14 @@ static void mpam_domains_destroy(struct resctrl_resource *r)


static void mpam_domains_init(struct resctrl_resource *r)
static void mpam_domains_init(struct resctrl_resource *r)
{
{
	int i, id = 0;
	int id = 0;
	size_t num_nodes = ARRAY_SIZE(mpam_node_all);
	struct mpam_node *n;
	struct mpam_node *n;
	struct list_head *add_pos = NULL;
	struct list_head *add_pos = NULL;
	struct rdt_domain *d;
	struct rdt_domain *d;
	struct raw_resctrl_resource *rr = (struct raw_resctrl_resource *)r->res;
	struct raw_resctrl_resource *rr = (struct raw_resctrl_resource *)r->res;
	u32 val;
	u32 val;


	for (i = 0; i < num_nodes; i++) {
	list_for_each_entry(n, &mpam_nodes_ptr->list, list) {
		n = &mpam_node_all[i];
		if (r->rid != n->type)
		if (r->rid != n->type)
			continue;
			continue;


@@ -1215,25 +1354,22 @@ static void mpam_domains_init(struct resctrl_resource *r)
	}
	}
}
}


int __read_mostly mpam_enabled;
enum mpam_enable_type __read_mostly mpam_enabled;
static int __init mpam_setup(char *str)
static int __init mpam_setup(char *str)
{
{
	mpam_enabled = 1;
	if (!strcmp(str, "=acpi"))
		mpam_enabled = enable_acpi;
	else
		mpam_enabled = enable_default;
	return 1;
	return 1;
}
}
__setup("mpam", mpam_setup);
__setup("mpam", mpam_setup);


static int __init mpam_late_init(void)
static int __init mpam_init(void)
{
{
	struct resctrl_resource *r;
	struct resctrl_resource *r;
	int state, ret;
	int state, ret;


	if (!mpam_enabled)
		return 0;

	if (!cpus_have_const_cap(ARM64_HAS_MPAM))
		return -ENODEV;

	rdt_alloc_capable = 1;
	rdt_alloc_capable = 1;
	rdt_mon_capable = 1;
	rdt_mon_capable = 1;


@@ -1242,7 +1378,7 @@ static int __init mpam_late_init(void)
	ret = mpam_nodes_init();
	ret = mpam_nodes_init();
	if (ret) {
	if (ret) {
		pr_err("internal error: bad cpu list\n");
		pr_err("internal error: bad cpu list\n");
		return ret;
		goto out;
	}
	}


	mpam_domains_init(&resctrl_resources_all[MPAM_RESOURCE_CACHE]);
	mpam_domains_init(&resctrl_resources_all[MPAM_RESOURCE_CACHE]);
@@ -1251,8 +1387,10 @@ static int __init mpam_late_init(void)
	state = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN,
	state = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN,
				  "arm64/mpam:online:",
				  "arm64/mpam:online:",
				  mpam_online_cpu, mpam_offline_cpu);
				  mpam_online_cpu, mpam_offline_cpu);
	if (state < 0)
	if (state < 0) {
		return state;
		ret = state;
		goto out;
	}


	register_resctrl_specific_files(res_specific_files, ARRAY_SIZE(res_specific_files));
	register_resctrl_specific_files(res_specific_files, ARRAY_SIZE(res_specific_files));


@@ -1262,7 +1400,7 @@ static int __init mpam_late_init(void)
	ret = resctrl_group_init();
	ret = resctrl_group_init();
	if (ret) {
	if (ret) {
		cpuhp_remove_state(state);
		cpuhp_remove_state(state);
		return ret;
		goto out;
	}
	}


	for_each_resctrl_resource(r) {
	for_each_resctrl_resource(r) {
@@ -1275,11 +1413,11 @@ static int __init mpam_late_init(void)
			pr_info("MPAM %s monitoring detected\n", r->name);
			pr_info("MPAM %s monitoring detected\n", r->name);
	}
	}


	return 0;
out:
	mpam_nodes_destroy();
	return ret;
}
}


late_initcall(mpam_late_init);

/*
/*
 * __intel_rdt_sched_in() - Writes the task's CLOSid/RMID to IA32_PQR_MSR
 * __intel_rdt_sched_in() - Writes the task's CLOSid/RMID to IA32_PQR_MSR
 *
 *
+3 −0
Original line number Original line Diff line number Diff line
@@ -8,3 +8,6 @@ config ACPI_IORT


config ACPI_GTDT
config ACPI_GTDT
	bool
	bool

config ACPI_MPAM
	bool
Loading