···38143814error number indicating the type of exception. This exception is also38153815raised directly at the corresponding VCPU if the flag38163816KVM_S390_MEMOP_F_INJECT_EXCEPTION is set.38173817+On protection exceptions, unless specified otherwise, the injected38183818+translation-exception identifier (TEID) indicates suppression.3817381938183820If the KVM_S390_MEMOP_F_SKEY_PROTECTION flag is set, storage key38193821protection is also in effect and may cause exceptions if accesses are38203822prohibited given the access key designated by "key"; the valid range is 0..15.38213823KVM_S390_MEMOP_F_SKEY_PROTECTION is available if KVM_CAP_S390_MEM_OP_EXTENSION38223824is > 0.38253825+Since the accessed memory may span multiple pages and those pages might have38263826+different storage keys, it is possible that a protection exception occurs38273827+after memory has been modified. In this case, if the exception is injected,38283828+the TEID does not indicate suppression.3823382938243830Absolute read/write:38253831^^^^^^^^^^^^^^^^^^^^
···11+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */22+/*33+ * Copyright IBM Corp. 202244+ * Author(s): Steffen Eiden <seiden@linux.ibm.com>55+ */66+#ifndef __S390_ASM_UVDEVICE_H77+#define __S390_ASM_UVDEVICE_H88+99+#include <linux/types.h>1010+1111+struct uvio_ioctl_cb {1212+ __u32 flags;1313+ __u16 uv_rc; /* UV header rc value */1414+ __u16 uv_rrc; /* UV header rrc value */1515+ __u64 argument_addr; /* Userspace address of uvio argument */1616+ __u32 argument_len;1717+ __u8 reserved14[0x40 - 0x14]; /* must be zero */1818+};1919+2020+#define UVIO_ATT_USER_DATA_LEN 0x1002121+#define UVIO_ATT_UID_LEN 0x102222+struct uvio_attest {2323+ __u64 arcb_addr; /* 0x0000 */2424+ __u64 meas_addr; /* 0x0008 */2525+ __u64 add_data_addr; /* 0x0010 */2626+ __u8 user_data[UVIO_ATT_USER_DATA_LEN]; /* 0x0018 */2727+ __u8 config_uid[UVIO_ATT_UID_LEN]; /* 0x0118 */2828+ __u32 arcb_len; /* 0x0128 */2929+ __u32 meas_len; /* 0x012c */3030+ __u32 add_data_len; /* 0x0130 */3131+ __u16 user_data_len; /* 0x0134 */3232+ __u16 reserved136; /* 0x0136 */3333+};3434+3535+/*3636+ * The following max values define an upper length for the IOCTL in/out buffers.3737+ * However, they do not represent the maximum the Ultravisor allows which is3838+ * often way smaller. By allowing larger buffer sizes we hopefully do not need3939+ * to update the code with every machine update. It is therefore possible for4040+ * userspace to request more memory than actually used by kernel/UV.4141+ */4242+#define UVIO_ATT_ARCB_MAX_LEN 0x1000004343+#define UVIO_ATT_MEASUREMENT_MAX_LEN 0x80004444+#define UVIO_ATT_ADDITIONAL_MAX_LEN 0x80004545+4646+#define UVIO_DEVICE_NAME "uv"4747+#define UVIO_TYPE_UVC 'u'4848+4949+#define UVIO_IOCTL_ATT _IOWR(UVIO_TYPE_UVC, 0x01, struct uvio_ioctl_cb)5050+5151+#endif /* __S390_ASM_UVDEVICE_H */
+18-4
arch/s390/kvm/gaccess.c
···491491 PROT_TYPE_IEP = 4,492492};493493494494-static int trans_exc(struct kvm_vcpu *vcpu, int code, unsigned long gva,495495- u8 ar, enum gacc_mode mode, enum prot_type prot)494494+static int trans_exc_ending(struct kvm_vcpu *vcpu, int code, unsigned long gva, u8 ar,495495+ enum gacc_mode mode, enum prot_type prot, bool terminate)496496{497497 struct kvm_s390_pgm_info *pgm = &vcpu->arch.pgm;498498 struct trans_exc_code_bits *tec;···519519 case PROT_TYPE_DAT:520520 tec->b61 = 1;521521 break;522522+ }523523+ if (terminate) {524524+ tec->b56 = 0;525525+ tec->b60 = 0;526526+ tec->b61 = 0;522527 }523528 fallthrough;524529 case PGM_ASCE_TYPE:···555550 break;556551 }557552 return code;553553+}554554+555555+static int trans_exc(struct kvm_vcpu *vcpu, int code, unsigned long gva, u8 ar,556556+ enum gacc_mode mode, enum prot_type prot)557557+{558558+ return trans_exc_ending(vcpu, code, gva, ar, mode, prot, false);558559}559560560561static int get_vcpu_asce(struct kvm_vcpu *vcpu, union asce *asce,···11201109 data += fragment_len;11211110 ga = kvm_s390_logical_to_effective(vcpu, ga + fragment_len);11221111 }11231123- if (rc > 0)11241124- rc = trans_exc(vcpu, rc, ga, ar, mode, prot);11121112+ if (rc > 0) {11131113+ bool terminate = (mode == GACC_STORE) && (idx > 0);11141114+11151115+ rc = trans_exc_ending(vcpu, rc, ga, ar, mode, prot, terminate);11161116+ }11251117out_unlock:11261118 if (need_ipte_lock)11271119 ipte_unlock(vcpu);
+10
drivers/s390/char/Kconfig
···100100 This option enables the Open-for-Business interface to the s390101101 Service Element.102102103103+config S390_UV_UAPI104104+ def_tristate m105105+ prompt "Ultravisor userspace API"106106+ help107107+ Selecting exposes parts of the UV interface to userspace108108+ by providing a misc character device at /dev/uv.109109+ Using IOCTLs one can interact with the UV.110110+ The device is only available if the Ultravisor111111+ Facility (158) is present.112112+103113config S390_TAPE104114 def_tristate m105115 prompt "S/390 tape device support"
···11+// SPDX-License-Identifier: GPL-2.022+/*33+ * Copyright IBM Corp. 202244+ * Author(s): Steffen Eiden <seiden@linux.ibm.com>55+ *66+ * This file provides a Linux misc device to give userspace access to some77+ * Ultravisor (UV) functions. The device only accepts IOCTLs and will only88+ * be present if the Ultravisor facility (158) is present.99+ *1010+ * When userspace sends a valid IOCTL uvdevice will copy the input data to1111+ * kernel space, do some basic validity checks to avoid kernel/system1212+ * corruption. Any other check that the Ultravisor does will not be done by1313+ * the uvdevice to keep changes minimal when adding new functionalities1414+ * to existing UV-calls.1515+ * After the checks uvdevice builds a corresponding1616+ * Ultravisor Call Control Block, and sends the request to the Ultravisor.1717+ * Then, it copies the response, including the return codes, back to userspace.1818+ * It is the responsibility of the userspace to check for any error issued1919+ * by UV and to interpret the UV response. The uvdevice acts as a communication2020+ * channel for userspace to the Ultravisor.2121+ */2222+2323+#include <linux/module.h>2424+#include <linux/kernel.h>2525+#include <linux/miscdevice.h>2626+#include <linux/types.h>2727+#include <linux/stddef.h>2828+#include <linux/vmalloc.h>2929+#include <linux/slab.h>3030+3131+#include <asm/uvdevice.h>3232+#include <asm/uv.h>3333+3434+static int uvio_build_uvcb_attest(struct uv_cb_attest *uvcb_attest, u8 *arcb,3535+ u8 *meas, u8 *add_data, struct uvio_attest *uvio_attest)3636+{3737+ void __user *user_buf_arcb = (void __user *)uvio_attest->arcb_addr;3838+3939+ if (copy_from_user(arcb, user_buf_arcb, uvio_attest->arcb_len))4040+ return -EFAULT;4141+4242+ uvcb_attest->header.len = sizeof(*uvcb_attest);4343+ uvcb_attest->header.cmd = UVC_CMD_RETR_ATTEST;4444+ uvcb_attest->arcb_addr = (u64)arcb;4545+ uvcb_attest->cont_token = 0;4646+ uvcb_attest->user_data_len = uvio_attest->user_data_len;4747+ memcpy(uvcb_attest->user_data, uvio_attest->user_data, sizeof(uvcb_attest->user_data));4848+ uvcb_attest->meas_len = uvio_attest->meas_len;4949+ uvcb_attest->meas_addr = (u64)meas;5050+ uvcb_attest->add_data_len = uvio_attest->add_data_len;5151+ uvcb_attest->add_data_addr = (u64)add_data;5252+5353+ return 0;5454+}5555+5656+static int uvio_copy_attest_result_to_user(struct uv_cb_attest *uvcb_attest,5757+ struct uvio_ioctl_cb *uv_ioctl,5858+ u8 *measurement, u8 *add_data,5959+ struct uvio_attest *uvio_attest)6060+{6161+ struct uvio_attest __user *user_uvio_attest = (void __user *)uv_ioctl->argument_addr;6262+ void __user *user_buf_add = (void __user *)uvio_attest->add_data_addr;6363+ void __user *user_buf_meas = (void __user *)uvio_attest->meas_addr;6464+ void __user *user_buf_uid = &user_uvio_attest->config_uid;6565+6666+ if (copy_to_user(user_buf_meas, measurement, uvio_attest->meas_len))6767+ return -EFAULT;6868+ if (add_data && copy_to_user(user_buf_add, add_data, uvio_attest->add_data_len))6969+ return -EFAULT;7070+ if (copy_to_user(user_buf_uid, uvcb_attest->config_uid, sizeof(uvcb_attest->config_uid)))7171+ return -EFAULT;7272+ return 0;7373+}7474+7575+static int get_uvio_attest(struct uvio_ioctl_cb *uv_ioctl, struct uvio_attest *uvio_attest)7676+{7777+ u8 __user *user_arg_buf = (u8 __user *)uv_ioctl->argument_addr;7878+7979+ if (copy_from_user(uvio_attest, user_arg_buf, sizeof(*uvio_attest)))8080+ return -EFAULT;8181+8282+ if (uvio_attest->arcb_len > UVIO_ATT_ARCB_MAX_LEN)8383+ return -EINVAL;8484+ if (uvio_attest->arcb_len == 0)8585+ return -EINVAL;8686+ if (uvio_attest->meas_len > UVIO_ATT_MEASUREMENT_MAX_LEN)8787+ return -EINVAL;8888+ if (uvio_attest->meas_len == 0)8989+ return -EINVAL;9090+ if (uvio_attest->add_data_len > UVIO_ATT_ADDITIONAL_MAX_LEN)9191+ return -EINVAL;9292+ if (uvio_attest->reserved136)9393+ return -EINVAL;9494+ return 0;9595+}9696+9797+/**9898+ * uvio_attestation() - Perform a Retrieve Attestation Measurement UVC.9999+ *100100+ * @uv_ioctl: ioctl control block101101+ *102102+ * uvio_attestation() does a Retrieve Attestation Measurement Ultravisor Call.103103+ * It verifies that the given userspace addresses are valid and request sizes104104+ * are sane. Every other check is made by the Ultravisor (UV) and won't result105105+ * in a negative return value. It copies the input to kernelspace, builds the106106+ * request, sends the UV-call, and copies the result to userspace.107107+ *108108+ * The Attestation Request has two input and two outputs.109109+ * ARCB and User Data are inputs for the UV generated by userspace.110110+ * Measurement and Additional Data are outputs for userspace generated by UV.111111+ *112112+ * The Attestation Request Control Block (ARCB) is a cryptographically verified113113+ * and secured request to UV and User Data is some plaintext data which is114114+ * going to be included in the Attestation Measurement calculation.115115+ *116116+ * Measurement is a cryptographic measurement of the callers properties,117117+ * optional data configured by the ARCB and the user data. If specified by the118118+ * ARCB, UV will add some Additional Data to the measurement calculation.119119+ * This Additional Data is then returned as well.120120+ *121121+ * If the Retrieve Attestation Measurement UV facility is not present,122122+ * UV will return invalid command rc. This won't be fenced in the driver123123+ * and does not result in a negative return value.124124+ *125125+ * Context: might sleep126126+ *127127+ * Return: 0 on success or a negative error code on error.128128+ */129129+static int uvio_attestation(struct uvio_ioctl_cb *uv_ioctl)130130+{131131+ struct uv_cb_attest *uvcb_attest = NULL;132132+ struct uvio_attest *uvio_attest = NULL;133133+ u8 *measurement = NULL;134134+ u8 *add_data = NULL;135135+ u8 *arcb = NULL;136136+ int ret;137137+138138+ ret = -EINVAL;139139+ if (uv_ioctl->argument_len != sizeof(*uvio_attest))140140+ goto out;141141+142142+ ret = -ENOMEM;143143+ uvio_attest = kzalloc(sizeof(*uvio_attest), GFP_KERNEL);144144+ if (!uvio_attest)145145+ goto out;146146+147147+ ret = get_uvio_attest(uv_ioctl, uvio_attest);148148+ if (ret)149149+ goto out;150150+151151+ ret = -ENOMEM;152152+ arcb = kvzalloc(uvio_attest->arcb_len, GFP_KERNEL);153153+ measurement = kvzalloc(uvio_attest->meas_len, GFP_KERNEL);154154+ if (!arcb || !measurement)155155+ goto out;156156+157157+ if (uvio_attest->add_data_len) {158158+ add_data = kvzalloc(uvio_attest->add_data_len, GFP_KERNEL);159159+ if (!add_data)160160+ goto out;161161+ }162162+163163+ uvcb_attest = kzalloc(sizeof(*uvcb_attest), GFP_KERNEL);164164+ if (!uvcb_attest)165165+ goto out;166166+167167+ ret = uvio_build_uvcb_attest(uvcb_attest, arcb, measurement, add_data, uvio_attest);168168+ if (ret)169169+ goto out;170170+171171+ uv_call_sched(0, (u64)uvcb_attest);172172+173173+ uv_ioctl->uv_rc = uvcb_attest->header.rc;174174+ uv_ioctl->uv_rrc = uvcb_attest->header.rrc;175175+176176+ ret = uvio_copy_attest_result_to_user(uvcb_attest, uv_ioctl, measurement, add_data,177177+ uvio_attest);178178+out:179179+ kvfree(arcb);180180+ kvfree(measurement);181181+ kvfree(add_data);182182+ kfree(uvio_attest);183183+ kfree(uvcb_attest);184184+ return ret;185185+}186186+187187+static int uvio_copy_and_check_ioctl(struct uvio_ioctl_cb *ioctl, void __user *argp)188188+{189189+ if (copy_from_user(ioctl, argp, sizeof(*ioctl)))190190+ return -EFAULT;191191+ if (ioctl->flags != 0)192192+ return -EINVAL;193193+ if (memchr_inv(ioctl->reserved14, 0, sizeof(ioctl->reserved14)))194194+ return -EINVAL;195195+196196+ return 0;197197+}198198+199199+/*200200+ * IOCTL entry point for the Ultravisor device.201201+ */202202+static long uvio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)203203+{204204+ void __user *argp = (void __user *)arg;205205+ struct uvio_ioctl_cb uv_ioctl = { };206206+ long ret;207207+208208+ switch (cmd) {209209+ case UVIO_IOCTL_ATT:210210+ ret = uvio_copy_and_check_ioctl(&uv_ioctl, argp);211211+ if (ret)212212+ return ret;213213+ ret = uvio_attestation(&uv_ioctl);214214+ break;215215+ default:216216+ ret = -ENOIOCTLCMD;217217+ break;218218+ }219219+ if (ret)220220+ return ret;221221+222222+ if (copy_to_user(argp, &uv_ioctl, sizeof(uv_ioctl)))223223+ ret = -EFAULT;224224+225225+ return ret;226226+}227227+228228+static const struct file_operations uvio_dev_fops = {229229+ .owner = THIS_MODULE,230230+ .unlocked_ioctl = uvio_ioctl,231231+ .llseek = no_llseek,232232+};233233+234234+static struct miscdevice uvio_dev_miscdev = {235235+ .minor = MISC_DYNAMIC_MINOR,236236+ .name = UVIO_DEVICE_NAME,237237+ .fops = &uvio_dev_fops,238238+};239239+240240+static void __exit uvio_dev_exit(void)241241+{242242+ misc_deregister(&uvio_dev_miscdev);243243+}244244+245245+static int __init uvio_dev_init(void)246246+{247247+ if (!test_facility(158))248248+ return -ENXIO;249249+ return misc_register(&uvio_dev_miscdev);250250+}251251+252252+module_init(uvio_dev_init);253253+module_exit(uvio_dev_exit);254254+255255+MODULE_AUTHOR("IBM Corporation");256256+MODULE_LICENSE("GPL");257257+MODULE_DESCRIPTION("Ultravisor UAPI driver");