18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Author:  Xiang Gao <gaoxiang@loongson.cn>
48c2ecf20Sopenharmony_ci *          Huacai Chen <chenhuacai@loongson.cn>
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci * Copyright (C) 2020-2021 Loongson Technology Corporation Limited
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci#include <linux/init.h>
98c2ecf20Sopenharmony_ci#include <linux/kernel.h>
108c2ecf20Sopenharmony_ci#include <linux/mm.h>
118c2ecf20Sopenharmony_ci#include <linux/mmzone.h>
128c2ecf20Sopenharmony_ci#include <linux/export.h>
138c2ecf20Sopenharmony_ci#include <linux/nodemask.h>
148c2ecf20Sopenharmony_ci#include <linux/swap.h>
158c2ecf20Sopenharmony_ci#include <linux/memblock.h>
168c2ecf20Sopenharmony_ci#include <linux/pfn.h>
178c2ecf20Sopenharmony_ci#include <linux/acpi.h>
188c2ecf20Sopenharmony_ci#include <linux/efi.h>
198c2ecf20Sopenharmony_ci#include <linux/pci.h>
208c2ecf20Sopenharmony_ci#include <asm/page.h>
218c2ecf20Sopenharmony_ci#include <asm/pgalloc.h>
228c2ecf20Sopenharmony_ci#include <asm/sections.h>
238c2ecf20Sopenharmony_ci#include <linux/irq.h>
248c2ecf20Sopenharmony_ci#include <asm/bootinfo.h>
258c2ecf20Sopenharmony_ci#include <asm/time.h>
268c2ecf20Sopenharmony_ci#include <loongson.h>
278c2ecf20Sopenharmony_ci#include <asm/numa.h>
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ciint numa_off;
308c2ecf20Sopenharmony_cistruct pglist_data *node_data[MAX_NUMNODES];
318c2ecf20Sopenharmony_ciunsigned char node_distances[MAX_NUMNODES][MAX_NUMNODES];
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ciEXPORT_SYMBOL(node_data);
348c2ecf20Sopenharmony_ciEXPORT_SYMBOL(node_distances);
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_cistatic struct numa_meminfo numa_meminfo;
378c2ecf20Sopenharmony_cicpumask_t cpus_on_node[MAX_NUMNODES];
388c2ecf20Sopenharmony_cicpumask_t phys_cpus_on_node[MAX_NUMNODES];
398c2ecf20Sopenharmony_ciEXPORT_SYMBOL(cpus_on_node);
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci/*
428c2ecf20Sopenharmony_ci * apicid, cpu, node mappings
438c2ecf20Sopenharmony_ci */
448c2ecf20Sopenharmony_cis16 __cpuid_to_node[CONFIG_NR_CPUS] = {
458c2ecf20Sopenharmony_ci	[0 ... CONFIG_NR_CPUS - 1] = NUMA_NO_NODE
468c2ecf20Sopenharmony_ci};
478c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__cpuid_to_node);
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_cinodemask_t numa_nodes_parsed __initdata;
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci#ifdef CONFIG_HAVE_SETUP_PER_CPU_AREA
528c2ecf20Sopenharmony_ciunsigned long __per_cpu_offset[NR_CPUS] __read_mostly;
538c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__per_cpu_offset);
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_cistatic int __init pcpu_cpu_distance(unsigned int from, unsigned int to)
568c2ecf20Sopenharmony_ci{
578c2ecf20Sopenharmony_ci	if (early_cpu_to_node(from) == early_cpu_to_node(to))
588c2ecf20Sopenharmony_ci		return LOCAL_DISTANCE;
598c2ecf20Sopenharmony_ci	else
608c2ecf20Sopenharmony_ci		return REMOTE_DISTANCE;
618c2ecf20Sopenharmony_ci}
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_cistatic void * __init pcpu_fc_alloc(unsigned int cpu, size_t size,
648c2ecf20Sopenharmony_ci				       size_t align)
658c2ecf20Sopenharmony_ci{
668c2ecf20Sopenharmony_ci	return memblock_alloc_try_nid(size, align, __pa(MAX_DMA_ADDRESS),
678c2ecf20Sopenharmony_ci				      MEMBLOCK_ALLOC_ACCESSIBLE, early_cpu_to_node(cpu));
688c2ecf20Sopenharmony_ci}
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_cistatic void __init pcpu_fc_free(void *ptr, size_t size)
718c2ecf20Sopenharmony_ci{
728c2ecf20Sopenharmony_ci	memblock_free_early(__pa(ptr), size);
738c2ecf20Sopenharmony_ci}
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_cistatic void __init pcpu_populate_pte(unsigned long addr)
768c2ecf20Sopenharmony_ci{
778c2ecf20Sopenharmony_ci	populate_kernel_pte(addr);
788c2ecf20Sopenharmony_ci}
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_civoid __init setup_per_cpu_areas(void)
818c2ecf20Sopenharmony_ci{
828c2ecf20Sopenharmony_ci	unsigned long delta;
838c2ecf20Sopenharmony_ci	unsigned int cpu;
848c2ecf20Sopenharmony_ci	int rc = -EINVAL;
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ci	if (pcpu_chosen_fc == PCPU_FC_AUTO) {
878c2ecf20Sopenharmony_ci		if (nr_node_ids >= 8)
888c2ecf20Sopenharmony_ci			pcpu_chosen_fc = PCPU_FC_PAGE;
898c2ecf20Sopenharmony_ci		else
908c2ecf20Sopenharmony_ci			pcpu_chosen_fc = PCPU_FC_EMBED;
918c2ecf20Sopenharmony_ci	}
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci	/*
948c2ecf20Sopenharmony_ci	 * Always reserve area for module percpu variables.  That's
958c2ecf20Sopenharmony_ci	 * what the legacy allocator did.
968c2ecf20Sopenharmony_ci	 */
978c2ecf20Sopenharmony_ci	if (pcpu_chosen_fc != PCPU_FC_PAGE) {
988c2ecf20Sopenharmony_ci		rc = pcpu_embed_first_chunk(PERCPU_MODULE_RESERVE,
998c2ecf20Sopenharmony_ci					    PERCPU_DYNAMIC_RESERVE, PMD_SIZE,
1008c2ecf20Sopenharmony_ci					    pcpu_cpu_distance,
1018c2ecf20Sopenharmony_ci					    pcpu_fc_alloc, pcpu_fc_free);
1028c2ecf20Sopenharmony_ci		if (rc < 0)
1038c2ecf20Sopenharmony_ci			pr_warn("%s allocator failed (%d), falling back to page size\n",
1048c2ecf20Sopenharmony_ci				pcpu_fc_names[pcpu_chosen_fc], rc);
1058c2ecf20Sopenharmony_ci	}
1068c2ecf20Sopenharmony_ci	if (rc < 0)
1078c2ecf20Sopenharmony_ci		rc = pcpu_page_first_chunk(PERCPU_MODULE_RESERVE,
1088c2ecf20Sopenharmony_ci					   pcpu_fc_alloc, pcpu_fc_free,
1098c2ecf20Sopenharmony_ci					   pcpu_populate_pte);
1108c2ecf20Sopenharmony_ci	if (rc < 0)
1118c2ecf20Sopenharmony_ci		panic("cannot initialize percpu area (err=%d)", rc);
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_ci	delta = (unsigned long)pcpu_base_addr - (unsigned long)__per_cpu_start;
1148c2ecf20Sopenharmony_ci	for_each_possible_cpu(cpu)
1158c2ecf20Sopenharmony_ci		__per_cpu_offset[cpu] = delta + pcpu_unit_offsets[cpu];
1168c2ecf20Sopenharmony_ci}
1178c2ecf20Sopenharmony_ci#endif
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_ci/*
1208c2ecf20Sopenharmony_ci * Get nodeid by logical cpu number.
1218c2ecf20Sopenharmony_ci * __cpuid_to_node maps phyical cpu id to node, so we
1228c2ecf20Sopenharmony_ci * should use cpu_logical_map(cpu) to index it.
1238c2ecf20Sopenharmony_ci *
1248c2ecf20Sopenharmony_ci * This routine is only used in early phase during
1258c2ecf20Sopenharmony_ci * booting, after setup_per_cpu_areas calling and numa_node
1268c2ecf20Sopenharmony_ci * initialization, cpu_to_node will be used instead.
1278c2ecf20Sopenharmony_ci * */
1288c2ecf20Sopenharmony_ciint early_cpu_to_node(int cpu)
1298c2ecf20Sopenharmony_ci{
1308c2ecf20Sopenharmony_ci	int physid = cpu_logical_map(cpu);
1318c2ecf20Sopenharmony_ci
1328c2ecf20Sopenharmony_ci	if (physid < 0)
1338c2ecf20Sopenharmony_ci		return NUMA_NO_NODE;
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_ci	return __cpuid_to_node[physid];
1368c2ecf20Sopenharmony_ci}
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_civoid __init early_numa_add_cpu(int cpuid, s16 node)
1398c2ecf20Sopenharmony_ci{
1408c2ecf20Sopenharmony_ci	int cpu = __cpu_number_map[cpuid];
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_ci	if (cpu < 0)
1438c2ecf20Sopenharmony_ci		return;
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_ci	cpumask_set_cpu(cpu, &cpus_on_node[node]);
1468c2ecf20Sopenharmony_ci	cpumask_set_cpu(cpuid, &phys_cpus_on_node[node]);
1478c2ecf20Sopenharmony_ci}
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_civoid numa_add_cpu(unsigned int cpu)
1508c2ecf20Sopenharmony_ci{
1518c2ecf20Sopenharmony_ci	int nid = cpu_to_node(cpu);
1528c2ecf20Sopenharmony_ci	cpumask_set_cpu(cpu, &cpus_on_node[nid]);
1538c2ecf20Sopenharmony_ci}
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_civoid numa_remove_cpu(unsigned int cpu)
1568c2ecf20Sopenharmony_ci{
1578c2ecf20Sopenharmony_ci	int nid = cpu_to_node(cpu);
1588c2ecf20Sopenharmony_ci	cpumask_clear_cpu(cpu, &cpus_on_node[nid]);
1598c2ecf20Sopenharmony_ci}
1608c2ecf20Sopenharmony_ci
1618c2ecf20Sopenharmony_cistatic int __init numa_add_memblk_to(int nid, u64 start, u64 end,
1628c2ecf20Sopenharmony_ci				     struct numa_meminfo *mi)
1638c2ecf20Sopenharmony_ci{
1648c2ecf20Sopenharmony_ci	/* ignore zero length blks */
1658c2ecf20Sopenharmony_ci	if (start == end)
1668c2ecf20Sopenharmony_ci		return 0;
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_ci	/* whine about and ignore invalid blks */
1698c2ecf20Sopenharmony_ci	if (start > end || nid < 0 || nid >= MAX_NUMNODES) {
1708c2ecf20Sopenharmony_ci		pr_warn("NUMA: Warning: invalid memblk node %d [mem %#010Lx-%#010Lx]\n",
1718c2ecf20Sopenharmony_ci			   nid, start, end - 1);
1728c2ecf20Sopenharmony_ci		return 0;
1738c2ecf20Sopenharmony_ci	}
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_ci	if (mi->nr_blks >= NR_NODE_MEMBLKS) {
1768c2ecf20Sopenharmony_ci		pr_err("NUMA: too many memblk ranges\n");
1778c2ecf20Sopenharmony_ci		return -EINVAL;
1788c2ecf20Sopenharmony_ci	}
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_ci	mi->blk[mi->nr_blks].start = PFN_ALIGN(start);
1818c2ecf20Sopenharmony_ci	mi->blk[mi->nr_blks].end = PFN_ALIGN(end - PAGE_SIZE + 1);
1828c2ecf20Sopenharmony_ci	mi->blk[mi->nr_blks].nid = nid;
1838c2ecf20Sopenharmony_ci	mi->nr_blks++;
1848c2ecf20Sopenharmony_ci	return 0;
1858c2ecf20Sopenharmony_ci}
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_ci/**
1888c2ecf20Sopenharmony_ci * numa_add_memblk - Add one numa_memblk to numa_meminfo
1898c2ecf20Sopenharmony_ci * @nid: NUMA node ID of the new memblk
1908c2ecf20Sopenharmony_ci * @start: Start address of the new memblk
1918c2ecf20Sopenharmony_ci * @end: End address of the new memblk
1928c2ecf20Sopenharmony_ci *
1938c2ecf20Sopenharmony_ci * Add a new memblk to the default numa_meminfo.
1948c2ecf20Sopenharmony_ci *
1958c2ecf20Sopenharmony_ci * RETURNS:
1968c2ecf20Sopenharmony_ci * 0 on success, -errno on failure.
1978c2ecf20Sopenharmony_ci */
1988c2ecf20Sopenharmony_ciint __init numa_add_memblk(int nid, u64 start, u64 end)
1998c2ecf20Sopenharmony_ci{
2008c2ecf20Sopenharmony_ci	return numa_add_memblk_to(nid, start, end, &numa_meminfo);
2018c2ecf20Sopenharmony_ci}
2028c2ecf20Sopenharmony_ci
2038c2ecf20Sopenharmony_cistatic void __init alloc_node_data(int nid)
2048c2ecf20Sopenharmony_ci{
2058c2ecf20Sopenharmony_ci	void *nd;
2068c2ecf20Sopenharmony_ci	unsigned long nd_pa;
2078c2ecf20Sopenharmony_ci	size_t nd_sz = roundup(sizeof(pg_data_t), PAGE_SIZE);
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_ci	nd_pa = memblock_phys_alloc_try_nid(nd_sz, SMP_CACHE_BYTES, nid);
2108c2ecf20Sopenharmony_ci	if (!nd_pa) {
2118c2ecf20Sopenharmony_ci		pr_err("Cannot find %zu Byte for node_data (initial node: %d)\n", nd_sz, nid);
2128c2ecf20Sopenharmony_ci		return;
2138c2ecf20Sopenharmony_ci	}
2148c2ecf20Sopenharmony_ci
2158c2ecf20Sopenharmony_ci	nd = __va(nd_pa);
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ci	node_data[nid] = nd;
2188c2ecf20Sopenharmony_ci	memset(nd, 0, sizeof(pg_data_t));
2198c2ecf20Sopenharmony_ci}
2208c2ecf20Sopenharmony_ci
2218c2ecf20Sopenharmony_cistatic void __init node_mem_init(unsigned int node)
2228c2ecf20Sopenharmony_ci{
2238c2ecf20Sopenharmony_ci	unsigned long start_pfn, end_pfn;
2248c2ecf20Sopenharmony_ci	unsigned long node_addrspace_offset;
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_ci	node_addrspace_offset = nid_to_addrbase(node);
2278c2ecf20Sopenharmony_ci	pr_info("Node%d's addrspace_offset is 0x%lx\n",
2288c2ecf20Sopenharmony_ci			node, node_addrspace_offset);
2298c2ecf20Sopenharmony_ci
2308c2ecf20Sopenharmony_ci	get_pfn_range_for_nid(node, &start_pfn, &end_pfn);
2318c2ecf20Sopenharmony_ci	pr_info("Node%d: start_pfn=0x%lx, end_pfn=0x%lx\n",
2328c2ecf20Sopenharmony_ci		node, start_pfn, end_pfn);
2338c2ecf20Sopenharmony_ci
2348c2ecf20Sopenharmony_ci	alloc_node_data(node);
2358c2ecf20Sopenharmony_ci}
2368c2ecf20Sopenharmony_ci
2378c2ecf20Sopenharmony_ci#ifdef CONFIG_ACPI_NUMA
2388c2ecf20Sopenharmony_ci
2398c2ecf20Sopenharmony_ci/*
2408c2ecf20Sopenharmony_ci * Sanity check to catch more bad NUMA configurations (they are amazingly
2418c2ecf20Sopenharmony_ci * common).  Make sure the nodes cover all memory.
2428c2ecf20Sopenharmony_ci */
2438c2ecf20Sopenharmony_cistatic bool __init numa_meminfo_cover_memory(const struct numa_meminfo *mi)
2448c2ecf20Sopenharmony_ci{
2458c2ecf20Sopenharmony_ci	u64 numaram, biosram;
2468c2ecf20Sopenharmony_ci	int i;
2478c2ecf20Sopenharmony_ci
2488c2ecf20Sopenharmony_ci	numaram = 0;
2498c2ecf20Sopenharmony_ci	for (i = 0; i < mi->nr_blks; i++) {
2508c2ecf20Sopenharmony_ci		u64 s = mi->blk[i].start >> PAGE_SHIFT;
2518c2ecf20Sopenharmony_ci		u64 e = mi->blk[i].end >> PAGE_SHIFT;
2528c2ecf20Sopenharmony_ci		numaram += e - s;
2538c2ecf20Sopenharmony_ci		numaram -= __absent_pages_in_range(mi->blk[i].nid, s, e);
2548c2ecf20Sopenharmony_ci		if ((s64)numaram < 0)
2558c2ecf20Sopenharmony_ci			numaram = 0;
2568c2ecf20Sopenharmony_ci	}
2578c2ecf20Sopenharmony_ci	max_pfn = max_low_pfn;
2588c2ecf20Sopenharmony_ci	biosram = max_pfn - absent_pages_in_range(0, max_pfn);
2598c2ecf20Sopenharmony_ci
2608c2ecf20Sopenharmony_ci	BUG_ON((s64)(biosram - numaram) >= (1 << (20 - PAGE_SHIFT)));
2618c2ecf20Sopenharmony_ci	return true;
2628c2ecf20Sopenharmony_ci}
2638c2ecf20Sopenharmony_ci
2648c2ecf20Sopenharmony_cistatic void __init add_node_intersection(u32 node, u64 start, u64 size, u32 type)
2658c2ecf20Sopenharmony_ci{
2668c2ecf20Sopenharmony_ci	static unsigned long num_physpages;
2678c2ecf20Sopenharmony_ci
2688c2ecf20Sopenharmony_ci	num_physpages += (size >> PAGE_SHIFT);
2698c2ecf20Sopenharmony_ci	pr_info("Node%d: mem_type:%d, mem_start:0x%llx, mem_size:0x%llx Bytes\n",
2708c2ecf20Sopenharmony_ci		node, type, start, size);
2718c2ecf20Sopenharmony_ci	pr_info("       start_pfn:0x%llx, end_pfn:0x%llx, num_physpages:0x%lx\n",
2728c2ecf20Sopenharmony_ci		start >> PAGE_SHIFT, (start + size) >> PAGE_SHIFT, num_physpages);
2738c2ecf20Sopenharmony_ci	memblock_set_node(start, size, &memblock.memory, node);
2748c2ecf20Sopenharmony_ci}
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_ci/*
2778c2ecf20Sopenharmony_ci * add_numamem_region
2788c2ecf20Sopenharmony_ci *
2798c2ecf20Sopenharmony_ci * Add a uasable memory region described by BIOS. The
2808c2ecf20Sopenharmony_ci * routine gets each intersection between BIOS's region
2818c2ecf20Sopenharmony_ci * and node's region, and adds them into node's memblock
2828c2ecf20Sopenharmony_ci * pool.
2838c2ecf20Sopenharmony_ci *
2848c2ecf20Sopenharmony_ci */
2858c2ecf20Sopenharmony_cistatic void __init add_numamem_region(u64 start, u64 end, u32 type)
2868c2ecf20Sopenharmony_ci{
2878c2ecf20Sopenharmony_ci	u32 i;
2888c2ecf20Sopenharmony_ci	u64 ofs = start;
2898c2ecf20Sopenharmony_ci
2908c2ecf20Sopenharmony_ci	if (start >= end) {
2918c2ecf20Sopenharmony_ci		pr_debug("Invalid region: %016llx-%016llx\n", start, end);
2928c2ecf20Sopenharmony_ci		return;
2938c2ecf20Sopenharmony_ci	}
2948c2ecf20Sopenharmony_ci
2958c2ecf20Sopenharmony_ci	for (i = 0; i < numa_meminfo.nr_blks; i++) {
2968c2ecf20Sopenharmony_ci		struct numa_memblk *mb = &numa_meminfo.blk[i];
2978c2ecf20Sopenharmony_ci
2988c2ecf20Sopenharmony_ci		if (ofs > mb->end)
2998c2ecf20Sopenharmony_ci			continue;
3008c2ecf20Sopenharmony_ci
3018c2ecf20Sopenharmony_ci		if (end > mb->end) {
3028c2ecf20Sopenharmony_ci			add_node_intersection(mb->nid, ofs, mb->end - ofs, type);
3038c2ecf20Sopenharmony_ci			ofs = mb->end;
3048c2ecf20Sopenharmony_ci		} else {
3058c2ecf20Sopenharmony_ci			add_node_intersection(mb->nid, ofs, end - ofs, type);
3068c2ecf20Sopenharmony_ci			break;
3078c2ecf20Sopenharmony_ci		}
3088c2ecf20Sopenharmony_ci	}
3098c2ecf20Sopenharmony_ci}
3108c2ecf20Sopenharmony_ci
3118c2ecf20Sopenharmony_cistatic void __init init_node_memblock(void)
3128c2ecf20Sopenharmony_ci{
3138c2ecf20Sopenharmony_ci	u32 mem_type;
3148c2ecf20Sopenharmony_ci	u64 mem_end, mem_start, mem_size;
3158c2ecf20Sopenharmony_ci	efi_memory_desc_t *md;
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_ci	/* Parse memory information and activate */
3188c2ecf20Sopenharmony_ci	for_each_efi_memory_desc(md) {
3198c2ecf20Sopenharmony_ci		mem_type = md->type;
3208c2ecf20Sopenharmony_ci		mem_start = md->phys_addr;
3218c2ecf20Sopenharmony_ci		mem_size = md->num_pages << EFI_PAGE_SHIFT;
3228c2ecf20Sopenharmony_ci		mem_end = mem_start + mem_size;
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_ci		switch (mem_type) {
3258c2ecf20Sopenharmony_ci		case EFI_LOADER_CODE:
3268c2ecf20Sopenharmony_ci		case EFI_LOADER_DATA:
3278c2ecf20Sopenharmony_ci		case EFI_BOOT_SERVICES_CODE:
3288c2ecf20Sopenharmony_ci		case EFI_BOOT_SERVICES_DATA:
3298c2ecf20Sopenharmony_ci		case EFI_PERSISTENT_MEMORY:
3308c2ecf20Sopenharmony_ci		case EFI_CONVENTIONAL_MEMORY:
3318c2ecf20Sopenharmony_ci			add_numamem_region(mem_start, mem_end, mem_type);
3328c2ecf20Sopenharmony_ci			break;
3338c2ecf20Sopenharmony_ci		case EFI_PAL_CODE:
3348c2ecf20Sopenharmony_ci		case EFI_UNUSABLE_MEMORY:
3358c2ecf20Sopenharmony_ci		case EFI_ACPI_RECLAIM_MEMORY:
3368c2ecf20Sopenharmony_ci			add_numamem_region(mem_start, mem_end, mem_type);
3378c2ecf20Sopenharmony_ci			fallthrough;
3388c2ecf20Sopenharmony_ci		case EFI_RESERVED_TYPE:
3398c2ecf20Sopenharmony_ci		case EFI_RUNTIME_SERVICES_CODE:
3408c2ecf20Sopenharmony_ci		case EFI_RUNTIME_SERVICES_DATA:
3418c2ecf20Sopenharmony_ci		case EFI_MEMORY_MAPPED_IO:
3428c2ecf20Sopenharmony_ci		case EFI_MEMORY_MAPPED_IO_PORT_SPACE:
3438c2ecf20Sopenharmony_ci			pr_info("Resvd: mem_type:%d, mem_start:0x%llx, mem_size:0x%llx Bytes\n",
3448c2ecf20Sopenharmony_ci					mem_type, mem_start, mem_size);
3458c2ecf20Sopenharmony_ci			break;
3468c2ecf20Sopenharmony_ci		}
3478c2ecf20Sopenharmony_ci	}
3488c2ecf20Sopenharmony_ci}
3498c2ecf20Sopenharmony_ci
3508c2ecf20Sopenharmony_cistatic void __init numa_default_distance(void)
3518c2ecf20Sopenharmony_ci{
3528c2ecf20Sopenharmony_ci	int row, col;
3538c2ecf20Sopenharmony_ci
3548c2ecf20Sopenharmony_ci	for (row = 0; row < MAX_NUMNODES; row++)
3558c2ecf20Sopenharmony_ci		for (col = 0; col < MAX_NUMNODES; col++) {
3568c2ecf20Sopenharmony_ci			if (col == row)
3578c2ecf20Sopenharmony_ci				node_distances[row][col] = LOCAL_DISTANCE;
3588c2ecf20Sopenharmony_ci			else
3598c2ecf20Sopenharmony_ci				/* We assume that one node per package here!
3608c2ecf20Sopenharmony_ci				 *
3618c2ecf20Sopenharmony_ci				 * A SLIT should be used for multiple nodes
3628c2ecf20Sopenharmony_ci				 * per package to override default setting.
3638c2ecf20Sopenharmony_ci				 */
3648c2ecf20Sopenharmony_ci				node_distances[row][col] = REMOTE_DISTANCE;
3658c2ecf20Sopenharmony_ci	}
3668c2ecf20Sopenharmony_ci}
3678c2ecf20Sopenharmony_ci
3688c2ecf20Sopenharmony_ciint __init init_numa_memory(void)
3698c2ecf20Sopenharmony_ci{
3708c2ecf20Sopenharmony_ci	int i;
3718c2ecf20Sopenharmony_ci	int ret;
3728c2ecf20Sopenharmony_ci	int node;
3738c2ecf20Sopenharmony_ci
3748c2ecf20Sopenharmony_ci	for (i = 0; i < NR_CPUS; i++)
3758c2ecf20Sopenharmony_ci		set_cpuid_to_node(i, NUMA_NO_NODE);
3768c2ecf20Sopenharmony_ci
3778c2ecf20Sopenharmony_ci	numa_default_distance();
3788c2ecf20Sopenharmony_ci	nodes_clear(numa_nodes_parsed);
3798c2ecf20Sopenharmony_ci	nodes_clear(node_possible_map);
3808c2ecf20Sopenharmony_ci	nodes_clear(node_online_map);
3818c2ecf20Sopenharmony_ci	memset(&numa_meminfo, 0, sizeof(numa_meminfo));
3828c2ecf20Sopenharmony_ci
3838c2ecf20Sopenharmony_ci	/* Parse SRAT and SLIT if provided by firmware. */
3848c2ecf20Sopenharmony_ci	ret = acpi_numa_init();
3858c2ecf20Sopenharmony_ci	if (ret < 0)
3868c2ecf20Sopenharmony_ci		return ret;
3878c2ecf20Sopenharmony_ci
3888c2ecf20Sopenharmony_ci	node_possible_map = numa_nodes_parsed;
3898c2ecf20Sopenharmony_ci	if (WARN_ON(nodes_empty(node_possible_map)))
3908c2ecf20Sopenharmony_ci		return -EINVAL;
3918c2ecf20Sopenharmony_ci
3928c2ecf20Sopenharmony_ci	init_node_memblock();
3938c2ecf20Sopenharmony_ci	if (numa_meminfo_cover_memory(&numa_meminfo) == false)
3948c2ecf20Sopenharmony_ci		return -EINVAL;
3958c2ecf20Sopenharmony_ci
3968c2ecf20Sopenharmony_ci	for_each_node_mask(node, node_possible_map) {
3978c2ecf20Sopenharmony_ci		node_mem_init(node);
3988c2ecf20Sopenharmony_ci		node_set_online(node);
3998c2ecf20Sopenharmony_ci	}
4008c2ecf20Sopenharmony_ci	max_low_pfn = PHYS_PFN(memblock_end_of_DRAM());
4018c2ecf20Sopenharmony_ci
4028c2ecf20Sopenharmony_ci	setup_nr_node_ids();
4038c2ecf20Sopenharmony_ci	loongson_sysconf.nr_nodes = nr_node_ids;
4048c2ecf20Sopenharmony_ci	loongson_sysconf.cores_per_node = cpumask_weight(&phys_cpus_on_node[0]);
4058c2ecf20Sopenharmony_ci
4068c2ecf20Sopenharmony_ci	return 0;
4078c2ecf20Sopenharmony_ci}
4088c2ecf20Sopenharmony_ci
4098c2ecf20Sopenharmony_ci#endif
4108c2ecf20Sopenharmony_ci
4118c2ecf20Sopenharmony_civoid __init paging_init(void)
4128c2ecf20Sopenharmony_ci{
4138c2ecf20Sopenharmony_ci	unsigned int node;
4148c2ecf20Sopenharmony_ci	unsigned long zones_size[MAX_NR_ZONES] = {0, };
4158c2ecf20Sopenharmony_ci
4168c2ecf20Sopenharmony_ci	for_each_online_node(node) {
4178c2ecf20Sopenharmony_ci		unsigned long start_pfn, end_pfn;
4188c2ecf20Sopenharmony_ci
4198c2ecf20Sopenharmony_ci		get_pfn_range_for_nid(node, &start_pfn, &end_pfn);
4208c2ecf20Sopenharmony_ci
4218c2ecf20Sopenharmony_ci		if (end_pfn > max_low_pfn)
4228c2ecf20Sopenharmony_ci			max_low_pfn = end_pfn;
4238c2ecf20Sopenharmony_ci	}
4248c2ecf20Sopenharmony_ci#ifdef CONFIG_ZONE_DMA32
4258c2ecf20Sopenharmony_ci	zones_size[ZONE_DMA32] = MAX_DMA32_PFN;
4268c2ecf20Sopenharmony_ci#endif
4278c2ecf20Sopenharmony_ci	zones_size[ZONE_NORMAL] = max_low_pfn;
4288c2ecf20Sopenharmony_ci	free_area_init(zones_size);
4298c2ecf20Sopenharmony_ci}
4308c2ecf20Sopenharmony_ci
4318c2ecf20Sopenharmony_civoid __init mem_init(void)
4328c2ecf20Sopenharmony_ci{
4338c2ecf20Sopenharmony_ci	high_memory = (void *) __va(max_low_pfn << PAGE_SHIFT);
4348c2ecf20Sopenharmony_ci	memblock_free_all();
4358c2ecf20Sopenharmony_ci	mem_init_print_info(NULL);
4368c2ecf20Sopenharmony_ci}
4378c2ecf20Sopenharmony_ci
4388c2ecf20Sopenharmony_ciint pcibus_to_node(struct pci_bus *bus)
4398c2ecf20Sopenharmony_ci{
4408c2ecf20Sopenharmony_ci	return dev_to_node(&bus->dev);
4418c2ecf20Sopenharmony_ci}
4428c2ecf20Sopenharmony_ciEXPORT_SYMBOL(pcibus_to_node);
443