8c5beb50d3
Because of the size limits of struct boot_params (zero page), the maximum number of E820 memory map entries can be passed to kernel is 128. As pointed by Paul Jackson, there is some machine produced by SGI with so many nodes that the number of E820 memory map entries is more than 128. To enabling Linux kernel on these system, a new setup data type named SETUP_E820_EXT is defined to pass additional memory map entries to Linux kernel. This patch is based on x86/auto-latest branch of git-x86 tree and has been tested on x86_64 and i386 platform. Signed-off-by: Huang Ying <ying.huang@intel.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
165 lines
4 KiB
C
165 lines
4 KiB
C
#include <linux/kernel.h>
|
|
#include <linux/module.h>
|
|
#include <linux/init.h>
|
|
#include <linux/bootmem.h>
|
|
#include <linux/percpu.h>
|
|
#include <asm/smp.h>
|
|
#include <asm/percpu.h>
|
|
#include <asm/sections.h>
|
|
#include <asm/processor.h>
|
|
#include <asm/setup.h>
|
|
#include <asm/topology.h>
|
|
#include <asm/mpspec.h>
|
|
#include <asm/apicdef.h>
|
|
|
|
#ifdef CONFIG_X86_LOCAL_APIC
|
|
unsigned int num_processors;
|
|
unsigned disabled_cpus __cpuinitdata;
|
|
/* Processor that is doing the boot up */
|
|
unsigned int boot_cpu_physical_apicid = -1U;
|
|
unsigned int max_physical_apicid;
|
|
EXPORT_SYMBOL(boot_cpu_physical_apicid);
|
|
|
|
DEFINE_PER_CPU(u16, x86_cpu_to_apicid) = BAD_APICID;
|
|
EXPORT_PER_CPU_SYMBOL(x86_cpu_to_apicid);
|
|
|
|
/* Bitmask of physically existing CPUs */
|
|
physid_mask_t phys_cpu_present_map;
|
|
#endif
|
|
|
|
#if defined(CONFIG_HAVE_SETUP_PER_CPU_AREA) && defined(CONFIG_X86_SMP)
|
|
/*
|
|
* Copy data used in early init routines from the initial arrays to the
|
|
* per cpu data areas. These arrays then become expendable and the
|
|
* *_early_ptr's are zeroed indicating that the static arrays are gone.
|
|
*/
|
|
static void __init setup_per_cpu_maps(void)
|
|
{
|
|
int cpu;
|
|
|
|
for_each_possible_cpu(cpu) {
|
|
per_cpu(x86_cpu_to_apicid, cpu) = x86_cpu_to_apicid_init[cpu];
|
|
per_cpu(x86_bios_cpu_apicid, cpu) =
|
|
x86_bios_cpu_apicid_init[cpu];
|
|
#ifdef CONFIG_NUMA
|
|
per_cpu(x86_cpu_to_node_map, cpu) =
|
|
x86_cpu_to_node_map_init[cpu];
|
|
#endif
|
|
}
|
|
|
|
/* indicate the early static arrays will soon be gone */
|
|
x86_cpu_to_apicid_early_ptr = NULL;
|
|
x86_bios_cpu_apicid_early_ptr = NULL;
|
|
#ifdef CONFIG_NUMA
|
|
x86_cpu_to_node_map_early_ptr = NULL;
|
|
#endif
|
|
}
|
|
|
|
#ifdef CONFIG_HAVE_CPUMASK_OF_CPU_MAP
|
|
cpumask_t *cpumask_of_cpu_map __read_mostly;
|
|
EXPORT_SYMBOL(cpumask_of_cpu_map);
|
|
|
|
/* requires nr_cpu_ids to be initialized */
|
|
static void __init setup_cpumask_of_cpu(void)
|
|
{
|
|
int i;
|
|
|
|
/* alloc_bootmem zeroes memory */
|
|
cpumask_of_cpu_map = alloc_bootmem_low(sizeof(cpumask_t) * nr_cpu_ids);
|
|
for (i = 0; i < nr_cpu_ids; i++)
|
|
cpu_set(i, cpumask_of_cpu_map[i]);
|
|
}
|
|
#else
|
|
static inline void setup_cpumask_of_cpu(void) { }
|
|
#endif
|
|
|
|
#ifdef CONFIG_X86_32
|
|
/*
|
|
* Great future not-so-futuristic plan: make i386 and x86_64 do it
|
|
* the same way
|
|
*/
|
|
unsigned long __per_cpu_offset[NR_CPUS] __read_mostly;
|
|
EXPORT_SYMBOL(__per_cpu_offset);
|
|
#endif
|
|
|
|
/*
|
|
* Great future plan:
|
|
* Declare PDA itself and support (irqstack,tss,pgd) as per cpu data.
|
|
* Always point %gs to its beginning
|
|
*/
|
|
void __init setup_per_cpu_areas(void)
|
|
{
|
|
int i, highest_cpu = 0;
|
|
unsigned long size;
|
|
|
|
#ifdef CONFIG_HOTPLUG_CPU
|
|
prefill_possible_map();
|
|
#endif
|
|
|
|
/* Copy section for each CPU (we discard the original) */
|
|
size = PERCPU_ENOUGH_ROOM;
|
|
printk(KERN_INFO "PERCPU: Allocating %lu bytes of per cpu data\n",
|
|
size);
|
|
|
|
for_each_possible_cpu(i) {
|
|
char *ptr;
|
|
#ifndef CONFIG_NEED_MULTIPLE_NODES
|
|
ptr = alloc_bootmem_pages(size);
|
|
#else
|
|
int node = early_cpu_to_node(i);
|
|
if (!node_online(node) || !NODE_DATA(node)) {
|
|
ptr = alloc_bootmem_pages(size);
|
|
printk(KERN_INFO
|
|
"cpu %d has no node or node-local memory\n", i);
|
|
}
|
|
else
|
|
ptr = alloc_bootmem_pages_node(NODE_DATA(node), size);
|
|
#endif
|
|
if (!ptr)
|
|
panic("Cannot allocate cpu data for CPU %d\n", i);
|
|
#ifdef CONFIG_X86_64
|
|
cpu_pda(i)->data_offset = ptr - __per_cpu_start;
|
|
#else
|
|
__per_cpu_offset[i] = ptr - __per_cpu_start;
|
|
#endif
|
|
memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start);
|
|
|
|
highest_cpu = i;
|
|
}
|
|
|
|
nr_cpu_ids = highest_cpu + 1;
|
|
printk(KERN_DEBUG "NR_CPUS: %d, nr_cpu_ids: %d\n", NR_CPUS, nr_cpu_ids);
|
|
|
|
/* Setup percpu data maps */
|
|
setup_per_cpu_maps();
|
|
|
|
/* Setup cpumask_of_cpu map */
|
|
setup_cpumask_of_cpu();
|
|
}
|
|
|
|
#endif
|
|
|
|
void __init parse_setup_data(void)
|
|
{
|
|
struct setup_data *data;
|
|
u64 pa_data;
|
|
|
|
if (boot_params.hdr.version < 0x0209)
|
|
return;
|
|
pa_data = boot_params.hdr.setup_data;
|
|
while (pa_data) {
|
|
data = early_ioremap(pa_data, PAGE_SIZE);
|
|
switch (data->type) {
|
|
case SETUP_E820_EXT:
|
|
parse_e820_ext(data, pa_data);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
#ifndef CONFIG_DEBUG_BOOT_PARAMS
|
|
free_early(pa_data, pa_data+sizeof(*data)+data->len);
|
|
#endif
|
|
pa_data = data->next;
|
|
early_iounmap(data, PAGE_SIZE);
|
|
}
|
|
}
|