1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <sys/mman.h>
4 #include <unistd.h>
5 #include <fcntl.h>
6 
7 /* This file includes a simple set of memory allocation calls that
8  * a user space program can use to allocate/free or move memory mappings.
9  * The intent of this program is to make it easier to verify if the kernel
10  * internal mappings are correct.
11  */
12 
13 #define PAGE_SHIFT 12
14 
15 #define ROUND_PAGES(memsize) ((memsize >> (PAGE_SHIFT)) << PAGE_SHIFT)
16 
17 /* approximately half of memsize, page aligned */
18 #define HALF_MEM(memsize) ((memsize >> (PAGE_SHIFT))<<(PAGE_SHIFT - 1))
19 
waitnext()20 inline void waitnext() {
21 	fflush(NULL);
22 	getchar();
23 }
24 
main(int argc,char * argv[])25 int main(int argc, char *argv[]) {
26 	unsigned int memsize;
27 	char *mem;
28 	int i, numpages, fd;
29 
30 	if (argc != 2) {
31 		printf("Usage: %s <memory_size>\n", argv[0]);
32 		exit(EXIT_FAILURE);
33 	}
34 
35 	memsize = strtoul(argv[1], NULL, 10);
36 
37 	memsize = ROUND_PAGES(memsize);
38 
39 	/* We should be limited to < 4G so any size other than 0 is ok */
40 	if (memsize == 0) {
41 		printf("Invalid memsize\n");
42 		exit(EXIT_FAILURE);
43 	}
44 
45 
46 	numpages = memsize >> PAGE_SHIFT;
47 
48 	mlockall(MCL_FUTURE);
49 
50 	mem = sbrk(memsize);
51 
52 	if (mem == (void*) -1) {
53 		perror("Failed to allocate memory using sbrk\n");
54 		exit(EXIT_FAILURE);
55 	}
56 
57 	printf("Successfully allocated sbrk memory %d bytes @%p\n",
58 				memsize,  mem);
59 
60 	waitnext();
61 
62 	sbrk(-(memsize));
63 
64 	mem =  mmap(0, memsize, PROT_READ | PROT_WRITE,
65 			MAP_PRIVATE| MAP_ANONYMOUS,
66 			-1, 0);
67 
68 	if (mem == (void*) -1) {
69 		perror("Failed to allocate anon private memory using mmap\n");
70 		exit(EXIT_FAILURE);
71 	}
72 
73 	printf("Successfully allocated anon mmap memory %d bytes @%p\n",
74 				memsize,  mem);
75 
76 	waitnext();
77 
78 	if (-1 == mprotect(mem, HALF_MEM(memsize), PROT_READ)) {
79 		perror("Failed to W protect memory using mprotect\n");
80 		exit(EXIT_FAILURE);
81 	}
82 
83 	printf("Successfully write protected %d bytes @%p\n",
84 			HALF_MEM(memsize), mem);
85 
86 	waitnext();
87 
88 	if (-1 == mprotect(mem, HALF_MEM(memsize),
89 					 PROT_READ | PROT_WRITE)) {
90 		perror("Failed to RW protect memory using mprotect\n");
91 		exit(EXIT_FAILURE);
92 	}
93 
94 	printf("Successfully cleared write protected %d bytes @%p\n",
95 			memsize, mem);
96 	waitnext();
97 
98 	/* Mark all pages with a specific pattern */
99 	for (i = 0; i < numpages; i++) {
100 		int *ptr = (int *)(mem + i*4096);
101 		*ptr = i;
102 	}
103 
104 	mem = mremap(mem , memsize,
105 				memsize + HALF_MEM(memsize),
106 				1 /* MREMAP_MAYMOVE */);
107 
108 	if (mem == MAP_FAILED) {
109 		perror("Failed to remap expand anon private memory\n");
110 		exit(EXIT_FAILURE);
111 	}
112 
113 	printf("Successfully remapped %d bytes @%p\n",
114 			memsize + HALF_MEM(memsize), mem);
115 
116 	waitnext();
117 
118 	/* Mark all pages with a specific pattern */
119 	for (i = 0; i < numpages; i++) {
120 		int value = *(int*)(mem + i*4096);
121 		if (value != i) {
122 			printf("remap error expected %d got %d\n",
123 					i, value);
124 			exit(EXIT_FAILURE);
125 		}
126 	}
127 
128 	if (munmap(mem, memsize + HALF_MEM(memsize))) {
129 		perror("Could not unmap and free memory\n");
130 		exit(EXIT_FAILURE);
131 	}
132 
133 
134 	fd = open("/dev/zero", O_RDONLY);
135 
136 	mem =  mmap(0, memsize, PROT_READ | PROT_WRITE,
137 			MAP_PRIVATE,
138 			fd, 0);
139 
140 	if (mem == (void*) -1) {
141 		perror("Failed to allocate file backed memory using mmap\n");
142 		exit(EXIT_FAILURE);
143 	}
144 
145 	printf("Successfully allocated file backed mmap memory %d bytes @%p\n",
146 					 memsize, mem);
147 	waitnext();
148 
149 	if (munmap(mem, memsize)) {
150 		perror("Could not unmap and free file backed memory\n");
151 		exit(EXIT_FAILURE);
152 	}
153 
154 	exit(EXIT_SUCCESS);
155 }
156