]> err.no Git - linux-2.6/blobdiff - arch/i386/mm/discontig.c
[PATCH] Additions to .data.read_mostly section
[linux-2.6] / arch / i386 / mm / discontig.c
index 088ca4722183a6339e8d1a65ea0837be5d8e3488..244d8ec66be2a473361bf00d81e81ba53cdf9fe0 100644 (file)
 #include <linux/highmem.h>
 #include <linux/initrd.h>
 #include <linux/nodemask.h>
+#include <linux/module.h>
+#include <linux/kexec.h>
+
 #include <asm/e820.h>
 #include <asm/setup.h>
 #include <asm/mmzone.h>
 #include <bios_ebda.h>
 
-struct pglist_data *node_data[MAX_NUMNODES];
+struct pglist_data *node_data[MAX_NUMNODES] __read_mostly;
+EXPORT_SYMBOL(node_data);
 bootmem_data_t node0_bdata;
 
 /*
@@ -42,12 +46,16 @@ bootmem_data_t node0_bdata;
  *                  populated the following initialisation.
  *
  * 1) node_online_map  - the map of all nodes configured (online) in the system
- * 2) physnode_map     - the mapping between a pfn and owning node
- * 3) node_start_pfn   - the starting page frame number for a node
+ * 2) node_start_pfn   - the starting page frame number for a node
  * 3) node_end_pfn     - the ending page fram number for a node
  */
+unsigned long node_start_pfn[MAX_NUMNODES] __read_mostly;
+unsigned long node_end_pfn[MAX_NUMNODES] __read_mostly;
+
 
+#ifdef CONFIG_DISCONTIGMEM
 /*
+ * 4) physnode_map     - the mapping between a pfn and owning node
  * physnode_map keeps track of the physical memory layout of a generic
  * numa node on a 256Mb break (each element of the array will
  * represent 256Mb of memory and will be marked by the node id.  so,
@@ -58,7 +66,8 @@ bootmem_data_t node0_bdata;
  *     physnode_map[4-7] = 1;
  *     physnode_map[8- ] = -1;
  */
-s8 physnode_map[MAX_ELEMENTS] = { [0 ... (MAX_ELEMENTS - 1)] = -1};
+s8 physnode_map[MAX_ELEMENTS] __read_mostly = { [0 ... (MAX_ELEMENTS - 1)] = -1};
+EXPORT_SYMBOL(physnode_map);
 
 void memory_present(int nid, unsigned long start, unsigned long end)
 {
@@ -85,9 +94,7 @@ unsigned long node_memmap_size_bytes(int nid, unsigned long start_pfn,
 
        return (nr_pages + 1) * sizeof(struct page);
 }
-
-unsigned long node_start_pfn[MAX_NUMNODES];
-unsigned long node_end_pfn[MAX_NUMNODES];
+#endif
 
 extern unsigned long find_max_low_pfn(void);
 extern void find_max_pfn(void);
@@ -255,6 +262,17 @@ static unsigned long calculate_numa_remap_pages(void)
                reserve_pages += size;
                printk("Shrinking node %d from %ld pages to %ld pages\n",
                        nid, node_end_pfn[nid], node_end_pfn[nid] - size);
+
+               if (node_end_pfn[nid] & (PTRS_PER_PTE-1)) {
+                       /*
+                        * Align node_end_pfn[] and node_remap_start_pfn[] to
+                        * pmd boundary. remap_numa_kva will barf otherwise.
+                        */
+                       printk("Shrinking node %d further by %ld pages for proper alignment\n",
+                               nid, node_end_pfn[nid] & (PTRS_PER_PTE-1));
+                       size +=  node_end_pfn[nid] & (PTRS_PER_PTE-1);
+               }
+
                node_end_pfn[nid] -= size;
                node_remap_start_pfn[nid] = node_end_pfn[nid];
        }
@@ -390,24 +408,26 @@ void __init set_highmem_pages_init(int bad_ppro)
 {
 #ifdef CONFIG_HIGHMEM
        struct zone *zone;
+       struct page *page;
 
        for_each_zone(zone) {
-               unsigned long node_pfn, node_high_size, zone_start_pfn;
-               struct page * zone_mem_map;
-               
+               unsigned long node_pfn, zone_start_pfn, zone_end_pfn;
+
                if (!is_highmem(zone))
                        continue;
 
-               printk("Initializing %s for node %d\n", zone->name,
-                       zone->zone_pgdat->node_id);
-
-               node_high_size = zone->spanned_pages;
-               zone_mem_map = zone->zone_mem_map;
                zone_start_pfn = zone->zone_start_pfn;
+               zone_end_pfn = zone_start_pfn + zone->spanned_pages;
+
+               printk("Initializing %s for node %d (%08lx:%08lx)\n",
+                               zone->name, zone->zone_pgdat->node_id,
+                               zone_start_pfn, zone_end_pfn);
 
-               for (node_pfn = 0; node_pfn < node_high_size; node_pfn++) {
-                       one_highpage_init((struct page *)(zone_mem_map + node_pfn),
-                                         zone_start_pfn + node_pfn, bad_ppro);
+               for (node_pfn = zone_start_pfn; node_pfn < zone_end_pfn; node_pfn++) {
+                       if (!pfn_valid(node_pfn))
+                               continue;
+                       page = pfn_to_page(node_pfn);
+                       one_highpage_init(page, node_pfn, bad_ppro);
                }
        }
        totalram_pages += totalhigh_pages;