197 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2#include <errno.h>3#include <fcntl.h>4#include <stdlib.h>5#include <sys/ioctl.h>6#include <unistd.h>7#include <asm/papr-sysparm.h>8 9#include "utils.h"10 11#define DEVPATH "/dev/papr-sysparm"12 13static int open_close(void)14{15 const int devfd = open(DEVPATH, O_RDONLY);16 17 SKIP_IF_MSG(devfd < 0 && errno == ENOENT,18 DEVPATH " not present");19 20 FAIL_IF(devfd < 0);21 FAIL_IF(close(devfd) != 0);22 23 return 0;24}25 26static int get_splpar(void)27{28 struct papr_sysparm_io_block sp = {29 .parameter = 20, // SPLPAR characteristics30 };31 const int devfd = open(DEVPATH, O_RDONLY);32 33 SKIP_IF_MSG(devfd < 0 && errno == ENOENT,34 DEVPATH " not present");35 36 FAIL_IF(devfd < 0);37 FAIL_IF(ioctl(devfd, PAPR_SYSPARM_IOC_GET, &sp) != 0);38 FAIL_IF(sp.length == 0);39 FAIL_IF(sp.length > sizeof(sp.data));40 FAIL_IF(close(devfd) != 0);41 42 return 0;43}44 45static int get_bad_parameter(void)46{47 struct papr_sysparm_io_block sp = {48 .parameter = UINT32_MAX, // there are only ~60 specified parameters49 };50 const int devfd = open(DEVPATH, O_RDONLY);51 52 SKIP_IF_MSG(devfd < 0 && errno == ENOENT,53 DEVPATH " not present");54 55 FAIL_IF(devfd < 0);56 57 // Ensure expected error58 FAIL_IF(ioctl(devfd, PAPR_SYSPARM_IOC_GET, &sp) != -1);59 FAIL_IF(errno != EOPNOTSUPP);60 61 // Ensure the buffer is unchanged62 FAIL_IF(sp.length != 0);63 for (size_t i = 0; i < ARRAY_SIZE(sp.data); ++i)64 FAIL_IF(sp.data[i] != 0);65 66 FAIL_IF(close(devfd) != 0);67 68 return 0;69}70 71static int check_efault_common(unsigned long cmd)72{73 const int devfd = open(DEVPATH, O_RDWR);74 75 SKIP_IF_MSG(devfd < 0 && errno == ENOENT,76 DEVPATH " not present");77 78 FAIL_IF(devfd < 0);79 80 // Ensure expected error81 FAIL_IF(ioctl(devfd, cmd, NULL) != -1);82 FAIL_IF(errno != EFAULT);83 84 FAIL_IF(close(devfd) != 0);85 86 return 0;87}88 89static int check_efault_get(void)90{91 return check_efault_common(PAPR_SYSPARM_IOC_GET);92}93 94static int check_efault_set(void)95{96 return check_efault_common(PAPR_SYSPARM_IOC_SET);97}98 99static int set_hmc0(void)100{101 struct papr_sysparm_io_block sp = {102 .parameter = 0, // HMC0, not a settable parameter103 };104 const int devfd = open(DEVPATH, O_RDWR);105 106 SKIP_IF_MSG(devfd < 0 && errno == ENOENT,107 DEVPATH " not present");108 109 FAIL_IF(devfd < 0);110 111 // Ensure expected error112 FAIL_IF(ioctl(devfd, PAPR_SYSPARM_IOC_SET, &sp) != -1);113 SKIP_IF_MSG(errno == EOPNOTSUPP, "operation not supported");114 FAIL_IF(errno != EPERM);115 116 FAIL_IF(close(devfd) != 0);117 118 return 0;119}120 121static int set_with_ro_fd(void)122{123 struct papr_sysparm_io_block sp = {124 .parameter = 0, // HMC0, not a settable parameter.125 };126 const int devfd = open(DEVPATH, O_RDONLY);127 128 SKIP_IF_MSG(devfd < 0 && errno == ENOENT,129 DEVPATH " not present");130 131 FAIL_IF(devfd < 0);132 133 // Ensure expected error134 FAIL_IF(ioctl(devfd, PAPR_SYSPARM_IOC_SET, &sp) != -1);135 SKIP_IF_MSG(errno == EOPNOTSUPP, "operation not supported");136 137 // HMC0 isn't a settable parameter and we would normally138 // expect to get EPERM on attempts to modify it. However, when139 // the file is open read-only, we expect the driver to prevent140 // the attempt with a distinct error.141 FAIL_IF(errno != EBADF);142 143 FAIL_IF(close(devfd) != 0);144 145 return 0;146}147 148struct sysparm_test {149 int (*function)(void);150 const char *description;151};152 153static const struct sysparm_test sysparm_tests[] = {154 {155 .function = open_close,156 .description = "open and close " DEVPATH " without issuing commands",157 },158 {159 .function = get_splpar,160 .description = "retrieve SPLPAR characteristics",161 },162 {163 .function = get_bad_parameter,164 .description = "verify EOPNOTSUPP for known-bad parameter",165 },166 {167 .function = check_efault_get,168 .description = "PAPR_SYSPARM_IOC_GET returns EFAULT on bad address",169 },170 {171 .function = check_efault_set,172 .description = "PAPR_SYSPARM_IOC_SET returns EFAULT on bad address",173 },174 {175 .function = set_hmc0,176 .description = "ensure EPERM on attempt to update HMC0",177 },178 {179 .function = set_with_ro_fd,180 .description = "PAPR_IOC_SYSPARM_SET returns EACCES on read-only fd",181 },182};183 184int main(void)185{186 size_t fails = 0;187 188 for (size_t i = 0; i < ARRAY_SIZE(sysparm_tests); ++i) {189 const struct sysparm_test *t = &sysparm_tests[i];190 191 if (test_harness(t->function, t->description))192 ++fails;193 }194 195 return fails == 0 ? EXIT_SUCCESS : EXIT_FAILURE;196}197