diff options
Diffstat (limited to 'mm/nommu.c')
-rw-r--r-- | mm/nommu.c | 45 |
1 files changed, 31 insertions, 14 deletions
diff --git a/mm/nommu.c b/mm/nommu.c index 66e81e7e9fe..1a4473faac4 100644 --- a/mm/nommu.c +++ b/mm/nommu.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <asm/uaccess.h> | 33 | #include <asm/uaccess.h> |
34 | #include <asm/tlb.h> | 34 | #include <asm/tlb.h> |
35 | #include <asm/tlbflush.h> | 35 | #include <asm/tlbflush.h> |
36 | #include <asm/mmu_context.h> | ||
36 | #include "internal.h" | 37 | #include "internal.h" |
37 | 38 | ||
38 | static inline __attribute__((format(printf, 1, 2))) | 39 | static inline __attribute__((format(printf, 1, 2))) |
@@ -56,8 +57,6 @@ void no_printk(const char *fmt, ...) | |||
56 | no_printk(KERN_DEBUG FMT"\n", ##__VA_ARGS__) | 57 | no_printk(KERN_DEBUG FMT"\n", ##__VA_ARGS__) |
57 | #endif | 58 | #endif |
58 | 59 | ||
59 | #include "internal.h" | ||
60 | |||
61 | void *high_memory; | 60 | void *high_memory; |
62 | struct page *mem_map; | 61 | struct page *mem_map; |
63 | unsigned long max_mapnr; | 62 | unsigned long max_mapnr; |
@@ -170,21 +169,20 @@ unsigned int kobjsize(const void *objp) | |||
170 | } | 169 | } |
171 | 170 | ||
172 | int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, | 171 | int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, |
173 | unsigned long start, int nr_pages, int flags, | 172 | unsigned long start, int nr_pages, int foll_flags, |
174 | struct page **pages, struct vm_area_struct **vmas) | 173 | struct page **pages, struct vm_area_struct **vmas) |
175 | { | 174 | { |
176 | struct vm_area_struct *vma; | 175 | struct vm_area_struct *vma; |
177 | unsigned long vm_flags; | 176 | unsigned long vm_flags; |
178 | int i; | 177 | int i; |
179 | int write = !!(flags & GUP_FLAGS_WRITE); | ||
180 | int force = !!(flags & GUP_FLAGS_FORCE); | ||
181 | int ignore = !!(flags & GUP_FLAGS_IGNORE_VMA_PERMISSIONS); | ||
182 | 178 | ||
183 | /* calculate required read or write permissions. | 179 | /* calculate required read or write permissions. |
184 | * - if 'force' is set, we only require the "MAY" flags. | 180 | * If FOLL_FORCE is set, we only require the "MAY" flags. |
185 | */ | 181 | */ |
186 | vm_flags = write ? (VM_WRITE | VM_MAYWRITE) : (VM_READ | VM_MAYREAD); | 182 | vm_flags = (foll_flags & FOLL_WRITE) ? |
187 | vm_flags &= force ? (VM_MAYREAD | VM_MAYWRITE) : (VM_READ | VM_WRITE); | 183 | (VM_WRITE | VM_MAYWRITE) : (VM_READ | VM_MAYREAD); |
184 | vm_flags &= (foll_flags & FOLL_FORCE) ? | ||
185 | (VM_MAYREAD | VM_MAYWRITE) : (VM_READ | VM_WRITE); | ||
188 | 186 | ||
189 | for (i = 0; i < nr_pages; i++) { | 187 | for (i = 0; i < nr_pages; i++) { |
190 | vma = find_vma(mm, start); | 188 | vma = find_vma(mm, start); |
@@ -192,8 +190,8 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, | |||
192 | goto finish_or_fault; | 190 | goto finish_or_fault; |
193 | 191 | ||
194 | /* protect what we can, including chardevs */ | 192 | /* protect what we can, including chardevs */ |
195 | if (vma->vm_flags & (VM_IO | VM_PFNMAP) || | 193 | if ((vma->vm_flags & (VM_IO | VM_PFNMAP)) || |
196 | (!ignore && !(vm_flags & vma->vm_flags))) | 194 | !(vm_flags & vma->vm_flags)) |
197 | goto finish_or_fault; | 195 | goto finish_or_fault; |
198 | 196 | ||
199 | if (pages) { | 197 | if (pages) { |
@@ -212,7 +210,6 @@ finish_or_fault: | |||
212 | return i ? : -EFAULT; | 210 | return i ? : -EFAULT; |
213 | } | 211 | } |
214 | 212 | ||
215 | |||
216 | /* | 213 | /* |
217 | * get a list of pages in an address range belonging to the specified process | 214 | * get a list of pages in an address range belonging to the specified process |
218 | * and indicate the VMA that covers each page | 215 | * and indicate the VMA that covers each page |
@@ -227,9 +224,9 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, | |||
227 | int flags = 0; | 224 | int flags = 0; |
228 | 225 | ||
229 | if (write) | 226 | if (write) |
230 | flags |= GUP_FLAGS_WRITE; | 227 | flags |= FOLL_WRITE; |
231 | if (force) | 228 | if (force) |
232 | flags |= GUP_FLAGS_FORCE; | 229 | flags |= FOLL_FORCE; |
233 | 230 | ||
234 | return __get_user_pages(tsk, mm, start, nr_pages, flags, pages, vmas); | 231 | return __get_user_pages(tsk, mm, start, nr_pages, flags, pages, vmas); |
235 | } | 232 | } |
@@ -627,6 +624,22 @@ static void put_nommu_region(struct vm_region *region) | |||
627 | } | 624 | } |
628 | 625 | ||
629 | /* | 626 | /* |
627 | * update protection on a vma | ||
628 | */ | ||
629 | static void protect_vma(struct vm_area_struct *vma, unsigned long flags) | ||
630 | { | ||
631 | #ifdef CONFIG_MPU | ||
632 | struct mm_struct *mm = vma->vm_mm; | ||
633 | long start = vma->vm_start & PAGE_MASK; | ||
634 | while (start < vma->vm_end) { | ||
635 | protect_page(mm, start, flags); | ||
636 | start += PAGE_SIZE; | ||
637 | } | ||
638 | update_protections(mm); | ||
639 | #endif | ||
640 | } | ||
641 | |||
642 | /* | ||
630 | * add a VMA into a process's mm_struct in the appropriate place in the list | 643 | * add a VMA into a process's mm_struct in the appropriate place in the list |
631 | * and tree and add to the address space's page tree also if not an anonymous | 644 | * and tree and add to the address space's page tree also if not an anonymous |
632 | * page | 645 | * page |
@@ -645,6 +658,8 @@ static void add_vma_to_mm(struct mm_struct *mm, struct vm_area_struct *vma) | |||
645 | mm->map_count++; | 658 | mm->map_count++; |
646 | vma->vm_mm = mm; | 659 | vma->vm_mm = mm; |
647 | 660 | ||
661 | protect_vma(vma, vma->vm_flags); | ||
662 | |||
648 | /* add the VMA to the mapping */ | 663 | /* add the VMA to the mapping */ |
649 | if (vma->vm_file) { | 664 | if (vma->vm_file) { |
650 | mapping = vma->vm_file->f_mapping; | 665 | mapping = vma->vm_file->f_mapping; |
@@ -707,6 +722,8 @@ static void delete_vma_from_mm(struct vm_area_struct *vma) | |||
707 | 722 | ||
708 | kenter("%p", vma); | 723 | kenter("%p", vma); |
709 | 724 | ||
725 | protect_vma(vma, 0); | ||
726 | |||
710 | mm->map_count--; | 727 | mm->map_count--; |
711 | if (mm->mmap_cache == vma) | 728 | if (mm->mmap_cache == vma) |
712 | mm->mmap_cache = NULL; | 729 | mm->mmap_cache = NULL; |