mm: verify the page links and memory model
[sfrench/cifs-2.6.git] / mm / mm_init.c
1 /*
2  * mm_init.c - Memory initialisation verification and debugging
3  *
4  * Copyright 2008 IBM Corporation, 2008
5  * Author Mel Gorman <mel@csn.ul.ie>
6  *
7  */
8 #include <linux/kernel.h>
9 #include <linux/init.h>
10 #include "internal.h"
11
12 int __meminitdata mminit_loglevel;
13
14 void __init mminit_verify_pageflags_layout(void)
15 {
16         int shift, width;
17         unsigned long or_mask, add_mask;
18
19         shift = 8 * sizeof(unsigned long);
20         width = shift - SECTIONS_WIDTH - NODES_WIDTH - ZONES_WIDTH;
21         mminit_dprintk(MMINIT_TRACE, "pageflags_layout_widths",
22                 "Section %d Node %d Zone %d Flags %d\n",
23                 SECTIONS_WIDTH,
24                 NODES_WIDTH,
25                 ZONES_WIDTH,
26                 NR_PAGEFLAGS);
27         mminit_dprintk(MMINIT_TRACE, "pageflags_layout_shifts",
28                 "Section %d Node %d Zone %d\n",
29 #ifdef SECTIONS_SHIFT
30                 SECTIONS_SHIFT,
31 #else
32                 0,
33 #endif
34                 NODES_SHIFT,
35                 ZONES_SHIFT);
36         mminit_dprintk(MMINIT_TRACE, "pageflags_layout_offsets",
37                 "Section %lu Node %lu Zone %lu\n",
38                 (unsigned long)SECTIONS_PGSHIFT,
39                 (unsigned long)NODES_PGSHIFT,
40                 (unsigned long)ZONES_PGSHIFT);
41         mminit_dprintk(MMINIT_TRACE, "pageflags_layout_zoneid",
42                 "Zone ID: %lu -> %lu\n",
43                 (unsigned long)ZONEID_PGOFF,
44                 (unsigned long)(ZONEID_PGOFF + ZONEID_SHIFT));
45         mminit_dprintk(MMINIT_TRACE, "pageflags_layout_usage",
46                 "location: %d -> %d unused %d -> %d flags %d -> %d\n",
47                 shift, width, width, NR_PAGEFLAGS, NR_PAGEFLAGS, 0);
48 #ifdef NODE_NOT_IN_PAGE_FLAGS
49         mminit_dprintk(MMINIT_TRACE, "pageflags_layout_nodeflags",
50                 "Node not in page flags");
51 #endif
52
53         if (SECTIONS_WIDTH) {
54                 shift -= SECTIONS_WIDTH;
55                 BUG_ON(shift != SECTIONS_PGSHIFT);
56         }
57         if (NODES_WIDTH) {
58                 shift -= NODES_WIDTH;
59                 BUG_ON(shift != NODES_PGSHIFT);
60         }
61         if (ZONES_WIDTH) {
62                 shift -= ZONES_WIDTH;
63                 BUG_ON(shift != ZONES_PGSHIFT);
64         }
65
66         /* Check for bitmask overlaps */
67         or_mask = (ZONES_MASK << ZONES_PGSHIFT) |
68                         (NODES_MASK << NODES_PGSHIFT) |
69                         (SECTIONS_MASK << SECTIONS_PGSHIFT);
70         add_mask = (ZONES_MASK << ZONES_PGSHIFT) +
71                         (NODES_MASK << NODES_PGSHIFT) +
72                         (SECTIONS_MASK << SECTIONS_PGSHIFT);
73         BUG_ON(or_mask != add_mask);
74 }
75
76 void __meminit mminit_verify_page_links(struct page *page, enum zone_type zone,
77                         unsigned long nid, unsigned long pfn)
78 {
79         BUG_ON(page_to_nid(page) != nid);
80         BUG_ON(page_zonenum(page) != zone);
81         BUG_ON(page_to_pfn(page) != pfn);
82 }
83
84 static __init int set_mminit_loglevel(char *str)
85 {
86         get_option(&str, &mminit_loglevel);
87         return 0;
88 }
89 early_param("mminit_loglevel", set_mminit_loglevel);