blob: 2437718bd6b16c27027f1d2bba3060fd45bf8862 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * This file contains NUMA specific variables and functions which can
7 * be split away from DISCONTIGMEM and are used on NUMA machines with
8 * contiguous memory.
9 *
10 * 2002/08/07 Erich Focht <efocht@ess.nec.de>
11 */
12
Linus Torvalds1da177e2005-04-16 15:20:36 -070013#include <linux/cpu.h>
14#include <linux/kernel.h>
15#include <linux/mm.h>
16#include <linux/node.h>
17#include <linux/init.h>
18#include <linux/bootmem.h>
Keith Mannthey8c2676a2006-09-30 23:27:07 -070019#include <linux/module.h>
Tony Luck4ec37de2010-05-27 15:35:13 -070020#include <linux/random.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070021#include <asm/mmzone.h>
22#include <asm/numa.h>
23
24
25/*
26 * The following structures are usually initialized by ACPI or
27 * similar mechanisms and describe the NUMA characteristics of the machine.
28 */
29int num_node_memblks;
30struct node_memblk_s node_memblk[NR_NODE_MEMBLKS];
holt@sgi.com2c6e6db2008-04-03 15:17:13 -050031struct node_cpuid_s node_cpuid[NR_CPUS] =
32 { [0 ... NR_CPUS-1] = { .phys_id = 0, .nid = NUMA_NO_NODE } };
33
Linus Torvalds1da177e2005-04-16 15:20:36 -070034/*
35 * This is a matrix with "distances" between nodes, they should be
36 * proportional to the memory access latency ratios.
37 */
38u8 numa_slit[MAX_NUMNODES * MAX_NUMNODES];
39
40/* Identify which cnode a physical address resides on */
41int
42paddr_to_nid(unsigned long paddr)
43{
44 int i;
45
46 for (i = 0; i < num_node_memblks; i++)
47 if (paddr >= node_memblk[i].start_paddr &&
48 paddr < node_memblk[i].start_paddr + node_memblk[i].size)
49 break;
50
51 return (i < num_node_memblks) ? node_memblk[i].nid : (num_node_memblks ? -1 : 0);
52}
Bob Picco2d4b1fa2005-10-04 15:13:57 -040053
Tony Luck4ec37de2010-05-27 15:35:13 -070054/*
55 * Return the bit number of a random bit set in the nodemask.
56 * (returns -1 if nodemask is empty)
57 */
58int __node_random(const nodemask_t *maskp)
59{
60 int w, bit = -1;
61
62 w = nodes_weight(*maskp);
63 if (w)
64 bit = bitmap_ord_to_pos(maskp->bits,
65 get_random_int() % w, MAX_NUMNODES);
66 return bit;
67}
68EXPORT_SYMBOL(__node_random);
69
Bob Picco2d4b1fa2005-10-04 15:13:57 -040070#if defined(CONFIG_SPARSEMEM) && defined(CONFIG_NUMA)
71/*
72 * Because of holes evaluate on section limits.
73 * If the section of memory exists, then return the node where the section
74 * resides. Otherwise return node 0 as the default. This is used by
75 * SPARSEMEM to allocate the SPARSEMEM sectionmap on the NUMA node where
76 * the section resides.
77 */
KAMEZAWA Hiroyukif2dbcfa2009-02-18 14:48:32 -080078int __meminit __early_pfn_to_nid(unsigned long pfn)
Bob Picco2d4b1fa2005-10-04 15:13:57 -040079{
80 int i, section = pfn >> PFN_SECTION_SHIFT, ssec, esec;
81
82 for (i = 0; i < num_node_memblks; i++) {
83 ssec = node_memblk[i].start_paddr >> PA_SECTION_SHIFT;
84 esec = (node_memblk[i].start_paddr + node_memblk[i].size +
85 ((1L << PA_SECTION_SHIFT) - 1)) >> PA_SECTION_SHIFT;
86 if (section >= ssec && section < esec)
87 return node_memblk[i].nid;
88 }
89
KAMEZAWA Hiroyukicc2559b2009-02-18 14:48:33 -080090 return -1;
Bob Picco2d4b1fa2005-10-04 15:13:57 -040091}
Keith Mannthey8c2676a2006-09-30 23:27:07 -070092
93#ifdef CONFIG_MEMORY_HOTPLUG
94/*
95 * SRAT information is stored in node_memblk[], then we can use SRAT
96 * information at memory-hot-add if necessary.
97 */
98
99int memory_add_physaddr_to_nid(u64 addr)
100{
101 int nid = paddr_to_nid(addr);
102 if (nid < 0)
103 return 0;
104 return nid;
105}
106
107EXPORT_SYMBOL_GPL(memory_add_physaddr_to_nid);
108#endif
Bob Picco2d4b1fa2005-10-04 15:13:57 -0400109#endif