diff options
Diffstat (limited to 'mm')
-rw-r--r-- | mm/allocpercpu.c | 2 | ||||
-rw-r--r-- | mm/memory.c | 6 | ||||
-rw-r--r-- | mm/percpu.c | 130 | ||||
-rw-r--r-- | mm/vmscan.c | 2 |
4 files changed, 121 insertions, 19 deletions
diff --git a/mm/allocpercpu.c b/mm/allocpercpu.c index 3653c570232b..1882923bc706 100644 --- a/mm/allocpercpu.c +++ b/mm/allocpercpu.c | |||
@@ -120,7 +120,7 @@ void *__alloc_percpu(size_t size, size_t align) | |||
120 | * on it. Larger alignment should only be used for module | 120 | * on it. Larger alignment should only be used for module |
121 | * percpu sections on SMP for which this path isn't used. | 121 | * percpu sections on SMP for which this path isn't used. |
122 | */ | 122 | */ |
123 | WARN_ON_ONCE(align > __alignof__(unsigned long long)); | 123 | WARN_ON_ONCE(align > SMP_CACHE_BYTES); |
124 | 124 | ||
125 | if (unlikely(!pdata)) | 125 | if (unlikely(!pdata)) |
126 | return NULL; | 126 | return NULL; |
diff --git a/mm/memory.c b/mm/memory.c index baa999e87cd2..2032ad2fc34b 100644 --- a/mm/memory.c +++ b/mm/memory.c | |||
@@ -1665,9 +1665,10 @@ int remap_pfn_range(struct vm_area_struct *vma, unsigned long addr, | |||
1665 | * behaviour that some programs depend on. We mark the "original" | 1665 | * behaviour that some programs depend on. We mark the "original" |
1666 | * un-COW'ed pages by matching them up with "vma->vm_pgoff". | 1666 | * un-COW'ed pages by matching them up with "vma->vm_pgoff". |
1667 | */ | 1667 | */ |
1668 | if (addr == vma->vm_start && end == vma->vm_end) | 1668 | if (addr == vma->vm_start && end == vma->vm_end) { |
1669 | vma->vm_pgoff = pfn; | 1669 | vma->vm_pgoff = pfn; |
1670 | else if (is_cow_mapping(vma->vm_flags)) | 1670 | vma->vm_flags |= VM_PFN_AT_MMAP; |
1671 | } else if (is_cow_mapping(vma->vm_flags)) | ||
1671 | return -EINVAL; | 1672 | return -EINVAL; |
1672 | 1673 | ||
1673 | vma->vm_flags |= VM_IO | VM_RESERVED | VM_PFNMAP; | 1674 | vma->vm_flags |= VM_IO | VM_RESERVED | VM_PFNMAP; |
@@ -1679,6 +1680,7 @@ int remap_pfn_range(struct vm_area_struct *vma, unsigned long addr, | |||
1679 | * needed from higher level routine calling unmap_vmas | 1680 | * needed from higher level routine calling unmap_vmas |
1680 | */ | 1681 | */ |
1681 | vma->vm_flags &= ~(VM_IO | VM_RESERVED | VM_PFNMAP); | 1682 | vma->vm_flags &= ~(VM_IO | VM_RESERVED | VM_PFNMAP); |
1683 | vma->vm_flags &= ~VM_PFN_AT_MMAP; | ||
1682 | return -EINVAL; | 1684 | return -EINVAL; |
1683 | } | 1685 | } |
1684 | 1686 | ||
diff --git a/mm/percpu.c b/mm/percpu.c index bfe6a3afaf45..1aa5d8fbca12 100644 --- a/mm/percpu.c +++ b/mm/percpu.c | |||
@@ -46,7 +46,8 @@ | |||
46 | * - define CONFIG_HAVE_DYNAMIC_PER_CPU_AREA | 46 | * - define CONFIG_HAVE_DYNAMIC_PER_CPU_AREA |
47 | * | 47 | * |
48 | * - define __addr_to_pcpu_ptr() and __pcpu_ptr_to_addr() to translate | 48 | * - define __addr_to_pcpu_ptr() and __pcpu_ptr_to_addr() to translate |
49 | * regular address to percpu pointer and back | 49 | * regular address to percpu pointer and back if they need to be |
50 | * different from the default | ||
50 | * | 51 | * |
51 | * - use pcpu_setup_first_chunk() during percpu area initialization to | 52 | * - use pcpu_setup_first_chunk() during percpu area initialization to |
52 | * setup the first chunk containing the kernel static percpu area | 53 | * setup the first chunk containing the kernel static percpu area |
@@ -67,11 +68,24 @@ | |||
67 | #include <linux/workqueue.h> | 68 | #include <linux/workqueue.h> |
68 | 69 | ||
69 | #include <asm/cacheflush.h> | 70 | #include <asm/cacheflush.h> |
71 | #include <asm/sections.h> | ||
70 | #include <asm/tlbflush.h> | 72 | #include <asm/tlbflush.h> |
71 | 73 | ||
72 | #define PCPU_SLOT_BASE_SHIFT 5 /* 1-31 shares the same slot */ | 74 | #define PCPU_SLOT_BASE_SHIFT 5 /* 1-31 shares the same slot */ |
73 | #define PCPU_DFL_MAP_ALLOC 16 /* start a map with 16 ents */ | 75 | #define PCPU_DFL_MAP_ALLOC 16 /* start a map with 16 ents */ |
74 | 76 | ||
77 | /* default addr <-> pcpu_ptr mapping, override in asm/percpu.h if necessary */ | ||
78 | #ifndef __addr_to_pcpu_ptr | ||
79 | #define __addr_to_pcpu_ptr(addr) \ | ||
80 | (void *)((unsigned long)(addr) - (unsigned long)pcpu_base_addr \ | ||
81 | + (unsigned long)__per_cpu_start) | ||
82 | #endif | ||
83 | #ifndef __pcpu_ptr_to_addr | ||
84 | #define __pcpu_ptr_to_addr(ptr) \ | ||
85 | (void *)((unsigned long)(ptr) + (unsigned long)pcpu_base_addr \ | ||
86 | - (unsigned long)__per_cpu_start) | ||
87 | #endif | ||
88 | |||
75 | struct pcpu_chunk { | 89 | struct pcpu_chunk { |
76 | struct list_head list; /* linked to pcpu_slot lists */ | 90 | struct list_head list; /* linked to pcpu_slot lists */ |
77 | struct rb_node rb_node; /* key is chunk->vm->addr */ | 91 | struct rb_node rb_node; /* key is chunk->vm->addr */ |
@@ -1013,8 +1027,8 @@ EXPORT_SYMBOL_GPL(free_percpu); | |||
1013 | * @get_page_fn: callback to fetch page pointer | 1027 | * @get_page_fn: callback to fetch page pointer |
1014 | * @static_size: the size of static percpu area in bytes | 1028 | * @static_size: the size of static percpu area in bytes |
1015 | * @reserved_size: the size of reserved percpu area in bytes | 1029 | * @reserved_size: the size of reserved percpu area in bytes |
1016 | * @unit_size: unit size in bytes, must be multiple of PAGE_SIZE, -1 for auto | ||
1017 | * @dyn_size: free size for dynamic allocation in bytes, -1 for auto | 1030 | * @dyn_size: free size for dynamic allocation in bytes, -1 for auto |
1031 | * @unit_size: unit size in bytes, must be multiple of PAGE_SIZE, -1 for auto | ||
1018 | * @base_addr: mapped address, NULL for auto | 1032 | * @base_addr: mapped address, NULL for auto |
1019 | * @populate_pte_fn: callback to allocate pagetable, NULL if unnecessary | 1033 | * @populate_pte_fn: callback to allocate pagetable, NULL if unnecessary |
1020 | * | 1034 | * |
@@ -1039,14 +1053,14 @@ EXPORT_SYMBOL_GPL(free_percpu); | |||
1039 | * limited offset range for symbol relocations to guarantee module | 1053 | * limited offset range for symbol relocations to guarantee module |
1040 | * percpu symbols fall inside the relocatable range. | 1054 | * percpu symbols fall inside the relocatable range. |
1041 | * | 1055 | * |
1056 | * @dyn_size, if non-negative, determines the number of bytes | ||
1057 | * available for dynamic allocation in the first chunk. Specifying | ||
1058 | * non-negative value makes percpu leave alone the area beyond | ||
1059 | * @static_size + @reserved_size + @dyn_size. | ||
1060 | * | ||
1042 | * @unit_size, if non-negative, specifies unit size and must be | 1061 | * @unit_size, if non-negative, specifies unit size and must be |
1043 | * aligned to PAGE_SIZE and equal to or larger than @static_size + | 1062 | * aligned to PAGE_SIZE and equal to or larger than @static_size + |
1044 | * @reserved_size + @dyn_size. | 1063 | * @reserved_size + if non-negative, @dyn_size. |
1045 | * | ||
1046 | * @dyn_size, if non-negative, limits the number of bytes available | ||
1047 | * for dynamic allocation in the first chunk. Specifying non-negative | ||
1048 | * value make percpu leave alone the area beyond @static_size + | ||
1049 | * @reserved_size + @dyn_size. | ||
1050 | * | 1064 | * |
1051 | * Non-null @base_addr means that the caller already allocated virtual | 1065 | * Non-null @base_addr means that the caller already allocated virtual |
1052 | * region for the first chunk and mapped it. percpu must not mess | 1066 | * region for the first chunk and mapped it. percpu must not mess |
@@ -1069,12 +1083,14 @@ EXPORT_SYMBOL_GPL(free_percpu); | |||
1069 | */ | 1083 | */ |
1070 | size_t __init pcpu_setup_first_chunk(pcpu_get_page_fn_t get_page_fn, | 1084 | size_t __init pcpu_setup_first_chunk(pcpu_get_page_fn_t get_page_fn, |
1071 | size_t static_size, size_t reserved_size, | 1085 | size_t static_size, size_t reserved_size, |
1072 | ssize_t unit_size, ssize_t dyn_size, | 1086 | ssize_t dyn_size, ssize_t unit_size, |
1073 | void *base_addr, | 1087 | void *base_addr, |
1074 | pcpu_populate_pte_fn_t populate_pte_fn) | 1088 | pcpu_populate_pte_fn_t populate_pte_fn) |
1075 | { | 1089 | { |
1076 | static struct vm_struct first_vm; | 1090 | static struct vm_struct first_vm; |
1077 | static int smap[2], dmap[2]; | 1091 | static int smap[2], dmap[2]; |
1092 | size_t size_sum = static_size + reserved_size + | ||
1093 | (dyn_size >= 0 ? dyn_size : 0); | ||
1078 | struct pcpu_chunk *schunk, *dchunk = NULL; | 1094 | struct pcpu_chunk *schunk, *dchunk = NULL; |
1079 | unsigned int cpu; | 1095 | unsigned int cpu; |
1080 | int nr_pages; | 1096 | int nr_pages; |
@@ -1085,20 +1101,18 @@ size_t __init pcpu_setup_first_chunk(pcpu_get_page_fn_t get_page_fn, | |||
1085 | ARRAY_SIZE(dmap) >= PCPU_DFL_MAP_ALLOC); | 1101 | ARRAY_SIZE(dmap) >= PCPU_DFL_MAP_ALLOC); |
1086 | BUG_ON(!static_size); | 1102 | BUG_ON(!static_size); |
1087 | if (unit_size >= 0) { | 1103 | if (unit_size >= 0) { |
1088 | BUG_ON(unit_size < static_size + reserved_size + | 1104 | BUG_ON(unit_size < size_sum); |
1089 | (dyn_size >= 0 ? dyn_size : 0)); | ||
1090 | BUG_ON(unit_size & ~PAGE_MASK); | 1105 | BUG_ON(unit_size & ~PAGE_MASK); |
1091 | } else { | 1106 | BUG_ON(unit_size < PCPU_MIN_UNIT_SIZE); |
1092 | BUG_ON(dyn_size >= 0); | 1107 | } else |
1093 | BUG_ON(base_addr); | 1108 | BUG_ON(base_addr); |
1094 | } | ||
1095 | BUG_ON(base_addr && populate_pte_fn); | 1109 | BUG_ON(base_addr && populate_pte_fn); |
1096 | 1110 | ||
1097 | if (unit_size >= 0) | 1111 | if (unit_size >= 0) |
1098 | pcpu_unit_pages = unit_size >> PAGE_SHIFT; | 1112 | pcpu_unit_pages = unit_size >> PAGE_SHIFT; |
1099 | else | 1113 | else |
1100 | pcpu_unit_pages = max_t(int, PCPU_MIN_UNIT_SIZE >> PAGE_SHIFT, | 1114 | pcpu_unit_pages = max_t(int, PCPU_MIN_UNIT_SIZE >> PAGE_SHIFT, |
1101 | PFN_UP(static_size + reserved_size)); | 1115 | PFN_UP(size_sum)); |
1102 | 1116 | ||
1103 | pcpu_unit_size = pcpu_unit_pages << PAGE_SHIFT; | 1117 | pcpu_unit_size = pcpu_unit_pages << PAGE_SHIFT; |
1104 | pcpu_chunk_size = num_possible_cpus() * pcpu_unit_size; | 1118 | pcpu_chunk_size = num_possible_cpus() * pcpu_unit_size; |
@@ -1224,3 +1238,89 @@ size_t __init pcpu_setup_first_chunk(pcpu_get_page_fn_t get_page_fn, | |||
1224 | pcpu_base_addr = (void *)pcpu_chunk_addr(schunk, 0, 0); | 1238 | pcpu_base_addr = (void *)pcpu_chunk_addr(schunk, 0, 0); |
1225 | return pcpu_unit_size; | 1239 | return pcpu_unit_size; |
1226 | } | 1240 | } |
1241 | |||
1242 | /* | ||
1243 | * Embedding first chunk setup helper. | ||
1244 | */ | ||
1245 | static void *pcpue_ptr __initdata; | ||
1246 | static size_t pcpue_size __initdata; | ||
1247 | static size_t pcpue_unit_size __initdata; | ||
1248 | |||
1249 | static struct page * __init pcpue_get_page(unsigned int cpu, int pageno) | ||
1250 | { | ||
1251 | size_t off = (size_t)pageno << PAGE_SHIFT; | ||
1252 | |||
1253 | if (off >= pcpue_size) | ||
1254 | return NULL; | ||
1255 | |||
1256 | return virt_to_page(pcpue_ptr + cpu * pcpue_unit_size + off); | ||
1257 | } | ||
1258 | |||
1259 | /** | ||
1260 | * pcpu_embed_first_chunk - embed the first percpu chunk into bootmem | ||
1261 | * @static_size: the size of static percpu area in bytes | ||
1262 | * @reserved_size: the size of reserved percpu area in bytes | ||
1263 | * @dyn_size: free size for dynamic allocation in bytes, -1 for auto | ||
1264 | * @unit_size: unit size in bytes, must be multiple of PAGE_SIZE, -1 for auto | ||
1265 | * | ||
1266 | * This is a helper to ease setting up embedded first percpu chunk and | ||
1267 | * can be called where pcpu_setup_first_chunk() is expected. | ||
1268 | * | ||
1269 | * If this function is used to setup the first chunk, it is allocated | ||
1270 | * as a contiguous area using bootmem allocator and used as-is without | ||
1271 | * being mapped into vmalloc area. This enables the first chunk to | ||
1272 | * piggy back on the linear physical mapping which often uses larger | ||
1273 | * page size. | ||
1274 | * | ||
1275 | * When @dyn_size is positive, dynamic area might be larger than | ||
1276 | * specified to fill page alignment. Also, when @dyn_size is auto, | ||
1277 | * @dyn_size does not fill the whole first chunk but only what's | ||
1278 | * necessary for page alignment after static and reserved areas. | ||
1279 | * | ||
1280 | * If the needed size is smaller than the minimum or specified unit | ||
1281 | * size, the leftover is returned to the bootmem allocator. | ||
1282 | * | ||
1283 | * RETURNS: | ||
1284 | * The determined pcpu_unit_size which can be used to initialize | ||
1285 | * percpu access on success, -errno on failure. | ||
1286 | */ | ||
1287 | ssize_t __init pcpu_embed_first_chunk(size_t static_size, size_t reserved_size, | ||
1288 | ssize_t dyn_size, ssize_t unit_size) | ||
1289 | { | ||
1290 | unsigned int cpu; | ||
1291 | |||
1292 | /* determine parameters and allocate */ | ||
1293 | pcpue_size = PFN_ALIGN(static_size + reserved_size + | ||
1294 | (dyn_size >= 0 ? dyn_size : 0)); | ||
1295 | if (dyn_size != 0) | ||
1296 | dyn_size = pcpue_size - static_size - reserved_size; | ||
1297 | |||
1298 | if (unit_size >= 0) { | ||
1299 | BUG_ON(unit_size < pcpue_size); | ||
1300 | pcpue_unit_size = unit_size; | ||
1301 | } else | ||
1302 | pcpue_unit_size = max_t(size_t, pcpue_size, PCPU_MIN_UNIT_SIZE); | ||
1303 | |||
1304 | pcpue_ptr = __alloc_bootmem_nopanic( | ||
1305 | num_possible_cpus() * pcpue_unit_size, | ||
1306 | PAGE_SIZE, __pa(MAX_DMA_ADDRESS)); | ||
1307 | if (!pcpue_ptr) | ||
1308 | return -ENOMEM; | ||
1309 | |||
1310 | /* return the leftover and copy */ | ||
1311 | for_each_possible_cpu(cpu) { | ||
1312 | void *ptr = pcpue_ptr + cpu * pcpue_unit_size; | ||
1313 | |||
1314 | free_bootmem(__pa(ptr + pcpue_size), | ||
1315 | pcpue_unit_size - pcpue_size); | ||
1316 | memcpy(ptr, __per_cpu_load, static_size); | ||
1317 | } | ||
1318 | |||
1319 | /* we're ready, commit */ | ||
1320 | pr_info("PERCPU: Embedded %zu pages at %p, static data %zu bytes\n", | ||
1321 | pcpue_size >> PAGE_SHIFT, pcpue_ptr, static_size); | ||
1322 | |||
1323 | return pcpu_setup_first_chunk(pcpue_get_page, static_size, | ||
1324 | reserved_size, dyn_size, | ||
1325 | pcpue_unit_size, pcpue_ptr, NULL); | ||
1326 | } | ||
diff --git a/mm/vmscan.c b/mm/vmscan.c index 6177e3bcd66b..e89517141657 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c | |||
@@ -1469,7 +1469,7 @@ static void shrink_zone(int priority, struct zone *zone, | |||
1469 | int file = is_file_lru(l); | 1469 | int file = is_file_lru(l); |
1470 | int scan; | 1470 | int scan; |
1471 | 1471 | ||
1472 | scan = zone_page_state(zone, NR_LRU_BASE + l); | 1472 | scan = zone_nr_pages(zone, sc, l); |
1473 | if (priority) { | 1473 | if (priority) { |
1474 | scan >>= priority; | 1474 | scan >>= priority; |
1475 | scan = (scan * percent[file]) / 100; | 1475 | scan = (scan * percent[file]) / 100; |