1 /* 2 * Check decoding of move_pages syscall. 3 * 4 * Copyright (c) 2016 Dmitry V. Levin <ldv (at) 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 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 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 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 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 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 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