aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-12-11 21:05:37 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2012-12-11 21:05:37 -0500
commit608ff1a210ab0e8b969399039bf8e18693605910 (patch)
treefaea7bb1764461c73d0953089bd5439d91733a03 /tools
parent414a6750e59b0b687034764c464e9ddecac0f7a6 (diff)
parent74d42d8fe146e870c52bde3b1c692f86cc8ff844 (diff)
Merge branch 'akpm' (Andrew's patchbomb)
Merge misc updates from Andrew Morton: "About half of most of MM. Going very early this time due to uncertainty over the coreautounifiednumasched things. I'll send the other half of most of MM tomorrow. The rest of MM awaits a slab merge from Pekka." * emailed patches from Andrew Morton: (71 commits) memory_hotplug: ensure every online node has NORMAL memory memory_hotplug: handle empty zone when online_movable/online_kernel mm, memory-hotplug: dynamic configure movable memory and portion memory drivers/base/node.c: cleanup node_state_attr[] bootmem: fix wrong call parameter for free_bootmem() avr32, kconfig: remove HAVE_ARCH_BOOTMEM mm: cma: remove watermark hacks mm: cma: skip watermarks check for already isolated blocks in split_free_page() mm, oom: fix race when specifying a thread as the oom origin mm, oom: change type of oom_score_adj to short mm: cleanup register_node() mm, mempolicy: remove duplicate code mm/vmscan.c: try_to_freeze() returns boolean mm: introduce putback_movable_pages() virtio_balloon: introduce migration primitives to balloon pages mm: introduce compaction and migration for ballooned pages mm: introduce a common interface for balloon pages mobility mm: redefine address_space.assoc_mapping mm: adjust address_space_operations.migratepage() return code arch/sparc/kernel/sys_sparc_64.c: s/COLOUR/COLOR/ ...
Diffstat (limited to 'tools')
-rw-r--r--tools/testing/selftests/vm/Makefile4
-rw-r--r--tools/testing/selftests/vm/thuge-gen.c254
2 files changed, 256 insertions, 2 deletions
diff --git a/tools/testing/selftests/vm/Makefile b/tools/testing/selftests/vm/Makefile
index b336b24aa6c0..7300d0702efe 100644
--- a/tools/testing/selftests/vm/Makefile
+++ b/tools/testing/selftests/vm/Makefile
@@ -1,9 +1,9 @@
1# Makefile for vm selftests 1# Makefile for vm selftests
2 2
3CC = $(CROSS_COMPILE)gcc 3CC = $(CROSS_COMPILE)gcc
4CFLAGS = -Wall -Wextra 4CFLAGS = -Wall
5 5
6all: hugepage-mmap hugepage-shm map_hugetlb 6all: hugepage-mmap hugepage-shm map_hugetlb thuge-gen
7%: %.c 7%: %.c
8 $(CC) $(CFLAGS) -o $@ $^ 8 $(CC) $(CFLAGS) -o $@ $^
9 9
diff --git a/tools/testing/selftests/vm/thuge-gen.c b/tools/testing/selftests/vm/thuge-gen.c
new file mode 100644
index 000000000000..c87957295f74
--- /dev/null
+++ b/tools/testing/selftests/vm/thuge-gen.c
@@ -0,0 +1,254 @@
1/* Test selecting other page sizes for mmap/shmget.
2
3 Before running this huge pages for each huge page size must have been
4 reserved.
5 For large pages beyond MAX_ORDER (like 1GB on x86) boot options must be used.
6 Also shmmax must be increased.
7 And you need to run as root to work around some weird permissions in shm.
8 And nothing using huge pages should run in parallel.
9 When the program aborts you may need to clean up the shm segments with
10 ipcrm -m by hand, like this
11 sudo ipcs | awk '$1 == "0x00000000" {print $2}' | xargs -n1 sudo ipcrm -m
12 (warning this will remove all if someone else uses them) */
13
14#define _GNU_SOURCE 1
15#include <sys/mman.h>
16#include <stdlib.h>
17#include <stdio.h>
18#include <sys/ipc.h>
19#include <sys/shm.h>
20#include <sys/stat.h>
21#include <glob.h>
22#include <assert.h>
23#include <unistd.h>
24#include <stdarg.h>
25#include <string.h>
26
27#define err(x) perror(x), exit(1)
28
29#define MAP_HUGE_2MB (21 << MAP_HUGE_SHIFT)
30#define MAP_HUGE_1GB (30 << MAP_HUGE_SHIFT)
31#define MAP_HUGE_SHIFT 26
32#define MAP_HUGE_MASK 0x3f
33#define MAP_HUGETLB 0x40000
34
35#define SHM_HUGETLB 04000 /* segment will use huge TLB pages */
36#define SHM_HUGE_SHIFT 26
37#define SHM_HUGE_MASK 0x3f
38#define SHM_HUGE_2MB (21 << SHM_HUGE_SHIFT)
39#define SHM_HUGE_1GB (30 << SHM_HUGE_SHIFT)
40
41#define NUM_PAGESIZES 5
42
43#define NUM_PAGES 4
44
45#define Dprintf(fmt...) // printf(fmt)
46
47unsigned long page_sizes[NUM_PAGESIZES];
48int num_page_sizes;
49
50int ilog2(unsigned long v)
51{
52 int l = 0;
53 while ((1UL << l) < v)
54 l++;
55 return l;
56}
57
58void find_pagesizes(void)
59{
60 glob_t g;
61 int i;
62 glob("/sys/kernel/mm/hugepages/hugepages-*kB", 0, NULL, &g);
63 assert(g.gl_pathc <= NUM_PAGESIZES);
64 for (i = 0; i < g.gl_pathc; i++) {
65 sscanf(g.gl_pathv[i], "/sys/kernel/mm/hugepages/hugepages-%lukB",
66 &page_sizes[i]);
67 page_sizes[i] <<= 10;
68 printf("Found %luMB\n", page_sizes[i] >> 20);
69 }
70 num_page_sizes = g.gl_pathc;
71 globfree(&g);
72}
73
74unsigned long default_huge_page_size(void)
75{
76 unsigned long hps = 0;
77 char *line = NULL;
78 size_t linelen = 0;
79 FILE *f = fopen("/proc/meminfo", "r");
80 if (!f)
81 return 0;
82 while (getline(&line, &linelen, f) > 0) {
83 if (sscanf(line, "Hugepagesize: %lu kB", &hps) == 1) {
84 hps <<= 10;
85 break;
86 }
87 }
88 free(line);
89 return hps;
90}
91
92void show(unsigned long ps)
93{
94 char buf[100];
95 if (ps == getpagesize())
96 return;
97 printf("%luMB: ", ps >> 20);
98 fflush(stdout);
99 snprintf(buf, sizeof buf,
100 "cat /sys/kernel/mm/hugepages/hugepages-%lukB/free_hugepages",
101 ps >> 10);
102 system(buf);
103}
104
105unsigned long read_sysfs(int warn, char *fmt, ...)
106{
107 char *line = NULL;
108 size_t linelen = 0;
109 char buf[100];
110 FILE *f;
111 va_list ap;
112 unsigned long val = 0;
113
114 va_start(ap, fmt);
115 vsnprintf(buf, sizeof buf, fmt, ap);
116 va_end(ap);
117
118 f = fopen(buf, "r");
119 if (!f) {
120 if (warn)
121 printf("missing %s\n", buf);
122 return 0;
123 }
124 if (getline(&line, &linelen, f) > 0) {
125 sscanf(line, "%lu", &val);
126 }
127 fclose(f);
128 free(line);
129 return val;
130}
131
132unsigned long read_free(unsigned long ps)
133{
134 return read_sysfs(ps != getpagesize(),
135 "/sys/kernel/mm/hugepages/hugepages-%lukB/free_hugepages",
136 ps >> 10);
137}
138
139void test_mmap(unsigned long size, unsigned flags)
140{
141 char *map;
142 unsigned long before, after;
143 int err;
144
145 before = read_free(size);
146 map = mmap(NULL, size*NUM_PAGES, PROT_READ|PROT_WRITE,
147 MAP_PRIVATE|MAP_ANONYMOUS|MAP_HUGETLB|flags, 0, 0);
148
149 if (map == (char *)-1) err("mmap");
150 memset(map, 0xff, size*NUM_PAGES);
151 after = read_free(size);
152 Dprintf("before %lu after %lu diff %ld size %lu\n",
153 before, after, before - after, size);
154 assert(size == getpagesize() || (before - after) == NUM_PAGES);
155 show(size);
156 err = munmap(map, size);
157 assert(!err);
158}
159
160void test_shmget(unsigned long size, unsigned flags)
161{
162 int id;
163 unsigned long before, after;
164 int err;
165
166 before = read_free(size);
167 id = shmget(IPC_PRIVATE, size * NUM_PAGES, IPC_CREAT|0600|flags);
168 if (id < 0) err("shmget");
169
170 struct shm_info i;
171 if (shmctl(id, SHM_INFO, (void *)&i) < 0) err("shmctl");
172 Dprintf("alloc %lu res %lu\n", i.shm_tot, i.shm_rss);
173
174
175 Dprintf("id %d\n", id);
176 char *map = shmat(id, NULL, 0600);
177 if (map == (char*)-1) err("shmat");
178
179 shmctl(id, IPC_RMID, NULL);
180
181 memset(map, 0xff, size*NUM_PAGES);
182 after = read_free(size);
183
184 Dprintf("before %lu after %lu diff %ld size %lu\n",
185 before, after, before - after, size);
186 assert(size == getpagesize() || (before - after) == NUM_PAGES);
187 show(size);
188 err = shmdt(map);
189 assert(!err);
190}
191
192void sanity_checks(void)
193{
194 int i;
195 unsigned long largest = getpagesize();
196
197 for (i = 0; i < num_page_sizes; i++) {
198 if (page_sizes[i] > largest)
199 largest = page_sizes[i];
200
201 if (read_free(page_sizes[i]) < NUM_PAGES) {
202 printf("Not enough huge pages for page size %lu MB, need %u\n",
203 page_sizes[i] >> 20,
204 NUM_PAGES);
205 exit(0);
206 }
207 }
208
209 if (read_sysfs(0, "/proc/sys/kernel/shmmax") < NUM_PAGES * largest) {
210 printf("Please do echo %lu > /proc/sys/kernel/shmmax", largest * NUM_PAGES);
211 exit(0);
212 }
213
214#if defined(__x86_64__)
215 if (largest != 1U<<30) {
216 printf("No GB pages available on x86-64\n"
217 "Please boot with hugepagesz=1G hugepages=%d\n", NUM_PAGES);
218 exit(0);
219 }
220#endif
221}
222
223int main(void)
224{
225 int i;
226 unsigned default_hps = default_huge_page_size();
227
228 find_pagesizes();
229
230 sanity_checks();
231
232 for (i = 0; i < num_page_sizes; i++) {
233 unsigned long ps = page_sizes[i];
234 int arg = ilog2(ps) << MAP_HUGE_SHIFT;
235 printf("Testing %luMB mmap with shift %x\n", ps >> 20, arg);
236 test_mmap(ps, MAP_HUGETLB | arg);
237 }
238 printf("Testing default huge mmap\n");
239 test_mmap(default_hps, SHM_HUGETLB);
240
241 puts("Testing non-huge shmget");
242 test_shmget(getpagesize(), 0);
243
244 for (i = 0; i < num_page_sizes; i++) {
245 unsigned long ps = page_sizes[i];
246 int arg = ilog2(ps) << SHM_HUGE_SHIFT;
247 printf("Testing %luMB shmget with shift %x\n", ps >> 20, arg);
248 test_shmget(ps, SHM_HUGETLB | arg);
249 }
250 puts("default huge shmget");
251 test_shmget(default_hps, SHM_HUGETLB);
252
253 return 0;
254}