Commit c5c39488 authored by H. Peter Anvin (Intel)'s avatar H. Peter Anvin (Intel) Committed by Thomas Gleixner
Browse files

selftests/x86/syscall: Simplify message reporting in syscall_numbering



Reduce some boiler plate in printing and indenting messages.
This makes it easier to produce clean status output.

Signed-off-by: default avatarH. Peter Anvin (Intel) <hpa@zytor.com>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Link: https://lore.kernel.org/r/20210518191303.4135296-3-hpa@zytor.com
parent 15c82d98
Loading
Loading
Loading
Loading
+72 −31
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@
#include <string.h>
#include <fcntl.h>
#include <limits.h>
#include <sysexits.h>

/* Common system call numbers */
#define SYS_READ	  0
@@ -34,6 +35,33 @@

static unsigned int nerr = 0;	/* Cumulative error count */
static int nullfd = -1;		/* File descriptor for /dev/null */
static int indent = 0;

static inline unsigned int offset(void)
{
	return 8 + indent * 4;
}

#define msg(lvl, fmt, ...) printf("%-*s" fmt, offset(), "[" #lvl "]", \
				  ## __VA_ARGS__)

#define run(fmt, ...)  msg(RUN,  fmt, ## __VA_ARGS__)
#define info(fmt, ...) msg(INFO, fmt, ## __VA_ARGS__)
#define ok(fmt, ...)   msg(OK,   fmt, ## __VA_ARGS__)

#define fail(fmt, ...)					\
	do {						\
		msg(FAIL, fmt, ## __VA_ARGS__);		\
		nerr++;					\
	} while (0)

#define crit(fmt, ...)					\
	do {						\
		indent = 0;				\
		msg(FAIL, fmt, ## __VA_ARGS__);		\
		msg(SKIP, "Unable to run test\n");	\
		exit(EX_OSERR);
	} while (0)

/*
 * Directly invokes the given syscall with nullfd as the first argument
@@ -91,28 +119,37 @@ static unsigned int _check_for(int msb, int start, int end, long long expect,
{
	unsigned int err = 0;

	indent++;
	if (start != end)
		indent++;

	for (int nr = start; nr <= end; nr++) {
		long long ret = probe_syscall(msb, nr);

		if (ret != expect) {
			printf("[FAIL]\t      %s returned %lld, but it should have returned %s\n",
			fail("%s returned %lld, but it should have returned %s\n",
			       syscall_str(msb, nr, nr),
			       ret, expect_str);
			err++;
		}
	}

	if (start != end)
		indent--;

	if (err) {
		nerr += err;
		if (start != end)
			printf("[FAIL]\t      %s had %u failure%s\n",
			fail("%s had %u failure%s\n",
			       syscall_str(msb, start, end),
			       err, (err == 1) ? "s" : "");
			       err, err == 1 ? "s" : "");
	} else {
		printf("[OK]\t      %s returned %s as expected\n",
		ok("%s returned %s as expected\n",
		   syscall_str(msb, start, end), expect_str);
	}

	indent--;

	return err;
}

@@ -137,35 +174,38 @@ static bool check_enosys(int msb, int nr)
static bool test_x32(void)
{
	long long ret;
	long long mypid = getpid();
	pid_t mypid = getpid();
	bool with_x32;

	printf("[RUN]\tChecking for x32 by calling x32 getpid()\n");
	run("Checking for x32 by calling x32 getpid()\n");
	ret = probe_syscall(0, SYS_GETPID | X32_BIT);

	indent++;
	if (ret == mypid) {
		printf("[INFO]\t   x32 is supported\n");
		return true;
		info("x32 is supported\n");
		with_x32 = true;
	} else if (ret == -ENOSYS) {
		printf("[INFO]\t   x32 is not supported\n");
		return false;
		info("x32 is not supported\n");
		with_x32 = false;
	} else {
		printf("[FAIL]\t   x32 getpid() returned %lld, but it should have returned either %lld or -ENOSYS\n", ret, mypid);
		nerr++;
		return true;	/* Proceed as if... */
		fail("x32 getpid() returned %lld, but it should have returned either %lld or -ENOSYS\n", ret, mypid);
		with_x32 = false;
	}
	indent--;
	return with_x32;
}

static void test_syscalls_common(int msb)
{
	printf("[RUN]\t   Checking some common syscalls as 64 bit\n");
	run("Checking some common syscalls as 64 bit\n");
	check_zero(msb, SYS_READ);
	check_zero(msb, SYS_WRITE);

	printf("[RUN]\t   Checking some 64-bit only syscalls as 64 bit\n");
	run("Checking some 64-bit only syscalls as 64 bit\n");
	check_zero(msb, X64_READV);
	check_zero(msb, X64_WRITEV);

	printf("[RUN]\t   Checking out of range system calls\n");
	run("Checking out of range system calls\n");
	check_for(msb, -64, -1, -ENOSYS);
	check_for(msb, X32_BIT-64, X32_BIT-1, -ENOSYS);
	check_for(msb, -64-X32_BIT, -1-X32_BIT, -ENOSYS);
@@ -180,18 +220,18 @@ static void test_syscalls_with_x32(int msb)
	 * set.  Calling them without the x32 bit set is
	 * nonsense and should not work.
	 */
	printf("[RUN]\t   Checking x32 syscalls as 64 bit\n");
	run("Checking x32 syscalls as 64 bit\n");
	check_for(msb, 512, 547, -ENOSYS);

	printf("[RUN]\t   Checking some common syscalls as x32\n");
	run("Checking some common syscalls as x32\n");
	check_zero(msb, SYS_READ   | X32_BIT);
	check_zero(msb, SYS_WRITE  | X32_BIT);

	printf("[RUN]\t   Checking some x32 syscalls as x32\n");
	run("Checking some x32 syscalls as x32\n");
	check_zero(msb, X32_READV  | X32_BIT);
	check_zero(msb, X32_WRITEV | X32_BIT);

	printf("[RUN]\t   Checking some 64-bit syscalls as x32\n");
	run("Checking some 64-bit syscalls as x32\n");
	check_enosys(msb, X64_IOCTL  | X32_BIT);
	check_enosys(msb, X64_READV  | X32_BIT);
	check_enosys(msb, X64_WRITEV | X32_BIT);
@@ -199,7 +239,7 @@ static void test_syscalls_with_x32(int msb)

static void test_syscalls_without_x32(int msb)
{
	printf("[RUN]\t  Checking for absence of x32 system calls\n");
	run("Checking for absence of x32 system calls\n");
	check_for(msb, 0 | X32_BIT, 999 | X32_BIT, -ENOSYS);
}

@@ -217,14 +257,18 @@ static void test_syscall_numbering(void)
	 */
	for (size_t i = 0; i < sizeof(msbs)/sizeof(msbs[0]); i++) {
		int msb = msbs[i];
		printf("[RUN]\tChecking system calls with msb = %d (0x%x)\n",
		run("Checking system calls with msb = %d (0x%x)\n",
		    msb, msb);

		indent++;

		test_syscalls_common(msb);
		if (with_x32)
			test_syscalls_with_x32(msb);
		else
			test_syscalls_without_x32(msb);

		indent--;
	}
}

@@ -241,18 +285,15 @@ int main(void)
	 */
	nullfd = open("/dev/null", O_RDWR);
	if (nullfd < 0) {
		printf("[FAIL]\tUnable to open /dev/null: %s\n",
		       strerror(errno));
		printf("[SKIP]\tCannot execute test\n");
		return 71;	/* EX_OSERR */
		crit("Unable to open /dev/null: %s\n", strerror(errno));
	}

	test_syscall_numbering();
	if (!nerr) {
		printf("[OK]\tAll system calls succeeded or failed as expected\n");
		ok("All system calls succeeded or failed as expected\n");
		return 0;
	} else {
		printf("[FAIL]\tA total of %u system call%s had incorrect behavior\n",
		fail("A total of %u system call%s had incorrect behavior\n",
		     nerr, nerr != 1 ? "s" : "");
		return 1;
	}