From ace9429bb58fd418f0c81d4c2835699bddf6bde6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 11 Apr 2024 10:27:49 +0200 Subject: Adding upstream version 6.6.15. Signed-off-by: Daniel Baumann --- arch/mips/loongson64/numa.c | 208 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 208 insertions(+) create mode 100644 arch/mips/loongson64/numa.c (limited to 'arch/mips/loongson64/numa.c') diff --git a/arch/mips/loongson64/numa.c b/arch/mips/loongson64/numa.c new file mode 100644 index 0000000000..8f61e93c0c --- /dev/null +++ b/arch/mips/loongson64/numa.c @@ -0,0 +1,208 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2010 Loongson Inc. & Lemote Inc. & + * Institute of Computing Technology + * Author: Xiang Gao, gaoxiang@ict.ac.cn + * Huacai Chen, chenhc@lemote.com + * Xiaofu Meng, Shuangshuang Zhang + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +unsigned char __node_distances[MAX_NUMNODES][MAX_NUMNODES]; +EXPORT_SYMBOL(__node_distances); +struct pglist_data *__node_data[MAX_NUMNODES]; +EXPORT_SYMBOL(__node_data); + +cpumask_t __node_cpumask[MAX_NUMNODES]; +EXPORT_SYMBOL(__node_cpumask); + +static void cpu_node_probe(void) +{ + int i; + + nodes_clear(node_possible_map); + nodes_clear(node_online_map); + for (i = 0; i < loongson_sysconf.nr_nodes; i++) { + node_set_state(num_online_nodes(), N_POSSIBLE); + node_set_online(num_online_nodes()); + } + + pr_info("NUMA: Discovered %d cpus on %d nodes\n", + loongson_sysconf.nr_cpus, num_online_nodes()); +} + +static int __init compute_node_distance(int row, int col) +{ + int package_row = row * loongson_sysconf.cores_per_node / + loongson_sysconf.cores_per_package; + int package_col = col * loongson_sysconf.cores_per_node / + loongson_sysconf.cores_per_package; + + if (col == row) + return LOCAL_DISTANCE; + else if (package_row == package_col) + return 40; + else + return 100; +} + +static void __init init_topology_matrix(void) +{ + int row, col; + + for (row = 0; row < MAX_NUMNODES; row++) + for (col = 0; col < MAX_NUMNODES; col++) + __node_distances[row][col] = -1; + + for_each_online_node(row) { + for_each_online_node(col) { + __node_distances[row][col] = + compute_node_distance(row, col); + } + } +} + +static void __init node_mem_init(unsigned int node) +{ + struct pglist_data *nd; + unsigned long node_addrspace_offset; + unsigned long start_pfn, end_pfn; + unsigned long nd_pa; + int tnid; + const size_t nd_size = roundup(sizeof(pg_data_t), SMP_CACHE_BYTES); + + node_addrspace_offset = nid_to_addrbase(node); + pr_info("Node%d's addrspace_offset is 0x%lx\n", + node, node_addrspace_offset); + + get_pfn_range_for_nid(node, &start_pfn, &end_pfn); + pr_info("Node%d: start_pfn=0x%lx, end_pfn=0x%lx\n", + node, start_pfn, end_pfn); + + nd_pa = memblock_phys_alloc_try_nid(nd_size, SMP_CACHE_BYTES, node); + if (!nd_pa) + panic("Cannot allocate %zu bytes for node %d data\n", + nd_size, node); + nd = __va(nd_pa); + memset(nd, 0, sizeof(struct pglist_data)); + tnid = early_pfn_to_nid(nd_pa >> PAGE_SHIFT); + if (tnid != node) + pr_info("NODE_DATA(%d) on node %d\n", node, tnid); + __node_data[node] = nd; + NODE_DATA(node)->node_start_pfn = start_pfn; + NODE_DATA(node)->node_spanned_pages = end_pfn - start_pfn; + + if (node == 0) { + /* kernel start address */ + unsigned long kernel_start_pfn = PFN_DOWN(__pa_symbol(&_text)); + + /* kernel end address */ + unsigned long kernel_end_pfn = PFN_UP(__pa_symbol(&_end)); + + /* used by finalize_initrd() */ + max_low_pfn = end_pfn; + + /* Reserve the kernel text/data/bss */ + memblock_reserve(kernel_start_pfn << PAGE_SHIFT, + ((kernel_end_pfn - kernel_start_pfn) << PAGE_SHIFT)); + + /* Reserve 0xfe000000~0xffffffff for RS780E integrated GPU */ + if (node_end_pfn(0) >= (0xffffffff >> PAGE_SHIFT)) + memblock_reserve((node_addrspace_offset | 0xfe000000), + 32 << 20); + + /* Reserve pfn range 0~node[0]->node_start_pfn */ + memblock_reserve(0, PAGE_SIZE * start_pfn); + } +} + +static __init void prom_meminit(void) +{ + unsigned int node, cpu, active_cpu = 0; + + cpu_node_probe(); + init_topology_matrix(); + + for (node = 0; node < loongson_sysconf.nr_nodes; node++) { + if (node_online(node)) { + szmem(node); + node_mem_init(node); + cpumask_clear(&__node_cpumask[node]); + } + } + max_low_pfn = PHYS_PFN(memblock_end_of_DRAM()); + + for (cpu = 0; cpu < loongson_sysconf.nr_cpus; cpu++) { + node = cpu / loongson_sysconf.cores_per_node; + if (node >= num_online_nodes()) + node = 0; + + if (loongson_sysconf.reserved_cpus_mask & (1<