From: Nayna Jain <na...@linux.ibm.com> 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. 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 <na...@linux.ibm.com> [ajd: split patch, extend to support additional v3 API fields, minor fixes] Co-developed-by: Andrew Donnellan <a...@linux.ibm.com> Signed-off-by: Andrew Donnellan <a...@linux.ibm.com> --- arch/powerpc/platforms/pseries/plpks.c | 118 ++++++++++++++++++++++--- arch/powerpc/platforms/pseries/plpks.h | 58 ++++++++++++ 2 files changed, 164 insertions(+), 12 deletions(-) diff --git a/arch/powerpc/platforms/pseries/plpks.c b/arch/powerpc/platforms/pseries/plpks.c index 8ccc91143370..c5ae00a8a968 100644 --- a/arch/powerpc/platforms/pseries/plpks.c +++ b/arch/powerpc/platforms/pseries/plpks.c @@ -38,8 +38,16 @@ static u8 *ospassword; static u16 ospasswordlength; // Retrieved with H_PKS_GET_CONFIG +static u8 version; +static u16 objoverhead; static u16 maxpwsize; static u16 maxobjsize; +static s16 maxobjlabelsize; +static u32 totalsize; +static u32 usedspace; +static u32 supportedpolicies; +static u32 maxlargeobjectsize; +static u64 signedupdatealgorithms; struct plpks_auth { u8 version; @@ -220,32 +228,118 @@ static struct label *construct_label(char *component, u8 varos, u8 *name, static int _plpks_get_config(void) { unsigned long retbuf[PLPAR_HCALL_BUFSIZE] = { 0 }; - struct { + struct config { u8 version; u8 flags; - __be32 rsvd0; + __be16 rsvd0; + __be16 objoverhead; __be16 maxpwsize; __be16 maxobjlabelsize; __be16 maxobjsize; __be32 totalsize; __be32 usedspace; __be32 supportedpolicies; - __be64 rsvd1; - } __packed config; + __be32 maxlargeobjectsize; + __be64 signedupdatealgorithms; + u8 rsvd1[476]; + } __packed *config; size_t size; - int rc; + int rc = 0; + + size = sizeof(*config); + + // Config struct must not cross a page boundary. So long as the struct + // size is a power of 2, this should be fine as alignment is guaranteed + config = kzalloc(size, GFP_KERNEL); + if (!config) { + rc = -ENOMEM; + goto err; + } - size = sizeof(config); + rc = plpar_hcall(H_PKS_GET_CONFIG, retbuf, virt_to_phys(config), size); - rc = plpar_hcall(H_PKS_GET_CONFIG, retbuf, virt_to_phys(&config), size); + if (rc != H_SUCCESS) { + rc = pseries_status_to_err(rc); + goto err; + } - if (rc != H_SUCCESS) - return pseries_status_to_err(rc); + version = config->version; + objoverhead = be16_to_cpu(config->objoverhead); + maxpwsize = be16_to_cpu(config->maxpwsize); + maxobjsize = be16_to_cpu(config->maxobjsize); + maxobjlabelsize = be16_to_cpu(config->maxobjlabelsize) - + MAX_LABEL_ATTR_SIZE; + maxobjlabelsize = maxobjlabelsize < 0 ? 0 : maxobjlabelsize; + totalsize = be32_to_cpu(config->totalsize); + usedspace = be32_to_cpu(config->usedspace); + supportedpolicies = be32_to_cpu(config->supportedpolicies); + maxlargeobjectsize = be32_to_cpu(config->maxlargeobjectsize); + signedupdatealgorithms = be64_to_cpu(config->signedupdatealgorithms); + +err: + kfree(config); + return rc; +} - maxpwsize = be16_to_cpu(config.maxpwsize); - maxobjsize = be16_to_cpu(config.maxobjsize); +u8 plpks_get_version(void) +{ + return version; +} + +u16 plpks_get_objoverhead(void) +{ + return objoverhead; +} + +u16 plpks_get_maxpwsize(void) +{ + return maxpwsize; +} + +u16 plpks_get_maxobjectsize(void) +{ + return maxobjsize; +} + +u16 plpks_get_maxobjectlabelsize(void) +{ + return maxobjlabelsize; +} + +u32 plpks_get_totalsize(void) +{ + return totalsize; +} + +u32 plpks_get_usedspace(void) +{ + return usedspace; +} + +u32 plpks_get_supportedpolicies(void) +{ + return supportedpolicies; +} + +u32 plpks_get_maxlargeobjectsize(void) +{ + return maxlargeobjectsize; +} + +u64 plpks_get_signedupdatealgorithms(void) +{ + return signedupdatealgorithms; +} + +bool plpks_is_available(void) +{ + int rc; + + rc = _plpks_get_config(); + if (rc) + return false; - return 0; + return true; } static int plpks_confirm_object_flushed(struct label *label, diff --git a/arch/powerpc/platforms/pseries/plpks.h b/arch/powerpc/platforms/pseries/plpks.h index 275ccd86bfb5..c89740796660 100644 --- a/arch/powerpc/platforms/pseries/plpks.h +++ b/arch/powerpc/platforms/pseries/plpks.h @@ -68,4 +68,62 @@ int plpks_read_fw_var(struct plpks_var *var); */ int plpks_read_bootloader_var(struct plpks_var *var); +/** + * Returns if PKS is available on this LPAR. + */ +bool plpks_is_available(void); + +/** + * Returns version of the Platform KeyStore. + */ +u8 plpks_get_version(void); + +/** + * Returns hypervisor storage overhead per object, not including the size of + * the object or label. Only valid for config version >= 2 + */ +u16 plpks_get_objoverhead(void); + +/** + * Returns maximum password size. Must be >= 32 bytes + */ +u16 plpks_get_maxpwsize(void); + +/** + * Returns maximum object size supported by Platform KeyStore. + */ +u16 plpks_get_maxobjectsize(void); + +/** + * Returns maximum object label size supported by Platform KeyStore. + */ +u16 plpks_get_maxobjectlabelsize(void); + +/** + * Returns total size of the configured Platform KeyStore. + */ +u32 plpks_get_totalsize(void); + +/** + * Returns used space from the total size of the Platform KeyStore. + */ +u32 plpks_get_usedspace(void); + +/** + * Returns bitmask of policies supported by the hypervisor. + */ +u32 plpks_get_supportedpolicies(void); + +/** + * Returns maximum byte size of a single object supported by the hypervisor. + * Only valid for config version >= 3 + */ +u32 plpks_get_maxlargeobjectsize(void); + +/** + * Returns bitmask of signature algorithms supported for signed updates. + * Only valid for config version >= 3 + */ +u64 plpks_get_signedupdatealgorithms(void); + #endif -- 2.38.1