Commit 932fcc5e authored by Hui Tang's avatar Hui Tang
Browse files

arm64/numa: Support node_reclaim_distance adjust for arch

hulk inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I8PG0C


CVE: NA

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

'node_reclaim_distance' affects scheduling behavior and memory reclamation,
but the value is currently the default value and can not be set.

Now introduce the way to adjust 'node_reclaim_distance' depending on
the cpu model.

Signed-off-by: default avatarHui Tang <tanghui20@huawei.com>
parent 567ef11f
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -2115,6 +2115,19 @@ config STACKPROTECTOR_PER_TASK
	def_bool y
	depends on STACKPROTECTOR && CC_HAVE_STACKPROTECTOR_SYSREG

config ARCH_CUSTOM_NUMA_DISTANCE
	bool "Support custom node relaim distance"
	depends on ARM64 && ARCH_HISI && NUMA
	default n
	help
	  Allow arch to adjust node_reclaim_distance.

	  Some machines may have a specific node distance to achieve optimal
	  system performance. You can set a specific node_reclaim_distance based
	  on the system topology.

	  If unsure, say N.

menuconfig ASCEND_FEATURES
	bool "Support Ascend Features"
	depends on ARM64
+79 −0
Original line number Diff line number Diff line
@@ -554,6 +554,83 @@ static int __init numa_register_nodes(void)
	return 0;
}

#ifdef CONFIG_ARCH_CUSTOM_NUMA_DISTANCE
#define DISTANCE_MAX		(1 << DISTANCE_BITS)
static void get_numa_distance_info(int *numa_levels, int *max_distance)
{
	DECLARE_BITMAP(distance_map, DISTANCE_MAX);
	int max = 0;
	int i, j;

	bitmap_zero(distance_map, DISTANCE_MAX);
	for (i = 0; i < nr_node_ids; i++) {
		for (j = 0; j < nr_node_ids; j++) {
			int distance = node_distance(i, j);

			if (distance < LOCAL_DISTANCE ||
			    distance >= DISTANCE_MAX) {
				return;
			}

			if (distance > max)
				max = distance;

			bitmap_set(distance_map, distance, 1);
		}
	}

	if (numa_levels)
		*numa_levels = bitmap_weight(distance_map, DISTANCE_MAX);

	if (max_distance)
		*max_distance = max;
}

static int __init node_reclaim_distance_setup(char *str)
{
	int val;

	if (kstrtoint(str, 0, &val))
		return 0;

	if (val < LOCAL_DISTANCE || val >= DISTANCE_MAX)
		return 0;

	if (val != RECLAIM_DISTANCE) {
		node_reclaim_distance = val;
		pr_info("Force set node_reclaim_distance to %d\n", val);
	}

	return 0;
}
early_param("node_reclaim_distance", node_reclaim_distance_setup);

static void __init node_reclaim_distance_adjust(void)
{
	unsigned int model = read_cpuid_id() & MIDR_CPU_MODEL_MASK;
	int max_distance = 0;
	int numa_levels = 0;

	switch (model) {
	case MIDR_HISI_TSV200:
		get_numa_distance_info(&numa_levels, &max_distance);
		if (nr_node_ids != 4 || numa_levels <= 3 ||
		    node_reclaim_distance != RECLAIM_DISTANCE ||
		    max_distance <= RECLAIM_DISTANCE)
			break;

		node_reclaim_distance = max_distance;
		pr_info("Force adjust node_reclaim_distance to %d\n",
			node_reclaim_distance);
		break;
	default:
		break;
	}
}
#else
static inline void __init node_reclaim_distance_adjust(void) {}
#endif

static int __init numa_init(int (*init_func)(void))
{
	int ret;
@@ -582,6 +659,8 @@ static int __init numa_init(int (*init_func)(void))

	setup_node_to_cpumask_map();

	node_reclaim_distance_adjust();

	return 0;
out_free_distance:
	numa_free_distance();