• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Check decoding of move_pages syscall.
3  *
4  * Copyright (c) 2016 Dmitry V. Levin <ldv@altlinux.org>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. The name of the author may not be used to endorse or promote products
16  *    derived from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #include "tests.h"
31 #include <asm/unistd.h>
32 
33 #ifdef __NR_move_pages
34 
35 # include <errno.h>
36 # include <stdio.h>
37 # include <unistd.h>
38 
39 # define MAX_STRLEN 3
40 
41 static void
print_page_array(const void ** const pages,const unsigned long count,const unsigned int offset)42 print_page_array(const void **const pages,
43 		 const unsigned long count,
44 		 const unsigned int offset)
45 {
46 	if (!count) {
47 		printf("%s", pages ? "[]" : "NULL");
48 		return;
49 	}
50 	if (count <= offset) {
51 		printf("%p", pages);
52 		return;
53 	}
54 	printf("[");
55 	unsigned long i;
56 	for (i = 0; i < count; ++i) {
57 		if (i)
58 			printf(", ");
59 		if (i + offset < count) {
60 			if (i >= MAX_STRLEN) {
61 				printf("...");
62 				break;
63 			}
64 		} else {
65 			printf("%p", pages + i);
66 			break;
67 		}
68 		const void *const addr = pages[i];
69 		if (addr)
70 			printf("%p", addr);
71 		else
72 			printf("NULL");
73 	}
74 	printf("]");
75 }
76 
77 static void
print_node_array(const int * const nodes,const unsigned long count,const unsigned int offset)78 print_node_array(const int *const nodes,
79 		 const unsigned long count,
80 		 const unsigned int offset)
81 {
82 	if (!count) {
83 		printf("%s", nodes ? "[]" : "NULL");
84 		return;
85 	}
86 	if (count <= offset) {
87 		printf("%p", nodes);
88 		return;
89 	}
90 	printf("[");
91 	unsigned long i;
92 	for (i = 0; i < count; ++i) {
93 		if (i)
94 			printf(", ");
95 		if (i + offset < count) {
96 			if (i >= MAX_STRLEN) {
97 				printf("...");
98 				break;
99 			}
100 		} else {
101 			printf("%p", nodes + i);
102 			break;
103 		}
104 		printf("%d", nodes[i]);
105 	}
106 	printf("]");
107 }
108 
109 static void
print_status_array(const int * const status,const unsigned long count)110 print_status_array(const int *const status, const unsigned long count)
111 {
112 	if (!count) {
113 		printf("%s", status ? "[]" : "NULL");
114 		return;
115 	}
116 	printf("[");
117 	unsigned long i;
118 	for (i = 0; i < count; ++i) {
119 		if (i)
120 			printf(", ");
121 		if (i >= MAX_STRLEN) {
122 			printf("...");
123 			break;
124 		}
125 		if (status[i] >= 0) {
126 			printf("%d", status[i]);
127 		} else {
128 			errno = -status[i];
129 			printf("%s", errno2name());
130 		}
131 	}
132 	printf("]");
133 }
134 
135 static void
print_stat_pages(const unsigned long pid,const unsigned long count,const void ** const pages,int * const status)136 print_stat_pages(const unsigned long pid, const unsigned long count,
137 		 const void **const pages, int *const status)
138 {
139 	const unsigned long flags = (unsigned long) 0xfacefeed00000002ULL;
140 
141 	long rc = syscall(__NR_move_pages,
142 			  pid, count, pages, NULL, status, flags);
143 	const char *errstr = sprintrc(rc);
144 	printf("move_pages(%d, %lu, ", (int) pid, count);
145 	print_page_array(pages, count, 0);
146 	printf(", NULL, ");
147 	if (rc) {
148 		if (count)
149 			printf("%p", status);
150 		else
151 			printf("[]");
152 	} else {
153 		print_status_array(status, count);
154 	}
155 	printf(", MPOL_MF_MOVE) = %s\n", errstr);
156 }
157 
158 static void
print_move_pages(const unsigned long pid,unsigned long count,const unsigned int offset,const void ** const pages,int * const nodes,int * const status)159 print_move_pages(const unsigned long pid,
160 		 unsigned long count,
161 		 const unsigned int offset,
162 		 const void **const pages,
163 		 int *const nodes,
164 		 int *const status)
165 {
166 	const unsigned long flags = (unsigned long) 0xfacefeed00000004ULL;
167 	count += offset;
168 
169 	long rc = syscall(__NR_move_pages,
170 			  pid, count, pages, nodes, status, flags);
171 	const char *errstr = sprintrc(rc);
172 	printf("move_pages(%d, %lu, ", (int) pid, count);
173 	print_page_array(pages, count, offset);
174 	printf(", ");
175 	print_node_array(nodes, count, offset);
176 	printf(", ");
177 	if (count)
178 		printf("%p", status);
179 	else
180 		printf("[]");
181 	printf(", MPOL_MF_MOVE_ALL) = %s\n", errstr);
182 }
183 
184 int
main(void)185 main(void)
186 {
187 	const unsigned long pid =
188 		(unsigned long) 0xfacefeed00000000ULL | getpid();
189 	unsigned long count = 1;
190 	const unsigned page_size = get_page_size();
191 	const void *const page = tail_alloc(page_size);
192 	const void *const efault = page + page_size;
193 	const void **pages = tail_alloc(sizeof(*pages));
194 	int *nodes = tail_alloc(sizeof(*nodes));
195 	int *status = tail_alloc(sizeof(*status));
196 
197 	print_stat_pages(pid, 0, pages, status);
198 	print_move_pages(pid, 0, 0, pages, nodes, status);
199 	print_move_pages(pid, 0, 1, pages + 1, nodes + 1, status + 1);
200 
201 	*pages = page;
202 	print_stat_pages(pid, count, pages, status);
203 	*nodes = 0xdeadbee1;
204 	print_move_pages(pid, count, 0, pages, nodes, status);
205 	print_move_pages(pid, count, 1, pages, nodes, status);
206 
207 	++count;
208 	--status;
209 	*(--pages) = efault;
210 	print_stat_pages(pid, count, pages, status);
211 	*(--nodes) = 0xdeadbee2;
212 	print_move_pages(pid, count, 0, pages, nodes, status);
213 	print_move_pages(pid, count, 1, pages, nodes, status);
214 
215 	++count;
216 	--status;
217 	*(--pages) = nodes;
218 	print_stat_pages(pid, count, pages, status);
219 	*(--nodes) = 0xdeadbee3;
220 	print_move_pages(pid, count, 0, pages, nodes, status);
221 	print_move_pages(pid, count, 1, pages, nodes, status);
222 
223 	++count;
224 	--status;
225 	*(--pages) = status;
226 	print_stat_pages(pid, count, pages, status);
227 	*(--nodes) = 0xdeadbee4;
228 	print_move_pages(pid, count, 0, pages, nodes, status);
229 	print_move_pages(pid, count, 1, pages, nodes, status);
230 
231 	puts("+++ exited with 0 +++");
232 	return 0;
233 }
234 
235 #else
236 
237 SKIP_MAIN_UNDEFINED("__NR_move_pages")
238 
239 #endif
240