Messages in this thread | | | Date | Wed, 16 Mar 2022 09:56:48 +0100 | Subject | Re: [PATCH v3 2/4] drivers/s390/char: Add Query Ultravisor Information to uvdevice | From | Janosch Frank <> |
| |
On 3/4/22 15:11, Steffen Eiden wrote: > This patch enables userspace to call the Query Ultravisor Information > Ultravisor Call using IOCTLs on the uvdevice. > > The uvdevice will do some sanity checks first, build the UVCB, > perform the UV call, and copy the result to userspace. > > Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Janosch Frank <frankja@linux.ibm.com>
> --- > arch/s390/include/uapi/asm/uvdevice.h | 2 + > drivers/s390/char/uvdevice.c | 56 +++++++++++++++++++++++++++ > 2 files changed, 58 insertions(+) > > diff --git a/arch/s390/include/uapi/asm/uvdevice.h b/arch/s390/include/uapi/asm/uvdevice.h > index d40f69345c75..7520bdde3102 100644 > --- a/arch/s390/include/uapi/asm/uvdevice.h > +++ b/arch/s390/include/uapi/asm/uvdevice.h > @@ -42,10 +42,12 @@ struct uvio_attest { > #define UVIO_ATT_ARCB_MAX_LEN 0x100000 > #define UVIO_ATT_MEASUREMENT_MAX_LEN 0x8000 > #define UVIO_ATT_ADDITIONAL_MAX_LEN 0x8000 > +#define UVIO_QUI_MAX_LEN 0x8000 > > #define UVIO_DEVICE_NAME "uv" > #define UVIO_TYPE_UVC 'u' > > #define UVIO_IOCTL_ATT _IOWR(UVIO_TYPE_UVC, 0x01, struct uvio_ioctl_cb) > +#define UVIO_IOCTL_QUI _IOWR(UVIO_TYPE_UVC, 0x02, struct uvio_ioctl_cb) > > #endif /* __S390X_ASM_UVDEVICE_H */ > diff --git a/drivers/s390/char/uvdevice.c b/drivers/s390/char/uvdevice.c > index b720dc8d0bd9..cfce8c5999e6 100644 > --- a/drivers/s390/char/uvdevice.c > +++ b/drivers/s390/char/uvdevice.c > @@ -31,6 +31,55 @@ > #include <asm/uvdevice.h> > #include <asm/uv.h> > > +/** > + * uvio_qui() - Perform a Query Ultravisor Information UVC. > + * > + * uv_ioctl: ioctl control block > + * > + * uvio_qui() does a Query Ultravisor Information (QUI) Ultravisor Call. > + * It creates the uvc qui request and sends it to the Ultravisor. After that > + * it copies the response to userspace and fills the rc and rrc of uv_ioctl > + * uv_call with the response values of the Ultravisor. > + * > + * Create the UVC structure, send the UVC to UV and write the response in the ioctl struct. > + * > + * Return: 0 on success or a negative error code on error. > + */ > +static int uvio_qui(struct uvio_ioctl_cb *uv_ioctl) > +{ > + u8 __user *user_buf_addr = (__user u8 *)uv_ioctl->argument_addr; > + size_t user_buf_len = uv_ioctl->argument_len; > + struct uv_cb_header *uvcb_qui = NULL; > + int ret; > + > + /* > + * Do not check for a too small buffer. If userspace provides a buffer > + * that is too small the Ultravisor will complain. > + */ > + ret = -EINVAL; > + if (!user_buf_len || user_buf_len > UVIO_QUI_MAX_LEN) > + goto out; > + ret = -ENOMEM; > + uvcb_qui = kvzalloc(user_buf_len, GFP_KERNEL); > + if (!uvcb_qui) > + goto out; > + uvcb_qui->len = user_buf_len; > + uvcb_qui->cmd = UVC_CMD_QUI; > + > + uv_call(0, (u64)uvcb_qui); > + > + ret = -EFAULT; > + if (copy_to_user(user_buf_addr, uvcb_qui, uvcb_qui->len)) > + goto out; > + uv_ioctl->uv_rc = uvcb_qui->rc; > + uv_ioctl->uv_rrc = uvcb_qui->rrc; > + > + ret = 0; > +out: > + kvfree(uvcb_qui); > + return ret; > +} > + > static int uvio_build_uvcb_attest(struct uv_cb_attest *uvcb_attest, u8 *arcb, > u8 *meas, u8 *add_data, struct uvio_attest *uvio_attest) > { > @@ -217,6 +266,13 @@ static long uvio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) > goto out; > ret = uvio_attestation(uv_ioctl); > break; > + case UVIO_IOCTL_QUI: > + ret = uvio_copy_and_check_ioctl(uv_ioctl, argp); > + if (ret) > + goto out; > + ret = uvio_qui(uv_ioctl); > + break; > + > default: > ret = -ENOIOCTLCMD; > break;
| |