Commit 4ddbd45e 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 1087e901
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -1582,6 +1582,19 @@ config NUMA_AWARE_SPINLOCKS

	  Say N if you want absolute first come first serve fairness.

config ARCH_CUSTOM_NUMA_DISTANCE
	bool "Support custom node relaim distance"
	depends on 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.

source "kernel/Kconfig.hz"

config ARCH_SPARSEMEM_ENABLE
+85 −0
Original line number Diff line number Diff line
@@ -189,6 +189,89 @@ void __init setup_per_cpu_areas(void)
}
#endif

#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 -EINVAL;

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

	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_LINXICORE9100:
		get_numa_distance_info(&numa_levels, &max_distance);

		/*
		 * When numa_level more than three, sched domain may be
		 * asymmetrical, the number of CPUs of sched group is different
		 * from the brother in sched domain.
		 */
		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

/**
 * numa_add_memblk() - Set node id to memblk
 * @nid: NUMA node ID of the new memblk
@@ -401,6 +484,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();