diff options
Diffstat (limited to 'mm/sparse.c')
| -rw-r--r-- | mm/sparse.c | 37 |
1 files changed, 29 insertions, 8 deletions
diff --git a/mm/sparse.c b/mm/sparse.c index 36511c7b5e2c..7a3650923d9a 100644 --- a/mm/sparse.c +++ b/mm/sparse.c | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | #include <asm/dma.h> | 12 | #include <asm/dma.h> |
| 13 | #include <asm/pgalloc.h> | 13 | #include <asm/pgalloc.h> |
| 14 | #include <asm/pgtable.h> | 14 | #include <asm/pgtable.h> |
| 15 | #include "internal.h" | ||
| 15 | 16 | ||
| 16 | /* | 17 | /* |
| 17 | * Permanent SPARSEMEM data: | 18 | * Permanent SPARSEMEM data: |
| @@ -147,22 +148,41 @@ static inline int sparse_early_nid(struct mem_section *section) | |||
| 147 | return (section->section_mem_map >> SECTION_NID_SHIFT); | 148 | return (section->section_mem_map >> SECTION_NID_SHIFT); |
| 148 | } | 149 | } |
| 149 | 150 | ||
| 150 | /* Record a memory area against a node. */ | 151 | /* Validate the physical addressing limitations of the model */ |
| 151 | void __init memory_present(int nid, unsigned long start, unsigned long end) | 152 | void __meminit mminit_validate_memmodel_limits(unsigned long *start_pfn, |
| 153 | unsigned long *end_pfn) | ||
| 152 | { | 154 | { |
| 153 | unsigned long max_arch_pfn = 1UL << (MAX_PHYSMEM_BITS-PAGE_SHIFT); | 155 | unsigned long max_sparsemem_pfn = 1UL << (MAX_PHYSMEM_BITS-PAGE_SHIFT); |
| 154 | unsigned long pfn; | ||
| 155 | 156 | ||
| 156 | /* | 157 | /* |
| 157 | * Sanity checks - do not allow an architecture to pass | 158 | * Sanity checks - do not allow an architecture to pass |
| 158 | * in larger pfns than the maximum scope of sparsemem: | 159 | * in larger pfns than the maximum scope of sparsemem: |
| 159 | */ | 160 | */ |
| 160 | if (start >= max_arch_pfn) | 161 | if (*start_pfn > max_sparsemem_pfn) { |
| 161 | return; | 162 | mminit_dprintk(MMINIT_WARNING, "pfnvalidation", |
| 162 | if (end >= max_arch_pfn) | 163 | "Start of range %lu -> %lu exceeds SPARSEMEM max %lu\n", |
| 163 | end = max_arch_pfn; | 164 | *start_pfn, *end_pfn, max_sparsemem_pfn); |
| 165 | WARN_ON_ONCE(1); | ||
| 166 | *start_pfn = max_sparsemem_pfn; | ||
| 167 | *end_pfn = max_sparsemem_pfn; | ||
| 168 | } | ||
| 169 | |||
| 170 | if (*end_pfn > max_sparsemem_pfn) { | ||
| 171 | mminit_dprintk(MMINIT_WARNING, "pfnvalidation", | ||
| 172 | "End of range %lu -> %lu exceeds SPARSEMEM max %lu\n", | ||
| 173 | *start_pfn, *end_pfn, max_sparsemem_pfn); | ||
| 174 | WARN_ON_ONCE(1); | ||
| 175 | *end_pfn = max_sparsemem_pfn; | ||
| 176 | } | ||
| 177 | } | ||
| 178 | |||
| 179 | /* Record a memory area against a node. */ | ||
| 180 | void __init memory_present(int nid, unsigned long start, unsigned long end) | ||
| 181 | { | ||
| 182 | unsigned long pfn; | ||
| 164 | 183 | ||
| 165 | start &= PAGE_SECTION_MASK; | 184 | start &= PAGE_SECTION_MASK; |
| 185 | mminit_validate_memmodel_limits(&start, &end); | ||
| 166 | for (pfn = start; pfn < end; pfn += PAGES_PER_SECTION) { | 186 | for (pfn = start; pfn < end; pfn += PAGES_PER_SECTION) { |
| 167 | unsigned long section = pfn_to_section_nr(pfn); | 187 | unsigned long section = pfn_to_section_nr(pfn); |
| 168 | struct mem_section *ms; | 188 | struct mem_section *ms; |
| @@ -187,6 +207,7 @@ unsigned long __init node_memmap_size_bytes(int nid, unsigned long start_pfn, | |||
| 187 | unsigned long pfn; | 207 | unsigned long pfn; |
| 188 | unsigned long nr_pages = 0; | 208 | unsigned long nr_pages = 0; |
| 189 | 209 | ||
| 210 | mminit_validate_memmodel_limits(&start_pfn, &end_pfn); | ||
| 190 | for (pfn = start_pfn; pfn < end_pfn; pfn += PAGES_PER_SECTION) { | 211 | for (pfn = start_pfn; pfn < end_pfn; pfn += PAGES_PER_SECTION) { |
| 191 | if (nid != early_pfn_to_nid(pfn)) | 212 | if (nid != early_pfn_to_nid(pfn)) |
| 192 | continue; | 213 | continue; |
