1 // SPDX-License-Identifier: GPL-2.0-only
7 #include <asm/papr-sysparm.h>
11 #define DEVPATH "/dev/papr-sysparm"
13 static int open_close(void)
15 const int devfd
= open(DEVPATH
, O_RDONLY
);
17 SKIP_IF_MSG(devfd
< 0 && errno
== ENOENT
,
18 DEVPATH
" not present");
21 FAIL_IF(close(devfd
) != 0);
26 static int get_splpar(void)
28 struct papr_sysparm_io_block sp
= {
29 .parameter
= 20, // SPLPAR characteristics
31 const int devfd
= open(DEVPATH
, O_RDONLY
);
33 SKIP_IF_MSG(devfd
< 0 && errno
== ENOENT
,
34 DEVPATH
" not present");
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);
45 static int get_bad_parameter(void)
47 struct papr_sysparm_io_block sp
= {
48 .parameter
= UINT32_MAX
, // there are only ~60 specified parameters
50 const int devfd
= open(DEVPATH
, O_RDONLY
);
52 SKIP_IF_MSG(devfd
< 0 && errno
== ENOENT
,
53 DEVPATH
" not present");
57 // Ensure expected error
58 FAIL_IF(ioctl(devfd
, PAPR_SYSPARM_IOC_GET
, &sp
) != -1);
59 FAIL_IF(errno
!= EOPNOTSUPP
);
61 // Ensure the buffer is unchanged
62 FAIL_IF(sp
.length
!= 0);
63 for (size_t i
= 0; i
< ARRAY_SIZE(sp
.data
); ++i
)
64 FAIL_IF(sp
.data
[i
] != 0);
66 FAIL_IF(close(devfd
) != 0);
71 static int check_efault_common(unsigned long cmd
)
73 const int devfd
= open(DEVPATH
, O_RDWR
);
75 SKIP_IF_MSG(devfd
< 0 && errno
== ENOENT
,
76 DEVPATH
" not present");
80 // Ensure expected error
81 FAIL_IF(ioctl(devfd
, cmd
, NULL
) != -1);
82 FAIL_IF(errno
!= EFAULT
);
84 FAIL_IF(close(devfd
) != 0);
89 static int check_efault_get(void)
91 return check_efault_common(PAPR_SYSPARM_IOC_GET
);
94 static int check_efault_set(void)
96 return check_efault_common(PAPR_SYSPARM_IOC_SET
);
99 static int set_hmc0(void)
101 struct papr_sysparm_io_block sp
= {
102 .parameter
= 0, // HMC0, not a settable parameter
104 const int devfd
= open(DEVPATH
, O_RDWR
);
106 SKIP_IF_MSG(devfd
< 0 && errno
== ENOENT
,
107 DEVPATH
" not present");
111 // Ensure expected error
112 FAIL_IF(ioctl(devfd
, PAPR_SYSPARM_IOC_SET
, &sp
) != -1);
113 SKIP_IF_MSG(errno
== EOPNOTSUPP
, "operation not supported");
114 FAIL_IF(errno
!= EPERM
);
116 FAIL_IF(close(devfd
) != 0);
121 static int set_with_ro_fd(void)
123 struct papr_sysparm_io_block sp
= {
124 .parameter
= 0, // HMC0, not a settable parameter.
126 const int devfd
= open(DEVPATH
, O_RDONLY
);
128 SKIP_IF_MSG(devfd
< 0 && errno
== ENOENT
,
129 DEVPATH
" not present");
133 // Ensure expected error
134 FAIL_IF(ioctl(devfd
, PAPR_SYSPARM_IOC_SET
, &sp
) != -1);
135 SKIP_IF_MSG(errno
== EOPNOTSUPP
, "operation not supported");
137 // HMC0 isn't a settable parameter and we would normally
138 // expect to get EPERM on attempts to modify it. However, when
139 // the file is open read-only, we expect the driver to prevent
140 // the attempt with a distinct error.
141 FAIL_IF(errno
!= EBADF
);
143 FAIL_IF(close(devfd
) != 0);
148 struct sysparm_test
{
149 int (*function
)(void);
150 const char *description
;
153 static const struct sysparm_test sysparm_tests
[] = {
155 .function
= open_close
,
156 .description
= "open and close " DEVPATH
" without issuing commands",
159 .function
= get_splpar
,
160 .description
= "retrieve SPLPAR characteristics",
163 .function
= get_bad_parameter
,
164 .description
= "verify EOPNOTSUPP for known-bad parameter",
167 .function
= check_efault_get
,
168 .description
= "PAPR_SYSPARM_IOC_GET returns EFAULT on bad address",
171 .function
= check_efault_set
,
172 .description
= "PAPR_SYSPARM_IOC_SET returns EFAULT on bad address",
175 .function
= set_hmc0
,
176 .description
= "ensure EPERM on attempt to update HMC0",
179 .function
= set_with_ro_fd
,
180 .description
= "PAPR_IOC_SYSPARM_SET returns EACCES on read-only fd",
188 for (size_t i
= 0; i
< ARRAY_SIZE(sysparm_tests
); ++i
) {
189 const struct sysparm_test
*t
= &sysparm_tests
[i
];
191 if (test_harness(t
->function
, t
->description
))
195 return fails
== 0 ? EXIT_SUCCESS
: EXIT_FAILURE
;