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