summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/s390/include/asm/trace/zcrypt.h122
-rw-r--r--drivers/s390/crypto/zcrypt_api.c105
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;
}