diff options
Diffstat (limited to 'mm/page_alloc.c')
-rw-r--r-- | mm/page_alloc.c | 39 |
1 files changed, 30 insertions, 9 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 20e239599db0..5c1b8982a6da 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
@@ -68,7 +68,7 @@ EXPORT_SYMBOL(nr_swap_pages); | |||
68 | * Used by page_zone() to look up the address of the struct zone whose | 68 | * Used by page_zone() to look up the address of the struct zone whose |
69 | * id is encoded in the upper bits of page->flags | 69 | * id is encoded in the upper bits of page->flags |
70 | */ | 70 | */ |
71 | struct zone *zone_table[1 << (ZONES_SHIFT + NODES_SHIFT)]; | 71 | struct zone *zone_table[1 << ZONETABLE_SHIFT]; |
72 | EXPORT_SYMBOL(zone_table); | 72 | EXPORT_SYMBOL(zone_table); |
73 | 73 | ||
74 | static char *zone_names[MAX_NR_ZONES] = { "DMA", "Normal", "HighMem" }; | 74 | static char *zone_names[MAX_NR_ZONES] = { "DMA", "Normal", "HighMem" }; |
@@ -1649,11 +1649,15 @@ static void __init calculate_zone_totalpages(struct pglist_data *pgdat, | |||
1649 | void __init memmap_init_zone(unsigned long size, int nid, unsigned long zone, | 1649 | void __init memmap_init_zone(unsigned long size, int nid, unsigned long zone, |
1650 | unsigned long start_pfn) | 1650 | unsigned long start_pfn) |
1651 | { | 1651 | { |
1652 | struct page *start = pfn_to_page(start_pfn); | ||
1653 | struct page *page; | 1652 | struct page *page; |
1653 | int end_pfn = start_pfn + size; | ||
1654 | int pfn; | ||
1654 | 1655 | ||
1655 | for (page = start; page < (start + size); page++) { | 1656 | for (pfn = start_pfn; pfn < end_pfn; pfn++, page++) { |
1656 | set_page_links(page, zone, nid); | 1657 | if (!early_pfn_valid(pfn)) |
1658 | continue; | ||
1659 | page = pfn_to_page(pfn); | ||
1660 | set_page_links(page, zone, nid, pfn); | ||
1657 | set_page_count(page, 0); | 1661 | set_page_count(page, 0); |
1658 | reset_page_mapcount(page); | 1662 | reset_page_mapcount(page); |
1659 | SetPageReserved(page); | 1663 | SetPageReserved(page); |
@@ -1677,6 +1681,20 @@ void zone_init_free_lists(struct pglist_data *pgdat, struct zone *zone, | |||
1677 | } | 1681 | } |
1678 | } | 1682 | } |
1679 | 1683 | ||
1684 | #define ZONETABLE_INDEX(x, zone_nr) ((x << ZONES_SHIFT) | zone_nr) | ||
1685 | void zonetable_add(struct zone *zone, int nid, int zid, unsigned long pfn, | ||
1686 | unsigned long size) | ||
1687 | { | ||
1688 | unsigned long snum = pfn_to_section_nr(pfn); | ||
1689 | unsigned long end = pfn_to_section_nr(pfn + size); | ||
1690 | |||
1691 | if (FLAGS_HAS_NODE) | ||
1692 | zone_table[ZONETABLE_INDEX(nid, zid)] = zone; | ||
1693 | else | ||
1694 | for (; snum <= end; snum++) | ||
1695 | zone_table[ZONETABLE_INDEX(snum, zid)] = zone; | ||
1696 | } | ||
1697 | |||
1680 | #ifndef __HAVE_ARCH_MEMMAP_INIT | 1698 | #ifndef __HAVE_ARCH_MEMMAP_INIT |
1681 | #define memmap_init(size, nid, zone, start_pfn) \ | 1699 | #define memmap_init(size, nid, zone, start_pfn) \ |
1682 | memmap_init_zone((size), (nid), (zone), (start_pfn)) | 1700 | memmap_init_zone((size), (nid), (zone), (start_pfn)) |
@@ -1861,7 +1879,6 @@ static void __init free_area_init_core(struct pglist_data *pgdat, | |||
1861 | unsigned long size, realsize; | 1879 | unsigned long size, realsize; |
1862 | unsigned long batch; | 1880 | unsigned long batch; |
1863 | 1881 | ||
1864 | zone_table[NODEZONE(nid, j)] = zone; | ||
1865 | realsize = size = zones_size[j]; | 1882 | realsize = size = zones_size[j]; |
1866 | if (zholes_size) | 1883 | if (zholes_size) |
1867 | realsize -= zholes_size[j]; | 1884 | realsize -= zholes_size[j]; |
@@ -1927,6 +1944,8 @@ static void __init free_area_init_core(struct pglist_data *pgdat, | |||
1927 | 1944 | ||
1928 | memmap_init(size, nid, j, zone_start_pfn); | 1945 | memmap_init(size, nid, j, zone_start_pfn); |
1929 | 1946 | ||
1947 | zonetable_add(zone, nid, j, zone_start_pfn, size); | ||
1948 | |||
1930 | zone_start_pfn += size; | 1949 | zone_start_pfn += size; |
1931 | 1950 | ||
1932 | zone_init_free_lists(pgdat, zone, zone->spanned_pages); | 1951 | zone_init_free_lists(pgdat, zone, zone->spanned_pages); |
@@ -1935,28 +1954,30 @@ static void __init free_area_init_core(struct pglist_data *pgdat, | |||
1935 | 1954 | ||
1936 | static void __init alloc_node_mem_map(struct pglist_data *pgdat) | 1955 | static void __init alloc_node_mem_map(struct pglist_data *pgdat) |
1937 | { | 1956 | { |
1938 | unsigned long size; | ||
1939 | struct page *map; | ||
1940 | |||
1941 | /* Skip empty nodes */ | 1957 | /* Skip empty nodes */ |
1942 | if (!pgdat->node_spanned_pages) | 1958 | if (!pgdat->node_spanned_pages) |
1943 | return; | 1959 | return; |
1944 | 1960 | ||
1961 | #ifdef CONFIG_FLAT_NODE_MEM_MAP | ||
1945 | /* ia64 gets its own node_mem_map, before this, without bootmem */ | 1962 | /* ia64 gets its own node_mem_map, before this, without bootmem */ |
1946 | if (!pgdat->node_mem_map) { | 1963 | if (!pgdat->node_mem_map) { |
1964 | unsigned long size; | ||
1965 | struct page *map; | ||
1966 | |||
1947 | size = (pgdat->node_spanned_pages + 1) * sizeof(struct page); | 1967 | size = (pgdat->node_spanned_pages + 1) * sizeof(struct page); |
1948 | map = alloc_remap(pgdat->node_id, size); | 1968 | map = alloc_remap(pgdat->node_id, size); |
1949 | if (!map) | 1969 | if (!map) |
1950 | map = alloc_bootmem_node(pgdat, size); | 1970 | map = alloc_bootmem_node(pgdat, size); |
1951 | pgdat->node_mem_map = map; | 1971 | pgdat->node_mem_map = map; |
1952 | } | 1972 | } |
1953 | #ifndef CONFIG_DISCONTIGMEM | 1973 | #ifdef CONFIG_FLATMEM |
1954 | /* | 1974 | /* |
1955 | * With no DISCONTIG, the global mem_map is just set as node 0's | 1975 | * With no DISCONTIG, the global mem_map is just set as node 0's |
1956 | */ | 1976 | */ |
1957 | if (pgdat == NODE_DATA(0)) | 1977 | if (pgdat == NODE_DATA(0)) |
1958 | mem_map = NODE_DATA(0)->node_mem_map; | 1978 | mem_map = NODE_DATA(0)->node_mem_map; |
1959 | #endif | 1979 | #endif |
1980 | #endif /* CONFIG_FLAT_NODE_MEM_MAP */ | ||
1960 | } | 1981 | } |
1961 | 1982 | ||
1962 | void __init free_area_init_node(int nid, struct pglist_data *pgdat, | 1983 | void __init free_area_init_node(int nid, struct pglist_data *pgdat, |