diff options
Diffstat (limited to 'arch/x86/mm/init_32.c')
| -rw-r--r-- | arch/x86/mm/init_32.c | 523 |
1 files changed, 427 insertions, 96 deletions
diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c index ec30d10154b6..029e8cffca9e 100644 --- a/arch/x86/mm/init_32.c +++ b/arch/x86/mm/init_32.c | |||
| @@ -50,6 +50,7 @@ | |||
| 50 | 50 | ||
| 51 | unsigned int __VMALLOC_RESERVE = 128 << 20; | 51 | unsigned int __VMALLOC_RESERVE = 128 << 20; |
| 52 | 52 | ||
| 53 | unsigned long max_low_pfn_mapped; | ||
| 53 | unsigned long max_pfn_mapped; | 54 | unsigned long max_pfn_mapped; |
| 54 | 55 | ||
| 55 | DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); | 56 | DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); |
| @@ -57,6 +58,27 @@ unsigned long highstart_pfn, highend_pfn; | |||
| 57 | 58 | ||
| 58 | static noinline int do_test_wp_bit(void); | 59 | static noinline int do_test_wp_bit(void); |
| 59 | 60 | ||
| 61 | |||
| 62 | static unsigned long __initdata table_start; | ||
| 63 | static unsigned long __meminitdata table_end; | ||
| 64 | static unsigned long __meminitdata table_top; | ||
| 65 | |||
| 66 | static int __initdata after_init_bootmem; | ||
| 67 | |||
| 68 | static __init void *alloc_low_page(unsigned long *phys) | ||
| 69 | { | ||
| 70 | unsigned long pfn = table_end++; | ||
| 71 | void *adr; | ||
| 72 | |||
| 73 | if (pfn >= table_top) | ||
| 74 | panic("alloc_low_page: ran out of memory"); | ||
| 75 | |||
| 76 | adr = __va(pfn * PAGE_SIZE); | ||
| 77 | memset(adr, 0, PAGE_SIZE); | ||
| 78 | *phys = pfn * PAGE_SIZE; | ||
| 79 | return adr; | ||
| 80 | } | ||
| 81 | |||
| 60 | /* | 82 | /* |
| 61 | * Creates a middle page table and puts a pointer to it in the | 83 | * Creates a middle page table and puts a pointer to it in the |
| 62 | * given global directory entry. This only returns the gd entry | 84 | * given global directory entry. This only returns the gd entry |
| @@ -68,9 +90,12 @@ static pmd_t * __init one_md_table_init(pgd_t *pgd) | |||
| 68 | pmd_t *pmd_table; | 90 | pmd_t *pmd_table; |
| 69 | 91 | ||
| 70 | #ifdef CONFIG_X86_PAE | 92 | #ifdef CONFIG_X86_PAE |
| 93 | unsigned long phys; | ||
| 71 | if (!(pgd_val(*pgd) & _PAGE_PRESENT)) { | 94 | if (!(pgd_val(*pgd) & _PAGE_PRESENT)) { |
| 72 | pmd_table = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE); | 95 | if (after_init_bootmem) |
| 73 | 96 | pmd_table = (pmd_t *)alloc_bootmem_low_pages(PAGE_SIZE); | |
| 97 | else | ||
| 98 | pmd_table = (pmd_t *)alloc_low_page(&phys); | ||
| 74 | paravirt_alloc_pmd(&init_mm, __pa(pmd_table) >> PAGE_SHIFT); | 99 | paravirt_alloc_pmd(&init_mm, __pa(pmd_table) >> PAGE_SHIFT); |
| 75 | set_pgd(pgd, __pgd(__pa(pmd_table) | _PAGE_PRESENT)); | 100 | set_pgd(pgd, __pgd(__pa(pmd_table) | _PAGE_PRESENT)); |
| 76 | pud = pud_offset(pgd, 0); | 101 | pud = pud_offset(pgd, 0); |
| @@ -92,12 +117,16 @@ static pte_t * __init one_page_table_init(pmd_t *pmd) | |||
| 92 | if (!(pmd_val(*pmd) & _PAGE_PRESENT)) { | 117 | if (!(pmd_val(*pmd) & _PAGE_PRESENT)) { |
| 93 | pte_t *page_table = NULL; | 118 | pte_t *page_table = NULL; |
| 94 | 119 | ||
| 120 | if (after_init_bootmem) { | ||
| 95 | #ifdef CONFIG_DEBUG_PAGEALLOC | 121 | #ifdef CONFIG_DEBUG_PAGEALLOC |
| 96 | page_table = (pte_t *) alloc_bootmem_pages(PAGE_SIZE); | 122 | page_table = (pte_t *) alloc_bootmem_pages(PAGE_SIZE); |
| 97 | #endif | 123 | #endif |
| 98 | if (!page_table) { | 124 | if (!page_table) |
| 99 | page_table = | 125 | page_table = |
| 100 | (pte_t *)alloc_bootmem_low_pages(PAGE_SIZE); | 126 | (pte_t *)alloc_bootmem_low_pages(PAGE_SIZE); |
| 127 | } else { | ||
| 128 | unsigned long phys; | ||
| 129 | page_table = (pte_t *)alloc_low_page(&phys); | ||
| 101 | } | 130 | } |
| 102 | 131 | ||
| 103 | paravirt_alloc_pte(&init_mm, __pa(page_table) >> PAGE_SHIFT); | 132 | paravirt_alloc_pte(&init_mm, __pa(page_table) >> PAGE_SHIFT); |
| @@ -155,38 +184,44 @@ static inline int is_kernel_text(unsigned long addr) | |||
| 155 | * of max_low_pfn pages, by creating page tables starting from address | 184 | * of max_low_pfn pages, by creating page tables starting from address |
| 156 | * PAGE_OFFSET: | 185 | * PAGE_OFFSET: |
| 157 | */ | 186 | */ |
| 158 | static void __init kernel_physical_mapping_init(pgd_t *pgd_base) | 187 | static void __init kernel_physical_mapping_init(pgd_t *pgd_base, |
| 188 | unsigned long start_pfn, | ||
| 189 | unsigned long end_pfn, | ||
| 190 | int use_pse) | ||
| 159 | { | 191 | { |
| 160 | int pgd_idx, pmd_idx, pte_ofs; | 192 | int pgd_idx, pmd_idx, pte_ofs; |
| 161 | unsigned long pfn; | 193 | unsigned long pfn; |
| 162 | pgd_t *pgd; | 194 | pgd_t *pgd; |
| 163 | pmd_t *pmd; | 195 | pmd_t *pmd; |
| 164 | pte_t *pte; | 196 | pte_t *pte; |
| 197 | unsigned pages_2m = 0, pages_4k = 0; | ||
| 165 | 198 | ||
| 166 | pgd_idx = pgd_index(PAGE_OFFSET); | 199 | if (!cpu_has_pse) |
| 167 | pgd = pgd_base + pgd_idx; | 200 | use_pse = 0; |
| 168 | pfn = 0; | ||
| 169 | 201 | ||
| 202 | pfn = start_pfn; | ||
| 203 | pgd_idx = pgd_index((pfn<<PAGE_SHIFT) + PAGE_OFFSET); | ||
| 204 | pgd = pgd_base + pgd_idx; | ||
| 170 | for (; pgd_idx < PTRS_PER_PGD; pgd++, pgd_idx++) { | 205 | for (; pgd_idx < PTRS_PER_PGD; pgd++, pgd_idx++) { |
| 171 | pmd = one_md_table_init(pgd); | 206 | pmd = one_md_table_init(pgd); |
| 172 | if (pfn >= max_low_pfn) | ||
| 173 | continue; | ||
| 174 | 207 | ||
| 175 | for (pmd_idx = 0; | 208 | if (pfn >= end_pfn) |
| 176 | pmd_idx < PTRS_PER_PMD && pfn < max_low_pfn; | 209 | continue; |
| 210 | #ifdef CONFIG_X86_PAE | ||
| 211 | pmd_idx = pmd_index((pfn<<PAGE_SHIFT) + PAGE_OFFSET); | ||
| 212 | pmd += pmd_idx; | ||
| 213 | #else | ||
| 214 | pmd_idx = 0; | ||
| 215 | #endif | ||
| 216 | for (; pmd_idx < PTRS_PER_PMD && pfn < end_pfn; | ||
| 177 | pmd++, pmd_idx++) { | 217 | pmd++, pmd_idx++) { |
| 178 | unsigned int addr = pfn * PAGE_SIZE + PAGE_OFFSET; | 218 | unsigned int addr = pfn * PAGE_SIZE + PAGE_OFFSET; |
| 179 | 219 | ||
| 180 | /* | 220 | /* |
| 181 | * Map with big pages if possible, otherwise | 221 | * Map with big pages if possible, otherwise |
| 182 | * create normal page tables: | 222 | * create normal page tables: |
| 183 | * | ||
| 184 | * Don't use a large page for the first 2/4MB of memory | ||
| 185 | * because there are often fixed size MTRRs in there | ||
| 186 | * and overlapping MTRRs into large pages can cause | ||
| 187 | * slowdowns. | ||
| 188 | */ | 223 | */ |
| 189 | if (cpu_has_pse && !(pgd_idx == 0 && pmd_idx == 0)) { | 224 | if (use_pse) { |
| 190 | unsigned int addr2; | 225 | unsigned int addr2; |
| 191 | pgprot_t prot = PAGE_KERNEL_LARGE; | 226 | pgprot_t prot = PAGE_KERNEL_LARGE; |
| 192 | 227 | ||
| @@ -197,34 +232,30 @@ static void __init kernel_physical_mapping_init(pgd_t *pgd_base) | |||
| 197 | is_kernel_text(addr2)) | 232 | is_kernel_text(addr2)) |
| 198 | prot = PAGE_KERNEL_LARGE_EXEC; | 233 | prot = PAGE_KERNEL_LARGE_EXEC; |
| 199 | 234 | ||
| 235 | pages_2m++; | ||
| 200 | set_pmd(pmd, pfn_pmd(pfn, prot)); | 236 | set_pmd(pmd, pfn_pmd(pfn, prot)); |
| 201 | 237 | ||
| 202 | pfn += PTRS_PER_PTE; | 238 | pfn += PTRS_PER_PTE; |
| 203 | max_pfn_mapped = pfn; | ||
| 204 | continue; | 239 | continue; |
| 205 | } | 240 | } |
| 206 | pte = one_page_table_init(pmd); | 241 | pte = one_page_table_init(pmd); |
| 207 | 242 | ||
| 208 | for (pte_ofs = 0; | 243 | pte_ofs = pte_index((pfn<<PAGE_SHIFT) + PAGE_OFFSET); |
| 209 | pte_ofs < PTRS_PER_PTE && pfn < max_low_pfn; | 244 | pte += pte_ofs; |
| 245 | for (; pte_ofs < PTRS_PER_PTE && pfn < end_pfn; | ||
| 210 | pte++, pfn++, pte_ofs++, addr += PAGE_SIZE) { | 246 | pte++, pfn++, pte_ofs++, addr += PAGE_SIZE) { |
| 211 | pgprot_t prot = PAGE_KERNEL; | 247 | pgprot_t prot = PAGE_KERNEL; |
| 212 | 248 | ||
| 213 | if (is_kernel_text(addr)) | 249 | if (is_kernel_text(addr)) |
| 214 | prot = PAGE_KERNEL_EXEC; | 250 | prot = PAGE_KERNEL_EXEC; |
| 215 | 251 | ||
| 252 | pages_4k++; | ||
| 216 | set_pte(pte, pfn_pte(pfn, prot)); | 253 | set_pte(pte, pfn_pte(pfn, prot)); |
| 217 | } | 254 | } |
| 218 | max_pfn_mapped = pfn; | ||
| 219 | } | 255 | } |
| 220 | } | 256 | } |
| 221 | } | 257 | update_page_count(PG_LEVEL_2M, pages_2m); |
| 222 | 258 | update_page_count(PG_LEVEL_4K, pages_4k); | |
| 223 | static inline int page_kills_ppro(unsigned long pagenr) | ||
| 224 | { | ||
| 225 | if (pagenr >= 0x70000 && pagenr <= 0x7003F) | ||
| 226 | return 1; | ||
| 227 | return 0; | ||
| 228 | } | 259 | } |
| 229 | 260 | ||
| 230 | /* | 261 | /* |
| @@ -287,29 +318,62 @@ static void __init permanent_kmaps_init(pgd_t *pgd_base) | |||
| 287 | pkmap_page_table = pte; | 318 | pkmap_page_table = pte; |
| 288 | } | 319 | } |
| 289 | 320 | ||
| 290 | void __init add_one_highpage_init(struct page *page, int pfn, int bad_ppro) | 321 | static void __init add_one_highpage_init(struct page *page, int pfn) |
| 291 | { | 322 | { |
| 292 | if (page_is_ram(pfn) && !(bad_ppro && page_kills_ppro(pfn))) { | 323 | ClearPageReserved(page); |
| 293 | ClearPageReserved(page); | 324 | init_page_count(page); |
| 294 | init_page_count(page); | 325 | __free_page(page); |
| 295 | __free_page(page); | 326 | totalhigh_pages++; |
| 296 | totalhigh_pages++; | ||
| 297 | } else | ||
| 298 | SetPageReserved(page); | ||
| 299 | } | 327 | } |
| 300 | 328 | ||
| 301 | #ifndef CONFIG_NUMA | 329 | struct add_highpages_data { |
| 302 | static void __init set_highmem_pages_init(int bad_ppro) | 330 | unsigned long start_pfn; |
| 331 | unsigned long end_pfn; | ||
| 332 | }; | ||
| 333 | |||
| 334 | static int __init add_highpages_work_fn(unsigned long start_pfn, | ||
| 335 | unsigned long end_pfn, void *datax) | ||
| 303 | { | 336 | { |
| 304 | int pfn; | 337 | int node_pfn; |
| 338 | struct page *page; | ||
| 339 | unsigned long final_start_pfn, final_end_pfn; | ||
| 340 | struct add_highpages_data *data; | ||
| 305 | 341 | ||
| 306 | for (pfn = highstart_pfn; pfn < highend_pfn; pfn++) { | 342 | data = (struct add_highpages_data *)datax; |
| 307 | /* | 343 | |
| 308 | * Holes under sparsemem might not have no mem_map[]: | 344 | final_start_pfn = max(start_pfn, data->start_pfn); |
| 309 | */ | 345 | final_end_pfn = min(end_pfn, data->end_pfn); |
| 310 | if (pfn_valid(pfn)) | 346 | if (final_start_pfn >= final_end_pfn) |
| 311 | add_one_highpage_init(pfn_to_page(pfn), pfn, bad_ppro); | 347 | return 0; |
| 348 | |||
| 349 | for (node_pfn = final_start_pfn; node_pfn < final_end_pfn; | ||
| 350 | node_pfn++) { | ||
| 351 | if (!pfn_valid(node_pfn)) | ||
| 352 | continue; | ||
| 353 | page = pfn_to_page(node_pfn); | ||
| 354 | add_one_highpage_init(page, node_pfn); | ||
| 312 | } | 355 | } |
| 356 | |||
| 357 | return 0; | ||
| 358 | |||
| 359 | } | ||
| 360 | |||
| 361 | void __init add_highpages_with_active_regions(int nid, unsigned long start_pfn, | ||
| 362 | unsigned long end_pfn) | ||
| 363 | { | ||
| 364 | struct add_highpages_data data; | ||
| 365 | |||
| 366 | data.start_pfn = start_pfn; | ||
| 367 | data.end_pfn = end_pfn; | ||
| 368 | |||
| 369 | work_with_active_regions(nid, add_highpages_work_fn, &data); | ||
| 370 | } | ||
| 371 | |||
| 372 | #ifndef CONFIG_NUMA | ||
| 373 | static void __init set_highmem_pages_init(void) | ||
| 374 | { | ||
| 375 | add_highpages_with_active_regions(0, highstart_pfn, highend_pfn); | ||
| 376 | |||
| 313 | totalram_pages += totalhigh_pages; | 377 | totalram_pages += totalhigh_pages; |
| 314 | } | 378 | } |
| 315 | #endif /* !CONFIG_NUMA */ | 379 | #endif /* !CONFIG_NUMA */ |
| @@ -317,14 +381,9 @@ static void __init set_highmem_pages_init(int bad_ppro) | |||
| 317 | #else | 381 | #else |
| 318 | # define kmap_init() do { } while (0) | 382 | # define kmap_init() do { } while (0) |
| 319 | # define permanent_kmaps_init(pgd_base) do { } while (0) | 383 | # define permanent_kmaps_init(pgd_base) do { } while (0) |
| 320 | # define set_highmem_pages_init(bad_ppro) do { } while (0) | 384 | # define set_highmem_pages_init() do { } while (0) |
| 321 | #endif /* CONFIG_HIGHMEM */ | 385 | #endif /* CONFIG_HIGHMEM */ |
| 322 | 386 | ||
| 323 | pteval_t __PAGE_KERNEL = _PAGE_KERNEL; | ||
| 324 | EXPORT_SYMBOL(__PAGE_KERNEL); | ||
| 325 | |||
| 326 | pteval_t __PAGE_KERNEL_EXEC = _PAGE_KERNEL_EXEC; | ||
| 327 | |||
| 328 | void __init native_pagetable_setup_start(pgd_t *base) | 387 | void __init native_pagetable_setup_start(pgd_t *base) |
| 329 | { | 388 | { |
| 330 | unsigned long pfn, va; | 389 | unsigned long pfn, va; |
| @@ -380,27 +439,10 @@ void __init native_pagetable_setup_done(pgd_t *base) | |||
| 380 | * be partially populated, and so it avoids stomping on any existing | 439 | * be partially populated, and so it avoids stomping on any existing |
| 381 | * mappings. | 440 | * mappings. |
| 382 | */ | 441 | */ |
| 383 | static void __init pagetable_init(void) | 442 | static void __init early_ioremap_page_table_range_init(pgd_t *pgd_base) |
| 384 | { | 443 | { |
| 385 | pgd_t *pgd_base = swapper_pg_dir; | ||
| 386 | unsigned long vaddr, end; | 444 | unsigned long vaddr, end; |
| 387 | 445 | ||
| 388 | paravirt_pagetable_setup_start(pgd_base); | ||
| 389 | |||
| 390 | /* Enable PSE if available */ | ||
| 391 | if (cpu_has_pse) | ||
| 392 | set_in_cr4(X86_CR4_PSE); | ||
| 393 | |||
| 394 | /* Enable PGE if available */ | ||
| 395 | if (cpu_has_pge) { | ||
| 396 | set_in_cr4(X86_CR4_PGE); | ||
| 397 | __PAGE_KERNEL |= _PAGE_GLOBAL; | ||
| 398 | __PAGE_KERNEL_EXEC |= _PAGE_GLOBAL; | ||
| 399 | } | ||
| 400 | |||
| 401 | kernel_physical_mapping_init(pgd_base); | ||
| 402 | remap_numa_kva(); | ||
| 403 | |||
| 404 | /* | 446 | /* |
| 405 | * Fixed mappings, only the page table structure has to be | 447 | * Fixed mappings, only the page table structure has to be |
| 406 | * created - mappings will be set by set_fixmap(): | 448 | * created - mappings will be set by set_fixmap(): |
| @@ -410,6 +452,13 @@ static void __init pagetable_init(void) | |||
| 410 | end = (FIXADDR_TOP + PMD_SIZE - 1) & PMD_MASK; | 452 | end = (FIXADDR_TOP + PMD_SIZE - 1) & PMD_MASK; |
| 411 | page_table_range_init(vaddr, end, pgd_base); | 453 | page_table_range_init(vaddr, end, pgd_base); |
| 412 | early_ioremap_reset(); | 454 | early_ioremap_reset(); |
| 455 | } | ||
| 456 | |||
| 457 | static void __init pagetable_init(void) | ||
| 458 | { | ||
| 459 | pgd_t *pgd_base = swapper_pg_dir; | ||
| 460 | |||
| 461 | paravirt_pagetable_setup_start(pgd_base); | ||
| 413 | 462 | ||
| 414 | permanent_kmaps_init(pgd_base); | 463 | permanent_kmaps_init(pgd_base); |
| 415 | 464 | ||
| @@ -456,7 +505,7 @@ void zap_low_mappings(void) | |||
| 456 | 505 | ||
| 457 | int nx_enabled; | 506 | int nx_enabled; |
| 458 | 507 | ||
| 459 | pteval_t __supported_pte_mask __read_mostly = ~_PAGE_NX; | 508 | pteval_t __supported_pte_mask __read_mostly = ~(_PAGE_NX | _PAGE_GLOBAL); |
| 460 | EXPORT_SYMBOL_GPL(__supported_pte_mask); | 509 | EXPORT_SYMBOL_GPL(__supported_pte_mask); |
| 461 | 510 | ||
| 462 | #ifdef CONFIG_X86_PAE | 511 | #ifdef CONFIG_X86_PAE |
| @@ -509,27 +558,318 @@ static void __init set_nx(void) | |||
| 509 | } | 558 | } |
| 510 | #endif | 559 | #endif |
| 511 | 560 | ||
| 561 | /* user-defined highmem size */ | ||
| 562 | static unsigned int highmem_pages = -1; | ||
| 563 | |||
| 512 | /* | 564 | /* |
| 513 | * paging_init() sets up the page tables - note that the first 8MB are | 565 | * highmem=size forces highmem to be exactly 'size' bytes. |
| 514 | * already mapped by head.S. | 566 | * This works even on boxes that have no highmem otherwise. |
| 515 | * | 567 | * This also works to reduce highmem size on bigger boxes. |
| 516 | * This routines also unmaps the page at virtual kernel address 0, so | ||
| 517 | * that we can trap those pesky NULL-reference errors in the kernel. | ||
| 518 | */ | 568 | */ |
| 519 | void __init paging_init(void) | 569 | static int __init parse_highmem(char *arg) |
| 570 | { | ||
| 571 | if (!arg) | ||
| 572 | return -EINVAL; | ||
| 573 | |||
| 574 | highmem_pages = memparse(arg, &arg) >> PAGE_SHIFT; | ||
| 575 | return 0; | ||
| 576 | } | ||
| 577 | early_param("highmem", parse_highmem); | ||
| 578 | |||
| 579 | /* | ||
| 580 | * Determine low and high memory ranges: | ||
| 581 | */ | ||
| 582 | void __init find_low_pfn_range(void) | ||
| 520 | { | 583 | { |
| 584 | /* it could update max_pfn */ | ||
| 585 | |||
| 586 | /* max_low_pfn is 0, we already have early_res support */ | ||
| 587 | |||
| 588 | max_low_pfn = max_pfn; | ||
| 589 | if (max_low_pfn > MAXMEM_PFN) { | ||
| 590 | if (highmem_pages == -1) | ||
| 591 | highmem_pages = max_pfn - MAXMEM_PFN; | ||
| 592 | if (highmem_pages + MAXMEM_PFN < max_pfn) | ||
| 593 | max_pfn = MAXMEM_PFN + highmem_pages; | ||
| 594 | if (highmem_pages + MAXMEM_PFN > max_pfn) { | ||
| 595 | printk(KERN_WARNING "only %luMB highmem pages " | ||
| 596 | "available, ignoring highmem size of %uMB.\n", | ||
| 597 | pages_to_mb(max_pfn - MAXMEM_PFN), | ||
| 598 | pages_to_mb(highmem_pages)); | ||
| 599 | highmem_pages = 0; | ||
| 600 | } | ||
| 601 | max_low_pfn = MAXMEM_PFN; | ||
| 602 | #ifndef CONFIG_HIGHMEM | ||
| 603 | /* Maximum memory usable is what is directly addressable */ | ||
| 604 | printk(KERN_WARNING "Warning only %ldMB will be used.\n", | ||
| 605 | MAXMEM>>20); | ||
| 606 | if (max_pfn > MAX_NONPAE_PFN) | ||
| 607 | printk(KERN_WARNING | ||
| 608 | "Use a HIGHMEM64G enabled kernel.\n"); | ||
| 609 | else | ||
| 610 | printk(KERN_WARNING "Use a HIGHMEM enabled kernel.\n"); | ||
| 611 | max_pfn = MAXMEM_PFN; | ||
| 612 | #else /* !CONFIG_HIGHMEM */ | ||
| 613 | #ifndef CONFIG_HIGHMEM64G | ||
| 614 | if (max_pfn > MAX_NONPAE_PFN) { | ||
| 615 | max_pfn = MAX_NONPAE_PFN; | ||
| 616 | printk(KERN_WARNING "Warning only 4GB will be used." | ||
| 617 | "Use a HIGHMEM64G enabled kernel.\n"); | ||
| 618 | } | ||
| 619 | #endif /* !CONFIG_HIGHMEM64G */ | ||
| 620 | #endif /* !CONFIG_HIGHMEM */ | ||
| 621 | } else { | ||
| 622 | if (highmem_pages == -1) | ||
| 623 | highmem_pages = 0; | ||
| 624 | #ifdef CONFIG_HIGHMEM | ||
| 625 | if (highmem_pages >= max_pfn) { | ||
| 626 | printk(KERN_ERR "highmem size specified (%uMB) is " | ||
| 627 | "bigger than pages available (%luMB)!.\n", | ||
| 628 | pages_to_mb(highmem_pages), | ||
| 629 | pages_to_mb(max_pfn)); | ||
| 630 | highmem_pages = 0; | ||
| 631 | } | ||
| 632 | if (highmem_pages) { | ||
| 633 | if (max_low_pfn - highmem_pages < | ||
| 634 | 64*1024*1024/PAGE_SIZE){ | ||
| 635 | printk(KERN_ERR "highmem size %uMB results in " | ||
| 636 | "smaller than 64MB lowmem, ignoring it.\n" | ||
| 637 | , pages_to_mb(highmem_pages)); | ||
| 638 | highmem_pages = 0; | ||
| 639 | } | ||
| 640 | max_low_pfn -= highmem_pages; | ||
| 641 | } | ||
| 642 | #else | ||
| 643 | if (highmem_pages) | ||
| 644 | printk(KERN_ERR "ignoring highmem size on non-highmem" | ||
| 645 | " kernel!\n"); | ||
| 646 | #endif | ||
| 647 | } | ||
| 648 | } | ||
| 649 | |||
| 650 | #ifndef CONFIG_NEED_MULTIPLE_NODES | ||
| 651 | void __init initmem_init(unsigned long start_pfn, | ||
| 652 | unsigned long end_pfn) | ||
| 653 | { | ||
| 654 | #ifdef CONFIG_HIGHMEM | ||
| 655 | highstart_pfn = highend_pfn = max_pfn; | ||
| 656 | if (max_pfn > max_low_pfn) | ||
| 657 | highstart_pfn = max_low_pfn; | ||
| 658 | memory_present(0, 0, highend_pfn); | ||
| 659 | e820_register_active_regions(0, 0, highend_pfn); | ||
| 660 | printk(KERN_NOTICE "%ldMB HIGHMEM available.\n", | ||
| 661 | pages_to_mb(highend_pfn - highstart_pfn)); | ||
| 662 | num_physpages = highend_pfn; | ||
| 663 | high_memory = (void *) __va(highstart_pfn * PAGE_SIZE - 1) + 1; | ||
| 664 | #else | ||
| 665 | memory_present(0, 0, max_low_pfn); | ||
| 666 | e820_register_active_regions(0, 0, max_low_pfn); | ||
| 667 | num_physpages = max_low_pfn; | ||
| 668 | high_memory = (void *) __va(max_low_pfn * PAGE_SIZE - 1) + 1; | ||
| 669 | #endif | ||
| 670 | #ifdef CONFIG_FLATMEM | ||
| 671 | max_mapnr = num_physpages; | ||
| 672 | #endif | ||
| 673 | printk(KERN_NOTICE "%ldMB LOWMEM available.\n", | ||
| 674 | pages_to_mb(max_low_pfn)); | ||
| 675 | |||
| 676 | setup_bootmem_allocator(); | ||
| 677 | } | ||
| 678 | #endif /* !CONFIG_NEED_MULTIPLE_NODES */ | ||
| 679 | |||
| 680 | static void __init zone_sizes_init(void) | ||
| 681 | { | ||
| 682 | unsigned long max_zone_pfns[MAX_NR_ZONES]; | ||
| 683 | memset(max_zone_pfns, 0, sizeof(max_zone_pfns)); | ||
| 684 | max_zone_pfns[ZONE_DMA] = | ||
| 685 | virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT; | ||
| 686 | max_zone_pfns[ZONE_NORMAL] = max_low_pfn; | ||
| 687 | #ifdef CONFIG_HIGHMEM | ||
| 688 | max_zone_pfns[ZONE_HIGHMEM] = highend_pfn; | ||
| 689 | #endif | ||
| 690 | |||
| 691 | free_area_init_nodes(max_zone_pfns); | ||
| 692 | } | ||
| 693 | |||
| 694 | void __init setup_bootmem_allocator(void) | ||
| 695 | { | ||
| 696 | int i; | ||
| 697 | unsigned long bootmap_size, bootmap; | ||
| 698 | /* | ||
| 699 | * Initialize the boot-time allocator (with low memory only): | ||
| 700 | */ | ||
| 701 | bootmap_size = bootmem_bootmap_pages(max_low_pfn)<<PAGE_SHIFT; | ||
| 702 | bootmap = find_e820_area(min_low_pfn<<PAGE_SHIFT, | ||
| 703 | max_pfn_mapped<<PAGE_SHIFT, bootmap_size, | ||
| 704 | PAGE_SIZE); | ||
| 705 | if (bootmap == -1L) | ||
| 706 | panic("Cannot find bootmem map of size %ld\n", bootmap_size); | ||
| 707 | reserve_early(bootmap, bootmap + bootmap_size, "BOOTMAP"); | ||
| 708 | |||
| 709 | /* don't touch min_low_pfn */ | ||
| 710 | bootmap_size = init_bootmem_node(NODE_DATA(0), bootmap >> PAGE_SHIFT, | ||
| 711 | min_low_pfn, max_low_pfn); | ||
| 712 | printk(KERN_INFO " mapped low ram: 0 - %08lx\n", | ||
| 713 | max_pfn_mapped<<PAGE_SHIFT); | ||
| 714 | printk(KERN_INFO " low ram: %08lx - %08lx\n", | ||
| 715 | min_low_pfn<<PAGE_SHIFT, max_low_pfn<<PAGE_SHIFT); | ||
| 716 | printk(KERN_INFO " bootmap %08lx - %08lx\n", | ||
| 717 | bootmap, bootmap + bootmap_size); | ||
| 718 | for_each_online_node(i) | ||
| 719 | free_bootmem_with_active_regions(i, max_low_pfn); | ||
| 720 | early_res_to_bootmem(0, max_low_pfn<<PAGE_SHIFT); | ||
| 721 | |||
| 722 | after_init_bootmem = 1; | ||
| 723 | } | ||
| 724 | |||
| 725 | static void __init find_early_table_space(unsigned long end) | ||
| 726 | { | ||
| 727 | unsigned long puds, pmds, ptes, tables, start; | ||
| 728 | |||
| 729 | puds = (end + PUD_SIZE - 1) >> PUD_SHIFT; | ||
| 730 | tables = PAGE_ALIGN(puds * sizeof(pud_t)); | ||
| 731 | |||
| 732 | pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT; | ||
| 733 | tables += PAGE_ALIGN(pmds * sizeof(pmd_t)); | ||
| 734 | |||
| 735 | if (cpu_has_pse) { | ||
| 736 | unsigned long extra; | ||
| 737 | |||
| 738 | extra = end - ((end>>PMD_SHIFT) << PMD_SHIFT); | ||
| 739 | extra += PMD_SIZE; | ||
| 740 | ptes = (extra + PAGE_SIZE - 1) >> PAGE_SHIFT; | ||
| 741 | } else | ||
| 742 | ptes = (end + PAGE_SIZE - 1) >> PAGE_SHIFT; | ||
| 743 | |||
| 744 | tables += PAGE_ALIGN(ptes * sizeof(pte_t)); | ||
| 745 | |||
| 746 | /* for fixmap */ | ||
| 747 | tables += PAGE_SIZE * 2; | ||
| 748 | |||
| 749 | /* | ||
| 750 | * RED-PEN putting page tables only on node 0 could | ||
| 751 | * cause a hotspot and fill up ZONE_DMA. The page tables | ||
| 752 | * need roughly 0.5KB per GB. | ||
| 753 | */ | ||
| 754 | start = 0x7000; | ||
| 755 | table_start = find_e820_area(start, max_pfn_mapped<<PAGE_SHIFT, | ||
| 756 | tables, PAGE_SIZE); | ||
| 757 | if (table_start == -1UL) | ||
| 758 | panic("Cannot find space for the kernel page tables"); | ||
| 759 | |||
| 760 | table_start >>= PAGE_SHIFT; | ||
| 761 | table_end = table_start; | ||
| 762 | table_top = table_start + (tables>>PAGE_SHIFT); | ||
| 763 | |||
| 764 | printk(KERN_DEBUG "kernel direct mapping tables up to %lx @ %lx-%lx\n", | ||
| 765 | end, table_start << PAGE_SHIFT, | ||
| 766 | (table_start << PAGE_SHIFT) + tables); | ||
| 767 | } | ||
| 768 | |||
| 769 | unsigned long __init_refok init_memory_mapping(unsigned long start, | ||
| 770 | unsigned long end) | ||
| 771 | { | ||
| 772 | pgd_t *pgd_base = swapper_pg_dir; | ||
| 773 | unsigned long start_pfn, end_pfn; | ||
| 774 | unsigned long big_page_start; | ||
| 775 | |||
| 776 | /* | ||
| 777 | * Find space for the kernel direct mapping tables. | ||
| 778 | */ | ||
| 779 | if (!after_init_bootmem) | ||
| 780 | find_early_table_space(end); | ||
| 781 | |||
| 521 | #ifdef CONFIG_X86_PAE | 782 | #ifdef CONFIG_X86_PAE |
| 522 | set_nx(); | 783 | set_nx(); |
| 523 | if (nx_enabled) | 784 | if (nx_enabled) |
| 524 | printk(KERN_INFO "NX (Execute Disable) protection: active\n"); | 785 | printk(KERN_INFO "NX (Execute Disable) protection: active\n"); |
| 525 | #endif | 786 | #endif |
| 526 | pagetable_init(); | 787 | |
| 788 | /* Enable PSE if available */ | ||
| 789 | if (cpu_has_pse) | ||
| 790 | set_in_cr4(X86_CR4_PSE); | ||
| 791 | |||
| 792 | /* Enable PGE if available */ | ||
| 793 | if (cpu_has_pge) { | ||
| 794 | set_in_cr4(X86_CR4_PGE); | ||
| 795 | __supported_pte_mask |= _PAGE_GLOBAL; | ||
| 796 | } | ||
| 797 | |||
| 798 | /* | ||
| 799 | * Don't use a large page for the first 2/4MB of memory | ||
| 800 | * because there are often fixed size MTRRs in there | ||
| 801 | * and overlapping MTRRs into large pages can cause | ||
| 802 | * slowdowns. | ||
| 803 | */ | ||
| 804 | big_page_start = PMD_SIZE; | ||
| 805 | |||
| 806 | if (start < big_page_start) { | ||
| 807 | start_pfn = start >> PAGE_SHIFT; | ||
| 808 | end_pfn = min(big_page_start>>PAGE_SHIFT, end>>PAGE_SHIFT); | ||
| 809 | } else { | ||
| 810 | /* head is not big page alignment ? */ | ||
| 811 | start_pfn = start >> PAGE_SHIFT; | ||
| 812 | end_pfn = ((start + (PMD_SIZE - 1))>>PMD_SHIFT) | ||
| 813 | << (PMD_SHIFT - PAGE_SHIFT); | ||
| 814 | } | ||
| 815 | if (start_pfn < end_pfn) | ||
| 816 | kernel_physical_mapping_init(pgd_base, start_pfn, end_pfn, 0); | ||
| 817 | |||
| 818 | /* big page range */ | ||
| 819 | start_pfn = ((start + (PMD_SIZE - 1))>>PMD_SHIFT) | ||
| 820 | << (PMD_SHIFT - PAGE_SHIFT); | ||
| 821 | if (start_pfn < (big_page_start >> PAGE_SHIFT)) | ||
| 822 | start_pfn = big_page_start >> PAGE_SHIFT; | ||
| 823 | end_pfn = (end>>PMD_SHIFT) << (PMD_SHIFT - PAGE_SHIFT); | ||
| 824 | if (start_pfn < end_pfn) | ||
| 825 | kernel_physical_mapping_init(pgd_base, start_pfn, end_pfn, | ||
| 826 | cpu_has_pse); | ||
| 827 | |||
| 828 | /* tail is not big page alignment ? */ | ||
| 829 | start_pfn = end_pfn; | ||
| 830 | if (start_pfn > (big_page_start>>PAGE_SHIFT)) { | ||
| 831 | end_pfn = end >> PAGE_SHIFT; | ||
| 832 | if (start_pfn < end_pfn) | ||
| 833 | kernel_physical_mapping_init(pgd_base, start_pfn, | ||
| 834 | end_pfn, 0); | ||
| 835 | } | ||
| 836 | |||
| 837 | early_ioremap_page_table_range_init(pgd_base); | ||
| 527 | 838 | ||
| 528 | load_cr3(swapper_pg_dir); | 839 | load_cr3(swapper_pg_dir); |
| 529 | 840 | ||
| 530 | __flush_tlb_all(); | 841 | __flush_tlb_all(); |
| 531 | 842 | ||
| 843 | if (!after_init_bootmem) | ||
| 844 | reserve_early(table_start << PAGE_SHIFT, | ||
| 845 | table_end << PAGE_SHIFT, "PGTABLE"); | ||
| 846 | |||
| 847 | return end >> PAGE_SHIFT; | ||
| 848 | } | ||
| 849 | |||
| 850 | |||
| 851 | /* | ||
| 852 | * paging_init() sets up the page tables - note that the first 8MB are | ||
| 853 | * already mapped by head.S. | ||
| 854 | * | ||
| 855 | * This routines also unmaps the page at virtual kernel address 0, so | ||
| 856 | * that we can trap those pesky NULL-reference errors in the kernel. | ||
| 857 | */ | ||
| 858 | void __init paging_init(void) | ||
| 859 | { | ||
| 860 | pagetable_init(); | ||
| 861 | |||
| 862 | __flush_tlb_all(); | ||
| 863 | |||
| 532 | kmap_init(); | 864 | kmap_init(); |
| 865 | |||
| 866 | /* | ||
| 867 | * NOTE: at this point the bootmem allocator is fully available. | ||
| 868 | */ | ||
| 869 | sparse_init(); | ||
| 870 | zone_sizes_init(); | ||
| 871 | |||
| 872 | paravirt_post_allocator_init(); | ||
| 533 | } | 873 | } |
| 534 | 874 | ||
| 535 | /* | 875 | /* |
| @@ -564,24 +904,11 @@ static struct kcore_list kcore_mem, kcore_vmalloc; | |||
| 564 | void __init mem_init(void) | 904 | void __init mem_init(void) |
| 565 | { | 905 | { |
| 566 | int codesize, reservedpages, datasize, initsize; | 906 | int codesize, reservedpages, datasize, initsize; |
| 567 | int tmp, bad_ppro; | 907 | int tmp; |
| 568 | 908 | ||
| 569 | #ifdef CONFIG_FLATMEM | 909 | #ifdef CONFIG_FLATMEM |
| 570 | BUG_ON(!mem_map); | 910 | BUG_ON(!mem_map); |
| 571 | #endif | 911 | #endif |
| 572 | bad_ppro = ppro_with_ram_bug(); | ||
| 573 | |||
| 574 | #ifdef CONFIG_HIGHMEM | ||
| 575 | /* check that fixmap and pkmap do not overlap */ | ||
| 576 | if (PKMAP_BASE + LAST_PKMAP*PAGE_SIZE >= FIXADDR_START) { | ||
| 577 | printk(KERN_ERR | ||
| 578 | "fixmap and kmap areas overlap - this will crash\n"); | ||
| 579 | printk(KERN_ERR "pkstart: %lxh pkend: %lxh fixstart %lxh\n", | ||
| 580 | PKMAP_BASE, PKMAP_BASE + LAST_PKMAP*PAGE_SIZE, | ||
| 581 | FIXADDR_START); | ||
| 582 | BUG(); | ||
| 583 | } | ||
| 584 | #endif | ||
| 585 | /* this will put all low memory onto the freelists */ | 912 | /* this will put all low memory onto the freelists */ |
| 586 | totalram_pages += free_all_bootmem(); | 913 | totalram_pages += free_all_bootmem(); |
| 587 | 914 | ||
| @@ -593,7 +920,7 @@ void __init mem_init(void) | |||
| 593 | if (page_is_ram(tmp) && PageReserved(pfn_to_page(tmp))) | 920 | if (page_is_ram(tmp) && PageReserved(pfn_to_page(tmp))) |
| 594 | reservedpages++; | 921 | reservedpages++; |
| 595 | 922 | ||
| 596 | set_highmem_pages_init(bad_ppro); | 923 | set_highmem_pages_init(); |
| 597 | 924 | ||
| 598 | codesize = (unsigned long) &_etext - (unsigned long) &_text; | 925 | codesize = (unsigned long) &_etext - (unsigned long) &_text; |
| 599 | datasize = (unsigned long) &_edata - (unsigned long) &_etext; | 926 | datasize = (unsigned long) &_edata - (unsigned long) &_etext; |
| @@ -614,7 +941,6 @@ void __init mem_init(void) | |||
| 614 | (unsigned long) (totalhigh_pages << (PAGE_SHIFT-10)) | 941 | (unsigned long) (totalhigh_pages << (PAGE_SHIFT-10)) |
| 615 | ); | 942 | ); |
| 616 | 943 | ||
| 617 | #if 1 /* double-sanity-check paranoia */ | ||
| 618 | printk(KERN_INFO "virtual kernel memory layout:\n" | 944 | printk(KERN_INFO "virtual kernel memory layout:\n" |
| 619 | " fixmap : 0x%08lx - 0x%08lx (%4ld kB)\n" | 945 | " fixmap : 0x%08lx - 0x%08lx (%4ld kB)\n" |
| 620 | #ifdef CONFIG_HIGHMEM | 946 | #ifdef CONFIG_HIGHMEM |
| @@ -655,7 +981,6 @@ void __init mem_init(void) | |||
| 655 | #endif | 981 | #endif |
| 656 | BUG_ON(VMALLOC_START > VMALLOC_END); | 982 | BUG_ON(VMALLOC_START > VMALLOC_END); |
| 657 | BUG_ON((unsigned long)high_memory > VMALLOC_START); | 983 | BUG_ON((unsigned long)high_memory > VMALLOC_START); |
| 658 | #endif /* double-sanity-check paranoia */ | ||
| 659 | 984 | ||
| 660 | if (boot_cpu_data.wp_works_ok < 0) | 985 | if (boot_cpu_data.wp_works_ok < 0) |
| 661 | test_wp_bit(); | 986 | test_wp_bit(); |
| @@ -784,3 +1109,9 @@ void free_initrd_mem(unsigned long start, unsigned long end) | |||
| 784 | free_init_pages("initrd memory", start, end); | 1109 | free_init_pages("initrd memory", start, end); |
| 785 | } | 1110 | } |
| 786 | #endif | 1111 | #endif |
| 1112 | |||
| 1113 | int __init reserve_bootmem_generic(unsigned long phys, unsigned long len, | ||
| 1114 | int flags) | ||
| 1115 | { | ||
| 1116 | return reserve_bootmem(phys, len, flags); | ||
| 1117 | } | ||
