(root)/
strace-6.5/
tests-mx32/
move_pages.c
       1  /*
       2   * Check decoding of move_pages syscall.
       3   *
       4   * Copyright (c) 2016 Dmitry V. Levin <ldv@strace.io>
       5   * Copyright (c) 2016-2021 The strace developers.
       6   * All rights reserved.
       7   *
       8   * SPDX-License-Identifier: GPL-2.0-or-later
       9   */
      10  
      11  #include "tests.h"
      12  #include "scno.h"
      13  #include "pidns.h"
      14  
      15  #include <errno.h>
      16  #include <stdio.h>
      17  #include <unistd.h>
      18  
      19  #define MAX_STRLEN 3
      20  
      21  static void
      22  print_page_array(const void **const pages,
      23  		 const unsigned long count,
      24  		 const unsigned int offset)
      25  {
      26  	if (!count) {
      27  		printf("%s", pages ? "[]" : "NULL");
      28  		return;
      29  	}
      30  	if (count <= offset) {
      31  		printf("%p", pages);
      32  		return;
      33  	}
      34  	printf("[");
      35  	for (unsigned long i = 0; i < count; ++i) {
      36  		if (i)
      37  			printf(", ");
      38  		if (i + offset < count) {
      39  			if (i >= MAX_STRLEN) {
      40  				printf("...");
      41  				break;
      42  			}
      43  		} else {
      44  			printf("... /* %p */", pages + i);
      45  			break;
      46  		}
      47  		const void *const addr = pages[i];
      48  		if (addr)
      49  			printf("%p", addr);
      50  		else
      51  			printf("NULL");
      52  	}
      53  	printf("]");
      54  }
      55  
      56  static void
      57  print_node_array(const int *const nodes,
      58  		 const unsigned long count,
      59  		 const unsigned int offset)
      60  {
      61  	if (!count) {
      62  		printf("%s", nodes ? "[]" : "NULL");
      63  		return;
      64  	}
      65  	if (count <= offset) {
      66  		printf("%p", nodes);
      67  		return;
      68  	}
      69  	printf("[");
      70  	for (unsigned long i = 0; i < count; ++i) {
      71  		if (i)
      72  			printf(", ");
      73  		if (i + offset < count) {
      74  			if (i >= MAX_STRLEN) {
      75  				printf("...");
      76  				break;
      77  			}
      78  		} else {
      79  			printf("... /* %p */", nodes + i);
      80  			break;
      81  		}
      82  		printf("%d", nodes[i]);
      83  	}
      84  	printf("]");
      85  }
      86  
      87  static void
      88  print_status_array(const int *const status, const unsigned long count)
      89  {
      90  	if (!count) {
      91  		printf("%s", status ? "[]" : "NULL");
      92  		return;
      93  	}
      94  	printf("[");
      95  	for (unsigned long i = 0; i < count; ++i) {
      96  		if (i)
      97  			printf(", ");
      98  		if (i >= MAX_STRLEN) {
      99  			printf("...");
     100  			break;
     101  		}
     102  		if (status[i] >= 0) {
     103  			printf("%d", status[i]);
     104  		} else {
     105  #if !XLAT_RAW
     106  			errno = -status[i];
     107  #endif
     108  #if XLAT_RAW
     109  			printf("%d", status[i]);
     110  #elif XLAT_VERBOSE
     111  			printf("%d /* -%s */", status[i], errno2name());
     112  #else
     113  			printf("-%s", errno2name());
     114  #endif
     115  		}
     116  	}
     117  	printf("]");
     118  }
     119  
     120  static void
     121  print_stat_pages(const unsigned long pid,
     122  		 const char *pid_str,
     123  		 const unsigned long count,
     124  		 const void **const pages,
     125  		 int *const status)
     126  {
     127  	const unsigned long flags = (unsigned long) 0xfacefeed00000002ULL;
     128  
     129  	long rc = syscall(__NR_move_pages,
     130  			  pid, count, pages, NULL, status, flags);
     131  	const char *errstr = sprintrc(rc);
     132  	pidns_print_leader();
     133  	printf("move_pages(%d%s, %lu, ", (int) pid, pid_str,
     134  		count);
     135  	print_page_array(pages, count, 0);
     136  	printf(", NULL, ");
     137  	if (rc) {
     138  		if (count)
     139  			printf("%p", status);
     140  		else
     141  			printf("[]");
     142  	} else {
     143  		print_status_array(status, count);
     144  	}
     145  #if XLAT_RAW
     146  	printf(", 0x2) = %s\n", errstr);
     147  #elif XLAT_VERBOSE
     148  	printf(", 0x2 /* MPOL_MF_MOVE */) = %s\n", errstr);
     149  #else /* XLAT_ABBREV */
     150  	printf(", MPOL_MF_MOVE) = %s\n", errstr);
     151  #endif
     152  }
     153  
     154  static void
     155  print_move_pages(const unsigned long pid,
     156  		 const char *pid_str,
     157  		 unsigned long count,
     158  		 const unsigned int offset,
     159  		 const void **const pages,
     160  		 int *const nodes,
     161  		 int *const status)
     162  {
     163  	const unsigned long flags = (unsigned long) 0xfacefeed00000004ULL;
     164  	count += offset;
     165  
     166  	long rc = syscall(__NR_move_pages,
     167  			  pid, count, pages, nodes, status, flags);
     168  	const char *errstr = sprintrc(rc);
     169  	pidns_print_leader();
     170  	printf("move_pages(%d%s, %lu, ", (int) pid, pid_str,
     171  		count);
     172  	print_page_array(pages, count, offset);
     173  	printf(", ");
     174  	print_node_array(nodes, count, offset);
     175  	printf(", ");
     176  	if (count)
     177  		printf("%p", status);
     178  	else
     179  		printf("[]");
     180  #if XLAT_RAW
     181  	printf(", 0x4) = %s\n", errstr);
     182  #elif XLAT_VERBOSE
     183  	printf(", 0x4 /* MPOL_MF_MOVE_ALL */) = %s\n", errstr);
     184  #else /* XLAT_ABBREV */
     185  	printf(", MPOL_MF_MOVE_ALL) = %s\n", errstr);
     186  #endif
     187  }
     188  
     189  int
     190  main(void)
     191  {
     192  	PIDNS_TEST_INIT;
     193  
     194  	const unsigned long pid =
     195  		(unsigned long) 0xfacefeed00000000ULL | getpid();
     196  	const char *pid_str = pidns_pid2str(PT_TGID);
     197  	unsigned long count = 1;
     198  	const unsigned page_size = get_page_size();
     199  	const void *const page = tail_alloc(page_size);
     200  	const void *const efault = page + page_size;
     201  	TAIL_ALLOC_OBJECT_VAR_PTR(const void *, pages);
     202  	TAIL_ALLOC_OBJECT_VAR_PTR(int, nodes);
     203  	TAIL_ALLOC_OBJECT_VAR_PTR(int, status);
     204  
     205  	print_stat_pages(pid, pid_str, 0, pages, status);
     206  	print_move_pages(pid, pid_str, 0, 0, pages, nodes, status);
     207  	print_move_pages(pid, pid_str, 0, 1, pages + 1, nodes + 1, status + 1);
     208  
     209  	*pages = page;
     210  	print_stat_pages(pid, pid_str, count, pages, status);
     211  	*nodes = 0xdeadbee1;
     212  	print_move_pages(pid, pid_str, count, 0, pages, nodes, status);
     213  	print_move_pages(pid, pid_str, count, 1, pages, nodes, status);
     214  
     215  	++count;
     216  	--status;
     217  	*(--pages) = efault;
     218  	print_stat_pages(pid, pid_str, count, pages, status);
     219  	*(--nodes) = 0xdeadbee2;
     220  	print_move_pages(pid, pid_str, count, 0, pages, nodes, status);
     221  	print_move_pages(pid, pid_str, count, 1, pages, nodes, status);
     222  
     223  	++count;
     224  	--status;
     225  	*(--pages) = nodes;
     226  	print_stat_pages(pid, pid_str, count, pages, status);
     227  	*(--nodes) = 0xdeadbee3;
     228  	print_move_pages(pid, pid_str, count, 0, pages, nodes, status);
     229  	print_move_pages(pid, pid_str, count, 1, pages, nodes, status);
     230  
     231  	++count;
     232  	--status;
     233  	*(--pages) = status;
     234  	print_stat_pages(pid, pid_str, count, pages, status);
     235  	*(--nodes) = 0xdeadbee4;
     236  	print_move_pages(pid, pid_str, count, 0, pages, nodes, status);
     237  	print_move_pages(pid, pid_str, count, 1, pages, nodes, status);
     238  
     239  	pidns_print_leader();
     240  	puts("+++ exited with 0 +++");
     241  	return 0;
     242  }