dmar: support for parsing Remapping Hardware Static Affinity structure
[safe/jmp/linux-2.6] / mm / nommu.c
index 4bde489..8d48424 100644 (file)
@@ -33,6 +33,7 @@
 #include <asm/uaccess.h>
 #include <asm/tlb.h>
 #include <asm/tlbflush.h>
+#include <asm/mmu_context.h>
 #include "internal.h"
 
 static inline __attribute__((format(printf, 1, 2)))
@@ -56,12 +57,11 @@ void no_printk(const char *fmt, ...)
        no_printk(KERN_DEBUG FMT"\n", ##__VA_ARGS__)
 #endif
 
-#include "internal.h"
-
 void *high_memory;
 struct page *mem_map;
 unsigned long max_mapnr;
 unsigned long num_physpages;
+unsigned long highest_memmap_pfn;
 struct percpu_counter vm_committed_as;
 int sysctl_overcommit_memory = OVERCOMMIT_GUESS; /* heuristic overcommit */
 int sysctl_overcommit_ratio = 50; /* default is 50% */
@@ -170,21 +170,20 @@ unsigned int kobjsize(const void *objp)
 }
 
 int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
-                    unsigned long start, int nr_pages, int flags,
+                    unsigned long start, int nr_pages, unsigned int foll_flags,
                     struct page **pages, struct vm_area_struct **vmas)
 {
        struct vm_area_struct *vma;
        unsigned long vm_flags;
        int i;
-       int write = !!(flags & GUP_FLAGS_WRITE);
-       int force = !!(flags & GUP_FLAGS_FORCE);
-       int ignore = !!(flags & GUP_FLAGS_IGNORE_VMA_PERMISSIONS);
 
        /* calculate required read or write permissions.
-        * - if 'force' is set, we only require the "MAY" flags.
+        * If FOLL_FORCE is set, we only require the "MAY" flags.
         */
-       vm_flags  = write ? (VM_WRITE | VM_MAYWRITE) : (VM_READ | VM_MAYREAD);
-       vm_flags &= force ? (VM_MAYREAD | VM_MAYWRITE) : (VM_READ | VM_WRITE);
+       vm_flags  = (foll_flags & FOLL_WRITE) ?
+                       (VM_WRITE | VM_MAYWRITE) : (VM_READ | VM_MAYREAD);
+       vm_flags &= (foll_flags & FOLL_FORCE) ?
+                       (VM_MAYREAD | VM_MAYWRITE) : (VM_READ | VM_WRITE);
 
        for (i = 0; i < nr_pages; i++) {
                vma = find_vma(mm, start);
@@ -192,8 +191,8 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
                        goto finish_or_fault;
 
                /* protect what we can, including chardevs */
-               if (vma->vm_flags & (VM_IO | VM_PFNMAP) ||
-                   (!ignore && !(vm_flags & vma->vm_flags)))
+               if ((vma->vm_flags & (VM_IO | VM_PFNMAP)) ||
+                   !(vm_flags & vma->vm_flags))
                        goto finish_or_fault;
 
                if (pages) {
@@ -212,7 +211,6 @@ finish_or_fault:
        return i ? : -EFAULT;
 }
 
-
 /*
  * get a list of pages in an address range belonging to the specified process
  * and indicate the VMA that covers each page
@@ -227,9 +225,9 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
        int flags = 0;
 
        if (write)
-               flags |= GUP_FLAGS_WRITE;
+               flags |= FOLL_WRITE;
        if (force)
-               flags |= GUP_FLAGS_FORCE;
+               flags |= FOLL_FORCE;
 
        return __get_user_pages(tsk, mm, start, nr_pages, flags, pages, vmas);
 }
@@ -627,6 +625,22 @@ static void put_nommu_region(struct vm_region *region)
 }
 
 /*
+ * update protection on a vma
+ */
+static void protect_vma(struct vm_area_struct *vma, unsigned long flags)
+{
+#ifdef CONFIG_MPU
+       struct mm_struct *mm = vma->vm_mm;
+       long start = vma->vm_start & PAGE_MASK;
+       while (start < vma->vm_end) {
+               protect_page(mm, start, flags);
+               start += PAGE_SIZE;
+       }
+       update_protections(mm);
+#endif
+}
+
+/*
  * add a VMA into a process's mm_struct in the appropriate place in the list
  * and tree and add to the address space's page tree also if not an anonymous
  * page
@@ -645,6 +659,8 @@ static void add_vma_to_mm(struct mm_struct *mm, struct vm_area_struct *vma)
        mm->map_count++;
        vma->vm_mm = mm;
 
+       protect_vma(vma, vma->vm_flags);
+
        /* add the VMA to the mapping */
        if (vma->vm_file) {
                mapping = vma->vm_file->f_mapping;
@@ -707,6 +723,8 @@ static void delete_vma_from_mm(struct vm_area_struct *vma)
 
        kenter("%p", vma);
 
+       protect_vma(vma, 0);
+
        mm->map_count--;
        if (mm->mmap_cache == vma)
                mm->mmap_cache = NULL;
@@ -1352,6 +1370,7 @@ unsigned long do_mmap_pgoff(struct file *file,
        }
 
        vma->vm_region = region;
+       add_nommu_region(region);
 
        /* set up the mapping */
        if (file && vma->vm_flags & VM_SHARED)
@@ -1361,8 +1380,6 @@ unsigned long do_mmap_pgoff(struct file *file,
        if (ret < 0)
                goto error_put_region;
 
-       add_nommu_region(region);
-
        /* okay... we have a mapping; now we have to register it */
        result = vma->vm_start;