aboutsummaryrefslogtreecommitdiffstats
path: root/include/asm-s390/pgalloc.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/asm-s390/pgalloc.h')
-rw-r--r--include/asm-s390/pgalloc.h85
1 files changed, 80 insertions, 5 deletions
diff --git a/include/asm-s390/pgalloc.h b/include/asm-s390/pgalloc.h
index 0707a7e2fc16..56c8a6c80e2e 100644
--- a/include/asm-s390/pgalloc.h
+++ b/include/asm-s390/pgalloc.h
@@ -47,6 +47,17 @@ static inline pgd_t *pgd_alloc(struct mm_struct *mm)
47 47
48 if (!pgd) 48 if (!pgd)
49 return NULL; 49 return NULL;
50 if (s390_noexec) {
51 pgd_t *shadow_pgd = (pgd_t *)
52 __get_free_pages(GFP_KERNEL, PGD_ALLOC_ORDER);
53 struct page *page = virt_to_page(pgd);
54
55 if (!shadow_pgd) {
56 free_pages((unsigned long) pgd, PGD_ALLOC_ORDER);
57 return NULL;
58 }
59 page->lru.next = (void *) shadow_pgd;
60 }
50 for (i = 0; i < PTRS_PER_PGD; i++) 61 for (i = 0; i < PTRS_PER_PGD; i++)
51#ifndef __s390x__ 62#ifndef __s390x__
52 pmd_clear(pmd_offset(pgd + i, i*PGDIR_SIZE)); 63 pmd_clear(pmd_offset(pgd + i, i*PGDIR_SIZE));
@@ -58,6 +69,10 @@ static inline pgd_t *pgd_alloc(struct mm_struct *mm)
58 69
59static inline void pgd_free(pgd_t *pgd) 70static inline void pgd_free(pgd_t *pgd)
60{ 71{
72 pgd_t *shadow_pgd = get_shadow_pgd(pgd);
73
74 if (shadow_pgd)
75 free_pages((unsigned long) shadow_pgd, PGD_ALLOC_ORDER);
61 free_pages((unsigned long) pgd, PGD_ALLOC_ORDER); 76 free_pages((unsigned long) pgd, PGD_ALLOC_ORDER);
62} 77}
63 78
@@ -71,6 +86,7 @@ static inline void pgd_free(pgd_t *pgd)
71#define pmd_free(x) do { } while (0) 86#define pmd_free(x) do { } while (0)
72#define __pmd_free_tlb(tlb,x) do { } while (0) 87#define __pmd_free_tlb(tlb,x) do { } while (0)
73#define pgd_populate(mm, pmd, pte) BUG() 88#define pgd_populate(mm, pmd, pte) BUG()
89#define pgd_populate_kernel(mm, pmd, pte) BUG()
74#else /* __s390x__ */ 90#else /* __s390x__ */
75static inline pmd_t * pmd_alloc_one(struct mm_struct *mm, unsigned long vmaddr) 91static inline pmd_t * pmd_alloc_one(struct mm_struct *mm, unsigned long vmaddr)
76{ 92{
@@ -79,6 +95,17 @@ static inline pmd_t * pmd_alloc_one(struct mm_struct *mm, unsigned long vmaddr)
79 95
80 if (!pmd) 96 if (!pmd)
81 return NULL; 97 return NULL;
98 if (s390_noexec) {
99 pmd_t *shadow_pmd = (pmd_t *)
100 __get_free_pages(GFP_KERNEL, PMD_ALLOC_ORDER);
101 struct page *page = virt_to_page(pmd);
102
103 if (!shadow_pmd) {
104 free_pages((unsigned long) pmd, PMD_ALLOC_ORDER);
105 return NULL;
106 }
107 page->lru.next = (void *) shadow_pmd;
108 }
82 for (i=0; i < PTRS_PER_PMD; i++) 109 for (i=0; i < PTRS_PER_PMD; i++)
83 pmd_clear(pmd + i); 110 pmd_clear(pmd + i);
84 return pmd; 111 return pmd;
@@ -86,6 +113,10 @@ static inline pmd_t * pmd_alloc_one(struct mm_struct *mm, unsigned long vmaddr)
86 113
87static inline void pmd_free (pmd_t *pmd) 114static inline void pmd_free (pmd_t *pmd)
88{ 115{
116 pmd_t *shadow_pmd = get_shadow_pmd(pmd);
117
118 if (shadow_pmd)
119 free_pages((unsigned long) shadow_pmd, PMD_ALLOC_ORDER);
89 free_pages((unsigned long) pmd, PMD_ALLOC_ORDER); 120 free_pages((unsigned long) pmd, PMD_ALLOC_ORDER);
90} 121}
91 122
@@ -95,11 +126,22 @@ static inline void pmd_free (pmd_t *pmd)
95 pmd_free(pmd); \ 126 pmd_free(pmd); \
96 } while (0) 127 } while (0)
97 128
98static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pmd_t *pmd) 129static inline void
130pgd_populate_kernel(struct mm_struct *mm, pgd_t *pgd, pmd_t *pmd)
99{ 131{
100 pgd_val(*pgd) = _PGD_ENTRY | __pa(pmd); 132 pgd_val(*pgd) = _PGD_ENTRY | __pa(pmd);
101} 133}
102 134
135static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pmd_t *pmd)
136{
137 pgd_t *shadow_pgd = get_shadow_pgd(pgd);
138 pmd_t *shadow_pmd = get_shadow_pmd(pmd);
139
140 if (shadow_pgd && shadow_pmd)
141 pgd_populate_kernel(mm, shadow_pgd, shadow_pmd);
142 pgd_populate_kernel(mm, pgd, pmd);
143}
144
103#endif /* __s390x__ */ 145#endif /* __s390x__ */
104 146
105static inline void 147static inline void
@@ -119,7 +161,13 @@ pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd, pte_t *pte)
119static inline void 161static inline void
120pmd_populate(struct mm_struct *mm, pmd_t *pmd, struct page *page) 162pmd_populate(struct mm_struct *mm, pmd_t *pmd, struct page *page)
121{ 163{
122 pmd_populate_kernel(mm, pmd, (pte_t *)page_to_phys(page)); 164 pte_t *pte = (pte_t *)page_to_phys(page);
165 pmd_t *shadow_pmd = get_shadow_pmd(pmd);
166 pte_t *shadow_pte = get_shadow_pte(pte);
167
168 pmd_populate_kernel(mm, pmd, pte);
169 if (shadow_pmd && shadow_pte)
170 pmd_populate_kernel(mm, shadow_pmd, shadow_pte);
123} 171}
124 172
125/* 173/*
@@ -133,6 +181,17 @@ pte_alloc_one_kernel(struct mm_struct *mm, unsigned long vmaddr)
133 181
134 if (!pte) 182 if (!pte)
135 return NULL; 183 return NULL;
184 if (s390_noexec) {
185 pte_t *shadow_pte = (pte_t *)
186 __get_free_page(GFP_KERNEL|__GFP_REPEAT);
187 struct page *page = virt_to_page(pte);
188
189 if (!shadow_pte) {
190 free_page((unsigned long) pte);
191 return NULL;
192 }
193 page->lru.next = (void *) shadow_pte;
194 }
136 for (i=0; i < PTRS_PER_PTE; i++) { 195 for (i=0; i < PTRS_PER_PTE; i++) {
137 pte_clear(mm, vmaddr, pte + i); 196 pte_clear(mm, vmaddr, pte + i);
138 vmaddr += PAGE_SIZE; 197 vmaddr += PAGE_SIZE;
@@ -151,14 +210,30 @@ pte_alloc_one(struct mm_struct *mm, unsigned long vmaddr)
151 210
152static inline void pte_free_kernel(pte_t *pte) 211static inline void pte_free_kernel(pte_t *pte)
153{ 212{
154 free_page((unsigned long) pte); 213 pte_t *shadow_pte = get_shadow_pte(pte);
214
215 if (shadow_pte)
216 free_page((unsigned long) shadow_pte);
217 free_page((unsigned long) pte);
155} 218}
156 219
157static inline void pte_free(struct page *pte) 220static inline void pte_free(struct page *pte)
158{ 221{
159 __free_page(pte); 222 struct page *shadow_page = get_shadow_page(pte);
223
224 if (shadow_page)
225 __free_page(shadow_page);
226 __free_page(pte);
160} 227}
161 228
162#define __pte_free_tlb(tlb,pte) tlb_remove_page(tlb,pte) 229#define __pte_free_tlb(tlb, pte) \
230({ \
231 struct mmu_gather *__tlb = (tlb); \
232 struct page *__pte = (pte); \
233 struct page *shadow_page = get_shadow_page(__pte); \
234 if (shadow_page) \
235 tlb_remove_page(__tlb, shadow_page); \
236 tlb_remove_page(__tlb, __pte); \
237})
163 238
164#endif /* _S390_PGALLOC_H */ 239#endif /* _S390_PGALLOC_H */