Blame view

mm/mm_init.c 3.75 KB
6b74ab97b   Mel Gorman   mm: add a basic d...
1
2
3
4
5
6
7
8
9
  /*
   * mm_init.c - Memory initialisation verification and debugging
   *
   * Copyright 2008 IBM Corporation, 2008
   * Author Mel Gorman <mel@csn.ul.ie>
   *
   */
  #include <linux/kernel.h>
  #include <linux/init.h>
ff7ea79cf   Nishanth Aravamudan   mm: create /sys/k...
10
  #include <linux/kobject.h>
b95f1b31b   Paul Gortmaker   mm: Map most file...
11
  #include <linux/export.h>
708614e61   Mel Gorman   mm: verify the pa...
12
  #include "internal.h"
6b74ab97b   Mel Gorman   mm: add a basic d...
13

5e9426abe   Nishanth Aravamudan   mm: remove mm_ini...
14
  #ifdef CONFIG_DEBUG_MEMORY_INIT
759f9a2df   Marcin Slusarz   mm: mminit_loglev...
15
  int mminit_loglevel;
6b74ab97b   Mel Gorman   mm: add a basic d...
16

5c9ffc9c3   Andrew Morton   mm_init.c: avoid ...
17
18
19
  #ifndef SECTIONS_SHIFT
  #define SECTIONS_SHIFT	0
  #endif
68ad8df42   Mel Gorman   mm: print out the...
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
  /* The zonelists are simply reported, validation is manual. */
  void mminit_verify_zonelist(void)
  {
  	int nid;
  
  	if (mminit_loglevel < MMINIT_VERIFY)
  		return;
  
  	for_each_online_node(nid) {
  		pg_data_t *pgdat = NODE_DATA(nid);
  		struct zone *zone;
  		struct zoneref *z;
  		struct zonelist *zonelist;
  		int i, listid, zoneid;
  
  		BUG_ON(MAX_ZONELISTS > 2);
  		for (i = 0; i < MAX_ZONELISTS * MAX_NR_ZONES; i++) {
  
  			/* Identify the zone and nodelist */
  			zoneid = i % MAX_NR_ZONES;
  			listid = i / MAX_NR_ZONES;
  			zonelist = &pgdat->node_zonelists[listid];
  			zone = &pgdat->node_zones[zoneid];
  			if (!populated_zone(zone))
  				continue;
  
  			/* Print information about the zonelist */
  			printk(KERN_DEBUG "mminit::zonelist %s %d:%s = ",
  				listid > 0 ? "thisnode" : "general", nid,
  				zone->name);
  
  			/* Iterate the zonelist */
  			for_each_zone_zonelist(zone, z, zonelist, zoneid) {
  #ifdef CONFIG_NUMA
  				printk(KERN_CONT "%d:%s ",
  					zone->node, zone->name);
  #else
  				printk(KERN_CONT "0:%s ", zone->name);
  #endif /* CONFIG_NUMA */
  			}
  			printk(KERN_CONT "
  ");
  		}
  	}
  }
708614e61   Mel Gorman   mm: verify the pa...
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
  void __init mminit_verify_pageflags_layout(void)
  {
  	int shift, width;
  	unsigned long or_mask, add_mask;
  
  	shift = 8 * sizeof(unsigned long);
  	width = shift - SECTIONS_WIDTH - NODES_WIDTH - ZONES_WIDTH;
  	mminit_dprintk(MMINIT_TRACE, "pageflags_layout_widths",
  		"Section %d Node %d Zone %d Flags %d
  ",
  		SECTIONS_WIDTH,
  		NODES_WIDTH,
  		ZONES_WIDTH,
  		NR_PAGEFLAGS);
  	mminit_dprintk(MMINIT_TRACE, "pageflags_layout_shifts",
  		"Section %d Node %d Zone %d
  ",
708614e61   Mel Gorman   mm: verify the pa...
82
  		SECTIONS_SHIFT,
708614e61   Mel Gorman   mm: verify the pa...
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
  		NODES_SHIFT,
  		ZONES_SHIFT);
  	mminit_dprintk(MMINIT_TRACE, "pageflags_layout_offsets",
  		"Section %lu Node %lu Zone %lu
  ",
  		(unsigned long)SECTIONS_PGSHIFT,
  		(unsigned long)NODES_PGSHIFT,
  		(unsigned long)ZONES_PGSHIFT);
  	mminit_dprintk(MMINIT_TRACE, "pageflags_layout_zoneid",
  		"Zone ID: %lu -> %lu
  ",
  		(unsigned long)ZONEID_PGOFF,
  		(unsigned long)(ZONEID_PGOFF + ZONEID_SHIFT));
  	mminit_dprintk(MMINIT_TRACE, "pageflags_layout_usage",
  		"location: %d -> %d unused %d -> %d flags %d -> %d
  ",
  		shift, width, width, NR_PAGEFLAGS, NR_PAGEFLAGS, 0);
  #ifdef NODE_NOT_IN_PAGE_FLAGS
  	mminit_dprintk(MMINIT_TRACE, "pageflags_layout_nodeflags",
  		"Node not in page flags");
  #endif
  
  	if (SECTIONS_WIDTH) {
  		shift -= SECTIONS_WIDTH;
  		BUG_ON(shift != SECTIONS_PGSHIFT);
  	}
  	if (NODES_WIDTH) {
  		shift -= NODES_WIDTH;
  		BUG_ON(shift != NODES_PGSHIFT);
  	}
  	if (ZONES_WIDTH) {
  		shift -= ZONES_WIDTH;
  		BUG_ON(shift != ZONES_PGSHIFT);
  	}
  
  	/* Check for bitmask overlaps */
  	or_mask = (ZONES_MASK << ZONES_PGSHIFT) |
  			(NODES_MASK << NODES_PGSHIFT) |
  			(SECTIONS_MASK << SECTIONS_PGSHIFT);
  	add_mask = (ZONES_MASK << ZONES_PGSHIFT) +
  			(NODES_MASK << NODES_PGSHIFT) +
  			(SECTIONS_MASK << SECTIONS_PGSHIFT);
  	BUG_ON(or_mask != add_mask);
  }
  
  void __meminit mminit_verify_page_links(struct page *page, enum zone_type zone,
  			unsigned long nid, unsigned long pfn)
  {
  	BUG_ON(page_to_nid(page) != nid);
  	BUG_ON(page_zonenum(page) != zone);
  	BUG_ON(page_to_pfn(page) != pfn);
  }
6b74ab97b   Mel Gorman   mm: add a basic d...
135
136
137
138
139
140
  static __init int set_mminit_loglevel(char *str)
  {
  	get_option(&str, &mminit_loglevel);
  	return 0;
  }
  early_param("mminit_loglevel", set_mminit_loglevel);
5e9426abe   Nishanth Aravamudan   mm: remove mm_ini...
141
  #endif /* CONFIG_DEBUG_MEMORY_INIT */
ff7ea79cf   Nishanth Aravamudan   mm: create /sys/k...
142
143
144
145
146
147
148
149
150
151
152
153
154
155
  
  struct kobject *mm_kobj;
  EXPORT_SYMBOL_GPL(mm_kobj);
  
  static int __init mm_sysfs_init(void)
  {
  	mm_kobj = kobject_create_and_add("mm", kernel_kobj);
  	if (!mm_kobj)
  		return -ENOMEM;
  
  	return 0;
  }
  
  __initcall(mm_sysfs_init);