Skip to content

Commit

Permalink
powerpc/selftests: Add test for papr-sysparm
Browse files Browse the repository at this point in the history
Consistently testing system parameter access is a bit difficult by
nature -- the set of parameters available depends on the model and
system configuration, and updating a parameter should be considered a
destructive operation reserved for the admin.

So we validate some of the error paths and retrieve the SPLPAR
characteristics string, but not much else.

Signed-off-by: Nathan Lynch <[email protected]>
Signed-off-by: Michael Ellerman <[email protected]>
Link: https://msgid.link/20231207-papr-sys_rtas-vs-lockdown-v5-13-2ce965636a58@linux.ibm.com
  • Loading branch information
nathanlynch authored and mpe committed Dec 11, 2023
1 parent 26a1e27 commit 69d32fd
Show file tree
Hide file tree
Showing 4 changed files with 179 additions and 0 deletions.
1 change: 1 addition & 0 deletions tools/testing/selftests/powerpc/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ SUB_DIRS = alignment \
math \
papr_attributes \
papr_vpd \
papr_sysparm \
ptrace \
security \
mce
Expand Down
1 change: 1 addition & 0 deletions tools/testing/selftests/powerpc/papr_sysparm/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/papr_sysparm
12 changes: 12 additions & 0 deletions tools/testing/selftests/powerpc/papr_sysparm/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# SPDX-License-Identifier: GPL-2.0
noarg:
$(MAKE) -C ../

TEST_GEN_PROGS := papr_sysparm

top_srcdir = ../../../../..
include ../../lib.mk

$(TEST_GEN_PROGS): ../harness.c ../utils.c

$(OUTPUT)/papr_sysparm: CFLAGS += $(KHDR_INCLUDES)
165 changes: 165 additions & 0 deletions tools/testing/selftests/powerpc/papr_sysparm/papr_sysparm.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
// SPDX-License-Identifier: GPL-2.0-only
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <asm/papr-sysparm.h>

#include "utils.h"

#define DEVPATH "/dev/papr-sysparm"

static int open_close(void)
{
const int devfd = open(DEVPATH, O_RDONLY);

SKIP_IF_MSG(devfd < 0 && errno == ENOENT,
DEVPATH " not present");

FAIL_IF(devfd < 0);
FAIL_IF(close(devfd) != 0);

return 0;
}

static int get_splpar(void)
{
struct papr_sysparm_io_block sp = {
.parameter = 20, // SPLPAR characteristics
};
const int devfd = open(DEVPATH, O_RDONLY);

SKIP_IF_MSG(devfd < 0 && errno == ENOENT,
DEVPATH " not present");

FAIL_IF(devfd < 0);
FAIL_IF(ioctl(devfd, PAPR_SYSPARM_IOC_GET, &sp) != 0);
FAIL_IF(sp.length == 0);
FAIL_IF(sp.length > sizeof(sp.data));
FAIL_IF(close(devfd) != 0);

return 0;
}

static int get_bad_parameter(void)
{
struct papr_sysparm_io_block sp = {
.parameter = UINT32_MAX, // there are only ~60 specified parameters
};
const int devfd = open(DEVPATH, O_RDONLY);

SKIP_IF_MSG(devfd < 0 && errno == ENOENT,
DEVPATH " not present");

FAIL_IF(devfd < 0);

// Ensure expected error
FAIL_IF(ioctl(devfd, PAPR_SYSPARM_IOC_GET, &sp) != -1);
FAIL_IF(errno != EOPNOTSUPP);

// Ensure the buffer is unchanged
FAIL_IF(sp.length != 0);
for (size_t i = 0; i < ARRAY_SIZE(sp.data); ++i)
FAIL_IF(sp.data[i] != 0);

FAIL_IF(close(devfd) != 0);

return 0;
}

static int check_efault_common(unsigned long cmd)
{
const int devfd = open(DEVPATH, O_RDONLY);

SKIP_IF_MSG(devfd < 0 && errno == ENOENT,
DEVPATH " not present");

FAIL_IF(devfd < 0);

// Ensure expected error
FAIL_IF(ioctl(devfd, cmd, NULL) != -1);
FAIL_IF(errno != EFAULT);

FAIL_IF(close(devfd) != 0);

return 0;
}

static int check_efault_get(void)
{
return check_efault_common(PAPR_SYSPARM_IOC_GET);
}

static int check_efault_set(void)
{
return check_efault_common(PAPR_SYSPARM_IOC_SET);
}

static int set_hmc0(void)
{
struct papr_sysparm_io_block sp = {
.parameter = 0, // HMC0, not a settable parameter
};
const int devfd = open(DEVPATH, O_RDONLY);

SKIP_IF_MSG(devfd < 0 && errno == ENOENT,
DEVPATH " not present");

FAIL_IF(devfd < 0);

// Ensure expected error
FAIL_IF(ioctl(devfd, PAPR_SYSPARM_IOC_SET, &sp) != -1);
SKIP_IF_MSG(errno == EOPNOTSUPP, "operation not supported");
FAIL_IF(errno != EPERM);

FAIL_IF(close(devfd) != 0);

return 0;
}

struct sysparm_test {
int (*function)(void);
const char *description;
};

static const struct sysparm_test sysparm_tests[] = {
{
.function = open_close,
.description = "open and close " DEVPATH " without issuing commands",
},
{
.function = get_splpar,
.description = "retrieve SPLPAR characteristics",
},
{
.function = get_bad_parameter,
.description = "verify EOPNOTSUPP for known-bad parameter",
},
{
.function = check_efault_get,
.description = "PAPR_SYSPARM_IOC_GET returns EFAULT on bad address",
},
{
.function = check_efault_set,
.description = "PAPR_SYSPARM_IOC_SET returns EFAULT on bad address",
},
{
.function = set_hmc0,
.description = "ensure EPERM on attempt to update HMC0",
},
};

int main(void)
{
size_t fails = 0;

for (size_t i = 0; i < ARRAY_SIZE(sysparm_tests); ++i) {
const struct sysparm_test *t = &sysparm_tests[i];

if (test_harness(t->function, t->description))
++fails;
}

return fails == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}

0 comments on commit 69d32fd

Please sign in to comment.