eb0e8b684a00653f958d78156009358f6dbe2c0b
[pandora-kernel.git] / arch / arm / include / asm / hugetlb-2level.h
1 /*
2  * arch/arm/include/asm/hugetlb-2level.h
3  *
4  * Copyright (C) 2012 ARM Ltd.
5  *
6  * Based on arch/x86/include/asm/hugetlb.h and Bill Carson's patches
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 as
10  * published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20  */
21
22 #ifndef _ASM_ARM_HUGETLB_2LEVEL_H
23 #define _ASM_ARM_HUGETLB_2LEVEL_H
24
25
26 static inline pte_t huge_ptep_get(pte_t *ptep)
27 {
28         pmd_t pmd =  *((pmd_t *)ptep);
29         pte_t retval;
30
31         if (!pmd_val(pmd))
32                 return __pte(0);
33
34         retval = __pte((pteval_t) (pmd_val(pmd) & HPAGE_MASK)
35                         | arm_hugepteprotval);
36
37         if (pmd_exec(pmd))
38                 retval = pte_mkexec(retval);
39         else
40                 retval = pte_mknexec(retval);
41
42         if (pmd_young(pmd))
43                 retval = pte_mkyoung(retval);
44         else
45                 retval = pte_mkold(retval);
46
47         if (pmd_dirty(pmd))
48                 retval = pte_mkdirty(retval);
49         else
50                 retval = pte_mkclean(retval);
51
52         if (pmd_write(pmd))
53                 retval = pte_mkwrite(retval);
54         else
55                 retval = pte_wrprotect(retval);
56
57         return retval;
58 }
59
60 static inline void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
61                                    pte_t *ptep, pte_t pte)
62 {
63         pmdval_t pmdval = (pmdval_t) pte_val(pte);
64         pmd_t *pmdp = (pmd_t *) ptep;
65
66         /* take the target address bits from the pte only */
67         pmdval &= HPAGE_MASK;
68
69         /*
70          * now use pmd_modify to translate the permission bits from the pte
71          * and set the memory type information.
72          */
73         pmdval = pmd_val(pmd_modify(__pmd(pmdval), __pgprot(pte_val(pte))));
74
75         __sync_icache_dcache(pte);
76
77         set_pmd_at(mm, addr, pmdp, __pmd(pmdval));
78 }
79
80 static inline pte_t pte_mkhuge(pte_t pte) { return pte; }
81
82 static inline void huge_ptep_clear_flush(struct vm_area_struct *vma,
83                                          unsigned long addr, pte_t *ptep)
84 {
85         pmd_t *pmdp = (pmd_t *)ptep;
86         pmd_clear(pmdp);
87         flush_tlb_range(vma, addr, addr + HPAGE_SIZE);
88 }
89
90 static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
91                                            unsigned long addr, pte_t *ptep)
92 {
93         pmd_t *pmdp = (pmd_t *) ptep;
94         set_pmd_at(mm, addr, pmdp, pmd_wrprotect(*pmdp));
95 }
96
97
98 static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
99                                             unsigned long addr, pte_t *ptep)
100 {
101         pmd_t *pmdp = (pmd_t *)ptep;
102         pte_t pte = huge_ptep_get(ptep);
103         pmd_clear(pmdp);
104
105         return pte;
106 }
107
108 static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma,
109                                              unsigned long addr, pte_t *ptep,
110                                              pte_t pte, int dirty)
111 {
112         int changed = !pte_same(huge_ptep_get(ptep), pte);
113         if (changed) {
114                 set_huge_pte_at(vma->vm_mm, addr, ptep, pte);
115                 flush_tlb_range(vma, addr, addr + HPAGE_SIZE);
116         }
117
118         return changed;
119 }
120
121 #endif /* _ASM_ARM_HUGETLB_2LEVEL_H */