diff options
-rw-r--r-- | arch/powerpc/mm/subpage-prot.c | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/arch/powerpc/mm/subpage-prot.c b/arch/powerpc/mm/subpage-prot.c index 7c415ddde948..aa74acb0fdfc 100644 --- a/arch/powerpc/mm/subpage-prot.c +++ b/arch/powerpc/mm/subpage-prot.c | |||
@@ -130,6 +130,53 @@ static void subpage_prot_clear(unsigned long addr, unsigned long len) | |||
130 | up_write(&mm->mmap_sem); | 130 | up_write(&mm->mmap_sem); |
131 | } | 131 | } |
132 | 132 | ||
133 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE | ||
134 | static int subpage_walk_pmd_entry(pmd_t *pmd, unsigned long addr, | ||
135 | unsigned long end, struct mm_walk *walk) | ||
136 | { | ||
137 | struct vm_area_struct *vma = walk->private; | ||
138 | split_huge_page_pmd(vma, addr, pmd); | ||
139 | return 0; | ||
140 | } | ||
141 | |||
142 | static void subpage_mark_vma_nohuge(struct mm_struct *mm, unsigned long addr, | ||
143 | unsigned long len) | ||
144 | { | ||
145 | struct vm_area_struct *vma; | ||
146 | struct mm_walk subpage_proto_walk = { | ||
147 | .mm = mm, | ||
148 | .pmd_entry = subpage_walk_pmd_entry, | ||
149 | }; | ||
150 | |||
151 | /* | ||
152 | * We don't try too hard, we just mark all the vma in that range | ||
153 | * VM_NOHUGEPAGE and split them. | ||
154 | */ | ||
155 | vma = find_vma(mm, addr); | ||
156 | /* | ||
157 | * If the range is in unmapped range, just return | ||
158 | */ | ||
159 | if (vma && ((addr + len) <= vma->vm_start)) | ||
160 | return; | ||
161 | |||
162 | while (vma) { | ||
163 | if (vma->vm_start >= (addr + len)) | ||
164 | break; | ||
165 | vma->vm_flags |= VM_NOHUGEPAGE; | ||
166 | subpage_proto_walk.private = vma; | ||
167 | walk_page_range(vma->vm_start, vma->vm_end, | ||
168 | &subpage_proto_walk); | ||
169 | vma = vma->vm_next; | ||
170 | } | ||
171 | } | ||
172 | #else | ||
173 | static void subpage_mark_vma_nohuge(struct mm_struct *mm, unsigned long addr, | ||
174 | unsigned long len) | ||
175 | { | ||
176 | return; | ||
177 | } | ||
178 | #endif | ||
179 | |||
133 | /* | 180 | /* |
134 | * Copy in a subpage protection map for an address range. | 181 | * Copy in a subpage protection map for an address range. |
135 | * The map has 2 bits per 4k subpage, so 32 bits per 64k page. | 182 | * The map has 2 bits per 4k subpage, so 32 bits per 64k page. |
@@ -168,6 +215,7 @@ long sys_subpage_prot(unsigned long addr, unsigned long len, u32 __user *map) | |||
168 | return -EFAULT; | 215 | return -EFAULT; |
169 | 216 | ||
170 | down_write(&mm->mmap_sem); | 217 | down_write(&mm->mmap_sem); |
218 | subpage_mark_vma_nohuge(mm, addr, len); | ||
171 | for (limit = addr + len; addr < limit; addr = next) { | 219 | for (limit = addr + len; addr < limit; addr = next) { |
172 | next = pmd_addr_end(addr, limit); | 220 | next = pmd_addr_end(addr, limit); |
173 | err = -ENOMEM; | 221 | err = -ENOMEM; |