diff options
Diffstat (limited to 'arch/powerpc/mm/hugetlbpage.c')
-rw-r--r-- | arch/powerpc/mm/hugetlbpage.c | 116 |
1 files changed, 73 insertions, 43 deletions
diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c index 5964371303ac..79c575d3dd63 100644 --- a/arch/powerpc/mm/hugetlbpage.c +++ b/arch/powerpc/mm/hugetlbpage.c | |||
@@ -28,22 +28,22 @@ unsigned int HPAGE_SHIFT; | |||
28 | 28 | ||
29 | /* | 29 | /* |
30 | * Tracks gpages after the device tree is scanned and before the | 30 | * Tracks gpages after the device tree is scanned and before the |
31 | * huge_boot_pages list is ready. On 64-bit implementations, this is | 31 | * huge_boot_pages list is ready. On non-Freescale implementations, this is |
32 | * just used to track 16G pages and so is a single array. 32-bit | 32 | * just used to track 16G pages and so is a single array. FSL-based |
33 | * implementations may have more than one gpage size due to limitations | 33 | * implementations may have more than one gpage size, so we need multiple |
34 | * of the memory allocators, so we need multiple arrays | 34 | * arrays |
35 | */ | 35 | */ |
36 | #ifdef CONFIG_PPC64 | 36 | #ifdef CONFIG_PPC_FSL_BOOK3E |
37 | #define MAX_NUMBER_GPAGES 1024 | ||
38 | static u64 gpage_freearray[MAX_NUMBER_GPAGES]; | ||
39 | static unsigned nr_gpages; | ||
40 | #else | ||
41 | #define MAX_NUMBER_GPAGES 128 | 37 | #define MAX_NUMBER_GPAGES 128 |
42 | struct psize_gpages { | 38 | struct psize_gpages { |
43 | u64 gpage_list[MAX_NUMBER_GPAGES]; | 39 | u64 gpage_list[MAX_NUMBER_GPAGES]; |
44 | unsigned int nr_gpages; | 40 | unsigned int nr_gpages; |
45 | }; | 41 | }; |
46 | static struct psize_gpages gpage_freearray[MMU_PAGE_COUNT]; | 42 | static struct psize_gpages gpage_freearray[MMU_PAGE_COUNT]; |
43 | #else | ||
44 | #define MAX_NUMBER_GPAGES 1024 | ||
45 | static u64 gpage_freearray[MAX_NUMBER_GPAGES]; | ||
46 | static unsigned nr_gpages; | ||
47 | #endif | 47 | #endif |
48 | 48 | ||
49 | static inline int shift_to_mmu_psize(unsigned int shift) | 49 | static inline int shift_to_mmu_psize(unsigned int shift) |
@@ -114,12 +114,12 @@ static int __hugepte_alloc(struct mm_struct *mm, hugepd_t *hpdp, | |||
114 | struct kmem_cache *cachep; | 114 | struct kmem_cache *cachep; |
115 | pte_t *new; | 115 | pte_t *new; |
116 | 116 | ||
117 | #ifdef CONFIG_PPC64 | 117 | #ifdef CONFIG_PPC_FSL_BOOK3E |
118 | cachep = PGT_CACHE(pdshift - pshift); | ||
119 | #else | ||
120 | int i; | 118 | int i; |
121 | int num_hugepd = 1 << (pshift - pdshift); | 119 | int num_hugepd = 1 << (pshift - pdshift); |
122 | cachep = hugepte_cache; | 120 | cachep = hugepte_cache; |
121 | #else | ||
122 | cachep = PGT_CACHE(pdshift - pshift); | ||
123 | #endif | 123 | #endif |
124 | 124 | ||
125 | new = kmem_cache_zalloc(cachep, GFP_KERNEL|__GFP_REPEAT); | 125 | new = kmem_cache_zalloc(cachep, GFP_KERNEL|__GFP_REPEAT); |
@@ -131,12 +131,7 @@ static int __hugepte_alloc(struct mm_struct *mm, hugepd_t *hpdp, | |||
131 | return -ENOMEM; | 131 | return -ENOMEM; |
132 | 132 | ||
133 | spin_lock(&mm->page_table_lock); | 133 | spin_lock(&mm->page_table_lock); |
134 | #ifdef CONFIG_PPC64 | 134 | #ifdef CONFIG_PPC_FSL_BOOK3E |
135 | if (!hugepd_none(*hpdp)) | ||
136 | kmem_cache_free(cachep, new); | ||
137 | else | ||
138 | hpdp->pd = ((unsigned long)new & ~PD_HUGE) | pshift; | ||
139 | #else | ||
140 | /* | 135 | /* |
141 | * We have multiple higher-level entries that point to the same | 136 | * We have multiple higher-level entries that point to the same |
142 | * actual pte location. Fill in each as we go and backtrack on error. | 137 | * actual pte location. Fill in each as we go and backtrack on error. |
@@ -155,11 +150,28 @@ static int __hugepte_alloc(struct mm_struct *mm, hugepd_t *hpdp, | |||
155 | hpdp->pd = 0; | 150 | hpdp->pd = 0; |
156 | kmem_cache_free(cachep, new); | 151 | kmem_cache_free(cachep, new); |
157 | } | 152 | } |
153 | #else | ||
154 | if (!hugepd_none(*hpdp)) | ||
155 | kmem_cache_free(cachep, new); | ||
156 | else | ||
157 | hpdp->pd = ((unsigned long)new & ~PD_HUGE) | pshift; | ||
158 | #endif | 158 | #endif |
159 | spin_unlock(&mm->page_table_lock); | 159 | spin_unlock(&mm->page_table_lock); |
160 | return 0; | 160 | return 0; |
161 | } | 161 | } |
162 | 162 | ||
163 | /* | ||
164 | * These macros define how to determine which level of the page table holds | ||
165 | * the hpdp. | ||
166 | */ | ||
167 | #ifdef CONFIG_PPC_FSL_BOOK3E | ||
168 | #define HUGEPD_PGD_SHIFT PGDIR_SHIFT | ||
169 | #define HUGEPD_PUD_SHIFT PUD_SHIFT | ||
170 | #else | ||
171 | #define HUGEPD_PGD_SHIFT PUD_SHIFT | ||
172 | #define HUGEPD_PUD_SHIFT PMD_SHIFT | ||
173 | #endif | ||
174 | |||
163 | pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr, unsigned long sz) | 175 | pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr, unsigned long sz) |
164 | { | 176 | { |
165 | pgd_t *pg; | 177 | pgd_t *pg; |
@@ -172,12 +184,13 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr, unsigned long sz | |||
172 | addr &= ~(sz-1); | 184 | addr &= ~(sz-1); |
173 | 185 | ||
174 | pg = pgd_offset(mm, addr); | 186 | pg = pgd_offset(mm, addr); |
175 | if (pshift >= PUD_SHIFT) { | 187 | |
188 | if (pshift >= HUGEPD_PGD_SHIFT) { | ||
176 | hpdp = (hugepd_t *)pg; | 189 | hpdp = (hugepd_t *)pg; |
177 | } else { | 190 | } else { |
178 | pdshift = PUD_SHIFT; | 191 | pdshift = PUD_SHIFT; |
179 | pu = pud_alloc(mm, pg, addr); | 192 | pu = pud_alloc(mm, pg, addr); |
180 | if (pshift >= PMD_SHIFT) { | 193 | if (pshift >= HUGEPD_PUD_SHIFT) { |
181 | hpdp = (hugepd_t *)pu; | 194 | hpdp = (hugepd_t *)pu; |
182 | } else { | 195 | } else { |
183 | pdshift = PMD_SHIFT; | 196 | pdshift = PMD_SHIFT; |
@@ -197,7 +210,7 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr, unsigned long sz | |||
197 | return hugepte_offset(hpdp, addr, pdshift); | 210 | return hugepte_offset(hpdp, addr, pdshift); |
198 | } | 211 | } |
199 | 212 | ||
200 | #ifdef CONFIG_PPC32 | 213 | #ifdef CONFIG_PPC_FSL_BOOK3E |
201 | /* Build list of addresses of gigantic pages. This function is used in early | 214 | /* Build list of addresses of gigantic pages. This function is used in early |
202 | * boot before the buddy or bootmem allocator is setup. | 215 | * boot before the buddy or bootmem allocator is setup. |
203 | */ | 216 | */ |
@@ -317,7 +330,7 @@ void __init reserve_hugetlb_gpages(void) | |||
317 | } | 330 | } |
318 | } | 331 | } |
319 | 332 | ||
320 | #else /* PPC64 */ | 333 | #else /* !PPC_FSL_BOOK3E */ |
321 | 334 | ||
322 | /* Build list of addresses of gigantic pages. This function is used in early | 335 | /* Build list of addresses of gigantic pages. This function is used in early |
323 | * boot before the buddy or bootmem allocator is setup. | 336 | * boot before the buddy or bootmem allocator is setup. |
@@ -355,7 +368,7 @@ int huge_pmd_unshare(struct mm_struct *mm, unsigned long *addr, pte_t *ptep) | |||
355 | return 0; | 368 | return 0; |
356 | } | 369 | } |
357 | 370 | ||
358 | #ifdef CONFIG_PPC32 | 371 | #ifdef CONFIG_PPC_FSL_BOOK3E |
359 | #define HUGEPD_FREELIST_SIZE \ | 372 | #define HUGEPD_FREELIST_SIZE \ |
360 | ((PAGE_SIZE - sizeof(struct hugepd_freelist)) / sizeof(pte_t)) | 373 | ((PAGE_SIZE - sizeof(struct hugepd_freelist)) / sizeof(pte_t)) |
361 | 374 | ||
@@ -415,11 +428,11 @@ static void free_hugepd_range(struct mmu_gather *tlb, hugepd_t *hpdp, int pdshif | |||
415 | unsigned long pdmask = ~((1UL << pdshift) - 1); | 428 | unsigned long pdmask = ~((1UL << pdshift) - 1); |
416 | unsigned int num_hugepd = 1; | 429 | unsigned int num_hugepd = 1; |
417 | 430 | ||
418 | #ifdef CONFIG_PPC64 | 431 | #ifdef CONFIG_PPC_FSL_BOOK3E |
419 | unsigned int shift = hugepd_shift(*hpdp); | 432 | /* Note: On fsl the hpdp may be the first of several */ |
420 | #else | ||
421 | /* Note: On 32-bit the hpdp may be the first of several */ | ||
422 | num_hugepd = (1 << (hugepd_shift(*hpdp) - pdshift)); | 433 | num_hugepd = (1 << (hugepd_shift(*hpdp) - pdshift)); |
434 | #else | ||
435 | unsigned int shift = hugepd_shift(*hpdp); | ||
423 | #endif | 436 | #endif |
424 | 437 | ||
425 | start &= pdmask; | 438 | start &= pdmask; |
@@ -437,10 +450,11 @@ static void free_hugepd_range(struct mmu_gather *tlb, hugepd_t *hpdp, int pdshif | |||
437 | hpdp->pd = 0; | 450 | hpdp->pd = 0; |
438 | 451 | ||
439 | tlb->need_flush = 1; | 452 | tlb->need_flush = 1; |
440 | #ifdef CONFIG_PPC64 | 453 | |
441 | pgtable_free_tlb(tlb, hugepte, pdshift - shift); | 454 | #ifdef CONFIG_PPC_FSL_BOOK3E |
442 | #else | ||
443 | hugepd_free(tlb, hugepte); | 455 | hugepd_free(tlb, hugepte); |
456 | #else | ||
457 | pgtable_free_tlb(tlb, hugepte, pdshift - shift); | ||
444 | #endif | 458 | #endif |
445 | } | 459 | } |
446 | 460 | ||
@@ -453,14 +467,23 @@ static void hugetlb_free_pmd_range(struct mmu_gather *tlb, pud_t *pud, | |||
453 | unsigned long start; | 467 | unsigned long start; |
454 | 468 | ||
455 | start = addr; | 469 | start = addr; |
456 | pmd = pmd_offset(pud, addr); | ||
457 | do { | 470 | do { |
471 | pmd = pmd_offset(pud, addr); | ||
458 | next = pmd_addr_end(addr, end); | 472 | next = pmd_addr_end(addr, end); |
459 | if (pmd_none(*pmd)) | 473 | if (pmd_none(*pmd)) |
460 | continue; | 474 | continue; |
475 | #ifdef CONFIG_PPC_FSL_BOOK3E | ||
476 | /* | ||
477 | * Increment next by the size of the huge mapping since | ||
478 | * there may be more than one entry at this level for a | ||
479 | * single hugepage, but all of them point to | ||
480 | * the same kmem cache that holds the hugepte. | ||
481 | */ | ||
482 | next = addr + (1 << hugepd_shift(*(hugepd_t *)pmd)); | ||
483 | #endif | ||
461 | free_hugepd_range(tlb, (hugepd_t *)pmd, PMD_SHIFT, | 484 | free_hugepd_range(tlb, (hugepd_t *)pmd, PMD_SHIFT, |
462 | addr, next, floor, ceiling); | 485 | addr, next, floor, ceiling); |
463 | } while (pmd++, addr = next, addr != end); | 486 | } while (addr = next, addr != end); |
464 | 487 | ||
465 | start &= PUD_MASK; | 488 | start &= PUD_MASK; |
466 | if (start < floor) | 489 | if (start < floor) |
@@ -487,8 +510,8 @@ static void hugetlb_free_pud_range(struct mmu_gather *tlb, pgd_t *pgd, | |||
487 | unsigned long start; | 510 | unsigned long start; |
488 | 511 | ||
489 | start = addr; | 512 | start = addr; |
490 | pud = pud_offset(pgd, addr); | ||
491 | do { | 513 | do { |
514 | pud = pud_offset(pgd, addr); | ||
492 | next = pud_addr_end(addr, end); | 515 | next = pud_addr_end(addr, end); |
493 | if (!is_hugepd(pud)) { | 516 | if (!is_hugepd(pud)) { |
494 | if (pud_none_or_clear_bad(pud)) | 517 | if (pud_none_or_clear_bad(pud)) |
@@ -496,10 +519,19 @@ static void hugetlb_free_pud_range(struct mmu_gather *tlb, pgd_t *pgd, | |||
496 | hugetlb_free_pmd_range(tlb, pud, addr, next, floor, | 519 | hugetlb_free_pmd_range(tlb, pud, addr, next, floor, |
497 | ceiling); | 520 | ceiling); |
498 | } else { | 521 | } else { |
522 | #ifdef CONFIG_PPC_FSL_BOOK3E | ||
523 | /* | ||
524 | * Increment next by the size of the huge mapping since | ||
525 | * there may be more than one entry at this level for a | ||
526 | * single hugepage, but all of them point to | ||
527 | * the same kmem cache that holds the hugepte. | ||
528 | */ | ||
529 | next = addr + (1 << hugepd_shift(*(hugepd_t *)pud)); | ||
530 | #endif | ||
499 | free_hugepd_range(tlb, (hugepd_t *)pud, PUD_SHIFT, | 531 | free_hugepd_range(tlb, (hugepd_t *)pud, PUD_SHIFT, |
500 | addr, next, floor, ceiling); | 532 | addr, next, floor, ceiling); |
501 | } | 533 | } |
502 | } while (pud++, addr = next, addr != end); | 534 | } while (addr = next, addr != end); |
503 | 535 | ||
504 | start &= PGDIR_MASK; | 536 | start &= PGDIR_MASK; |
505 | if (start < floor) | 537 | if (start < floor) |
@@ -554,12 +586,12 @@ void hugetlb_free_pgd_range(struct mmu_gather *tlb, | |||
554 | continue; | 586 | continue; |
555 | hugetlb_free_pud_range(tlb, pgd, addr, next, floor, ceiling); | 587 | hugetlb_free_pud_range(tlb, pgd, addr, next, floor, ceiling); |
556 | } else { | 588 | } else { |
557 | #ifdef CONFIG_PPC32 | 589 | #ifdef CONFIG_PPC_FSL_BOOK3E |
558 | /* | 590 | /* |
559 | * Increment next by the size of the huge mapping since | 591 | * Increment next by the size of the huge mapping since |
560 | * on 32-bit there may be more than one entry at the pgd | 592 | * there may be more than one entry at the pgd level |
561 | * level for a single hugepage, but all of them point to | 593 | * for a single hugepage, but all of them point to the |
562 | * the same kmem cache that holds the hugepte. | 594 | * same kmem cache that holds the hugepte. |
563 | */ | 595 | */ |
564 | next = addr + (1 << hugepd_shift(*(hugepd_t *)pgd)); | 596 | next = addr + (1 << hugepd_shift(*(hugepd_t *)pgd)); |
565 | #endif | 597 | #endif |
@@ -697,19 +729,17 @@ int gup_hugepd(hugepd_t *hugepd, unsigned pdshift, | |||
697 | return 1; | 729 | return 1; |
698 | } | 730 | } |
699 | 731 | ||
732 | #ifdef CONFIG_PPC_MM_SLICES | ||
700 | unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr, | 733 | unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr, |
701 | unsigned long len, unsigned long pgoff, | 734 | unsigned long len, unsigned long pgoff, |
702 | unsigned long flags) | 735 | unsigned long flags) |
703 | { | 736 | { |
704 | #ifdef CONFIG_PPC_MM_SLICES | ||
705 | struct hstate *hstate = hstate_file(file); | 737 | struct hstate *hstate = hstate_file(file); |
706 | int mmu_psize = shift_to_mmu_psize(huge_page_shift(hstate)); | 738 | int mmu_psize = shift_to_mmu_psize(huge_page_shift(hstate)); |
707 | 739 | ||
708 | return slice_get_unmapped_area(addr, len, flags, mmu_psize, 1, 0); | 740 | return slice_get_unmapped_area(addr, len, flags, mmu_psize, 1, 0); |
709 | #else | ||
710 | return get_unmapped_area(file, addr, len, pgoff, flags); | ||
711 | #endif | ||
712 | } | 741 | } |
742 | #endif | ||
713 | 743 | ||
714 | unsigned long vma_mmu_pagesize(struct vm_area_struct *vma) | 744 | unsigned long vma_mmu_pagesize(struct vm_area_struct *vma) |
715 | { | 745 | { |
@@ -783,7 +813,7 @@ static int __init hugepage_setup_sz(char *str) | |||
783 | } | 813 | } |
784 | __setup("hugepagesz=", hugepage_setup_sz); | 814 | __setup("hugepagesz=", hugepage_setup_sz); |
785 | 815 | ||
786 | #ifdef CONFIG_FSL_BOOKE | 816 | #ifdef CONFIG_PPC_FSL_BOOK3E |
787 | struct kmem_cache *hugepte_cache; | 817 | struct kmem_cache *hugepte_cache; |
788 | static int __init hugetlbpage_init(void) | 818 | static int __init hugetlbpage_init(void) |
789 | { | 819 | { |