/* Called with mm->mmap_sem held for writing. Insert a new vma covering the given region, with the given flags. Its pages are supplied by the given array of struct page *. The array can be shorter than len >> PAGE_SHIFT if it's null-terminated. The region past the last page supplied will always produce SIGBUS. The array pointer and the pages it points to are assumed to stay alive for as long as this mapping might exist.  */
int install_special_mapping(struct mm_struct *mm, unsigned long addr, unsigned long len, unsigned long vm_flags, struct page **pages)
/* Called with mm->mmap_sem held for writing. Insert a new vma covering the given region, with the given flags. Its pages are supplied by the given array of struct page *. The array can be shorter than len >> PAGE_SHIFT if it's null-terminated. The region past the last page supplied will always produce SIGBUS. The array pointer and the pages it points to are assumed to stay alive for as long as this mapping might exist.  */
int install_special_mapping(struct mm_struct *mm, unsigned long addr, unsigned long len, unsigned long vm_flags, struct page **pages)
{
	struct vm_area_struct *vma;
	vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL);
	if (unlikely(vma == NULL))
		return -ENOMEM;
	vma->vm_mm = mm;
	vma->vm_start = addr;
	vma->vm_end = addr + len;
	vma->vm_flags = vm_flags | mm->def_flags | VM_DONTEXPAND;
	vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
	vma->vm_ops = &special_mapping_vmops;
	vma->vm_private_data = pages;
	if (unlikely(insert_vm_struct(mm, vma))) {
		kmem_cache_free(vm_area_cachep, vma);
		return -ENOMEM;
	}
	mm->total_vm += len >> PAGE_SHIFT;
	perf_event_mmap(vma);
	return 0;
}