11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This file is subject to the terms and conditions of the GNU General Public
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * License.  See the file "COPYING" in the main directory of this archive
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * for more details.
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This file contains NUMA specific variables and functions which can
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * be split away from DISCONTIGMEM and are used on NUMA machines with
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * contiguous memory.
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                         2002/08/07 Erich Focht <efocht@ess.nec.de>
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/cpu.h>
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h>
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mm.h>
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/node.h>
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/bootmem.h>
198c2676a5870ab15cbeea9f826266bc946fe3cc26Keith Mannthey#include <linux/module.h>
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/mmzone.h>
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/numa.h>
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The following structures are usually initialized by ACPI or
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * similar mechanisms and describe the NUMA characteristics of the machine.
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint num_node_memblks;
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct node_memblk_s node_memblk[NR_NODE_MEMBLKS];
302c6e6db41f01b6b4eb98809350827c9678996698holt@sgi.comstruct node_cpuid_s node_cpuid[NR_CPUS] =
312c6e6db41f01b6b4eb98809350827c9678996698holt@sgi.com	{ [0 ... NR_CPUS-1] = { .phys_id = 0, .nid = NUMA_NO_NODE } };
322c6e6db41f01b6b4eb98809350827c9678996698holt@sgi.com
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This is a matrix with "distances" between nodes, they should be
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * proportional to the memory access latency ratios.
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsu8 numa_slit[MAX_NUMNODES * MAX_NUMNODES];
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Identify which cnode a physical address resides on */
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldspaddr_to_nid(unsigned long paddr)
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int	i;
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < num_node_memblks; i++)
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (paddr >= node_memblk[i].start_paddr &&
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    paddr < node_memblk[i].start_paddr + node_memblk[i].size)
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (i < num_node_memblks) ? node_memblk[i].nid : (num_node_memblks ? -1 : 0);
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
522d4b1fa234417b902c9d3034442387c1805bfa7bBob Picco
532d4b1fa234417b902c9d3034442387c1805bfa7bBob Picco#if defined(CONFIG_SPARSEMEM) && defined(CONFIG_NUMA)
542d4b1fa234417b902c9d3034442387c1805bfa7bBob Picco/*
552d4b1fa234417b902c9d3034442387c1805bfa7bBob Picco * Because of holes evaluate on section limits.
562d4b1fa234417b902c9d3034442387c1805bfa7bBob Picco * If the section of memory exists, then return the node where the section
572d4b1fa234417b902c9d3034442387c1805bfa7bBob Picco * resides.  Otherwise return node 0 as the default.  This is used by
582d4b1fa234417b902c9d3034442387c1805bfa7bBob Picco * SPARSEMEM to allocate the SPARSEMEM sectionmap on the NUMA node where
592d4b1fa234417b902c9d3034442387c1805bfa7bBob Picco * the section resides.
602d4b1fa234417b902c9d3034442387c1805bfa7bBob Picco */
61f2dbcfa738368c8a40d4a5f0b65dc9879577cb21KAMEZAWA Hiroyukiint __meminit __early_pfn_to_nid(unsigned long pfn)
622d4b1fa234417b902c9d3034442387c1805bfa7bBob Picco{
632d4b1fa234417b902c9d3034442387c1805bfa7bBob Picco	int i, section = pfn >> PFN_SECTION_SHIFT, ssec, esec;
642d4b1fa234417b902c9d3034442387c1805bfa7bBob Picco
652d4b1fa234417b902c9d3034442387c1805bfa7bBob Picco	for (i = 0; i < num_node_memblks; i++) {
662d4b1fa234417b902c9d3034442387c1805bfa7bBob Picco		ssec = node_memblk[i].start_paddr >> PA_SECTION_SHIFT;
672d4b1fa234417b902c9d3034442387c1805bfa7bBob Picco		esec = (node_memblk[i].start_paddr + node_memblk[i].size +
682d4b1fa234417b902c9d3034442387c1805bfa7bBob Picco			((1L << PA_SECTION_SHIFT) - 1)) >> PA_SECTION_SHIFT;
692d4b1fa234417b902c9d3034442387c1805bfa7bBob Picco		if (section >= ssec && section < esec)
702d4b1fa234417b902c9d3034442387c1805bfa7bBob Picco			return node_memblk[i].nid;
712d4b1fa234417b902c9d3034442387c1805bfa7bBob Picco	}
722d4b1fa234417b902c9d3034442387c1805bfa7bBob Picco
73cc2559bccc72767cb446f79b071d96c30c26439bKAMEZAWA Hiroyuki	return -1;
742d4b1fa234417b902c9d3034442387c1805bfa7bBob Picco}
758c2676a5870ab15cbeea9f826266bc946fe3cc26Keith Mannthey
768c2676a5870ab15cbeea9f826266bc946fe3cc26Keith Mannthey#ifdef CONFIG_MEMORY_HOTPLUG
778c2676a5870ab15cbeea9f826266bc946fe3cc26Keith Mannthey/*
788c2676a5870ab15cbeea9f826266bc946fe3cc26Keith Mannthey *  SRAT information is stored in node_memblk[], then we can use SRAT
798c2676a5870ab15cbeea9f826266bc946fe3cc26Keith Mannthey *  information at memory-hot-add if necessary.
808c2676a5870ab15cbeea9f826266bc946fe3cc26Keith Mannthey */
818c2676a5870ab15cbeea9f826266bc946fe3cc26Keith Mannthey
828c2676a5870ab15cbeea9f826266bc946fe3cc26Keith Manntheyint memory_add_physaddr_to_nid(u64 addr)
838c2676a5870ab15cbeea9f826266bc946fe3cc26Keith Mannthey{
848c2676a5870ab15cbeea9f826266bc946fe3cc26Keith Mannthey	int nid = paddr_to_nid(addr);
858c2676a5870ab15cbeea9f826266bc946fe3cc26Keith Mannthey	if (nid < 0)
868c2676a5870ab15cbeea9f826266bc946fe3cc26Keith Mannthey		return 0;
878c2676a5870ab15cbeea9f826266bc946fe3cc26Keith Mannthey	return nid;
888c2676a5870ab15cbeea9f826266bc946fe3cc26Keith Mannthey}
898c2676a5870ab15cbeea9f826266bc946fe3cc26Keith Mannthey
908c2676a5870ab15cbeea9f826266bc946fe3cc26Keith ManntheyEXPORT_SYMBOL_GPL(memory_add_physaddr_to_nid);
918c2676a5870ab15cbeea9f826266bc946fe3cc26Keith Mannthey#endif
922d4b1fa234417b902c9d3034442387c1805bfa7bBob Picco#endif
93