diff options
Diffstat (limited to 'arch/arc/mm/init.c')
-rw-r--r-- | arch/arc/mm/init.c | 54 |
1 files changed, 39 insertions, 15 deletions
diff --git a/arch/arc/mm/init.c b/arch/arc/mm/init.c index 5487d0b97400..8be930394750 100644 --- a/arch/arc/mm/init.c +++ b/arch/arc/mm/init.c | |||
@@ -30,11 +30,16 @@ static const unsigned long low_mem_start = CONFIG_LINUX_LINK_BASE; | |||
30 | static unsigned long low_mem_sz; | 30 | static unsigned long low_mem_sz; |
31 | 31 | ||
32 | #ifdef CONFIG_HIGHMEM | 32 | #ifdef CONFIG_HIGHMEM |
33 | static unsigned long min_high_pfn; | 33 | static unsigned long min_high_pfn, max_high_pfn; |
34 | static u64 high_mem_start; | 34 | static u64 high_mem_start; |
35 | static u64 high_mem_sz; | 35 | static u64 high_mem_sz; |
36 | #endif | 36 | #endif |
37 | 37 | ||
38 | #ifdef CONFIG_DISCONTIGMEM | ||
39 | struct pglist_data node_data[MAX_NUMNODES] __read_mostly; | ||
40 | EXPORT_SYMBOL(node_data); | ||
41 | #endif | ||
42 | |||
38 | /* User can over-ride above with "mem=nnn[KkMm]" in cmdline */ | 43 | /* User can over-ride above with "mem=nnn[KkMm]" in cmdline */ |
39 | static int __init setup_mem_sz(char *str) | 44 | static int __init setup_mem_sz(char *str) |
40 | { | 45 | { |
@@ -109,13 +114,11 @@ void __init setup_arch_memory(void) | |||
109 | /* Last usable page of low mem */ | 114 | /* Last usable page of low mem */ |
110 | max_low_pfn = max_pfn = PFN_DOWN(low_mem_start + low_mem_sz); | 115 | max_low_pfn = max_pfn = PFN_DOWN(low_mem_start + low_mem_sz); |
111 | 116 | ||
112 | #ifdef CONFIG_HIGHMEM | 117 | #ifdef CONFIG_FLATMEM |
113 | min_high_pfn = PFN_DOWN(high_mem_start); | 118 | /* pfn_valid() uses this */ |
114 | max_pfn = PFN_DOWN(high_mem_start + high_mem_sz); | 119 | max_mapnr = max_low_pfn - min_low_pfn; |
115 | #endif | 120 | #endif |
116 | 121 | ||
117 | max_mapnr = max_pfn - min_low_pfn; | ||
118 | |||
119 | /*------------- bootmem allocator setup -----------------------*/ | 122 | /*------------- bootmem allocator setup -----------------------*/ |
120 | 123 | ||
121 | /* | 124 | /* |
@@ -129,7 +132,7 @@ void __init setup_arch_memory(void) | |||
129 | * the crash | 132 | * the crash |
130 | */ | 133 | */ |
131 | 134 | ||
132 | memblock_add(low_mem_start, low_mem_sz); | 135 | memblock_add_node(low_mem_start, low_mem_sz, 0); |
133 | memblock_reserve(low_mem_start, __pa(_end) - low_mem_start); | 136 | memblock_reserve(low_mem_start, __pa(_end) - low_mem_start); |
134 | 137 | ||
135 | #ifdef CONFIG_BLK_DEV_INITRD | 138 | #ifdef CONFIG_BLK_DEV_INITRD |
@@ -149,13 +152,6 @@ void __init setup_arch_memory(void) | |||
149 | zones_size[ZONE_NORMAL] = max_low_pfn - min_low_pfn; | 152 | zones_size[ZONE_NORMAL] = max_low_pfn - min_low_pfn; |
150 | zones_holes[ZONE_NORMAL] = 0; | 153 | zones_holes[ZONE_NORMAL] = 0; |
151 | 154 | ||
152 | #ifdef CONFIG_HIGHMEM | ||
153 | zones_size[ZONE_HIGHMEM] = max_pfn - max_low_pfn; | ||
154 | |||
155 | /* This handles the peripheral address space hole */ | ||
156 | zones_holes[ZONE_HIGHMEM] = min_high_pfn - max_low_pfn; | ||
157 | #endif | ||
158 | |||
159 | /* | 155 | /* |
160 | * We can't use the helper free_area_init(zones[]) because it uses | 156 | * We can't use the helper free_area_init(zones[]) because it uses |
161 | * PAGE_OFFSET to compute the @min_low_pfn which would be wrong | 157 | * PAGE_OFFSET to compute the @min_low_pfn which would be wrong |
@@ -168,6 +164,34 @@ void __init setup_arch_memory(void) | |||
168 | zones_holes); /* holes */ | 164 | zones_holes); /* holes */ |
169 | 165 | ||
170 | #ifdef CONFIG_HIGHMEM | 166 | #ifdef CONFIG_HIGHMEM |
167 | /* | ||
168 | * Populate a new node with highmem | ||
169 | * | ||
170 | * On ARC (w/o PAE) HIGHMEM addresses are actually smaller (0 based) | ||
171 | * than addresses in normal ala low memory (0x8000_0000 based). | ||
172 | * Even with PAE, the huge peripheral space hole would waste a lot of | ||
173 | * mem with single mem_map[]. This warrants a mem_map per region design. | ||
174 | * Thus HIGHMEM on ARC is imlemented with DISCONTIGMEM. | ||
175 | * | ||
176 | * DISCONTIGMEM in turns requires multiple nodes. node 0 above is | ||
177 | * populated with normal memory zone while node 1 only has highmem | ||
178 | */ | ||
179 | node_set_online(1); | ||
180 | |||
181 | min_high_pfn = PFN_DOWN(high_mem_start); | ||
182 | max_high_pfn = PFN_DOWN(high_mem_start + high_mem_sz); | ||
183 | |||
184 | zones_size[ZONE_NORMAL] = 0; | ||
185 | zones_holes[ZONE_NORMAL] = 0; | ||
186 | |||
187 | zones_size[ZONE_HIGHMEM] = max_high_pfn - min_high_pfn; | ||
188 | zones_holes[ZONE_HIGHMEM] = 0; | ||
189 | |||
190 | free_area_init_node(1, /* node-id */ | ||
191 | zones_size, /* num pages per zone */ | ||
192 | min_high_pfn, /* first pfn of node */ | ||
193 | zones_holes); /* holes */ | ||
194 | |||
171 | high_memory = (void *)(min_high_pfn << PAGE_SHIFT); | 195 | high_memory = (void *)(min_high_pfn << PAGE_SHIFT); |
172 | kmap_init(); | 196 | kmap_init(); |
173 | #endif | 197 | #endif |
@@ -185,7 +209,7 @@ void __init mem_init(void) | |||
185 | unsigned long tmp; | 209 | unsigned long tmp; |
186 | 210 | ||
187 | reset_all_zones_managed_pages(); | 211 | reset_all_zones_managed_pages(); |
188 | for (tmp = min_high_pfn; tmp < max_pfn; tmp++) | 212 | for (tmp = min_high_pfn; tmp < max_high_pfn; tmp++) |
189 | free_highmem_page(pfn_to_page(tmp)); | 213 | free_highmem_page(pfn_to_page(tmp)); |
190 | #endif | 214 | #endif |
191 | 215 | ||