diff options
-rw-r--r-- | arch/s390/include/asm/trace/zcrypt.h | 122 | ||||
-rw-r--r-- | drivers/s390/crypto/zcrypt_api.c | 105 |
2 files changed, 203 insertions, 24 deletions
diff --git a/arch/s390/include/asm/trace/zcrypt.h b/arch/s390/include/asm/trace/zcrypt.h new file mode 100644 index 000000000000..adcb77fafa9d --- /dev/null +++ b/arch/s390/include/asm/trace/zcrypt.h @@ -0,0 +1,122 @@ +/* + * Tracepoint definitions for the s390 zcrypt device driver + * + * Copyright IBM Corp. 2016 + * Author(s): Harald Freudenberger <freude@de.ibm.com> + * + * Currently there are two tracepoint events defined here. + * An s390_zcrypt_req request event occurs as soon as the request is + * recognized by the zcrypt ioctl function. This event may act as some kind + * of request-processing-starts-now indication. + * As late as possible within the zcrypt ioctl function there occurs the + * s390_zcrypt_rep event which may act as the point in time where the + * request has been processed by the kernel and the result is about to be + * transferred back to userspace. + * The glue which binds together request and reply event is the ptr + * parameter, which is the local buffer address where the request from + * userspace has been stored by the ioctl function. + * + * The main purpose of this zcrypt tracepoint api is to get some data for + * performance measurements together with information about on which card + * and queue the request has been processed. It is not an ffdc interface as + * there is already code in the zcrypt device driver to serve the s390 + * debug feature interface. + */ + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM s390 + +#if !defined(_TRACE_S390_ZCRYPT_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_S390_ZCRYPT_H + +#include <linux/tracepoint.h> + +#define TP_ICARSAMODEXPO 0x0001 +#define TP_ICARSACRT 0x0002 +#define TB_ZSECSENDCPRB 0x0003 +#define TP_ZSENDEP11CPRB 0x0004 +#define TP_HWRNGCPRB 0x0005 + +#define show_zcrypt_tp_type(type) \ + __print_symbolic(type, \ + { TP_ICARSAMODEXPO, "ICARSAMODEXPO" }, \ + { TP_ICARSACRT, "ICARSACRT" }, \ + { TB_ZSECSENDCPRB, "ZSECSENDCPRB" }, \ + { TP_ZSENDEP11CPRB, "ZSENDEP11CPRB" }, \ + { TP_HWRNGCPRB, "HWRNGCPRB" }) + +/** + * trace_s390_zcrypt_req - zcrypt request tracepoint function + * @ptr: Address of the local buffer where the request from userspace + * is stored. Can be used as a unique id to relate together + * request and reply. + * @type: One of the TP_ defines above. + * + * Called when a request from userspace is recognised within the ioctl + * function of the zcrypt device driver and may act as an entry + * timestamp. + */ +TRACE_EVENT(s390_zcrypt_req, + TP_PROTO(void *ptr, u32 type), + TP_ARGS(ptr, type), + TP_STRUCT__entry( + __field(void *, ptr) + __field(u32, type)), + TP_fast_assign( + __entry->ptr = ptr; + __entry->type = type;), + TP_printk("ptr=%p type=%s", + __entry->ptr, + show_zcrypt_tp_type(__entry->type)) +); + +/** + * trace_s390_zcrypt_rep - zcrypt reply tracepoint function + * @ptr: Address of the local buffer where the request from userspace + * is stored. Can be used as a unique id to match together + * request and reply. + * @fc: Function code. + * @rc: The bare returncode as returned by the device driver ioctl + * function. + * @dev: The adapter nr where this request was actually processed. + * @dom: Domain id of the device where this request was processed. + * + * Called upon recognising the reply from the crypto adapter. This + * message may act as the exit timestamp for the request but also + * carries some info about on which adapter the request was processed + * and the returncode from the device driver. + */ +TRACE_EVENT(s390_zcrypt_rep, + TP_PROTO(void *ptr, u32 fc, u32 rc, u16 dev, u16 dom), + TP_ARGS(ptr, fc, rc, dev, dom), + TP_STRUCT__entry( + __field(void *, ptr) + __field(u32, fc) + __field(u32, rc) + __field(u16, device) + __field(u16, domain)), + TP_fast_assign( + __entry->ptr = ptr; + __entry->fc = fc; + __entry->rc = rc; + __entry->device = dev; + __entry->domain = dom;), + TP_printk("ptr=%p fc=0x%04x rc=%d dev=0x%02hx domain=0x%04hx", + __entry->ptr, + (unsigned int) __entry->fc, + (int) __entry->rc, + (unsigned short) __entry->device, + (unsigned short) __entry->domain) +); + +#endif /* _TRACE_S390_ZCRYPT_H */ + +/* This part must be outside protection */ + +#undef TRACE_INCLUDE_PATH +#undef TRACE_INCLUDE_FILE + +#define TRACE_INCLUDE_PATH asm/trace +#define TRACE_INCLUDE_FILE zcrypt + +#include <trace/define_trace.h> diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c index 7ca25e77bd6a..854a6e58dfea 100644 --- a/drivers/s390/crypto/zcrypt_api.c +++ b/drivers/s390/crypto/zcrypt_api.c @@ -41,6 +41,9 @@ #include <linux/debugfs.h> #include <asm/debug.h> +#define CREATE_TRACE_POINTS +#include <asm/trace/zcrypt.h> + #include "zcrypt_api.h" #include "zcrypt_debug.h" @@ -55,6 +58,12 @@ MODULE_DESCRIPTION("Cryptographic Coprocessor interface, " \ "Copyright IBM Corp. 2001, 2012"); MODULE_LICENSE("GPL"); +/* + * zcrypt tracepoint functions + */ +EXPORT_TRACEPOINT_SYMBOL(s390_zcrypt_req); +EXPORT_TRACEPOINT_SYMBOL(s390_zcrypt_rep); + static int zcrypt_hwrng_seed = 1; module_param_named(hwrng_seed, zcrypt_hwrng_seed, int, S_IRUSR|S_IRGRP); MODULE_PARM_DESC(hwrng_seed, "Turn on/off hwrng auto seed, default is 1 (on)."); @@ -224,10 +233,15 @@ static long zcrypt_rsa_modexpo(struct ica_rsa_modexpo *mex) struct zcrypt_queue *zq, *pref_zq; unsigned int weight, pref_weight; unsigned int func_code; - int rc; + int qid = 0, rc = -ENODEV; + + trace_s390_zcrypt_req(mex, TP_ICARSAMODEXPO); + + if (mex->outputdatalength < mex->inputdatalength) { + rc = -EINVAL; + goto out; + } - if (mex->outputdatalength < mex->inputdatalength) - return -EINVAL; /* * As long as outputdatalength is big enough, we can set the * outputdatalength equal to the inputdatalength, since that is the @@ -237,7 +251,7 @@ static long zcrypt_rsa_modexpo(struct ica_rsa_modexpo *mex) rc = get_rsa_modex_fc(mex, &func_code); if (rc) - return rc; + goto out; pref_zc = NULL; pref_zq = NULL; @@ -269,15 +283,21 @@ static long zcrypt_rsa_modexpo(struct ica_rsa_modexpo *mex) pref_zq = zcrypt_pick_queue(pref_zc, pref_zq, weight); spin_unlock(&zcrypt_list_lock); - if (!pref_zq) - return -ENODEV; + if (!pref_zq) { + rc = -ENODEV; + goto out; + } + qid = pref_zq->queue->qid; rc = pref_zq->ops->rsa_modexpo(pref_zq, mex); spin_lock(&zcrypt_list_lock); zcrypt_drop_queue(pref_zc, pref_zq, weight); spin_unlock(&zcrypt_list_lock); +out: + trace_s390_zcrypt_rep(mex, func_code, rc, + AP_QID_CARD(qid), AP_QID_QUEUE(qid)); return rc; } @@ -287,10 +307,15 @@ static long zcrypt_rsa_crt(struct ica_rsa_modexpo_crt *crt) struct zcrypt_queue *zq, *pref_zq; unsigned int weight, pref_weight; unsigned int func_code; - int rc; + int qid = 0, rc = -ENODEV; + + trace_s390_zcrypt_req(crt, TP_ICARSACRT); + + if (crt->outputdatalength < crt->inputdatalength) { + rc = -EINVAL; + goto out; + } - if (crt->outputdatalength < crt->inputdatalength) - return -EINVAL; /* * As long as outputdatalength is big enough, we can set the * outputdatalength equal to the inputdatalength, since that is the @@ -300,7 +325,7 @@ static long zcrypt_rsa_crt(struct ica_rsa_modexpo_crt *crt) rc = get_rsa_crt_fc(crt, &func_code); if (rc) - return rc; + goto out; pref_zc = NULL; pref_zq = NULL; @@ -332,15 +357,21 @@ static long zcrypt_rsa_crt(struct ica_rsa_modexpo_crt *crt) pref_zq = zcrypt_pick_queue(pref_zc, pref_zq, weight); spin_unlock(&zcrypt_list_lock); - if (!pref_zq) - return -ENODEV; + if (!pref_zq) { + rc = -ENODEV; + goto out; + } + qid = pref_zq->queue->qid; rc = pref_zq->ops->rsa_modexpo_crt(pref_zq, crt); spin_lock(&zcrypt_list_lock); zcrypt_drop_queue(pref_zc, pref_zq, weight); spin_unlock(&zcrypt_list_lock); +out: + trace_s390_zcrypt_rep(crt, func_code, rc, + AP_QID_CARD(qid), AP_QID_QUEUE(qid)); return rc; } @@ -352,11 +383,13 @@ static long zcrypt_send_cprb(struct ica_xcRB *xcRB) unsigned int weight, pref_weight; unsigned int func_code; unsigned short *domain; - int rc; + int qid = 0, rc = -ENODEV; + + trace_s390_zcrypt_req(xcRB, TB_ZSECSENDCPRB); rc = get_cprb_fc(xcRB, &ap_msg, &func_code, &domain); if (rc) - return rc; + goto out; pref_zc = NULL; pref_zq = NULL; @@ -391,18 +424,25 @@ static long zcrypt_send_cprb(struct ica_xcRB *xcRB) pref_zq = zcrypt_pick_queue(pref_zc, pref_zq, weight); spin_unlock(&zcrypt_list_lock); - if (!pref_zq) - return -ENODEV; + if (!pref_zq) { + rc = -ENODEV; + goto out; + } /* in case of auto select, provide the correct domain */ + qid = pref_zq->queue->qid; if (*domain == (unsigned short) AUTOSELECT) - *domain = AP_QID_QUEUE(pref_zq->queue->qid); + *domain = AP_QID_QUEUE(qid); rc = pref_zq->ops->send_cprb(pref_zq, xcRB, &ap_msg); spin_lock(&zcrypt_list_lock); zcrypt_drop_queue(pref_zc, pref_zq, weight); spin_unlock(&zcrypt_list_lock); + +out: + trace_s390_zcrypt_rep(xcRB, func_code, rc, + AP_QID_CARD(qid), AP_QID_QUEUE(qid)); return rc; } @@ -439,7 +479,9 @@ static long zcrypt_send_ep11_cprb(struct ep11_urb *xcrb) unsigned int weight, pref_weight; unsigned int func_code; struct ap_message ap_msg; - int rc; + int qid = 0, rc = -ENODEV; + + trace_s390_zcrypt_req(xcrb, TP_ZSENDEP11CPRB); target_num = (unsigned short) xcrb->targets_num; @@ -449,13 +491,17 @@ static long zcrypt_send_ep11_cprb(struct ep11_urb *xcrb) struct ep11_target_dev __user *uptr; targets = kcalloc(target_num, sizeof(*targets), GFP_KERNEL); - if (!targets) - return -ENOMEM; + if (!targets) { + rc = -ENOMEM; + goto out; + } uptr = (struct ep11_target_dev __force __user *) xcrb->targets; if (copy_from_user(targets, uptr, - target_num * sizeof(*targets))) - return -EFAULT; + target_num * sizeof(*targets))) { + rc = -EFAULT; + goto out; + } } rc = get_ep11cprb_fc(xcrb, &ap_msg, &func_code); @@ -501,6 +547,7 @@ static long zcrypt_send_ep11_cprb(struct ep11_urb *xcrb) goto out_free; } + qid = pref_zq->queue->qid; rc = pref_zq->ops->send_ep11_cprb(pref_zq, xcrb, &ap_msg); spin_lock(&zcrypt_list_lock); @@ -509,6 +556,9 @@ static long zcrypt_send_ep11_cprb(struct ep11_urb *xcrb) out_free: kfree(targets); +out: + trace_s390_zcrypt_rep(xcrb, func_code, rc, + AP_QID_CARD(qid), AP_QID_QUEUE(qid)); return rc; } @@ -520,11 +570,13 @@ static long zcrypt_rng(char *buffer) unsigned int func_code; struct ap_message ap_msg; unsigned int domain; - int rc; + int qid = 0, rc = -ENODEV; + + trace_s390_zcrypt_req(buffer, TP_HWRNGCPRB); rc = get_rng_fc(&ap_msg, &func_code, &domain); if (rc) - return rc; + goto out; pref_zc = NULL; pref_zq = NULL; @@ -555,11 +607,16 @@ static long zcrypt_rng(char *buffer) if (!pref_zq) return -ENODEV; + qid = pref_zq->queue->qid; rc = pref_zq->ops->rng(pref_zq, buffer, &ap_msg); spin_lock(&zcrypt_list_lock); zcrypt_drop_queue(pref_zc, pref_zq, weight); spin_unlock(&zcrypt_list_lock); + +out: + trace_s390_zcrypt_rep(buffer, func_code, rc, + AP_QID_CARD(qid), AP_QID_QUEUE(qid)); return rc; } |