Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 #include <stdio.h>
0003 #include <string.h>
0004 #include <inttypes.h>
0005 #include "event-parse.h"
0006 #include "trace-seq.h"
0007 
0008 typedef unsigned long sector_t;
0009 typedef uint64_t u64;
0010 typedef unsigned int u32;
0011 
0012 /*
0013  *      SCSI opcodes
0014  */
0015 #define TEST_UNIT_READY         0x00
0016 #define REZERO_UNIT         0x01
0017 #define REQUEST_SENSE           0x03
0018 #define FORMAT_UNIT         0x04
0019 #define READ_BLOCK_LIMITS       0x05
0020 #define REASSIGN_BLOCKS         0x07
0021 #define INITIALIZE_ELEMENT_STATUS   0x07
0022 #define READ_6              0x08
0023 #define WRITE_6             0x0a
0024 #define SEEK_6              0x0b
0025 #define READ_REVERSE            0x0f
0026 #define WRITE_FILEMARKS         0x10
0027 #define SPACE               0x11
0028 #define INQUIRY             0x12
0029 #define RECOVER_BUFFERED_DATA       0x14
0030 #define MODE_SELECT         0x15
0031 #define RESERVE             0x16
0032 #define RELEASE             0x17
0033 #define COPY                0x18
0034 #define ERASE               0x19
0035 #define MODE_SENSE          0x1a
0036 #define START_STOP          0x1b
0037 #define RECEIVE_DIAGNOSTIC      0x1c
0038 #define SEND_DIAGNOSTIC         0x1d
0039 #define ALLOW_MEDIUM_REMOVAL        0x1e
0040 
0041 #define READ_FORMAT_CAPACITIES      0x23
0042 #define SET_WINDOW          0x24
0043 #define READ_CAPACITY           0x25
0044 #define READ_10             0x28
0045 #define WRITE_10            0x2a
0046 #define SEEK_10             0x2b
0047 #define POSITION_TO_ELEMENT     0x2b
0048 #define WRITE_VERIFY            0x2e
0049 #define VERIFY              0x2f
0050 #define SEARCH_HIGH         0x30
0051 #define SEARCH_EQUAL            0x31
0052 #define SEARCH_LOW          0x32
0053 #define SET_LIMITS          0x33
0054 #define PRE_FETCH           0x34
0055 #define READ_POSITION           0x34
0056 #define SYNCHRONIZE_CACHE       0x35
0057 #define LOCK_UNLOCK_CACHE       0x36
0058 #define READ_DEFECT_DATA        0x37
0059 #define MEDIUM_SCAN         0x38
0060 #define COMPARE             0x39
0061 #define COPY_VERIFY         0x3a
0062 #define WRITE_BUFFER            0x3b
0063 #define READ_BUFFER         0x3c
0064 #define UPDATE_BLOCK            0x3d
0065 #define READ_LONG           0x3e
0066 #define WRITE_LONG          0x3f
0067 #define CHANGE_DEFINITION       0x40
0068 #define WRITE_SAME          0x41
0069 #define UNMAP               0x42
0070 #define READ_TOC            0x43
0071 #define READ_HEADER         0x44
0072 #define GET_EVENT_STATUS_NOTIFICATION   0x4a
0073 #define LOG_SELECT          0x4c
0074 #define LOG_SENSE           0x4d
0075 #define XDWRITEREAD_10          0x53
0076 #define MODE_SELECT_10          0x55
0077 #define RESERVE_10          0x56
0078 #define RELEASE_10          0x57
0079 #define MODE_SENSE_10           0x5a
0080 #define PERSISTENT_RESERVE_IN       0x5e
0081 #define PERSISTENT_RESERVE_OUT      0x5f
0082 #define VARIABLE_LENGTH_CMD     0x7f
0083 #define REPORT_LUNS         0xa0
0084 #define SECURITY_PROTOCOL_IN        0xa2
0085 #define MAINTENANCE_IN          0xa3
0086 #define MAINTENANCE_OUT         0xa4
0087 #define MOVE_MEDIUM         0xa5
0088 #define EXCHANGE_MEDIUM         0xa6
0089 #define READ_12             0xa8
0090 #define SERVICE_ACTION_OUT_12       0xa9
0091 #define WRITE_12            0xaa
0092 #define SERVICE_ACTION_IN_12        0xab
0093 #define WRITE_VERIFY_12         0xae
0094 #define VERIFY_12           0xaf
0095 #define SEARCH_HIGH_12          0xb0
0096 #define SEARCH_EQUAL_12         0xb1
0097 #define SEARCH_LOW_12           0xb2
0098 #define SECURITY_PROTOCOL_OUT       0xb5
0099 #define READ_ELEMENT_STATUS     0xb8
0100 #define SEND_VOLUME_TAG         0xb6
0101 #define WRITE_LONG_2            0xea
0102 #define EXTENDED_COPY           0x83
0103 #define RECEIVE_COPY_RESULTS        0x84
0104 #define ACCESS_CONTROL_IN       0x86
0105 #define ACCESS_CONTROL_OUT      0x87
0106 #define READ_16             0x88
0107 #define WRITE_16            0x8a
0108 #define READ_ATTRIBUTE          0x8c
0109 #define WRITE_ATTRIBUTE         0x8d
0110 #define VERIFY_16           0x8f
0111 #define SYNCHRONIZE_CACHE_16        0x91
0112 #define WRITE_SAME_16           0x93
0113 #define SERVICE_ACTION_BIDIRECTIONAL    0x9d
0114 #define SERVICE_ACTION_IN_16        0x9e
0115 #define SERVICE_ACTION_OUT_16       0x9f
0116 /* values for service action in */
0117 #define SAI_READ_CAPACITY_16        0x10
0118 #define SAI_GET_LBA_STATUS      0x12
0119 /* values for VARIABLE_LENGTH_CMD service action codes
0120  * see spc4r17 Section D.3.5, table D.7 and D.8 */
0121 #define VLC_SA_RECEIVE_CREDENTIAL   0x1800
0122 /* values for maintenance in */
0123 #define MI_REPORT_IDENTIFYING_INFORMATION       0x05
0124 #define MI_REPORT_TARGET_PGS                0x0a
0125 #define MI_REPORT_ALIASES               0x0b
0126 #define MI_REPORT_SUPPORTED_OPERATION_CODES     0x0c
0127 #define MI_REPORT_SUPPORTED_TASK_MANAGEMENT_FUNCTIONS   0x0d
0128 #define MI_REPORT_PRIORITY              0x0e
0129 #define MI_REPORT_TIMESTAMP             0x0f
0130 #define MI_MANAGEMENT_PROTOCOL_IN           0x10
0131 /* value for MI_REPORT_TARGET_PGS ext header */
0132 #define MI_EXT_HDR_PARAM_FMT        0x20
0133 /* values for maintenance out */
0134 #define MO_SET_IDENTIFYING_INFORMATION  0x06
0135 #define MO_SET_TARGET_PGS       0x0a
0136 #define MO_CHANGE_ALIASES       0x0b
0137 #define MO_SET_PRIORITY         0x0e
0138 #define MO_SET_TIMESTAMP        0x0f
0139 #define MO_MANAGEMENT_PROTOCOL_OUT  0x10
0140 /* values for variable length command */
0141 #define XDREAD_32           0x03
0142 #define XDWRITE_32          0x04
0143 #define XPWRITE_32          0x06
0144 #define XDWRITEREAD_32          0x07
0145 #define READ_32             0x09
0146 #define VERIFY_32           0x0a
0147 #define WRITE_32            0x0b
0148 #define WRITE_SAME_32           0x0d
0149 
0150 #define SERVICE_ACTION16(cdb) (cdb[1] & 0x1f)
0151 #define SERVICE_ACTION32(cdb) ((cdb[8] << 8) | cdb[9])
0152 
0153 static const char *
0154 scsi_trace_misc(struct trace_seq *, unsigned char *, int);
0155 
0156 static const char *
0157 scsi_trace_rw6(struct trace_seq *p, unsigned char *cdb, int len)
0158 {
0159     const char *ret = p->buffer + p->len;
0160     sector_t lba = 0, txlen = 0;
0161 
0162     lba |= ((cdb[1] & 0x1F) << 16);
0163     lba |=  (cdb[2] << 8);
0164     lba |=   cdb[3];
0165     txlen = cdb[4];
0166 
0167     trace_seq_printf(p, "lba=%llu txlen=%llu",
0168              (unsigned long long)lba, (unsigned long long)txlen);
0169     trace_seq_putc(p, 0);
0170     return ret;
0171 }
0172 
0173 static const char *
0174 scsi_trace_rw10(struct trace_seq *p, unsigned char *cdb, int len)
0175 {
0176     const char *ret = p->buffer + p->len;
0177     sector_t lba = 0, txlen = 0;
0178 
0179     lba |= (cdb[2] << 24);
0180     lba |= (cdb[3] << 16);
0181     lba |= (cdb[4] << 8);
0182     lba |=  cdb[5];
0183     txlen |= (cdb[7] << 8);
0184     txlen |=  cdb[8];
0185 
0186     trace_seq_printf(p, "lba=%llu txlen=%llu protect=%u",
0187              (unsigned long long)lba, (unsigned long long)txlen,
0188              cdb[1] >> 5);
0189 
0190     if (cdb[0] == WRITE_SAME)
0191         trace_seq_printf(p, " unmap=%u", cdb[1] >> 3 & 1);
0192 
0193     trace_seq_putc(p, 0);
0194     return ret;
0195 }
0196 
0197 static const char *
0198 scsi_trace_rw12(struct trace_seq *p, unsigned char *cdb, int len)
0199 {
0200     const char *ret = p->buffer + p->len;
0201     sector_t lba = 0, txlen = 0;
0202 
0203     lba |= (cdb[2] << 24);
0204     lba |= (cdb[3] << 16);
0205     lba |= (cdb[4] << 8);
0206     lba |=  cdb[5];
0207     txlen |= (cdb[6] << 24);
0208     txlen |= (cdb[7] << 16);
0209     txlen |= (cdb[8] << 8);
0210     txlen |=  cdb[9];
0211 
0212     trace_seq_printf(p, "lba=%llu txlen=%llu protect=%u",
0213              (unsigned long long)lba, (unsigned long long)txlen,
0214              cdb[1] >> 5);
0215     trace_seq_putc(p, 0);
0216     return ret;
0217 }
0218 
0219 static const char *
0220 scsi_trace_rw16(struct trace_seq *p, unsigned char *cdb, int len)
0221 {
0222     const char *ret = p->buffer + p->len;
0223     sector_t lba = 0, txlen = 0;
0224 
0225     lba |= ((u64)cdb[2] << 56);
0226     lba |= ((u64)cdb[3] << 48);
0227     lba |= ((u64)cdb[4] << 40);
0228     lba |= ((u64)cdb[5] << 32);
0229     lba |= (cdb[6] << 24);
0230     lba |= (cdb[7] << 16);
0231     lba |= (cdb[8] << 8);
0232     lba |=  cdb[9];
0233     txlen |= (cdb[10] << 24);
0234     txlen |= (cdb[11] << 16);
0235     txlen |= (cdb[12] << 8);
0236     txlen |=  cdb[13];
0237 
0238     trace_seq_printf(p, "lba=%llu txlen=%llu protect=%u",
0239              (unsigned long long)lba, (unsigned long long)txlen,
0240              cdb[1] >> 5);
0241 
0242     if (cdb[0] == WRITE_SAME_16)
0243         trace_seq_printf(p, " unmap=%u", cdb[1] >> 3 & 1);
0244 
0245     trace_seq_putc(p, 0);
0246     return ret;
0247 }
0248 
0249 static const char *
0250 scsi_trace_rw32(struct trace_seq *p, unsigned char *cdb, int len)
0251 {
0252     const char *ret = p->buffer + p->len, *cmd;
0253     sector_t lba = 0, txlen = 0;
0254     u32 ei_lbrt = 0;
0255 
0256     switch (SERVICE_ACTION32(cdb)) {
0257     case READ_32:
0258         cmd = "READ";
0259         break;
0260     case VERIFY_32:
0261         cmd = "VERIFY";
0262         break;
0263     case WRITE_32:
0264         cmd = "WRITE";
0265         break;
0266     case WRITE_SAME_32:
0267         cmd = "WRITE_SAME";
0268         break;
0269     default:
0270         trace_seq_printf(p, "UNKNOWN");
0271         goto out;
0272     }
0273 
0274     lba |= ((u64)cdb[12] << 56);
0275     lba |= ((u64)cdb[13] << 48);
0276     lba |= ((u64)cdb[14] << 40);
0277     lba |= ((u64)cdb[15] << 32);
0278     lba |= (cdb[16] << 24);
0279     lba |= (cdb[17] << 16);
0280     lba |= (cdb[18] << 8);
0281     lba |=  cdb[19];
0282     ei_lbrt |= (cdb[20] << 24);
0283     ei_lbrt |= (cdb[21] << 16);
0284     ei_lbrt |= (cdb[22] << 8);
0285     ei_lbrt |=  cdb[23];
0286     txlen |= (cdb[28] << 24);
0287     txlen |= (cdb[29] << 16);
0288     txlen |= (cdb[30] << 8);
0289     txlen |=  cdb[31];
0290 
0291     trace_seq_printf(p, "%s_32 lba=%llu txlen=%llu protect=%u ei_lbrt=%u",
0292              cmd, (unsigned long long)lba,
0293              (unsigned long long)txlen, cdb[10] >> 5, ei_lbrt);
0294 
0295     if (SERVICE_ACTION32(cdb) == WRITE_SAME_32)
0296         trace_seq_printf(p, " unmap=%u", cdb[10] >> 3 & 1);
0297 
0298 out:
0299     trace_seq_putc(p, 0);
0300     return ret;
0301 }
0302 
0303 static const char *
0304 scsi_trace_unmap(struct trace_seq *p, unsigned char *cdb, int len)
0305 {
0306     const char *ret = p->buffer + p->len;
0307     unsigned int regions = cdb[7] << 8 | cdb[8];
0308 
0309     trace_seq_printf(p, "regions=%u", (regions - 8) / 16);
0310     trace_seq_putc(p, 0);
0311     return ret;
0312 }
0313 
0314 static const char *
0315 scsi_trace_service_action_in(struct trace_seq *p, unsigned char *cdb, int len)
0316 {
0317     const char *ret = p->buffer + p->len, *cmd;
0318     sector_t lba = 0;
0319     u32 alloc_len = 0;
0320 
0321     switch (SERVICE_ACTION16(cdb)) {
0322     case SAI_READ_CAPACITY_16:
0323         cmd = "READ_CAPACITY_16";
0324         break;
0325     case SAI_GET_LBA_STATUS:
0326         cmd = "GET_LBA_STATUS";
0327         break;
0328     default:
0329         trace_seq_printf(p, "UNKNOWN");
0330         goto out;
0331     }
0332 
0333     lba |= ((u64)cdb[2] << 56);
0334     lba |= ((u64)cdb[3] << 48);
0335     lba |= ((u64)cdb[4] << 40);
0336     lba |= ((u64)cdb[5] << 32);
0337     lba |= (cdb[6] << 24);
0338     lba |= (cdb[7] << 16);
0339     lba |= (cdb[8] << 8);
0340     lba |=  cdb[9];
0341     alloc_len |= (cdb[10] << 24);
0342     alloc_len |= (cdb[11] << 16);
0343     alloc_len |= (cdb[12] << 8);
0344     alloc_len |=  cdb[13];
0345 
0346     trace_seq_printf(p, "%s lba=%llu alloc_len=%u", cmd,
0347              (unsigned long long)lba, alloc_len);
0348 
0349 out:
0350     trace_seq_putc(p, 0);
0351     return ret;
0352 }
0353 
0354 static const char *
0355 scsi_trace_varlen(struct trace_seq *p, unsigned char *cdb, int len)
0356 {
0357     switch (SERVICE_ACTION32(cdb)) {
0358     case READ_32:
0359     case VERIFY_32:
0360     case WRITE_32:
0361     case WRITE_SAME_32:
0362         return scsi_trace_rw32(p, cdb, len);
0363     default:
0364         return scsi_trace_misc(p, cdb, len);
0365     }
0366 }
0367 
0368 static const char *
0369 scsi_trace_misc(struct trace_seq *p, unsigned char *cdb, int len)
0370 {
0371     const char *ret = p->buffer + p->len;
0372 
0373     trace_seq_printf(p, "-");
0374     trace_seq_putc(p, 0);
0375     return ret;
0376 }
0377 
0378 const char *
0379 scsi_trace_parse_cdb(struct trace_seq *p, unsigned char *cdb, int len)
0380 {
0381     switch (cdb[0]) {
0382     case READ_6:
0383     case WRITE_6:
0384         return scsi_trace_rw6(p, cdb, len);
0385     case READ_10:
0386     case VERIFY:
0387     case WRITE_10:
0388     case WRITE_SAME:
0389         return scsi_trace_rw10(p, cdb, len);
0390     case READ_12:
0391     case VERIFY_12:
0392     case WRITE_12:
0393         return scsi_trace_rw12(p, cdb, len);
0394     case READ_16:
0395     case VERIFY_16:
0396     case WRITE_16:
0397     case WRITE_SAME_16:
0398         return scsi_trace_rw16(p, cdb, len);
0399     case UNMAP:
0400         return scsi_trace_unmap(p, cdb, len);
0401     case SERVICE_ACTION_IN_16:
0402         return scsi_trace_service_action_in(p, cdb, len);
0403     case VARIABLE_LENGTH_CMD:
0404         return scsi_trace_varlen(p, cdb, len);
0405     default:
0406         return scsi_trace_misc(p, cdb, len);
0407     }
0408 }
0409 
0410 unsigned long long process_scsi_trace_parse_cdb(struct trace_seq *s,
0411                         unsigned long long *args)
0412 {
0413     scsi_trace_parse_cdb(s, (unsigned char *) (unsigned long) args[1], args[2]);
0414     return 0;
0415 }
0416 
0417 int TEP_PLUGIN_LOADER(struct tep_handle *tep)
0418 {
0419     tep_register_print_function(tep,
0420                     process_scsi_trace_parse_cdb,
0421                     TEP_FUNC_ARG_STRING,
0422                     "scsi_trace_parse_cdb",
0423                     TEP_FUNC_ARG_PTR,
0424                     TEP_FUNC_ARG_PTR,
0425                     TEP_FUNC_ARG_INT,
0426                     TEP_FUNC_ARG_VOID);
0427     return 0;
0428 }
0429 
0430 void TEP_PLUGIN_UNLOADER(struct tep_handle *tep)
0431 {
0432     tep_unregister_print_function(tep, process_scsi_trace_parse_cdb,
0433                       "scsi_trace_parse_cdb");
0434 }