diff options
author | Peter Oberparleiter <oberpar@linux.vnet.ibm.com> | 2015-12-18 12:59:36 +0100 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2015-12-18 14:59:36 +0100 |
commit | 42248979d5705e056b509cdcfb548e40f708cba8 (patch) | |
tree | 0046a29f78bdfff21bfa8cbfd5896cf1b5b6f9b0 | |
parent | 2ab59de7c5ce7c5ed6db07278554901d43fe80a0 (diff) | |
download | linux-42248979d5705e056b509cdcfb548e40f708cba8.tar.gz linux-42248979d5705e056b509cdcfb548e40f708cba8.tar.bz2 linux-42248979d5705e056b509cdcfb548e40f708cba8.zip |
s390/cio: Introduce common I/O layer tracepoints
Add tracepoints to interrupt handler and core inline assemblies used by
the s390 common I/O layer. These tracepoints can be used to monitor and
validate hardware and hypervisor requests and responses.
Signed-off-by: Peter Oberparleiter <oberpar@linux.vnet.ibm.com>
Reviewed-by: Sebastian Ott <sebott@linux.vnet.ibm.com>
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
-rw-r--r-- | drivers/s390/cio/Makefile | 5 | ||||
-rw-r--r-- | drivers/s390/cio/airq.c | 1 | ||||
-rw-r--r-- | drivers/s390/cio/cio.c | 2 | ||||
-rw-r--r-- | drivers/s390/cio/ioasm.h | 25 | ||||
-rw-r--r-- | drivers/s390/cio/trace.c | 24 | ||||
-rw-r--r-- | drivers/s390/cio/trace.h | 363 |
6 files changed, 419 insertions, 1 deletions
diff --git a/drivers/s390/cio/Makefile b/drivers/s390/cio/Makefile index 8c4a386e97f6..2c7cf0b3c5a0 100644 --- a/drivers/s390/cio/Makefile +++ b/drivers/s390/cio/Makefile @@ -2,8 +2,11 @@ # Makefile for the S/390 common i/o drivers # +# The following is required for define_trace.h to find ./trace.h +CFLAGS_trace.o := -I$(src) + obj-y += airq.o blacklist.o chsc.o cio.o css.o chp.o idset.o isc.o \ - fcx.o itcw.o crw.o ccwreq.o + fcx.o itcw.o crw.o ccwreq.o trace.o ccw_device-objs += device.o device_fsm.o device_ops.o ccw_device-objs += device_id.o device_pgid.o device_status.o obj-y += ccw_device.o cmf.o diff --git a/drivers/s390/cio/airq.c b/drivers/s390/cio/airq.c index 56eb4ee4deba..99b5db469097 100644 --- a/drivers/s390/cio/airq.c +++ b/drivers/s390/cio/airq.c @@ -89,6 +89,7 @@ static irqreturn_t do_airq_interrupt(int irq, void *dummy) set_cpu_flag(CIF_NOHZ_DELAY); tpi_info = (struct tpi_info *) &get_irq_regs()->int_code; + trace_s390_cio_adapter_int(tpi_info); head = &airq_lists[tpi_info->isc]; rcu_read_lock(); hlist_for_each_entry_rcu(airq, head, list) diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index 5f5c24030405..39a8ae54e9c1 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c @@ -41,6 +41,7 @@ #include "blacklist.h" #include "cio_debug.h" #include "chp.h" +#include "trace.h" debug_info_t *cio_debug_msg_id; debug_info_t *cio_debug_trace_id; @@ -539,6 +540,7 @@ static irqreturn_t do_cio_interrupt(int irq, void *dummy) set_cpu_flag(CIF_NOHZ_DELAY); tpi_info = (struct tpi_info *) &get_irq_regs()->int_code; + trace_s390_cio_interrupt(tpi_info); irb = this_cpu_ptr(&cio_irb); sch = (struct subchannel *)(unsigned long) tpi_info->intparm; if (!sch) { diff --git a/drivers/s390/cio/ioasm.h b/drivers/s390/cio/ioasm.h index dce25500812a..11e255a4fbad 100644 --- a/drivers/s390/cio/ioasm.h +++ b/drivers/s390/cio/ioasm.h @@ -6,6 +6,7 @@ #include <asm/crw.h> #include "orb.h" #include "cio.h" +#include "trace.h" /* * Some S390 specific IO instructions as inline @@ -25,6 +26,8 @@ static inline int stsch(struct subchannel_id schid, struct schib *addr) : "+d" (ccode), "=m" (*addr) : "d" (reg1), "a" (addr) : "cc"); + trace_s390_cio_stsch(schid, addr, ccode); + return ccode; } @@ -42,6 +45,8 @@ static inline int msch(struct subchannel_id schid, struct schib *addr) : "+d" (ccode) : "d" (reg1), "a" (addr), "m" (*addr) : "cc"); + trace_s390_cio_msch(schid, addr, ccode); + return ccode; } @@ -57,6 +62,8 @@ static inline int tsch(struct subchannel_id schid, struct irb *addr) : "=d" (ccode), "=m" (*addr) : "d" (reg1), "a" (addr) : "cc"); + trace_s390_cio_tsch(schid, addr, ccode); + return ccode; } @@ -74,6 +81,8 @@ static inline int ssch(struct subchannel_id schid, union orb *addr) : "+d" (ccode) : "d" (reg1), "a" (addr), "m" (*addr) : "cc", "memory"); + trace_s390_cio_ssch(schid, addr, ccode); + return ccode; } @@ -89,6 +98,8 @@ static inline int csch(struct subchannel_id schid) : "=d" (ccode) : "d" (reg1) : "cc"); + trace_s390_cio_csch(schid, ccode); + return ccode; } @@ -103,6 +114,8 @@ static inline int tpi(struct tpi_info *addr) : "=d" (ccode), "=m" (*addr) : "a" (addr) : "cc"); + trace_s390_cio_tpi(addr, ccode); + return ccode; } @@ -118,6 +131,8 @@ static inline int chsc(void *chsc_area) : "=d" (cc), "=m" (*(addr_type *) chsc_area) : "d" (chsc_area), "m" (*(addr_type *) chsc_area) : "cc"); + trace_s390_cio_chsc(chsc_area, cc); + return cc; } @@ -132,6 +147,8 @@ static inline int rchp(struct chp_id chpid) " ipm %0\n" " srl %0,28" : "=d" (ccode) : "d" (reg1) : "cc"); + trace_s390_cio_rchp(chpid, ccode); + return ccode; } @@ -147,6 +164,8 @@ static inline int rsch(struct subchannel_id schid) : "=d" (ccode) : "d" (reg1) : "cc", "memory"); + trace_s390_cio_rsch(schid, ccode); + return ccode; } @@ -162,6 +181,8 @@ static inline int hsch(struct subchannel_id schid) : "=d" (ccode) : "d" (reg1) : "cc"); + trace_s390_cio_hsch(schid, ccode); + return ccode; } @@ -177,6 +198,8 @@ static inline int xsch(struct subchannel_id schid) : "=d" (ccode) : "d" (reg1) : "cc"); + trace_s390_cio_xsch(schid, ccode); + return ccode; } @@ -191,6 +214,8 @@ static inline int stcrw(struct crw *crw) : "=d" (ccode), "=m" (*crw) : "a" (crw) : "cc"); + trace_s390_cio_stcrw(crw, ccode); + return ccode; } diff --git a/drivers/s390/cio/trace.c b/drivers/s390/cio/trace.c new file mode 100644 index 000000000000..8e706669ac8b --- /dev/null +++ b/drivers/s390/cio/trace.c @@ -0,0 +1,24 @@ +/* + * Tracepoint definitions for s390_cio + * + * Copyright IBM Corp. 2015 + * Author(s): Peter Oberparleiter <oberpar@linux.vnet.ibm.com> + */ + +#include <asm/crw.h> +#include "cio.h" + +#define CREATE_TRACE_POINTS +#include "trace.h" + +EXPORT_TRACEPOINT_SYMBOL(s390_cio_stsch); +EXPORT_TRACEPOINT_SYMBOL(s390_cio_msch); +EXPORT_TRACEPOINT_SYMBOL(s390_cio_tsch); +EXPORT_TRACEPOINT_SYMBOL(s390_cio_tpi); +EXPORT_TRACEPOINT_SYMBOL(s390_cio_ssch); +EXPORT_TRACEPOINT_SYMBOL(s390_cio_csch); +EXPORT_TRACEPOINT_SYMBOL(s390_cio_hsch); +EXPORT_TRACEPOINT_SYMBOL(s390_cio_xsch); +EXPORT_TRACEPOINT_SYMBOL(s390_cio_rsch); +EXPORT_TRACEPOINT_SYMBOL(s390_cio_rchp); +EXPORT_TRACEPOINT_SYMBOL(s390_cio_chsc); diff --git a/drivers/s390/cio/trace.h b/drivers/s390/cio/trace.h new file mode 100644 index 000000000000..5b807a09f21b --- /dev/null +++ b/drivers/s390/cio/trace.h @@ -0,0 +1,363 @@ +/* + * Tracepoint header for the s390 Common I/O layer (CIO) + * + * Copyright IBM Corp. 2015 + * Author(s): Peter Oberparleiter <oberpar@linux.vnet.ibm.com> + */ + +#include <linux/kernel.h> +#include <asm/crw.h> +#include <uapi/asm/chpid.h> +#include <uapi/asm/schid.h> +#include "cio.h" +#include "orb.h" + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM s390 + +#if !defined(_TRACE_S390_CIO_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_S390_CIO_H + +#include <linux/tracepoint.h> + +DECLARE_EVENT_CLASS(s390_class_schib, + TP_PROTO(struct subchannel_id schid, struct schib *schib, int cc), + TP_ARGS(schid, schib, cc), + TP_STRUCT__entry( + __field(u8, cssid) + __field(u8, ssid) + __field(u16, schno) + __field(u16, devno) + __field_struct(struct schib, schib) + __field(int, cc) + ), + TP_fast_assign( + __entry->cssid = schid.cssid; + __entry->ssid = schid.ssid; + __entry->schno = schid.sch_no; + __entry->devno = schib->pmcw.dev; + __entry->schib = *schib; + __entry->cc = cc; + ), + TP_printk("schid=%x.%x.%04x cc=%d ena=%d st=%d dnv=%d dev=%04x " + "lpm=0x%02x pnom=0x%02x lpum=0x%02x pim=0x%02x pam=0x%02x " + "pom=0x%02x chpids=%016llx", + __entry->cssid, __entry->ssid, __entry->schno, __entry->cc, + __entry->schib.pmcw.ena, __entry->schib.pmcw.st, + __entry->schib.pmcw.dnv, __entry->schib.pmcw.dev, + __entry->schib.pmcw.lpm, __entry->schib.pmcw.pnom, + __entry->schib.pmcw.lpum, __entry->schib.pmcw.pim, + __entry->schib.pmcw.pam, __entry->schib.pmcw.pom, + *((u64 *) __entry->schib.pmcw.chpid) + ) +); + +/** + * s390_cio_stsch - Store Subchannel instruction (STSCH) was performed + * @schid: Subchannel ID + * @schib: Subchannel-Information block + * @cc: Condition code + */ +DEFINE_EVENT(s390_class_schib, s390_cio_stsch, + TP_PROTO(struct subchannel_id schid, struct schib *schib, int cc), + TP_ARGS(schid, schib, cc) +); + +/** + * s390_cio_msch - Modify Subchannel instruction (MSCH) was performed + * @schid: Subchannel ID + * @schib: Subchannel-Information block + * @cc: Condition code + */ +DEFINE_EVENT(s390_class_schib, s390_cio_msch, + TP_PROTO(struct subchannel_id schid, struct schib *schib, int cc), + TP_ARGS(schid, schib, cc) +); + +/** + * s390_cio_tsch - Test Subchannel instruction (TSCH) was performed + * @schid: Subchannel ID + * @irb: Interruption-Response Block + * @cc: Condition code + */ +TRACE_EVENT(s390_cio_tsch, + TP_PROTO(struct subchannel_id schid, struct irb *irb, int cc), + TP_ARGS(schid, irb, cc), + TP_STRUCT__entry( + __field(u8, cssid) + __field(u8, ssid) + __field(u16, schno) + __field_struct(struct irb, irb) + __field(int, cc) + ), + TP_fast_assign( + __entry->cssid = schid.cssid; + __entry->ssid = schid.ssid; + __entry->schno = schid.sch_no; + __entry->irb = *irb; + __entry->cc = cc; + ), + TP_printk("schid=%x.%x.%04x cc=%d dcc=%d pno=%d fctl=0x%x actl=0x%x " + "stctl=0x%x dstat=0x%x cstat=0x%x", + __entry->cssid, __entry->ssid, __entry->schno, __entry->cc, + scsw_cc(&__entry->irb.scsw), scsw_pno(&__entry->irb.scsw), + scsw_fctl(&__entry->irb.scsw), scsw_actl(&__entry->irb.scsw), + scsw_stctl(&__entry->irb.scsw), + scsw_dstat(&__entry->irb.scsw), scsw_cstat(&__entry->irb.scsw) + ) +); + +/** + * s390_cio_tpi - Test Pending Interruption instruction (TPI) was performed + * @addr: Address of the I/O interruption code or %NULL + * @cc: Condition code + */ +TRACE_EVENT(s390_cio_tpi, + TP_PROTO(struct tpi_info *addr, int cc), + TP_ARGS(addr, cc), + TP_STRUCT__entry( + __field(int, cc) + __field_struct(struct tpi_info, tpi_info) + __field(u8, cssid) + __field(u8, ssid) + __field(u16, schno) + ), + TP_fast_assign( + __entry->cc = cc; + if (cc != 0) + memset(&__entry->tpi_info, 0, sizeof(struct tpi_info)); + else if (addr) + __entry->tpi_info = *addr; + else { + memcpy(&__entry->tpi_info, &S390_lowcore.subchannel_id, + sizeof(struct tpi_info)); + } + __entry->cssid = __entry->tpi_info.schid.cssid; + __entry->ssid = __entry->tpi_info.schid.ssid; + __entry->schno = __entry->tpi_info.schid.sch_no; + ), + TP_printk("schid=%x.%x.%04x cc=%d a=%d isc=%d type=%d", + __entry->cssid, __entry->ssid, __entry->schno, __entry->cc, + __entry->tpi_info.adapter_IO, __entry->tpi_info.isc, + __entry->tpi_info.type + ) +); + +/** + * s390_cio_ssch - Start Subchannel instruction (SSCH) was performed + * @schid: Subchannel ID + * @orb: Operation-Request Block + * @cc: Condition code + */ +TRACE_EVENT(s390_cio_ssch, + TP_PROTO(struct subchannel_id schid, union orb *orb, int cc), + TP_ARGS(schid, orb, cc), + TP_STRUCT__entry( + __field(u8, cssid) + __field(u8, ssid) + __field(u16, schno) + __field_struct(union orb, orb) + __field(int, cc) + ), + TP_fast_assign( + __entry->cssid = schid.cssid; + __entry->ssid = schid.ssid; + __entry->schno = schid.sch_no; + __entry->orb = *orb; + __entry->cc = cc; + ), + TP_printk("schid=%x.%x.%04x cc=%d", __entry->cssid, __entry->ssid, + __entry->schno, __entry->cc + ) +); + +DECLARE_EVENT_CLASS(s390_class_schid, + TP_PROTO(struct subchannel_id schid, int cc), + TP_ARGS(schid, cc), + TP_STRUCT__entry( + __field(u8, cssid) + __field(u8, ssid) + __field(u16, schno) + __field(int, cc) + ), + TP_fast_assign( + __entry->cssid = schid.cssid; + __entry->ssid = schid.ssid; + __entry->schno = schid.sch_no; + __entry->cc = cc; + ), + TP_printk("schid=%x.%x.%04x cc=%d", __entry->cssid, __entry->ssid, + __entry->schno, __entry->cc + ) +); + +/** + * s390_cio_csch - Clear Subchannel instruction (CSCH) was performed + * @schid: Subchannel ID + * @cc: Condition code + */ +DEFINE_EVENT(s390_class_schid, s390_cio_csch, + TP_PROTO(struct subchannel_id schid, int cc), + TP_ARGS(schid, cc) +); + +/** + * s390_cio_hsch - Halt Subchannel instruction (HSCH) was performed + * @schid: Subchannel ID + * @cc: Condition code + */ +DEFINE_EVENT(s390_class_schid, s390_cio_hsch, + TP_PROTO(struct subchannel_id schid, int cc), + TP_ARGS(schid, cc) +); + +/** + * s390_cio_xsch - Cancel Subchannel instruction (XSCH) was performed + * @schid: Subchannel ID + * @cc: Condition code + */ +DEFINE_EVENT(s390_class_schid, s390_cio_xsch, + TP_PROTO(struct subchannel_id schid, int cc), + TP_ARGS(schid, cc) +); + +/** + * s390_cio_rsch - Resume Subchannel instruction (RSCH) was performed + * @schid: Subchannel ID + * @cc: Condition code + */ +DEFINE_EVENT(s390_class_schid, s390_cio_rsch, + TP_PROTO(struct subchannel_id schid, int cc), + TP_ARGS(schid, cc) +); + +/** + * s390_cio_rchp - Reset Channel Path (RCHP) instruction was performed + * @chpid: Channel-Path Identifier + * @cc: Condition code + */ +TRACE_EVENT(s390_cio_rchp, + TP_PROTO(struct chp_id chpid, int cc), + TP_ARGS(chpid, cc), + TP_STRUCT__entry( + __field(u8, cssid) + __field(u8, id) + __field(int, cc) + ), + TP_fast_assign( + __entry->cssid = chpid.cssid; + __entry->id = chpid.id; + __entry->cc = cc; + ), + TP_printk("chpid=%x.%02x cc=%d", __entry->cssid, __entry->id, + __entry->cc + ) +); + +#define CHSC_MAX_REQUEST_LEN 64 +#define CHSC_MAX_RESPONSE_LEN 64 + +/** + * s390_cio_chsc - Channel Subsystem Call (CHSC) instruction was performed + * @chsc: CHSC block + * @cc: Condition code + */ +TRACE_EVENT(s390_cio_chsc, + TP_PROTO(struct chsc_header *chsc, int cc), + TP_ARGS(chsc, cc), + TP_STRUCT__entry( + __field(int, cc) + __field(u16, code) + __field(u16, rcode) + __array(u8, request, CHSC_MAX_REQUEST_LEN) + __array(u8, response, CHSC_MAX_RESPONSE_LEN) + ), + TP_fast_assign( + __entry->cc = cc; + __entry->code = chsc->code; + memcpy(&entry->request, chsc, + min_t(u16, chsc->length, CHSC_MAX_REQUEST_LEN)); + chsc = (struct chsc_header *) ((char *) chsc + chsc->length); + __entry->rcode = chsc->code; + memcpy(&entry->response, chsc, + min_t(u16, chsc->length, CHSC_MAX_RESPONSE_LEN)); + ), + TP_printk("code=0x%04x cc=%d rcode=0x%04x", __entry->code, + __entry->cc, __entry->rcode) +); + +/** + * s390_cio_interrupt - An I/O interrupt occurred + * @tpi_info: Address of the I/O interruption code + */ +TRACE_EVENT(s390_cio_interrupt, + TP_PROTO(struct tpi_info *tpi_info), + TP_ARGS(tpi_info), + TP_STRUCT__entry( + __field_struct(struct tpi_info, tpi_info) + __field(u8, cssid) + __field(u8, ssid) + __field(u16, schno) + ), + TP_fast_assign( + __entry->tpi_info = *tpi_info; + __entry->cssid = __entry->tpi_info.schid.cssid; + __entry->ssid = __entry->tpi_info.schid.ssid; + __entry->schno = __entry->tpi_info.schid.sch_no; + ), + TP_printk("schid=%x.%x.%04x isc=%d type=%d", + __entry->cssid, __entry->ssid, __entry->schno, + __entry->tpi_info.isc, __entry->tpi_info.type + ) +); + +/** + * s390_cio_adapter_int - An adapter interrupt occurred + * @tpi_info: Address of the I/O interruption code + */ +TRACE_EVENT(s390_cio_adapter_int, + TP_PROTO(struct tpi_info *tpi_info), + TP_ARGS(tpi_info), + TP_STRUCT__entry( + __field_struct(struct tpi_info, tpi_info) + ), + TP_fast_assign( + __entry->tpi_info = *tpi_info; + ), + TP_printk("isc=%d", __entry->tpi_info.isc) +); + +/** + * s390_cio_stcrw - Store Channel Report Word (STCRW) was performed + * @crw: Channel Report Word + * @cc: Condition code + */ +TRACE_EVENT(s390_cio_stcrw, + TP_PROTO(struct crw *crw, int cc), + TP_ARGS(crw, cc), + TP_STRUCT__entry( + __field_struct(struct crw, crw) + __field(int, cc) + ), + TP_fast_assign( + __entry->crw = *crw; + __entry->cc = cc; + ), + TP_printk("cc=%d slct=%d oflw=%d chn=%d rsc=%d anc=%d erc=0x%x " + "rsid=0x%x", + __entry->cc, __entry->crw.slct, __entry->crw.oflw, + __entry->crw.chn, __entry->crw.rsc, __entry->crw.anc, + __entry->crw.erc, __entry->crw.rsid + ) +); + +#endif /* _TRACE_S390_CIO_H */ + +/* This part must be outside protection */ +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH . + +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_FILE trace + +#include <trace/define_trace.h> |