1*378b39a4SYinghai Lu #include <linux/kernel.h> 2*378b39a4SYinghai Lu #include <linux/module.h> 3*378b39a4SYinghai Lu #include <linux/init.h> 4*378b39a4SYinghai Lu #include <linux/bootmem.h> 5*378b39a4SYinghai Lu #include <linux/percpu.h> 6*378b39a4SYinghai Lu #include <linux/kexec.h> 7*378b39a4SYinghai Lu #include <linux/crash_dump.h> 8*378b39a4SYinghai Lu #include <asm/smp.h> 9*378b39a4SYinghai Lu #include <asm/percpu.h> 10*378b39a4SYinghai Lu #include <asm/sections.h> 11*378b39a4SYinghai Lu #include <asm/processor.h> 12*378b39a4SYinghai Lu #include <asm/setup.h> 13*378b39a4SYinghai Lu #include <asm/topology.h> 14*378b39a4SYinghai Lu #include <asm/mpspec.h> 15*378b39a4SYinghai Lu #include <asm/apicdef.h> 16*378b39a4SYinghai Lu #include <asm/highmem.h> 17*378b39a4SYinghai Lu 18*378b39a4SYinghai Lu #ifndef CONFIG_DEBUG_BOOT_PARAMS 19*378b39a4SYinghai Lu struct boot_params __initdata boot_params; 20*378b39a4SYinghai Lu #else 21*378b39a4SYinghai Lu struct boot_params boot_params; 22*378b39a4SYinghai Lu #endif 23*378b39a4SYinghai Lu 24*378b39a4SYinghai Lu #ifdef CONFIG_X86_LOCAL_APIC 25*378b39a4SYinghai Lu unsigned int num_processors; 26*378b39a4SYinghai Lu unsigned disabled_cpus __cpuinitdata; 27*378b39a4SYinghai Lu /* Processor that is doing the boot up */ 28*378b39a4SYinghai Lu unsigned int boot_cpu_physical_apicid = -1U; 29*378b39a4SYinghai Lu unsigned int max_physical_apicid; 30*378b39a4SYinghai Lu EXPORT_SYMBOL(boot_cpu_physical_apicid); 31*378b39a4SYinghai Lu 32*378b39a4SYinghai Lu /* Bitmask of physically existing CPUs */ 33*378b39a4SYinghai Lu physid_mask_t phys_cpu_present_map; 34*378b39a4SYinghai Lu #endif 35*378b39a4SYinghai Lu 36*378b39a4SYinghai Lu /* map cpu index to physical APIC ID */ 37*378b39a4SYinghai Lu DEFINE_EARLY_PER_CPU(u16, x86_cpu_to_apicid, BAD_APICID); 38*378b39a4SYinghai Lu DEFINE_EARLY_PER_CPU(u16, x86_bios_cpu_apicid, BAD_APICID); 39*378b39a4SYinghai Lu EXPORT_EARLY_PER_CPU_SYMBOL(x86_cpu_to_apicid); 40*378b39a4SYinghai Lu EXPORT_EARLY_PER_CPU_SYMBOL(x86_bios_cpu_apicid); 41*378b39a4SYinghai Lu 42*378b39a4SYinghai Lu #if defined(CONFIG_NUMA) && defined(CONFIG_X86_64) 43*378b39a4SYinghai Lu #define X86_64_NUMA 1 44*378b39a4SYinghai Lu 45*378b39a4SYinghai Lu /* map cpu index to node index */ 46*378b39a4SYinghai Lu DEFINE_EARLY_PER_CPU(int, x86_cpu_to_node_map, NUMA_NO_NODE); 47*378b39a4SYinghai Lu EXPORT_EARLY_PER_CPU_SYMBOL(x86_cpu_to_node_map); 48*378b39a4SYinghai Lu 49*378b39a4SYinghai Lu /* which logical CPUs are on which nodes */ 50*378b39a4SYinghai Lu cpumask_t *node_to_cpumask_map; 51*378b39a4SYinghai Lu EXPORT_SYMBOL(node_to_cpumask_map); 52*378b39a4SYinghai Lu 53*378b39a4SYinghai Lu /* setup node_to_cpumask_map */ 54*378b39a4SYinghai Lu static void __init setup_node_to_cpumask_map(void); 55*378b39a4SYinghai Lu 56*378b39a4SYinghai Lu #else 57*378b39a4SYinghai Lu static inline void setup_node_to_cpumask_map(void) { } 58*378b39a4SYinghai Lu #endif 59*378b39a4SYinghai Lu 60*378b39a4SYinghai Lu #if defined(CONFIG_HAVE_SETUP_PER_CPU_AREA) && defined(CONFIG_X86_SMP) 61*378b39a4SYinghai Lu /* 62*378b39a4SYinghai Lu * Copy data used in early init routines from the initial arrays to the 63*378b39a4SYinghai Lu * per cpu data areas. These arrays then become expendable and the 64*378b39a4SYinghai Lu * *_early_ptr's are zeroed indicating that the static arrays are gone. 65*378b39a4SYinghai Lu */ 66*378b39a4SYinghai Lu static void __init setup_per_cpu_maps(void) 67*378b39a4SYinghai Lu { 68*378b39a4SYinghai Lu int cpu; 69*378b39a4SYinghai Lu 70*378b39a4SYinghai Lu for_each_possible_cpu(cpu) { 71*378b39a4SYinghai Lu per_cpu(x86_cpu_to_apicid, cpu) = 72*378b39a4SYinghai Lu early_per_cpu_map(x86_cpu_to_apicid, cpu); 73*378b39a4SYinghai Lu per_cpu(x86_bios_cpu_apicid, cpu) = 74*378b39a4SYinghai Lu early_per_cpu_map(x86_bios_cpu_apicid, cpu); 75*378b39a4SYinghai Lu #ifdef X86_64_NUMA 76*378b39a4SYinghai Lu per_cpu(x86_cpu_to_node_map, cpu) = 77*378b39a4SYinghai Lu early_per_cpu_map(x86_cpu_to_node_map, cpu); 78*378b39a4SYinghai Lu #endif 79*378b39a4SYinghai Lu } 80*378b39a4SYinghai Lu 81*378b39a4SYinghai Lu /* indicate the early static arrays will soon be gone */ 82*378b39a4SYinghai Lu early_per_cpu_ptr(x86_cpu_to_apicid) = NULL; 83*378b39a4SYinghai Lu early_per_cpu_ptr(x86_bios_cpu_apicid) = NULL; 84*378b39a4SYinghai Lu #ifdef X86_64_NUMA 85*378b39a4SYinghai Lu early_per_cpu_ptr(x86_cpu_to_node_map) = NULL; 86*378b39a4SYinghai Lu #endif 87*378b39a4SYinghai Lu } 88*378b39a4SYinghai Lu 89*378b39a4SYinghai Lu #ifdef CONFIG_HAVE_CPUMASK_OF_CPU_MAP 90*378b39a4SYinghai Lu cpumask_t *cpumask_of_cpu_map __read_mostly; 91*378b39a4SYinghai Lu EXPORT_SYMBOL(cpumask_of_cpu_map); 92*378b39a4SYinghai Lu 93*378b39a4SYinghai Lu /* requires nr_cpu_ids to be initialized */ 94*378b39a4SYinghai Lu static void __init setup_cpumask_of_cpu(void) 95*378b39a4SYinghai Lu { 96*378b39a4SYinghai Lu int i; 97*378b39a4SYinghai Lu 98*378b39a4SYinghai Lu /* alloc_bootmem zeroes memory */ 99*378b39a4SYinghai Lu cpumask_of_cpu_map = alloc_bootmem_low(sizeof(cpumask_t) * nr_cpu_ids); 100*378b39a4SYinghai Lu for (i = 0; i < nr_cpu_ids; i++) 101*378b39a4SYinghai Lu cpu_set(i, cpumask_of_cpu_map[i]); 102*378b39a4SYinghai Lu } 103*378b39a4SYinghai Lu #else 104*378b39a4SYinghai Lu static inline void setup_cpumask_of_cpu(void) { } 105*378b39a4SYinghai Lu #endif 106*378b39a4SYinghai Lu 107*378b39a4SYinghai Lu #ifdef CONFIG_X86_32 108*378b39a4SYinghai Lu /* 109*378b39a4SYinghai Lu * Great future not-so-futuristic plan: make i386 and x86_64 do it 110*378b39a4SYinghai Lu * the same way 111*378b39a4SYinghai Lu */ 112*378b39a4SYinghai Lu unsigned long __per_cpu_offset[NR_CPUS] __read_mostly; 113*378b39a4SYinghai Lu EXPORT_SYMBOL(__per_cpu_offset); 114*378b39a4SYinghai Lu static inline void setup_cpu_pda_map(void) { } 115*378b39a4SYinghai Lu 116*378b39a4SYinghai Lu #elif !defined(CONFIG_SMP) 117*378b39a4SYinghai Lu static inline void setup_cpu_pda_map(void) { } 118*378b39a4SYinghai Lu 119*378b39a4SYinghai Lu #else /* CONFIG_SMP && CONFIG_X86_64 */ 120*378b39a4SYinghai Lu 121*378b39a4SYinghai Lu /* 122*378b39a4SYinghai Lu * Allocate cpu_pda pointer table and array via alloc_bootmem. 123*378b39a4SYinghai Lu */ 124*378b39a4SYinghai Lu static void __init setup_cpu_pda_map(void) 125*378b39a4SYinghai Lu { 126*378b39a4SYinghai Lu char *pda; 127*378b39a4SYinghai Lu struct x8664_pda **new_cpu_pda; 128*378b39a4SYinghai Lu unsigned long size; 129*378b39a4SYinghai Lu int cpu; 130*378b39a4SYinghai Lu 131*378b39a4SYinghai Lu size = roundup(sizeof(struct x8664_pda), cache_line_size()); 132*378b39a4SYinghai Lu 133*378b39a4SYinghai Lu /* allocate cpu_pda array and pointer table */ 134*378b39a4SYinghai Lu { 135*378b39a4SYinghai Lu unsigned long tsize = nr_cpu_ids * sizeof(void *); 136*378b39a4SYinghai Lu unsigned long asize = size * (nr_cpu_ids - 1); 137*378b39a4SYinghai Lu 138*378b39a4SYinghai Lu tsize = roundup(tsize, cache_line_size()); 139*378b39a4SYinghai Lu new_cpu_pda = alloc_bootmem(tsize + asize); 140*378b39a4SYinghai Lu pda = (char *)new_cpu_pda + tsize; 141*378b39a4SYinghai Lu } 142*378b39a4SYinghai Lu 143*378b39a4SYinghai Lu /* initialize pointer table to static pda's */ 144*378b39a4SYinghai Lu for_each_possible_cpu(cpu) { 145*378b39a4SYinghai Lu if (cpu == 0) { 146*378b39a4SYinghai Lu /* leave boot cpu pda in place */ 147*378b39a4SYinghai Lu new_cpu_pda[0] = cpu_pda(0); 148*378b39a4SYinghai Lu continue; 149*378b39a4SYinghai Lu } 150*378b39a4SYinghai Lu new_cpu_pda[cpu] = (struct x8664_pda *)pda; 151*378b39a4SYinghai Lu new_cpu_pda[cpu]->in_bootmem = 1; 152*378b39a4SYinghai Lu pda += size; 153*378b39a4SYinghai Lu } 154*378b39a4SYinghai Lu 155*378b39a4SYinghai Lu /* point to new pointer table */ 156*378b39a4SYinghai Lu _cpu_pda = new_cpu_pda; 157*378b39a4SYinghai Lu } 158*378b39a4SYinghai Lu #endif 159*378b39a4SYinghai Lu 160*378b39a4SYinghai Lu /* 161*378b39a4SYinghai Lu * Great future plan: 162*378b39a4SYinghai Lu * Declare PDA itself and support (irqstack,tss,pgd) as per cpu data. 163*378b39a4SYinghai Lu * Always point %gs to its beginning 164*378b39a4SYinghai Lu */ 165*378b39a4SYinghai Lu void __init setup_per_cpu_areas(void) 166*378b39a4SYinghai Lu { 167*378b39a4SYinghai Lu ssize_t size = PERCPU_ENOUGH_ROOM; 168*378b39a4SYinghai Lu char *ptr; 169*378b39a4SYinghai Lu int cpu; 170*378b39a4SYinghai Lu 171*378b39a4SYinghai Lu /* no processor from mptable or madt */ 172*378b39a4SYinghai Lu if (!num_processors) 173*378b39a4SYinghai Lu num_processors = 1; 174*378b39a4SYinghai Lu 175*378b39a4SYinghai Lu #ifdef CONFIG_HOTPLUG_CPU 176*378b39a4SYinghai Lu prefill_possible_map(); 177*378b39a4SYinghai Lu #else 178*378b39a4SYinghai Lu nr_cpu_ids = num_processors; 179*378b39a4SYinghai Lu #endif 180*378b39a4SYinghai Lu 181*378b39a4SYinghai Lu /* Setup cpu_pda map */ 182*378b39a4SYinghai Lu setup_cpu_pda_map(); 183*378b39a4SYinghai Lu 184*378b39a4SYinghai Lu /* Copy section for each CPU (we discard the original) */ 185*378b39a4SYinghai Lu size = PERCPU_ENOUGH_ROOM; 186*378b39a4SYinghai Lu printk(KERN_INFO "PERCPU: Allocating %zd bytes of per cpu data\n", 187*378b39a4SYinghai Lu size); 188*378b39a4SYinghai Lu 189*378b39a4SYinghai Lu for_each_possible_cpu(cpu) { 190*378b39a4SYinghai Lu #ifndef CONFIG_NEED_MULTIPLE_NODES 191*378b39a4SYinghai Lu ptr = alloc_bootmem_pages(size); 192*378b39a4SYinghai Lu #else 193*378b39a4SYinghai Lu int node = early_cpu_to_node(cpu); 194*378b39a4SYinghai Lu if (!node_online(node) || !NODE_DATA(node)) { 195*378b39a4SYinghai Lu ptr = alloc_bootmem_pages(size); 196*378b39a4SYinghai Lu printk(KERN_INFO 197*378b39a4SYinghai Lu "cpu %d has no node %d or node-local memory\n", 198*378b39a4SYinghai Lu cpu, node); 199*378b39a4SYinghai Lu } 200*378b39a4SYinghai Lu else 201*378b39a4SYinghai Lu ptr = alloc_bootmem_pages_node(NODE_DATA(node), size); 202*378b39a4SYinghai Lu #endif 203*378b39a4SYinghai Lu per_cpu_offset(cpu) = ptr - __per_cpu_start; 204*378b39a4SYinghai Lu memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start); 205*378b39a4SYinghai Lu 206*378b39a4SYinghai Lu } 207*378b39a4SYinghai Lu 208*378b39a4SYinghai Lu printk(KERN_DEBUG "NR_CPUS: %d, nr_cpu_ids: %d, nr_node_ids %d\n", 209*378b39a4SYinghai Lu NR_CPUS, nr_cpu_ids, nr_node_ids); 210*378b39a4SYinghai Lu 211*378b39a4SYinghai Lu /* Setup percpu data maps */ 212*378b39a4SYinghai Lu setup_per_cpu_maps(); 213*378b39a4SYinghai Lu 214*378b39a4SYinghai Lu /* Setup node to cpumask map */ 215*378b39a4SYinghai Lu setup_node_to_cpumask_map(); 216*378b39a4SYinghai Lu 217*378b39a4SYinghai Lu /* Setup cpumask_of_cpu map */ 218*378b39a4SYinghai Lu setup_cpumask_of_cpu(); 219*378b39a4SYinghai Lu } 220*378b39a4SYinghai Lu 221*378b39a4SYinghai Lu #endif 222*378b39a4SYinghai Lu 223*378b39a4SYinghai Lu void __init parse_setup_data(void) 224*378b39a4SYinghai Lu { 225*378b39a4SYinghai Lu struct setup_data *data; 226*378b39a4SYinghai Lu u64 pa_data; 227*378b39a4SYinghai Lu 228*378b39a4SYinghai Lu if (boot_params.hdr.version < 0x0209) 229*378b39a4SYinghai Lu return; 230*378b39a4SYinghai Lu pa_data = boot_params.hdr.setup_data; 231*378b39a4SYinghai Lu while (pa_data) { 232*378b39a4SYinghai Lu data = early_ioremap(pa_data, PAGE_SIZE); 233*378b39a4SYinghai Lu switch (data->type) { 234*378b39a4SYinghai Lu case SETUP_E820_EXT: 235*378b39a4SYinghai Lu parse_e820_ext(data, pa_data); 236*378b39a4SYinghai Lu break; 237*378b39a4SYinghai Lu default: 238*378b39a4SYinghai Lu break; 239*378b39a4SYinghai Lu } 240*378b39a4SYinghai Lu #ifndef CONFIG_DEBUG_BOOT_PARAMS 241*378b39a4SYinghai Lu free_early(pa_data, pa_data+sizeof(*data)+data->len); 242*378b39a4SYinghai Lu #endif 243*378b39a4SYinghai Lu pa_data = data->next; 244*378b39a4SYinghai Lu early_iounmap(data, PAGE_SIZE); 245*378b39a4SYinghai Lu } 246*378b39a4SYinghai Lu } 247*378b39a4SYinghai Lu 248*378b39a4SYinghai Lu #ifdef X86_64_NUMA 249*378b39a4SYinghai Lu 250*378b39a4SYinghai Lu /* 251*378b39a4SYinghai Lu * Allocate node_to_cpumask_map based on number of available nodes 252*378b39a4SYinghai Lu * Requires node_possible_map to be valid. 253*378b39a4SYinghai Lu * 254*378b39a4SYinghai Lu * Note: node_to_cpumask() is not valid until after this is done. 255*378b39a4SYinghai Lu */ 256*378b39a4SYinghai Lu static void __init setup_node_to_cpumask_map(void) 257*378b39a4SYinghai Lu { 258*378b39a4SYinghai Lu unsigned int node, num = 0; 259*378b39a4SYinghai Lu cpumask_t *map; 260*378b39a4SYinghai Lu 261*378b39a4SYinghai Lu /* setup nr_node_ids if not done yet */ 262*378b39a4SYinghai Lu if (nr_node_ids == MAX_NUMNODES) { 263*378b39a4SYinghai Lu for_each_node_mask(node, node_possible_map) 264*378b39a4SYinghai Lu num = node; 265*378b39a4SYinghai Lu nr_node_ids = num + 1; 266*378b39a4SYinghai Lu } 267*378b39a4SYinghai Lu 268*378b39a4SYinghai Lu /* allocate the map */ 269*378b39a4SYinghai Lu map = alloc_bootmem_low(nr_node_ids * sizeof(cpumask_t)); 270*378b39a4SYinghai Lu 271*378b39a4SYinghai Lu Dprintk(KERN_DEBUG "Node to cpumask map at %p for %d nodes\n", 272*378b39a4SYinghai Lu map, nr_node_ids); 273*378b39a4SYinghai Lu 274*378b39a4SYinghai Lu /* node_to_cpumask() will now work */ 275*378b39a4SYinghai Lu node_to_cpumask_map = map; 276*378b39a4SYinghai Lu } 277*378b39a4SYinghai Lu 278*378b39a4SYinghai Lu void __cpuinit numa_set_node(int cpu, int node) 279*378b39a4SYinghai Lu { 280*378b39a4SYinghai Lu int *cpu_to_node_map = early_per_cpu_ptr(x86_cpu_to_node_map); 281*378b39a4SYinghai Lu 282*378b39a4SYinghai Lu if (cpu_pda(cpu) && node != NUMA_NO_NODE) 283*378b39a4SYinghai Lu cpu_pda(cpu)->nodenumber = node; 284*378b39a4SYinghai Lu 285*378b39a4SYinghai Lu if (cpu_to_node_map) 286*378b39a4SYinghai Lu cpu_to_node_map[cpu] = node; 287*378b39a4SYinghai Lu 288*378b39a4SYinghai Lu else if (per_cpu_offset(cpu)) 289*378b39a4SYinghai Lu per_cpu(x86_cpu_to_node_map, cpu) = node; 290*378b39a4SYinghai Lu 291*378b39a4SYinghai Lu else 292*378b39a4SYinghai Lu Dprintk(KERN_INFO "Setting node for non-present cpu %d\n", cpu); 293*378b39a4SYinghai Lu } 294*378b39a4SYinghai Lu 295*378b39a4SYinghai Lu void __cpuinit numa_clear_node(int cpu) 296*378b39a4SYinghai Lu { 297*378b39a4SYinghai Lu numa_set_node(cpu, NUMA_NO_NODE); 298*378b39a4SYinghai Lu } 299*378b39a4SYinghai Lu 300*378b39a4SYinghai Lu #ifndef CONFIG_DEBUG_PER_CPU_MAPS 301*378b39a4SYinghai Lu 302*378b39a4SYinghai Lu void __cpuinit numa_add_cpu(int cpu) 303*378b39a4SYinghai Lu { 304*378b39a4SYinghai Lu cpu_set(cpu, node_to_cpumask_map[early_cpu_to_node(cpu)]); 305*378b39a4SYinghai Lu } 306*378b39a4SYinghai Lu 307*378b39a4SYinghai Lu void __cpuinit numa_remove_cpu(int cpu) 308*378b39a4SYinghai Lu { 309*378b39a4SYinghai Lu cpu_clear(cpu, node_to_cpumask_map[cpu_to_node(cpu)]); 310*378b39a4SYinghai Lu } 311*378b39a4SYinghai Lu 312*378b39a4SYinghai Lu #else /* CONFIG_DEBUG_PER_CPU_MAPS */ 313*378b39a4SYinghai Lu 314*378b39a4SYinghai Lu /* 315*378b39a4SYinghai Lu * --------- debug versions of the numa functions --------- 316*378b39a4SYinghai Lu */ 317*378b39a4SYinghai Lu static void __cpuinit numa_set_cpumask(int cpu, int enable) 318*378b39a4SYinghai Lu { 319*378b39a4SYinghai Lu int node = cpu_to_node(cpu); 320*378b39a4SYinghai Lu cpumask_t *mask; 321*378b39a4SYinghai Lu char buf[64]; 322*378b39a4SYinghai Lu 323*378b39a4SYinghai Lu if (node_to_cpumask_map == NULL) { 324*378b39a4SYinghai Lu printk(KERN_ERR "node_to_cpumask_map NULL\n"); 325*378b39a4SYinghai Lu dump_stack(); 326*378b39a4SYinghai Lu return; 327*378b39a4SYinghai Lu } 328*378b39a4SYinghai Lu 329*378b39a4SYinghai Lu mask = &node_to_cpumask_map[node]; 330*378b39a4SYinghai Lu if (enable) 331*378b39a4SYinghai Lu cpu_set(cpu, *mask); 332*378b39a4SYinghai Lu else 333*378b39a4SYinghai Lu cpu_clear(cpu, *mask); 334*378b39a4SYinghai Lu 335*378b39a4SYinghai Lu cpulist_scnprintf(buf, sizeof(buf), *mask); 336*378b39a4SYinghai Lu printk(KERN_DEBUG "%s cpu %d node %d: mask now %s\n", 337*378b39a4SYinghai Lu enable? "numa_add_cpu":"numa_remove_cpu", cpu, node, buf); 338*378b39a4SYinghai Lu } 339*378b39a4SYinghai Lu 340*378b39a4SYinghai Lu void __cpuinit numa_add_cpu(int cpu) 341*378b39a4SYinghai Lu { 342*378b39a4SYinghai Lu numa_set_cpumask(cpu, 1); 343*378b39a4SYinghai Lu } 344*378b39a4SYinghai Lu 345*378b39a4SYinghai Lu void __cpuinit numa_remove_cpu(int cpu) 346*378b39a4SYinghai Lu { 347*378b39a4SYinghai Lu numa_set_cpumask(cpu, 0); 348*378b39a4SYinghai Lu } 349*378b39a4SYinghai Lu 350*378b39a4SYinghai Lu int cpu_to_node(int cpu) 351*378b39a4SYinghai Lu { 352*378b39a4SYinghai Lu if (early_per_cpu_ptr(x86_cpu_to_node_map)) { 353*378b39a4SYinghai Lu printk(KERN_WARNING 354*378b39a4SYinghai Lu "cpu_to_node(%d): usage too early!\n", cpu); 355*378b39a4SYinghai Lu dump_stack(); 356*378b39a4SYinghai Lu return early_per_cpu_ptr(x86_cpu_to_node_map)[cpu]; 357*378b39a4SYinghai Lu } 358*378b39a4SYinghai Lu return per_cpu(x86_cpu_to_node_map, cpu); 359*378b39a4SYinghai Lu } 360*378b39a4SYinghai Lu EXPORT_SYMBOL(cpu_to_node); 361*378b39a4SYinghai Lu 362*378b39a4SYinghai Lu /* 363*378b39a4SYinghai Lu * Same function as cpu_to_node() but used if called before the 364*378b39a4SYinghai Lu * per_cpu areas are setup. 365*378b39a4SYinghai Lu */ 366*378b39a4SYinghai Lu int early_cpu_to_node(int cpu) 367*378b39a4SYinghai Lu { 368*378b39a4SYinghai Lu if (early_per_cpu_ptr(x86_cpu_to_node_map)) 369*378b39a4SYinghai Lu return early_per_cpu_ptr(x86_cpu_to_node_map)[cpu]; 370*378b39a4SYinghai Lu 371*378b39a4SYinghai Lu if (!per_cpu_offset(cpu)) { 372*378b39a4SYinghai Lu printk(KERN_WARNING 373*378b39a4SYinghai Lu "early_cpu_to_node(%d): no per_cpu area!\n", cpu); 374*378b39a4SYinghai Lu dump_stack(); 375*378b39a4SYinghai Lu return NUMA_NO_NODE; 376*378b39a4SYinghai Lu } 377*378b39a4SYinghai Lu return per_cpu(x86_cpu_to_node_map, cpu); 378*378b39a4SYinghai Lu } 379*378b39a4SYinghai Lu 380*378b39a4SYinghai Lu /* 381*378b39a4SYinghai Lu * Returns a pointer to the bitmask of CPUs on Node 'node'. 382*378b39a4SYinghai Lu */ 383*378b39a4SYinghai Lu cpumask_t *_node_to_cpumask_ptr(int node) 384*378b39a4SYinghai Lu { 385*378b39a4SYinghai Lu if (node_to_cpumask_map == NULL) { 386*378b39a4SYinghai Lu printk(KERN_WARNING 387*378b39a4SYinghai Lu "_node_to_cpumask_ptr(%d): no node_to_cpumask_map!\n", 388*378b39a4SYinghai Lu node); 389*378b39a4SYinghai Lu dump_stack(); 390*378b39a4SYinghai Lu return &cpu_online_map; 391*378b39a4SYinghai Lu } 392*378b39a4SYinghai Lu BUG_ON(node >= nr_node_ids); 393*378b39a4SYinghai Lu return &node_to_cpumask_map[node]; 394*378b39a4SYinghai Lu } 395*378b39a4SYinghai Lu EXPORT_SYMBOL(_node_to_cpumask_ptr); 396*378b39a4SYinghai Lu 397*378b39a4SYinghai Lu /* 398*378b39a4SYinghai Lu * Returns a bitmask of CPUs on Node 'node'. 399*378b39a4SYinghai Lu */ 400*378b39a4SYinghai Lu cpumask_t node_to_cpumask(int node) 401*378b39a4SYinghai Lu { 402*378b39a4SYinghai Lu if (node_to_cpumask_map == NULL) { 403*378b39a4SYinghai Lu printk(KERN_WARNING 404*378b39a4SYinghai Lu "node_to_cpumask(%d): no node_to_cpumask_map!\n", node); 405*378b39a4SYinghai Lu dump_stack(); 406*378b39a4SYinghai Lu return cpu_online_map; 407*378b39a4SYinghai Lu } 408*378b39a4SYinghai Lu BUG_ON(node >= nr_node_ids); 409*378b39a4SYinghai Lu return node_to_cpumask_map[node]; 410*378b39a4SYinghai Lu } 411*378b39a4SYinghai Lu EXPORT_SYMBOL(node_to_cpumask); 412*378b39a4SYinghai Lu 413*378b39a4SYinghai Lu /* 414*378b39a4SYinghai Lu * --------- end of debug versions of the numa functions --------- 415*378b39a4SYinghai Lu */ 416*378b39a4SYinghai Lu 417*378b39a4SYinghai Lu #endif /* CONFIG_DEBUG_PER_CPU_MAPS */ 418*378b39a4SYinghai Lu 419*378b39a4SYinghai Lu #endif /* X86_64_NUMA */ 420*378b39a4SYinghai Lu 421*378b39a4SYinghai Lu 422*378b39a4SYinghai Lu /* 423*378b39a4SYinghai Lu * --------- Crashkernel reservation ------------------------------ 424*378b39a4SYinghai Lu */ 425*378b39a4SYinghai Lu 426*378b39a4SYinghai Lu static inline unsigned long long get_total_mem(void) 427*378b39a4SYinghai Lu { 428*378b39a4SYinghai Lu unsigned long long total; 429*378b39a4SYinghai Lu 430*378b39a4SYinghai Lu total = max_low_pfn - min_low_pfn; 431*378b39a4SYinghai Lu #ifdef CONFIG_HIGHMEM 432*378b39a4SYinghai Lu total += highend_pfn - highstart_pfn; 433*378b39a4SYinghai Lu #endif 434*378b39a4SYinghai Lu 435*378b39a4SYinghai Lu return total << PAGE_SHIFT; 436*378b39a4SYinghai Lu } 437*378b39a4SYinghai Lu 438*378b39a4SYinghai Lu #ifdef CONFIG_KEXEC 439*378b39a4SYinghai Lu void __init reserve_crashkernel(void) 440*378b39a4SYinghai Lu { 441*378b39a4SYinghai Lu unsigned long long total_mem; 442*378b39a4SYinghai Lu unsigned long long crash_size, crash_base; 443*378b39a4SYinghai Lu int ret; 444*378b39a4SYinghai Lu 445*378b39a4SYinghai Lu total_mem = get_total_mem(); 446*378b39a4SYinghai Lu 447*378b39a4SYinghai Lu ret = parse_crashkernel(boot_command_line, total_mem, 448*378b39a4SYinghai Lu &crash_size, &crash_base); 449*378b39a4SYinghai Lu if (ret == 0 && crash_size > 0) { 450*378b39a4SYinghai Lu if (crash_base <= 0) { 451*378b39a4SYinghai Lu printk(KERN_INFO "crashkernel reservation failed - " 452*378b39a4SYinghai Lu "you have to specify a base address\n"); 453*378b39a4SYinghai Lu return; 454*378b39a4SYinghai Lu } 455*378b39a4SYinghai Lu 456*378b39a4SYinghai Lu if (reserve_bootmem_generic(crash_base, crash_size, 457*378b39a4SYinghai Lu BOOTMEM_EXCLUSIVE) < 0) { 458*378b39a4SYinghai Lu printk(KERN_INFO "crashkernel reservation failed - " 459*378b39a4SYinghai Lu "memory is in use\n"); 460*378b39a4SYinghai Lu return; 461*378b39a4SYinghai Lu } 462*378b39a4SYinghai Lu 463*378b39a4SYinghai Lu printk(KERN_INFO "Reserving %ldMB of memory at %ldMB " 464*378b39a4SYinghai Lu "for crashkernel (System RAM: %ldMB)\n", 465*378b39a4SYinghai Lu (unsigned long)(crash_size >> 20), 466*378b39a4SYinghai Lu (unsigned long)(crash_base >> 20), 467*378b39a4SYinghai Lu (unsigned long)(total_mem >> 20)); 468*378b39a4SYinghai Lu 469*378b39a4SYinghai Lu crashk_res.start = crash_base; 470*378b39a4SYinghai Lu crashk_res.end = crash_base + crash_size - 1; 471*378b39a4SYinghai Lu insert_resource(&iomem_resource, &crashk_res); 472*378b39a4SYinghai Lu } 473*378b39a4SYinghai Lu } 474*378b39a4SYinghai Lu #else 475*378b39a4SYinghai Lu void __init reserve_crashkernel(void) 476*378b39a4SYinghai Lu {} 477*378b39a4SYinghai Lu #endif 478*378b39a4SYinghai Lu static struct resource standard_io_resources[] = { 479*378b39a4SYinghai Lu { .name = "dma1", .start = 0x00, .end = 0x1f, 480*378b39a4SYinghai Lu .flags = IORESOURCE_BUSY | IORESOURCE_IO }, 481*378b39a4SYinghai Lu { .name = "pic1", .start = 0x20, .end = 0x21, 482*378b39a4SYinghai Lu .flags = IORESOURCE_BUSY | IORESOURCE_IO }, 483*378b39a4SYinghai Lu { .name = "timer0", .start = 0x40, .end = 0x43, 484*378b39a4SYinghai Lu .flags = IORESOURCE_BUSY | IORESOURCE_IO }, 485*378b39a4SYinghai Lu { .name = "timer1", .start = 0x50, .end = 0x53, 486*378b39a4SYinghai Lu .flags = IORESOURCE_BUSY | IORESOURCE_IO }, 487*378b39a4SYinghai Lu { .name = "keyboard", .start = 0x60, .end = 0x60, 488*378b39a4SYinghai Lu .flags = IORESOURCE_BUSY | IORESOURCE_IO }, 489*378b39a4SYinghai Lu { .name = "keyboard", .start = 0x64, .end = 0x64, 490*378b39a4SYinghai Lu .flags = IORESOURCE_BUSY | IORESOURCE_IO }, 491*378b39a4SYinghai Lu { .name = "dma page reg", .start = 0x80, .end = 0x8f, 492*378b39a4SYinghai Lu .flags = IORESOURCE_BUSY | IORESOURCE_IO }, 493*378b39a4SYinghai Lu { .name = "pic2", .start = 0xa0, .end = 0xa1, 494*378b39a4SYinghai Lu .flags = IORESOURCE_BUSY | IORESOURCE_IO }, 495*378b39a4SYinghai Lu { .name = "dma2", .start = 0xc0, .end = 0xdf, 496*378b39a4SYinghai Lu .flags = IORESOURCE_BUSY | IORESOURCE_IO }, 497*378b39a4SYinghai Lu { .name = "fpu", .start = 0xf0, .end = 0xff, 498*378b39a4SYinghai Lu .flags = IORESOURCE_BUSY | IORESOURCE_IO } 499*378b39a4SYinghai Lu }; 500*378b39a4SYinghai Lu 501*378b39a4SYinghai Lu void __init reserve_standard_io_resources(void) 502*378b39a4SYinghai Lu { 503*378b39a4SYinghai Lu int i; 504*378b39a4SYinghai Lu 505*378b39a4SYinghai Lu /* request I/O space for devices used on all i[345]86 PCs */ 506*378b39a4SYinghai Lu for (i = 0; i < ARRAY_SIZE(standard_io_resources); i++) 507*378b39a4SYinghai Lu request_resource(&ioport_resource, &standard_io_resources[i]); 508*378b39a4SYinghai Lu 509*378b39a4SYinghai Lu } 510*378b39a4SYinghai Lu 511*378b39a4SYinghai Lu #ifdef CONFIG_PROC_VMCORE 512*378b39a4SYinghai Lu /* elfcorehdr= specifies the location of elf core header 513*378b39a4SYinghai Lu * stored by the crashed kernel. This option will be passed 514*378b39a4SYinghai Lu * by kexec loader to the capture kernel. 515*378b39a4SYinghai Lu */ 516*378b39a4SYinghai Lu static int __init setup_elfcorehdr(char *arg) 517*378b39a4SYinghai Lu { 518*378b39a4SYinghai Lu char *end; 519*378b39a4SYinghai Lu if (!arg) 520*378b39a4SYinghai Lu return -EINVAL; 521*378b39a4SYinghai Lu elfcorehdr_addr = memparse(arg, &end); 522*378b39a4SYinghai Lu return end > arg ? 0 : -EINVAL; 523*378b39a4SYinghai Lu } 524*378b39a4SYinghai Lu early_param("elfcorehdr", setup_elfcorehdr); 525*378b39a4SYinghai Lu #endif 526*378b39a4SYinghai Lu 527*378b39a4SYinghai Lu 528*378b39a4SYinghai Lu 529