xref: /linux/arch/x86/kernel/setup_percpu.c (revision 378b39a4f91ab0846eb6e13d47ea812bc82b44d9)
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