162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public 362306a36Sopenharmony_ci * License. See the file "COPYING" in the main directory of this archive 462306a36Sopenharmony_ci * for more details. 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * This file contains NUMA specific variables and functions which are used on 762306a36Sopenharmony_ci * NUMA machines with contiguous memory. 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci * 2002/08/07 Erich Focht <efocht@ess.nec.de> 1062306a36Sopenharmony_ci */ 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include <linux/cpu.h> 1362306a36Sopenharmony_ci#include <linux/kernel.h> 1462306a36Sopenharmony_ci#include <linux/mm.h> 1562306a36Sopenharmony_ci#include <linux/node.h> 1662306a36Sopenharmony_ci#include <linux/init.h> 1762306a36Sopenharmony_ci#include <linux/memblock.h> 1862306a36Sopenharmony_ci#include <linux/module.h> 1962306a36Sopenharmony_ci#include <asm/mmzone.h> 2062306a36Sopenharmony_ci#include <asm/numa.h> 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci/* 2462306a36Sopenharmony_ci * The following structures are usually initialized by ACPI or 2562306a36Sopenharmony_ci * similar mechanisms and describe the NUMA characteristics of the machine. 2662306a36Sopenharmony_ci */ 2762306a36Sopenharmony_ciint num_node_memblks; 2862306a36Sopenharmony_cistruct node_memblk_s node_memblk[NR_NODE_MEMBLKS]; 2962306a36Sopenharmony_cistruct node_cpuid_s node_cpuid[NR_CPUS] = 3062306a36Sopenharmony_ci { [0 ... NR_CPUS-1] = { .phys_id = 0, .nid = NUMA_NO_NODE } }; 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci/* 3362306a36Sopenharmony_ci * This is a matrix with "distances" between nodes, they should be 3462306a36Sopenharmony_ci * proportional to the memory access latency ratios. 3562306a36Sopenharmony_ci */ 3662306a36Sopenharmony_ciu8 numa_slit[MAX_NUMNODES * MAX_NUMNODES]; 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ciint __node_distance(int from, int to) 3962306a36Sopenharmony_ci{ 4062306a36Sopenharmony_ci return slit_distance(from, to); 4162306a36Sopenharmony_ci} 4262306a36Sopenharmony_ciEXPORT_SYMBOL(__node_distance); 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci/* Identify which cnode a physical address resides on */ 4562306a36Sopenharmony_ciint 4662306a36Sopenharmony_cipaddr_to_nid(unsigned long paddr) 4762306a36Sopenharmony_ci{ 4862306a36Sopenharmony_ci int i; 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci for (i = 0; i < num_node_memblks; i++) 5162306a36Sopenharmony_ci if (paddr >= node_memblk[i].start_paddr && 5262306a36Sopenharmony_ci paddr < node_memblk[i].start_paddr + node_memblk[i].size) 5362306a36Sopenharmony_ci break; 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci return (i < num_node_memblks) ? node_memblk[i].nid : (num_node_memblks ? -1 : 0); 5662306a36Sopenharmony_ci} 5762306a36Sopenharmony_ciEXPORT_SYMBOL(paddr_to_nid); 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci#if defined(CONFIG_SPARSEMEM) && defined(CONFIG_NUMA) 6062306a36Sopenharmony_civoid numa_clear_node(int cpu) 6162306a36Sopenharmony_ci{ 6262306a36Sopenharmony_ci unmap_cpu_from_node(cpu, NUMA_NO_NODE); 6362306a36Sopenharmony_ci} 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci#ifdef CONFIG_MEMORY_HOTPLUG 6662306a36Sopenharmony_ci/* 6762306a36Sopenharmony_ci * SRAT information is stored in node_memblk[], then we can use SRAT 6862306a36Sopenharmony_ci * information at memory-hot-add if necessary. 6962306a36Sopenharmony_ci */ 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ciint memory_add_physaddr_to_nid(u64 addr) 7262306a36Sopenharmony_ci{ 7362306a36Sopenharmony_ci int nid = paddr_to_nid(addr); 7462306a36Sopenharmony_ci if (nid < 0) 7562306a36Sopenharmony_ci return 0; 7662306a36Sopenharmony_ci return nid; 7762306a36Sopenharmony_ci} 7862306a36Sopenharmony_ciEXPORT_SYMBOL(memory_add_physaddr_to_nid); 7962306a36Sopenharmony_ci#endif 8062306a36Sopenharmony_ci#endif 81