1378b39a4SYinghai Lu #include <linux/kernel.h> 2378b39a4SYinghai Lu #include <linux/module.h> 3378b39a4SYinghai Lu #include <linux/init.h> 4378b39a4SYinghai Lu #include <linux/bootmem.h> 5378b39a4SYinghai Lu #include <linux/percpu.h> 6378b39a4SYinghai Lu #include <linux/kexec.h> 7378b39a4SYinghai Lu #include <linux/crash_dump.h> 88a87dd9aSJaswinder Singh Rajput #include <linux/smp.h> 98a87dd9aSJaswinder Singh Rajput #include <linux/topology.h> 10378b39a4SYinghai Lu #include <asm/sections.h> 11378b39a4SYinghai Lu #include <asm/processor.h> 12378b39a4SYinghai Lu #include <asm/setup.h> 13378b39a4SYinghai Lu #include <asm/mpspec.h> 14378b39a4SYinghai Lu #include <asm/apicdef.h> 15378b39a4SYinghai Lu #include <asm/highmem.h> 16*06879033SJaswinder Singh Rajput #include <asm/cpumask.h> 17378b39a4SYinghai Lu 18378b39a4SYinghai Lu #ifdef CONFIG_X86_LOCAL_APIC 19378b39a4SYinghai Lu unsigned int num_processors; 20378b39a4SYinghai Lu unsigned disabled_cpus __cpuinitdata; 21378b39a4SYinghai Lu /* Processor that is doing the boot up */ 22378b39a4SYinghai Lu unsigned int boot_cpu_physical_apicid = -1U; 23378b39a4SYinghai Lu EXPORT_SYMBOL(boot_cpu_physical_apicid); 248a87dd9aSJaswinder Singh Rajput unsigned int max_physical_apicid; 25378b39a4SYinghai Lu 26378b39a4SYinghai Lu /* Bitmask of physically existing CPUs */ 27378b39a4SYinghai Lu physid_mask_t phys_cpu_present_map; 28378b39a4SYinghai Lu #endif 29378b39a4SYinghai Lu 30378b39a4SYinghai Lu /* map cpu index to physical APIC ID */ 31378b39a4SYinghai Lu DEFINE_EARLY_PER_CPU(u16, x86_cpu_to_apicid, BAD_APICID); 32378b39a4SYinghai Lu DEFINE_EARLY_PER_CPU(u16, x86_bios_cpu_apicid, BAD_APICID); 33378b39a4SYinghai Lu EXPORT_EARLY_PER_CPU_SYMBOL(x86_cpu_to_apicid); 34378b39a4SYinghai Lu EXPORT_EARLY_PER_CPU_SYMBOL(x86_bios_cpu_apicid); 35378b39a4SYinghai Lu 36378b39a4SYinghai Lu #if defined(CONFIG_NUMA) && defined(CONFIG_X86_64) 37378b39a4SYinghai Lu #define X86_64_NUMA 1 38378b39a4SYinghai Lu 39378b39a4SYinghai Lu /* map cpu index to node index */ 40378b39a4SYinghai Lu DEFINE_EARLY_PER_CPU(int, x86_cpu_to_node_map, NUMA_NO_NODE); 41378b39a4SYinghai Lu EXPORT_EARLY_PER_CPU_SYMBOL(x86_cpu_to_node_map); 42378b39a4SYinghai Lu 43378b39a4SYinghai Lu /* which logical CPUs are on which nodes */ 44378b39a4SYinghai Lu cpumask_t *node_to_cpumask_map; 45378b39a4SYinghai Lu EXPORT_SYMBOL(node_to_cpumask_map); 46378b39a4SYinghai Lu 47378b39a4SYinghai Lu /* setup node_to_cpumask_map */ 48378b39a4SYinghai Lu static void __init setup_node_to_cpumask_map(void); 49378b39a4SYinghai Lu 50378b39a4SYinghai Lu #else 51378b39a4SYinghai Lu static inline void setup_node_to_cpumask_map(void) { } 52378b39a4SYinghai Lu #endif 53378b39a4SYinghai Lu 54378b39a4SYinghai Lu #if defined(CONFIG_HAVE_SETUP_PER_CPU_AREA) && defined(CONFIG_X86_SMP) 55378b39a4SYinghai Lu /* 56378b39a4SYinghai Lu * Copy data used in early init routines from the initial arrays to the 57378b39a4SYinghai Lu * per cpu data areas. These arrays then become expendable and the 58378b39a4SYinghai Lu * *_early_ptr's are zeroed indicating that the static arrays are gone. 59378b39a4SYinghai Lu */ 60378b39a4SYinghai Lu static void __init setup_per_cpu_maps(void) 61378b39a4SYinghai Lu { 62378b39a4SYinghai Lu int cpu; 63378b39a4SYinghai Lu 64378b39a4SYinghai Lu for_each_possible_cpu(cpu) { 65378b39a4SYinghai Lu per_cpu(x86_cpu_to_apicid, cpu) = 66378b39a4SYinghai Lu early_per_cpu_map(x86_cpu_to_apicid, cpu); 67378b39a4SYinghai Lu per_cpu(x86_bios_cpu_apicid, cpu) = 68378b39a4SYinghai Lu early_per_cpu_map(x86_bios_cpu_apicid, cpu); 69378b39a4SYinghai Lu #ifdef X86_64_NUMA 70378b39a4SYinghai Lu per_cpu(x86_cpu_to_node_map, cpu) = 71378b39a4SYinghai Lu early_per_cpu_map(x86_cpu_to_node_map, cpu); 72378b39a4SYinghai Lu #endif 73378b39a4SYinghai Lu } 74378b39a4SYinghai Lu 75378b39a4SYinghai Lu /* indicate the early static arrays will soon be gone */ 76378b39a4SYinghai Lu early_per_cpu_ptr(x86_cpu_to_apicid) = NULL; 77378b39a4SYinghai Lu early_per_cpu_ptr(x86_bios_cpu_apicid) = NULL; 78378b39a4SYinghai Lu #ifdef X86_64_NUMA 79378b39a4SYinghai Lu early_per_cpu_ptr(x86_cpu_to_node_map) = NULL; 80378b39a4SYinghai Lu #endif 81378b39a4SYinghai Lu } 82378b39a4SYinghai Lu 83378b39a4SYinghai Lu #ifdef CONFIG_X86_32 84378b39a4SYinghai Lu /* 85378b39a4SYinghai Lu * Great future not-so-futuristic plan: make i386 and x86_64 do it 86378b39a4SYinghai Lu * the same way 87378b39a4SYinghai Lu */ 88378b39a4SYinghai Lu unsigned long __per_cpu_offset[NR_CPUS] __read_mostly; 89378b39a4SYinghai Lu EXPORT_SYMBOL(__per_cpu_offset); 90378b39a4SYinghai Lu static inline void setup_cpu_pda_map(void) { } 91378b39a4SYinghai Lu 92378b39a4SYinghai Lu #elif !defined(CONFIG_SMP) 93378b39a4SYinghai Lu static inline void setup_cpu_pda_map(void) { } 94378b39a4SYinghai Lu 95378b39a4SYinghai Lu #else /* CONFIG_SMP && CONFIG_X86_64 */ 96378b39a4SYinghai Lu 97378b39a4SYinghai Lu /* 98378b39a4SYinghai Lu * Allocate cpu_pda pointer table and array via alloc_bootmem. 99378b39a4SYinghai Lu */ 100378b39a4SYinghai Lu static void __init setup_cpu_pda_map(void) 101378b39a4SYinghai Lu { 102378b39a4SYinghai Lu char *pda; 103378b39a4SYinghai Lu struct x8664_pda **new_cpu_pda; 104378b39a4SYinghai Lu unsigned long size; 105378b39a4SYinghai Lu int cpu; 106378b39a4SYinghai Lu 107378b39a4SYinghai Lu size = roundup(sizeof(struct x8664_pda), cache_line_size()); 108378b39a4SYinghai Lu 109378b39a4SYinghai Lu /* allocate cpu_pda array and pointer table */ 110378b39a4SYinghai Lu { 111378b39a4SYinghai Lu unsigned long tsize = nr_cpu_ids * sizeof(void *); 112378b39a4SYinghai Lu unsigned long asize = size * (nr_cpu_ids - 1); 113378b39a4SYinghai Lu 114378b39a4SYinghai Lu tsize = roundup(tsize, cache_line_size()); 115378b39a4SYinghai Lu new_cpu_pda = alloc_bootmem(tsize + asize); 116378b39a4SYinghai Lu pda = (char *)new_cpu_pda + tsize; 117378b39a4SYinghai Lu } 118378b39a4SYinghai Lu 119378b39a4SYinghai Lu /* initialize pointer table to static pda's */ 120378b39a4SYinghai Lu for_each_possible_cpu(cpu) { 121378b39a4SYinghai Lu if (cpu == 0) { 122378b39a4SYinghai Lu /* leave boot cpu pda in place */ 123378b39a4SYinghai Lu new_cpu_pda[0] = cpu_pda(0); 124378b39a4SYinghai Lu continue; 125378b39a4SYinghai Lu } 126378b39a4SYinghai Lu new_cpu_pda[cpu] = (struct x8664_pda *)pda; 127378b39a4SYinghai Lu new_cpu_pda[cpu]->in_bootmem = 1; 128378b39a4SYinghai Lu pda += size; 129378b39a4SYinghai Lu } 130378b39a4SYinghai Lu 131378b39a4SYinghai Lu /* point to new pointer table */ 132378b39a4SYinghai Lu _cpu_pda = new_cpu_pda; 133378b39a4SYinghai Lu } 134c2d1cec1SMike Travis 135c2d1cec1SMike Travis #endif /* CONFIG_SMP && CONFIG_X86_64 */ 136c2d1cec1SMike Travis 137c2d1cec1SMike Travis #ifdef CONFIG_X86_64 138c2d1cec1SMike Travis 139c2d1cec1SMike Travis /* correctly size the local cpu masks */ 140c2d1cec1SMike Travis static void setup_cpu_local_masks(void) 141c2d1cec1SMike Travis { 142c2d1cec1SMike Travis alloc_bootmem_cpumask_var(&cpu_initialized_mask); 143c2d1cec1SMike Travis alloc_bootmem_cpumask_var(&cpu_callin_mask); 144c2d1cec1SMike Travis alloc_bootmem_cpumask_var(&cpu_callout_mask); 145c2d1cec1SMike Travis alloc_bootmem_cpumask_var(&cpu_sibling_setup_mask); 146c2d1cec1SMike Travis } 147c2d1cec1SMike Travis 148c2d1cec1SMike Travis #else /* CONFIG_X86_32 */ 149c2d1cec1SMike Travis 150c2d1cec1SMike Travis static inline void setup_cpu_local_masks(void) 151c2d1cec1SMike Travis { 152c2d1cec1SMike Travis } 153c2d1cec1SMike Travis 154c2d1cec1SMike Travis #endif /* CONFIG_X86_32 */ 155378b39a4SYinghai Lu 156378b39a4SYinghai Lu /* 157378b39a4SYinghai Lu * Great future plan: 158378b39a4SYinghai Lu * Declare PDA itself and support (irqstack,tss,pgd) as per cpu data. 159378b39a4SYinghai Lu * Always point %gs to its beginning 160378b39a4SYinghai Lu */ 161378b39a4SYinghai Lu void __init setup_per_cpu_areas(void) 162378b39a4SYinghai Lu { 163d6c88a50SThomas Gleixner ssize_t size, old_size; 164378b39a4SYinghai Lu char *ptr; 165378b39a4SYinghai Lu int cpu; 1661f8ff037SYinghai Lu unsigned long align = 1; 167378b39a4SYinghai Lu 168378b39a4SYinghai Lu /* Setup cpu_pda map */ 169378b39a4SYinghai Lu setup_cpu_pda_map(); 170378b39a4SYinghai Lu 171378b39a4SYinghai Lu /* Copy section for each CPU (we discard the original) */ 1721f3fcd4bSYinghai Lu old_size = PERCPU_ENOUGH_ROOM; 1731f8ff037SYinghai Lu align = max_t(unsigned long, PAGE_SIZE, align); 174d6c88a50SThomas Gleixner size = roundup(old_size, align); 175a1681965SMike Travis 176ab14398aSCyrill Gorcunov pr_info("NR_CPUS:%d nr_cpumask_bits:%d nr_cpu_ids:%d nr_node_ids:%d\n", 177a1681965SMike Travis NR_CPUS, nr_cpumask_bits, nr_cpu_ids, nr_node_ids); 178a1681965SMike Travis 179ab14398aSCyrill Gorcunov pr_info("PERCPU: Allocating %zd bytes of per cpu data\n", size); 180378b39a4SYinghai Lu 181378b39a4SYinghai Lu for_each_possible_cpu(cpu) { 182378b39a4SYinghai Lu #ifndef CONFIG_NEED_MULTIPLE_NODES 1831f8ff037SYinghai Lu ptr = __alloc_bootmem(size, align, 1841f8ff037SYinghai Lu __pa(MAX_DMA_ADDRESS)); 185378b39a4SYinghai Lu #else 186378b39a4SYinghai Lu int node = early_cpu_to_node(cpu); 187378b39a4SYinghai Lu if (!node_online(node) || !NODE_DATA(node)) { 1881f8ff037SYinghai Lu ptr = __alloc_bootmem(size, align, 1891f8ff037SYinghai Lu __pa(MAX_DMA_ADDRESS)); 190ab14398aSCyrill Gorcunov pr_info("cpu %d has no node %d or node-local memory\n", 191378b39a4SYinghai Lu cpu, node); 192ab14398aSCyrill Gorcunov pr_debug("per cpu data for cpu%d at %016lx\n", 193a677f58aSYinghai Lu cpu, __pa(ptr)); 194ab14398aSCyrill Gorcunov } else { 1951f8ff037SYinghai Lu ptr = __alloc_bootmem_node(NODE_DATA(node), size, align, 1961f8ff037SYinghai Lu __pa(MAX_DMA_ADDRESS)); 197ab14398aSCyrill Gorcunov pr_debug("per cpu data for cpu%d on node%d at %016lx\n", 198a677f58aSYinghai Lu cpu, node, __pa(ptr)); 199a677f58aSYinghai Lu } 200378b39a4SYinghai Lu #endif 201378b39a4SYinghai Lu per_cpu_offset(cpu) = ptr - __per_cpu_start; 202378b39a4SYinghai Lu memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start); 203378b39a4SYinghai Lu } 204378b39a4SYinghai Lu 205378b39a4SYinghai Lu /* Setup percpu data maps */ 206378b39a4SYinghai Lu setup_per_cpu_maps(); 207378b39a4SYinghai Lu 208378b39a4SYinghai Lu /* Setup node to cpumask map */ 209378b39a4SYinghai Lu setup_node_to_cpumask_map(); 210c2d1cec1SMike Travis 211c2d1cec1SMike Travis /* Setup cpu initialized, callin, callout masks */ 212c2d1cec1SMike Travis setup_cpu_local_masks(); 213378b39a4SYinghai Lu } 214378b39a4SYinghai Lu 215378b39a4SYinghai Lu #endif 216378b39a4SYinghai Lu 217378b39a4SYinghai Lu #ifdef X86_64_NUMA 218378b39a4SYinghai Lu 219378b39a4SYinghai Lu /* 220378b39a4SYinghai Lu * Allocate node_to_cpumask_map based on number of available nodes 221378b39a4SYinghai Lu * Requires node_possible_map to be valid. 222378b39a4SYinghai Lu * 223378b39a4SYinghai Lu * Note: node_to_cpumask() is not valid until after this is done. 224378b39a4SYinghai Lu */ 225378b39a4SYinghai Lu static void __init setup_node_to_cpumask_map(void) 226378b39a4SYinghai Lu { 227378b39a4SYinghai Lu unsigned int node, num = 0; 228378b39a4SYinghai Lu cpumask_t *map; 229378b39a4SYinghai Lu 230378b39a4SYinghai Lu /* setup nr_node_ids if not done yet */ 231378b39a4SYinghai Lu if (nr_node_ids == MAX_NUMNODES) { 232378b39a4SYinghai Lu for_each_node_mask(node, node_possible_map) 233378b39a4SYinghai Lu num = node; 234378b39a4SYinghai Lu nr_node_ids = num + 1; 235378b39a4SYinghai Lu } 236378b39a4SYinghai Lu 237378b39a4SYinghai Lu /* allocate the map */ 238378b39a4SYinghai Lu map = alloc_bootmem_low(nr_node_ids * sizeof(cpumask_t)); 239378b39a4SYinghai Lu 24055410791SGustavo F. Padovan pr_debug("Node to cpumask map at %p for %d nodes\n", 241378b39a4SYinghai Lu map, nr_node_ids); 242378b39a4SYinghai Lu 243378b39a4SYinghai Lu /* node_to_cpumask() will now work */ 244378b39a4SYinghai Lu node_to_cpumask_map = map; 245378b39a4SYinghai Lu } 246378b39a4SYinghai Lu 247378b39a4SYinghai Lu void __cpuinit numa_set_node(int cpu, int node) 248378b39a4SYinghai Lu { 249378b39a4SYinghai Lu int *cpu_to_node_map = early_per_cpu_ptr(x86_cpu_to_node_map); 250378b39a4SYinghai Lu 251378b39a4SYinghai Lu if (cpu_pda(cpu) && node != NUMA_NO_NODE) 252378b39a4SYinghai Lu cpu_pda(cpu)->nodenumber = node; 253378b39a4SYinghai Lu 254378b39a4SYinghai Lu if (cpu_to_node_map) 255378b39a4SYinghai Lu cpu_to_node_map[cpu] = node; 256378b39a4SYinghai Lu 257378b39a4SYinghai Lu else if (per_cpu_offset(cpu)) 258378b39a4SYinghai Lu per_cpu(x86_cpu_to_node_map, cpu) = node; 259378b39a4SYinghai Lu 260378b39a4SYinghai Lu else 261cfc1b9a6SThomas Gleixner pr_debug("Setting node for non-present cpu %d\n", cpu); 262378b39a4SYinghai Lu } 263378b39a4SYinghai Lu 264378b39a4SYinghai Lu void __cpuinit numa_clear_node(int cpu) 265378b39a4SYinghai Lu { 266378b39a4SYinghai Lu numa_set_node(cpu, NUMA_NO_NODE); 267378b39a4SYinghai Lu } 268378b39a4SYinghai Lu 269378b39a4SYinghai Lu #ifndef CONFIG_DEBUG_PER_CPU_MAPS 270378b39a4SYinghai Lu 271378b39a4SYinghai Lu void __cpuinit numa_add_cpu(int cpu) 272378b39a4SYinghai Lu { 273378b39a4SYinghai Lu cpu_set(cpu, node_to_cpumask_map[early_cpu_to_node(cpu)]); 274378b39a4SYinghai Lu } 275378b39a4SYinghai Lu 276378b39a4SYinghai Lu void __cpuinit numa_remove_cpu(int cpu) 277378b39a4SYinghai Lu { 278378b39a4SYinghai Lu cpu_clear(cpu, node_to_cpumask_map[cpu_to_node(cpu)]); 279378b39a4SYinghai Lu } 280378b39a4SYinghai Lu 281378b39a4SYinghai Lu #else /* CONFIG_DEBUG_PER_CPU_MAPS */ 282378b39a4SYinghai Lu 283378b39a4SYinghai Lu /* 284378b39a4SYinghai Lu * --------- debug versions of the numa functions --------- 285378b39a4SYinghai Lu */ 286378b39a4SYinghai Lu static void __cpuinit numa_set_cpumask(int cpu, int enable) 287378b39a4SYinghai Lu { 288378b39a4SYinghai Lu int node = cpu_to_node(cpu); 289378b39a4SYinghai Lu cpumask_t *mask; 290378b39a4SYinghai Lu char buf[64]; 291378b39a4SYinghai Lu 292378b39a4SYinghai Lu if (node_to_cpumask_map == NULL) { 293378b39a4SYinghai Lu printk(KERN_ERR "node_to_cpumask_map NULL\n"); 294378b39a4SYinghai Lu dump_stack(); 295378b39a4SYinghai Lu return; 296378b39a4SYinghai Lu } 297378b39a4SYinghai Lu 298378b39a4SYinghai Lu mask = &node_to_cpumask_map[node]; 299378b39a4SYinghai Lu if (enable) 300378b39a4SYinghai Lu cpu_set(cpu, *mask); 301378b39a4SYinghai Lu else 302378b39a4SYinghai Lu cpu_clear(cpu, *mask); 303378b39a4SYinghai Lu 30429c0177eSRusty Russell cpulist_scnprintf(buf, sizeof(buf), mask); 305378b39a4SYinghai Lu printk(KERN_DEBUG "%s cpu %d node %d: mask now %s\n", 306378b39a4SYinghai Lu enable ? "numa_add_cpu" : "numa_remove_cpu", cpu, node, buf); 307378b39a4SYinghai Lu } 308378b39a4SYinghai Lu 309378b39a4SYinghai Lu void __cpuinit numa_add_cpu(int cpu) 310378b39a4SYinghai Lu { 311378b39a4SYinghai Lu numa_set_cpumask(cpu, 1); 312378b39a4SYinghai Lu } 313378b39a4SYinghai Lu 314378b39a4SYinghai Lu void __cpuinit numa_remove_cpu(int cpu) 315378b39a4SYinghai Lu { 316378b39a4SYinghai Lu numa_set_cpumask(cpu, 0); 317378b39a4SYinghai Lu } 318378b39a4SYinghai Lu 319378b39a4SYinghai Lu int cpu_to_node(int cpu) 320378b39a4SYinghai Lu { 321378b39a4SYinghai Lu if (early_per_cpu_ptr(x86_cpu_to_node_map)) { 322378b39a4SYinghai Lu printk(KERN_WARNING 323378b39a4SYinghai Lu "cpu_to_node(%d): usage too early!\n", cpu); 324378b39a4SYinghai Lu dump_stack(); 325378b39a4SYinghai Lu return early_per_cpu_ptr(x86_cpu_to_node_map)[cpu]; 326378b39a4SYinghai Lu } 327378b39a4SYinghai Lu return per_cpu(x86_cpu_to_node_map, cpu); 328378b39a4SYinghai Lu } 329378b39a4SYinghai Lu EXPORT_SYMBOL(cpu_to_node); 330378b39a4SYinghai Lu 331378b39a4SYinghai Lu /* 332378b39a4SYinghai Lu * Same function as cpu_to_node() but used if called before the 333378b39a4SYinghai Lu * per_cpu areas are setup. 334378b39a4SYinghai Lu */ 335378b39a4SYinghai Lu int early_cpu_to_node(int cpu) 336378b39a4SYinghai Lu { 337378b39a4SYinghai Lu if (early_per_cpu_ptr(x86_cpu_to_node_map)) 338378b39a4SYinghai Lu return early_per_cpu_ptr(x86_cpu_to_node_map)[cpu]; 339378b39a4SYinghai Lu 340378b39a4SYinghai Lu if (!per_cpu_offset(cpu)) { 341378b39a4SYinghai Lu printk(KERN_WARNING 342378b39a4SYinghai Lu "early_cpu_to_node(%d): no per_cpu area!\n", cpu); 343378b39a4SYinghai Lu dump_stack(); 344378b39a4SYinghai Lu return NUMA_NO_NODE; 345378b39a4SYinghai Lu } 346378b39a4SYinghai Lu return per_cpu(x86_cpu_to_node_map, cpu); 347378b39a4SYinghai Lu } 348378b39a4SYinghai Lu 3496a2f47caSMike Travis 3506a2f47caSMike Travis /* empty cpumask */ 3516a2f47caSMike Travis static const cpumask_t cpu_mask_none; 3526a2f47caSMike Travis 353378b39a4SYinghai Lu /* 354378b39a4SYinghai Lu * Returns a pointer to the bitmask of CPUs on Node 'node'. 355378b39a4SYinghai Lu */ 356393d68fbSRusty Russell const cpumask_t *cpumask_of_node(int node) 357378b39a4SYinghai Lu { 358378b39a4SYinghai Lu if (node_to_cpumask_map == NULL) { 359378b39a4SYinghai Lu printk(KERN_WARNING 360393d68fbSRusty Russell "cpumask_of_node(%d): no node_to_cpumask_map!\n", 361378b39a4SYinghai Lu node); 362378b39a4SYinghai Lu dump_stack(); 36311369f35SMike Travis return (const cpumask_t *)&cpu_online_map; 364378b39a4SYinghai Lu } 3656a2f47caSMike Travis if (node >= nr_node_ids) { 3666a2f47caSMike Travis printk(KERN_WARNING 367393d68fbSRusty Russell "cpumask_of_node(%d): node > nr_node_ids(%d)\n", 3686a2f47caSMike Travis node, nr_node_ids); 3696a2f47caSMike Travis dump_stack(); 37011369f35SMike Travis return &cpu_mask_none; 3716a2f47caSMike Travis } 37211369f35SMike Travis return &node_to_cpumask_map[node]; 373378b39a4SYinghai Lu } 374393d68fbSRusty Russell EXPORT_SYMBOL(cpumask_of_node); 375378b39a4SYinghai Lu 376378b39a4SYinghai Lu /* 377378b39a4SYinghai Lu * Returns a bitmask of CPUs on Node 'node'. 3786a2f47caSMike Travis * 3796a2f47caSMike Travis * Side note: this function creates the returned cpumask on the stack 3806a2f47caSMike Travis * so with a high NR_CPUS count, excessive stack space is used. The 3816a2f47caSMike Travis * node_to_cpumask_ptr function should be used whenever possible. 382378b39a4SYinghai Lu */ 383378b39a4SYinghai Lu cpumask_t node_to_cpumask(int node) 384378b39a4SYinghai Lu { 385378b39a4SYinghai Lu if (node_to_cpumask_map == NULL) { 386378b39a4SYinghai Lu printk(KERN_WARNING 387378b39a4SYinghai Lu "node_to_cpumask(%d): no node_to_cpumask_map!\n", node); 388378b39a4SYinghai Lu dump_stack(); 389378b39a4SYinghai Lu return cpu_online_map; 390378b39a4SYinghai Lu } 3916a2f47caSMike Travis if (node >= nr_node_ids) { 3926a2f47caSMike Travis printk(KERN_WARNING 3936a2f47caSMike Travis "node_to_cpumask(%d): node > nr_node_ids(%d)\n", 3946a2f47caSMike Travis node, nr_node_ids); 3956a2f47caSMike Travis dump_stack(); 3966a2f47caSMike Travis return cpu_mask_none; 3976a2f47caSMike Travis } 398378b39a4SYinghai Lu return node_to_cpumask_map[node]; 399378b39a4SYinghai Lu } 400378b39a4SYinghai Lu EXPORT_SYMBOL(node_to_cpumask); 401378b39a4SYinghai Lu 402378b39a4SYinghai Lu /* 403378b39a4SYinghai Lu * --------- end of debug versions of the numa functions --------- 404378b39a4SYinghai Lu */ 405378b39a4SYinghai Lu 406378b39a4SYinghai Lu #endif /* CONFIG_DEBUG_PER_CPU_MAPS */ 407378b39a4SYinghai Lu 408378b39a4SYinghai Lu #endif /* X86_64_NUMA */ 409378b39a4SYinghai Lu 410