Skip to content

Commit 119da30

Browse files
naynajainmpe
authored andcommitted
powerpc/pseries: Expose PLPKS config values, support additional fields
The plpks driver uses the H_PKS_GET_CONFIG hcall to retrieve configuration and status information about the PKS from the hypervisor. Update _plpks_get_config() to handle some additional fields. Add getter functions to allow the PKS configuration information to be accessed from other files. Validate that the values we're getting comply with the spec. While we're here, move the config struct in _plpks_get_config() off the stack - it's getting large and we also need to make sure it doesn't cross a page boundary. Signed-off-by: Nayna Jain <[email protected]> [ajd: split patch, extend to support additional v3 API fields, minor fixes] Co-developed-by: Andrew Donnellan <[email protected]> Signed-off-by: Andrew Donnellan <[email protected]> Signed-off-by: Russell Currey <[email protected]> Reviewed-by: Stefan Berger <[email protected]> Signed-off-by: Michael Ellerman <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 3def7a3 commit 119da30

File tree

2 files changed

+195
-12
lines changed

2 files changed

+195
-12
lines changed

arch/powerpc/include/asm/plpks.h

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,64 @@ int plpks_read_fw_var(struct plpks_var *var);
9696
*/
9797
int plpks_read_bootloader_var(struct plpks_var *var);
9898

99+
/**
100+
* Returns if PKS is available on this LPAR.
101+
*/
102+
bool plpks_is_available(void);
103+
104+
/**
105+
* Returns version of the Platform KeyStore.
106+
*/
107+
u8 plpks_get_version(void);
108+
109+
/**
110+
* Returns hypervisor storage overhead per object, not including the size of
111+
* the object or label. Only valid for config version >= 2
112+
*/
113+
u16 plpks_get_objoverhead(void);
114+
115+
/**
116+
* Returns maximum password size. Must be >= 32 bytes
117+
*/
118+
u16 plpks_get_maxpwsize(void);
119+
120+
/**
121+
* Returns maximum object size supported by Platform KeyStore.
122+
*/
123+
u16 plpks_get_maxobjectsize(void);
124+
125+
/**
126+
* Returns maximum object label size supported by Platform KeyStore.
127+
*/
128+
u16 plpks_get_maxobjectlabelsize(void);
129+
130+
/**
131+
* Returns total size of the configured Platform KeyStore.
132+
*/
133+
u32 plpks_get_totalsize(void);
134+
135+
/**
136+
* Returns used space from the total size of the Platform KeyStore.
137+
*/
138+
u32 plpks_get_usedspace(void);
139+
140+
/**
141+
* Returns bitmask of policies supported by the hypervisor.
142+
*/
143+
u32 plpks_get_supportedpolicies(void);
144+
145+
/**
146+
* Returns maximum byte size of a single object supported by the hypervisor.
147+
* Only valid for config version >= 3
148+
*/
149+
u32 plpks_get_maxlargeobjectsize(void);
150+
151+
/**
152+
* Returns bitmask of signature algorithms supported for signed updates.
153+
* Only valid for config version >= 3
154+
*/
155+
u64 plpks_get_signedupdatealgorithms(void);
156+
99157
#endif // CONFIG_PSERIES_PLPKS
100158

101159
#endif // _ASM_POWERPC_PLPKS_H

arch/powerpc/platforms/pseries/plpks.c

Lines changed: 137 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,16 @@ static u8 *ospassword;
2424
static u16 ospasswordlength;
2525

2626
// Retrieved with H_PKS_GET_CONFIG
27+
static u8 version;
28+
static u16 objoverhead;
2729
static u16 maxpwsize;
2830
static u16 maxobjsize;
31+
static s16 maxobjlabelsize;
32+
static u32 totalsize;
33+
static u32 usedspace;
34+
static u32 supportedpolicies;
35+
static u32 maxlargeobjectsize;
36+
static u64 signedupdatealgorithms;
2937

3038
struct plpks_auth {
3139
u8 version;
@@ -206,32 +214,149 @@ static struct label *construct_label(char *component, u8 varos, u8 *name,
206214
static int _plpks_get_config(void)
207215
{
208216
unsigned long retbuf[PLPAR_HCALL_BUFSIZE] = { 0 };
209-
struct {
217+
struct config {
210218
u8 version;
211219
u8 flags;
212-
__be32 rsvd0;
220+
__be16 rsvd0;
221+
__be16 objoverhead;
213222
__be16 maxpwsize;
214223
__be16 maxobjlabelsize;
215224
__be16 maxobjsize;
216225
__be32 totalsize;
217226
__be32 usedspace;
218227
__be32 supportedpolicies;
219-
__be64 rsvd1;
220-
} __packed config;
228+
__be32 maxlargeobjectsize;
229+
__be64 signedupdatealgorithms;
230+
u8 rsvd1[476];
231+
} __packed * config;
221232
size_t size;
222-
int rc;
233+
int rc = 0;
234+
235+
size = sizeof(*config);
236+
237+
// Config struct must not cross a page boundary. So long as the struct
238+
// size is a power of 2, this should be fine as alignment is guaranteed
239+
config = kzalloc(size, GFP_KERNEL);
240+
if (!config) {
241+
rc = -ENOMEM;
242+
goto err;
243+
}
244+
245+
rc = plpar_hcall(H_PKS_GET_CONFIG, retbuf, virt_to_phys(config), size);
246+
247+
if (rc != H_SUCCESS) {
248+
rc = pseries_status_to_err(rc);
249+
goto err;
250+
}
251+
252+
version = config->version;
253+
objoverhead = be16_to_cpu(config->objoverhead);
254+
maxpwsize = be16_to_cpu(config->maxpwsize);
255+
maxobjsize = be16_to_cpu(config->maxobjsize);
256+
maxobjlabelsize = be16_to_cpu(config->maxobjlabelsize);
257+
totalsize = be32_to_cpu(config->totalsize);
258+
usedspace = be32_to_cpu(config->usedspace);
259+
supportedpolicies = be32_to_cpu(config->supportedpolicies);
260+
maxlargeobjectsize = be32_to_cpu(config->maxlargeobjectsize);
261+
signedupdatealgorithms = be64_to_cpu(config->signedupdatealgorithms);
262+
263+
// Validate that the numbers we get back match the requirements of the spec
264+
if (maxpwsize < 32) {
265+
pr_err("Invalid Max Password Size received from hypervisor (%d < 32)\n", maxpwsize);
266+
rc = -EIO;
267+
goto err;
268+
}
269+
270+
if (maxobjlabelsize < 255) {
271+
pr_err("Invalid Max Object Label Size received from hypervisor (%d < 255)\n",
272+
maxobjlabelsize);
273+
rc = -EIO;
274+
goto err;
275+
}
223276

224-
size = sizeof(config);
277+
if (totalsize < 4096) {
278+
pr_err("Invalid Total Size received from hypervisor (%d < 4096)\n", totalsize);
279+
rc = -EIO;
280+
goto err;
281+
}
282+
283+
if (version >= 3 && maxlargeobjectsize >= 65536 && maxobjsize != 0xFFFF) {
284+
pr_err("Invalid Max Object Size (0x%x != 0xFFFF)\n", maxobjsize);
285+
rc = -EIO;
286+
goto err;
287+
}
288+
289+
err:
290+
kfree(config);
291+
return rc;
292+
}
293+
294+
u8 plpks_get_version(void)
295+
{
296+
return version;
297+
}
225298

226-
rc = plpar_hcall(H_PKS_GET_CONFIG, retbuf, virt_to_phys(&config), size);
299+
u16 plpks_get_objoverhead(void)
300+
{
301+
return objoverhead;
302+
}
227303

228-
if (rc != H_SUCCESS)
229-
return pseries_status_to_err(rc);
304+
u16 plpks_get_maxpwsize(void)
305+
{
306+
return maxpwsize;
307+
}
230308

231-
maxpwsize = be16_to_cpu(config.maxpwsize);
232-
maxobjsize = be16_to_cpu(config.maxobjsize);
309+
u16 plpks_get_maxobjectsize(void)
310+
{
311+
return maxobjsize;
312+
}
313+
314+
u16 plpks_get_maxobjectlabelsize(void)
315+
{
316+
return maxobjlabelsize;
317+
}
318+
319+
u32 plpks_get_totalsize(void)
320+
{
321+
return totalsize;
322+
}
323+
324+
u32 plpks_get_usedspace(void)
325+
{
326+
// Unlike other config values, usedspace regularly changes as objects
327+
// are updated, so we need to refresh.
328+
int rc = _plpks_get_config();
329+
if (rc) {
330+
pr_err("Couldn't get config, rc: %d\n", rc);
331+
return 0;
332+
}
333+
return usedspace;
334+
}
335+
336+
u32 plpks_get_supportedpolicies(void)
337+
{
338+
return supportedpolicies;
339+
}
340+
341+
u32 plpks_get_maxlargeobjectsize(void)
342+
{
343+
return maxlargeobjectsize;
344+
}
345+
346+
u64 plpks_get_signedupdatealgorithms(void)
347+
{
348+
return signedupdatealgorithms;
349+
}
350+
351+
bool plpks_is_available(void)
352+
{
353+
int rc;
354+
355+
rc = _plpks_get_config();
356+
if (rc)
357+
return false;
233358

234-
return 0;
359+
return true;
235360
}
236361

237362
static int plpks_confirm_object_flushed(struct label *label,

0 commit comments

Comments
 (0)