diff options
Diffstat (limited to 'mm/vmalloc.c')
-rw-r--r-- | mm/vmalloc.c | 97 |
1 files changed, 94 insertions, 3 deletions
diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 520a75980269..af58324c361a 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/radix-tree.h> | 24 | #include <linux/radix-tree.h> |
25 | #include <linux/rcupdate.h> | 25 | #include <linux/rcupdate.h> |
26 | #include <linux/bootmem.h> | 26 | #include <linux/bootmem.h> |
27 | #include <linux/pfn.h> | ||
27 | 28 | ||
28 | #include <asm/atomic.h> | 29 | #include <asm/atomic.h> |
29 | #include <asm/uaccess.h> | 30 | #include <asm/uaccess.h> |
@@ -152,8 +153,8 @@ static int vmap_pud_range(pgd_t *pgd, unsigned long addr, | |||
152 | * | 153 | * |
153 | * Ie. pte at addr+N*PAGE_SIZE shall point to pfn corresponding to pages[N] | 154 | * Ie. pte at addr+N*PAGE_SIZE shall point to pfn corresponding to pages[N] |
154 | */ | 155 | */ |
155 | static int vmap_page_range(unsigned long start, unsigned long end, | 156 | static int vmap_page_range_noflush(unsigned long start, unsigned long end, |
156 | pgprot_t prot, struct page **pages) | 157 | pgprot_t prot, struct page **pages) |
157 | { | 158 | { |
158 | pgd_t *pgd; | 159 | pgd_t *pgd; |
159 | unsigned long next; | 160 | unsigned long next; |
@@ -169,13 +170,22 @@ static int vmap_page_range(unsigned long start, unsigned long end, | |||
169 | if (err) | 170 | if (err) |
170 | break; | 171 | break; |
171 | } while (pgd++, addr = next, addr != end); | 172 | } while (pgd++, addr = next, addr != end); |
172 | flush_cache_vmap(start, end); | ||
173 | 173 | ||
174 | if (unlikely(err)) | 174 | if (unlikely(err)) |
175 | return err; | 175 | return err; |
176 | return nr; | 176 | return nr; |
177 | } | 177 | } |
178 | 178 | ||
179 | static int vmap_page_range(unsigned long start, unsigned long end, | ||
180 | pgprot_t prot, struct page **pages) | ||
181 | { | ||
182 | int ret; | ||
183 | |||
184 | ret = vmap_page_range_noflush(start, end, prot, pages); | ||
185 | flush_cache_vmap(start, end); | ||
186 | return ret; | ||
187 | } | ||
188 | |||
179 | static inline int is_vmalloc_or_module_addr(const void *x) | 189 | static inline int is_vmalloc_or_module_addr(const void *x) |
180 | { | 190 | { |
181 | /* | 191 | /* |
@@ -990,6 +1000,32 @@ void *vm_map_ram(struct page **pages, unsigned int count, int node, pgprot_t pro | |||
990 | } | 1000 | } |
991 | EXPORT_SYMBOL(vm_map_ram); | 1001 | EXPORT_SYMBOL(vm_map_ram); |
992 | 1002 | ||
1003 | /** | ||
1004 | * vm_area_register_early - register vmap area early during boot | ||
1005 | * @vm: vm_struct to register | ||
1006 | * @align: requested alignment | ||
1007 | * | ||
1008 | * This function is used to register kernel vm area before | ||
1009 | * vmalloc_init() is called. @vm->size and @vm->flags should contain | ||
1010 | * proper values on entry and other fields should be zero. On return, | ||
1011 | * vm->addr contains the allocated address. | ||
1012 | * | ||
1013 | * DO NOT USE THIS FUNCTION UNLESS YOU KNOW WHAT YOU'RE DOING. | ||
1014 | */ | ||
1015 | void __init vm_area_register_early(struct vm_struct *vm, size_t align) | ||
1016 | { | ||
1017 | static size_t vm_init_off __initdata; | ||
1018 | unsigned long addr; | ||
1019 | |||
1020 | addr = ALIGN(VMALLOC_START + vm_init_off, align); | ||
1021 | vm_init_off = PFN_ALIGN(addr + vm->size) - VMALLOC_START; | ||
1022 | |||
1023 | vm->addr = (void *)addr; | ||
1024 | |||
1025 | vm->next = vmlist; | ||
1026 | vmlist = vm; | ||
1027 | } | ||
1028 | |||
993 | void __init vmalloc_init(void) | 1029 | void __init vmalloc_init(void) |
994 | { | 1030 | { |
995 | struct vmap_area *va; | 1031 | struct vmap_area *va; |
@@ -1017,6 +1053,58 @@ void __init vmalloc_init(void) | |||
1017 | vmap_initialized = true; | 1053 | vmap_initialized = true; |
1018 | } | 1054 | } |
1019 | 1055 | ||
1056 | /** | ||
1057 | * map_kernel_range_noflush - map kernel VM area with the specified pages | ||
1058 | * @addr: start of the VM area to map | ||
1059 | * @size: size of the VM area to map | ||
1060 | * @prot: page protection flags to use | ||
1061 | * @pages: pages to map | ||
1062 | * | ||
1063 | * Map PFN_UP(@size) pages at @addr. The VM area @addr and @size | ||
1064 | * specify should have been allocated using get_vm_area() and its | ||
1065 | * friends. | ||
1066 | * | ||
1067 | * NOTE: | ||
1068 | * This function does NOT do any cache flushing. The caller is | ||
1069 | * responsible for calling flush_cache_vmap() on to-be-mapped areas | ||
1070 | * before calling this function. | ||
1071 | * | ||
1072 | * RETURNS: | ||
1073 | * The number of pages mapped on success, -errno on failure. | ||
1074 | */ | ||
1075 | int map_kernel_range_noflush(unsigned long addr, unsigned long size, | ||
1076 | pgprot_t prot, struct page **pages) | ||
1077 | { | ||
1078 | return vmap_page_range_noflush(addr, addr + size, prot, pages); | ||
1079 | } | ||
1080 | |||
1081 | /** | ||
1082 | * unmap_kernel_range_noflush - unmap kernel VM area | ||
1083 | * @addr: start of the VM area to unmap | ||
1084 | * @size: size of the VM area to unmap | ||
1085 | * | ||
1086 | * Unmap PFN_UP(@size) pages at @addr. The VM area @addr and @size | ||
1087 | * specify should have been allocated using get_vm_area() and its | ||
1088 | * friends. | ||
1089 | * | ||
1090 | * NOTE: | ||
1091 | * This function does NOT do any cache flushing. The caller is | ||
1092 | * responsible for calling flush_cache_vunmap() on to-be-mapped areas | ||
1093 | * before calling this function and flush_tlb_kernel_range() after. | ||
1094 | */ | ||
1095 | void unmap_kernel_range_noflush(unsigned long addr, unsigned long size) | ||
1096 | { | ||
1097 | vunmap_page_range(addr, addr + size); | ||
1098 | } | ||
1099 | |||
1100 | /** | ||
1101 | * unmap_kernel_range - unmap kernel VM area and flush cache and TLB | ||
1102 | * @addr: start of the VM area to unmap | ||
1103 | * @size: size of the VM area to unmap | ||
1104 | * | ||
1105 | * Similar to unmap_kernel_range_noflush() but flushes vcache before | ||
1106 | * the unmapping and tlb after. | ||
1107 | */ | ||
1020 | void unmap_kernel_range(unsigned long addr, unsigned long size) | 1108 | void unmap_kernel_range(unsigned long addr, unsigned long size) |
1021 | { | 1109 | { |
1022 | unsigned long end = addr + size; | 1110 | unsigned long end = addr + size; |
@@ -1267,6 +1355,7 @@ EXPORT_SYMBOL(vfree); | |||
1267 | void vunmap(const void *addr) | 1355 | void vunmap(const void *addr) |
1268 | { | 1356 | { |
1269 | BUG_ON(in_interrupt()); | 1357 | BUG_ON(in_interrupt()); |
1358 | might_sleep(); | ||
1270 | __vunmap(addr, 0); | 1359 | __vunmap(addr, 0); |
1271 | } | 1360 | } |
1272 | EXPORT_SYMBOL(vunmap); | 1361 | EXPORT_SYMBOL(vunmap); |
@@ -1286,6 +1375,8 @@ void *vmap(struct page **pages, unsigned int count, | |||
1286 | { | 1375 | { |
1287 | struct vm_struct *area; | 1376 | struct vm_struct *area; |
1288 | 1377 | ||
1378 | might_sleep(); | ||
1379 | |||
1289 | if (count > num_physpages) | 1380 | if (count > num_physpages) |
1290 | return NULL; | 1381 | return NULL; |
1291 | 1382 | ||