|
@@ -79,19 +79,75 @@ void __init zones_init(void)
|
|
|
free_area_init_node(0, zones_size, ARCH_PFN_OFFSET, NULL);
|
|
|
}
|
|
|
|
|
|
+#ifdef CONFIG_HIGHMEM
|
|
|
+static void __init free_area_high(unsigned long pfn, unsigned long end)
|
|
|
+{
|
|
|
+ for (; pfn < end; pfn++)
|
|
|
+ free_highmem_page(pfn_to_page(pfn));
|
|
|
+}
|
|
|
+
|
|
|
+static void __init free_highpages(void)
|
|
|
+{
|
|
|
+ unsigned long max_low = max_low_pfn;
|
|
|
+ struct memblock_region *mem, *res;
|
|
|
+
|
|
|
+ reset_all_zones_managed_pages();
|
|
|
+ /* set highmem page free */
|
|
|
+ for_each_memblock(memory, mem) {
|
|
|
+ unsigned long start = memblock_region_memory_base_pfn(mem);
|
|
|
+ unsigned long end = memblock_region_memory_end_pfn(mem);
|
|
|
+
|
|
|
+ /* Ignore complete lowmem entries */
|
|
|
+ if (end <= max_low)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ if (memblock_is_nomap(mem))
|
|
|
+ continue;
|
|
|
+
|
|
|
+ /* Truncate partial highmem entries */
|
|
|
+ if (start < max_low)
|
|
|
+ start = max_low;
|
|
|
+
|
|
|
+ /* Find and exclude any reserved regions */
|
|
|
+ for_each_memblock(reserved, res) {
|
|
|
+ unsigned long res_start, res_end;
|
|
|
+
|
|
|
+ res_start = memblock_region_reserved_base_pfn(res);
|
|
|
+ res_end = memblock_region_reserved_end_pfn(res);
|
|
|
+
|
|
|
+ if (res_end < start)
|
|
|
+ continue;
|
|
|
+ if (res_start < start)
|
|
|
+ res_start = start;
|
|
|
+ if (res_start > end)
|
|
|
+ res_start = end;
|
|
|
+ if (res_end > end)
|
|
|
+ res_end = end;
|
|
|
+ if (res_start != start)
|
|
|
+ free_area_high(start, res_start);
|
|
|
+ start = res_end;
|
|
|
+ if (start == end)
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* And now free anything which remains */
|
|
|
+ if (start < end)
|
|
|
+ free_area_high(start, end);
|
|
|
+ }
|
|
|
+}
|
|
|
+#else
|
|
|
+static void __init free_highpages(void)
|
|
|
+{
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
/*
|
|
|
* Initialize memory pages.
|
|
|
*/
|
|
|
|
|
|
void __init mem_init(void)
|
|
|
{
|
|
|
-#ifdef CONFIG_HIGHMEM
|
|
|
- unsigned long tmp;
|
|
|
-
|
|
|
- reset_all_zones_managed_pages();
|
|
|
- for (tmp = max_low_pfn; tmp < max_pfn; tmp++)
|
|
|
- free_highmem_page(pfn_to_page(tmp));
|
|
|
-#endif
|
|
|
+ free_highpages();
|
|
|
|
|
|
max_mapnr = max_pfn - ARCH_PFN_OFFSET;
|
|
|
high_memory = (void *)__va(max_low_pfn << PAGE_SHIFT);
|