diff options
Diffstat (limited to 'mm')
-rw-r--r-- | mm/vmalloc.c | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 8e05a11155c9..3130c343088f 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c | |||
@@ -767,3 +767,56 @@ EXPORT_SYMBOL(remap_vmalloc_range); | |||
767 | void __attribute__((weak)) vmalloc_sync_all(void) | 767 | void __attribute__((weak)) vmalloc_sync_all(void) |
768 | { | 768 | { |
769 | } | 769 | } |
770 | |||
771 | |||
772 | static int f(pte_t *pte, struct page *pmd_page, unsigned long addr, void *data) | ||
773 | { | ||
774 | /* apply_to_page_range() does all the hard work. */ | ||
775 | return 0; | ||
776 | } | ||
777 | |||
778 | /** | ||
779 | * alloc_vm_area - allocate a range of kernel address space | ||
780 | * @size: size of the area | ||
781 | * @returns: NULL on failure, vm_struct on success | ||
782 | * | ||
783 | * This function reserves a range of kernel address space, and | ||
784 | * allocates pagetables to map that range. No actual mappings | ||
785 | * are created. If the kernel address space is not shared | ||
786 | * between processes, it syncs the pagetable across all | ||
787 | * processes. | ||
788 | */ | ||
789 | struct vm_struct *alloc_vm_area(size_t size) | ||
790 | { | ||
791 | struct vm_struct *area; | ||
792 | |||
793 | area = get_vm_area(size, VM_IOREMAP); | ||
794 | if (area == NULL) | ||
795 | return NULL; | ||
796 | |||
797 | /* | ||
798 | * This ensures that page tables are constructed for this region | ||
799 | * of kernel virtual address space and mapped into init_mm. | ||
800 | */ | ||
801 | if (apply_to_page_range(&init_mm, (unsigned long)area->addr, | ||
802 | area->size, f, NULL)) { | ||
803 | free_vm_area(area); | ||
804 | return NULL; | ||
805 | } | ||
806 | |||
807 | /* Make sure the pagetables are constructed in process kernel | ||
808 | mappings */ | ||
809 | vmalloc_sync_all(); | ||
810 | |||
811 | return area; | ||
812 | } | ||
813 | EXPORT_SYMBOL_GPL(alloc_vm_area); | ||
814 | |||
815 | void free_vm_area(struct vm_struct *area) | ||
816 | { | ||
817 | struct vm_struct *ret; | ||
818 | ret = remove_vm_area(area->addr); | ||
819 | BUG_ON(ret != area); | ||
820 | kfree(area); | ||
821 | } | ||
822 | EXPORT_SYMBOL_GPL(free_vm_area); | ||