aboutsummaryrefslogtreecommitdiffstats
path: root/mm/nommu.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/nommu.c')
-rw-r--r--mm/nommu.c45
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
38static inline __attribute__((format(printf, 1, 2))) 39static 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
61void *high_memory; 60void *high_memory;
62struct page *mem_map; 61struct page *mem_map;
63unsigned long max_mapnr; 62unsigned long max_mapnr;
@@ -170,21 +169,20 @@ unsigned int kobjsize(const void *objp)
170} 169}
171 170
172int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, 171int __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 */
629static 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;