patch-2.4.23 linux-2.4.23/arch/ia64/kernel/setup.c
Next file: linux-2.4.23/arch/ia64/kernel/signal.c
Previous file: linux-2.4.23/arch/ia64/kernel/salinfo.c
Back to the patch index
Back to the overall index
- Lines: 276
- Date:
2003-11-28 10:26:19.000000000 -0800
- Orig file:
linux-2.4.22/arch/ia64/kernel/setup.c
- Orig date:
2003-08-25 04:44:39.000000000 -0700
diff -urN linux-2.4.22/arch/ia64/kernel/setup.c linux-2.4.23/arch/ia64/kernel/setup.c
@@ -32,6 +32,10 @@
#include <linux/ioport.h>
#include <linux/efi.h>
+#ifdef CONFIG_BLK_DEV_RAM
+# include <linux/blk.h>
+#endif
+
#include <asm/ia32.h>
#include <asm/page.h>
#include <asm/machvec.h>
@@ -39,6 +43,8 @@
#include <asm/sal.h>
#include <asm/system.h>
#include <asm/mca.h>
+#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
#include <asm/smp.h>
#ifdef CONFIG_BLK_DEV_RAM
@@ -55,7 +61,7 @@
extern char _end;
#ifdef CONFIG_NUMA
- struct cpuinfo_ia64 *boot_cpu_data;
+ struct cpuinfo_ia64 *_cpu_data[NR_CPUS];
#else
struct cpuinfo_ia64 _cpu_data[NR_CPUS] __attribute__ ((section ("__special_page_section")));
#endif
@@ -97,6 +103,7 @@
static struct rsvd_region rsvd_region[IA64_MAX_RSVD_REGIONS + 1];
static int num_rsvd_regions;
+#ifndef CONFIG_DISCONTIGMEM
static unsigned long bootmap_start; /* physical address where the bootmem map is located */
static int
@@ -109,18 +116,74 @@
*max_pfn = pfn;
return 0;
}
+#endif /* !CONFIG_DISCONTIGMEM */
#define IGNORE_PFN0 1 /* XXX fix me: ignore pfn 0 until TLB miss handler is updated... */
+#ifdef CONFIG_DISCONTIGMEM
/*
- * Free available memory based on the primitive map created from
- * the boot parameters. This routine does not assume the incoming
- * segments are sorted.
+ * efi_memmap_walk() knows nothing about layout of memory across nodes. Find
+ * out to which node a block of memory belongs. Ignore memory that we cannot
+ * identify, and split blocks that run across multiple nodes.
+ *
+ * Take this opportunity to round the start address up and the end address
+ * down to page boundaries.
*/
+void
+call_pernode_memory (unsigned long start, unsigned long end, void *arg)
+{
+ unsigned long rs, re;
+ void (*func)(unsigned long, unsigned long, int);
+ int i;
+
+ start = PAGE_ALIGN(start);
+ end &= PAGE_MASK;
+ if (start >= end)
+ return;
+
+ func = arg;
+
+ if (!num_memblks) {
+ /* this machine doesn't have SRAT, */
+ /* so call func with nid=0, bank=0 */
+ if (start < end)
+ (*func)(start, end, 0);
+ return;
+ }
+
+ for (i = 0; i < num_memblks; i++) {
+ rs = MAX(__pa(start), node_memblk[i].start_paddr);
+ re = MIN(__pa(end), node_memblk[i].start_paddr+node_memblk[i].size);
+
+ if (rs < re)
+ (*func)((unsigned long)__va(rs), (unsigned long)__va(re), node_memblk[i].nid);
+ if ((unsigned long)__va(re) == end)
+ break;
+ }
+}
+
+#else /* CONFIG_DISCONTIGMEM */
+
static int
free_available_memory (unsigned long start, unsigned long end, void *arg)
{
+ free_bootmem(__pa(start), end - start);
+ return 0;
+}
+#endif /* CONFIG_DISCONTIGMEM */
+
+/*
+ * Filter incoming memory segments based on the primitive map created from
+ * the boot parameters. Segments contained in the map are removed from the
+ * memory ranges. A caller-specified function is called with the memory
+ * ranges that remain after filtering.
+ * This routine does not assume the incoming segments are sorted.
+ */
+int
+filter_rsvd_memory (unsigned long start, unsigned long end, void *arg)
+{
unsigned long range_start, range_end, prev_start;
+ void (*func)(unsigned long, unsigned long, int);
int i;
#if IGNORE_PFN0
@@ -134,13 +197,18 @@
* lowest possible address(walker uses virtual)
*/
prev_start = PAGE_OFFSET;
+ func = arg;
for (i = 0; i < num_rsvd_regions; ++i) {
range_start = MAX(start, prev_start);
range_end = MIN(end, rsvd_region[i].start);
if (range_start < range_end)
- free_bootmem(__pa(range_start), range_end - range_start);
+#ifdef CONFIG_DISCONTIGMEM
+ call_pernode_memory(range_start, range_end, func);
+#else
+ (*func)(range_start, range_end, 0);
+#endif
/* nothing more available in this segment */
if (range_end == end) return 0;
@@ -152,6 +220,7 @@
}
+#ifndef CONFIG_DISCONTIGMEM
/*
* Find a place to put the bootmap and return its starting address in bootmap_start.
* This address must be page-aligned.
@@ -190,6 +259,7 @@
}
return 0;
}
+#endif /* CONFIG_DISCONTIGMEM */
static void
sort_regions (struct rsvd_region *rsvd_region, int max)
@@ -233,8 +303,8 @@
+ strlen(__va(ia64_boot_param->command_line)) + 1);
n++;
- rsvd_region[n].start = KERNEL_START;
- rsvd_region[n].end = KERNEL_END;
+ rsvd_region[n].start = ia64_imva(KERNEL_START);
+ rsvd_region[n].end = ia64_imva(KERNEL_END);
n++;
#ifdef CONFIG_BLK_DEV_INITRD
@@ -254,6 +324,14 @@
sort_regions(rsvd_region, num_rsvd_regions);
+#ifdef CONFIG_DISCONTIGMEM
+ {
+ extern void discontig_mem_init(void);
+ bootmap_size = max_pfn = 0; /* stop gcc warnings */
+ discontig_mem_init();
+ }
+#else /* !CONFIG_DISCONTIGMEM */
+
/* first find highest page frame number */
max_pfn = 0;
efi_memmap_walk(find_max_pfn, &max_pfn);
@@ -270,8 +348,9 @@
bootmap_size = init_bootmem(bootmap_start >> PAGE_SHIFT, max_pfn);
/* Free all available memory, then mark bootmem-map as being in use. */
- efi_memmap_walk(free_available_memory, 0);
+ efi_memmap_walk(filter_rsvd_memory, free_available_memory);
reserve_bootmem(bootmap_start, bootmap_size);
+#endif /* !CONFIG_DISCONTIGMEM */
#ifdef CONFIG_BLK_DEV_INITRD
if (ia64_boot_param->initrd_start) {
@@ -297,9 +376,22 @@
saved_command_line[COMMAND_LINE_SIZE-1] = '\0'; /* for safety */
efi_init();
+ find_memory();
+
+#ifdef CONFIG_ACPI_BOOT
+ /* Initialize the ACPI boot-time table parser */
+ acpi_table_init();
+
+# ifdef CONFIG_ACPI_NUMA
+ acpi_numa_init();
+# endif
+#else
+# ifdef CONFIG_SMP
+ smp_build_cpu_map(); /* happens, e.g., with the Ski simulator */
+# endif
+#endif /* CONFIG_APCI_BOOT */
iomem_resource.end = ~0UL; /* FIXME probably belongs elsewhere */
- find_memory();
#if 0
/* XXX fix me */
@@ -353,7 +445,7 @@
cpu_init(); /* initialize the bootstrap CPU */
#ifdef CONFIG_ACPI_BOOT
- acpi_boot_init(*cmdline_p);
+ acpi_boot_init();
#endif
#ifdef CONFIG_SERIAL_HCDP
if (efi.hcdp) {
@@ -446,6 +538,8 @@
c->itc_freq / 1000000, c->itc_freq % 1000000,
lpj*HZ/500000, (lpj*HZ/5000) % 100);
return 0;
+#undef lpj
+#undef cpu
}
static void *
@@ -546,7 +640,7 @@
unsigned int max_ctx;
struct cpuinfo_ia64 *my_cpu_data;
#ifdef CONFIG_NUMA
- int cpu, order;
+ int cpu;
/*
* If NUMA is configured, the cpu_data array is not preallocated. The boot cpu
@@ -555,28 +649,14 @@
* is required because some boot code references all cpu_data structures
* before the cpus are actually started.
*/
- if (!boot_cpu_data) {
- my_cpu_data = alloc_bootmem_pages_node(NODE_DATA(numa_node_id()),
- sizeof(struct cpuinfo_ia64));
- boot_cpu_data = my_cpu_data;
- my_cpu_data->cpu_data[0] = my_cpu_data;
- for (cpu = 1; cpu < NR_CPUS; ++cpu)
- my_cpu_data->cpu_data[cpu]
- = alloc_bootmem_pages_node(NODE_DATA(numa_node_id()),
- sizeof(struct cpuinfo_ia64));
- for (cpu = 1; cpu < NR_CPUS; ++cpu)
- memcpy(my_cpu_data->cpu_data[cpu]->cpu_data,
- my_cpu_data->cpu_data, sizeof(my_cpu_data->cpu_data));
- } else {
- order = get_order(sizeof(struct cpuinfo_ia64));
- my_cpu_data = page_address(alloc_pages_node(numa_node_id(), GFP_KERNEL, order));
- memcpy(my_cpu_data, boot_cpu_data->cpu_data[smp_processor_id()],
- sizeof(struct cpuinfo_ia64));
- __free_pages(virt_to_page(boot_cpu_data->cpu_data[smp_processor_id()]),
- order);
- for (cpu = 0; cpu < NR_CPUS; ++cpu)
- boot_cpu_data->cpu_data[cpu]->cpu_data[smp_processor_id()] = my_cpu_data;
- }
+ for (cpu=0; cpu < NR_CPUS; cpu++)
+ if (node_cpuid[cpu].phys_id == hard_smp_processor_id())
+ break;
+ my_cpu_data = _cpu_data[cpu];
+ my_cpu_data->node_data->active_cpu_count++;
+
+ for (cpu=0; cpu<NR_CPUS; cpu++)
+ _cpu_data[cpu]->cpu_data[smp_processor_id()] = my_cpu_data;
#else
my_cpu_data = cpu_data(smp_processor_id());
#endif
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)