Merge branches 'pm-cpufreq-fixes' and 'pm-cpuidle'
[cascardo/linux.git] / arch / powerpc / mm / hugetlbpage-radix.c
1 #include <linux/mm.h>
2 #include <linux/hugetlb.h>
3 #include <asm/pgtable.h>
4 #include <asm/pgalloc.h>
5 #include <asm/cacheflush.h>
6 #include <asm/machdep.h>
7 #include <asm/mman.h>
8
9 void radix__flush_hugetlb_page(struct vm_area_struct *vma, unsigned long vmaddr)
10 {
11         unsigned long ap, shift;
12         struct hstate *hstate = hstate_file(vma->vm_file);
13
14         shift = huge_page_shift(hstate);
15         if (shift == mmu_psize_defs[MMU_PAGE_2M].shift)
16                 ap = mmu_get_ap(MMU_PAGE_2M);
17         else if (shift == mmu_psize_defs[MMU_PAGE_1G].shift)
18                 ap = mmu_get_ap(MMU_PAGE_1G);
19         else {
20                 WARN(1, "Wrong huge page shift\n");
21                 return ;
22         }
23         radix___flush_tlb_page(vma->vm_mm, vmaddr, ap, 0);
24 }
25
26 void radix__local_flush_hugetlb_page(struct vm_area_struct *vma, unsigned long vmaddr)
27 {
28         unsigned long ap, shift;
29         struct hstate *hstate = hstate_file(vma->vm_file);
30
31         shift = huge_page_shift(hstate);
32         if (shift == mmu_psize_defs[MMU_PAGE_2M].shift)
33                 ap = mmu_get_ap(MMU_PAGE_2M);
34         else if (shift == mmu_psize_defs[MMU_PAGE_1G].shift)
35                 ap = mmu_get_ap(MMU_PAGE_1G);
36         else {
37                 WARN(1, "Wrong huge page shift\n");
38                 return ;
39         }
40         radix___local_flush_tlb_page(vma->vm_mm, vmaddr, ap, 0);
41 }
42
43 /*
44  * A vairant of hugetlb_get_unmapped_area doing topdown search
45  * FIXME!! should we do as x86 does or non hugetlb area does ?
46  * ie, use topdown or not based on mmap_is_legacy check ?
47  */
48 unsigned long
49 radix__hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
50                                 unsigned long len, unsigned long pgoff,
51                                 unsigned long flags)
52 {
53         struct mm_struct *mm = current->mm;
54         struct vm_area_struct *vma;
55         struct hstate *h = hstate_file(file);
56         struct vm_unmapped_area_info info;
57
58         if (len & ~huge_page_mask(h))
59                 return -EINVAL;
60         if (len > TASK_SIZE)
61                 return -ENOMEM;
62
63         if (flags & MAP_FIXED) {
64                 if (prepare_hugepage_range(file, addr, len))
65                         return -EINVAL;
66                 return addr;
67         }
68
69         if (addr) {
70                 addr = ALIGN(addr, huge_page_size(h));
71                 vma = find_vma(mm, addr);
72                 if (TASK_SIZE - len >= addr &&
73                     (!vma || addr + len <= vma->vm_start))
74                         return addr;
75         }
76         /*
77          * We are always doing an topdown search here. Slice code
78          * does that too.
79          */
80         info.flags = VM_UNMAPPED_AREA_TOPDOWN;
81         info.length = len;
82         info.low_limit = PAGE_SIZE;
83         info.high_limit = current->mm->mmap_base;
84         info.align_mask = PAGE_MASK & ~huge_page_mask(h);
85         info.align_offset = 0;
86         return vm_unmapped_area(&info);
87 }