cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

efct_unsol.c (12700B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright (C) 2021 Broadcom. All Rights Reserved. The term
      4 * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
      5 */
      6
      7#include "efct_driver.h"
      8#include "efct_unsol.h"
      9
     10#define frame_printf(efct, hdr, fmt, ...) \
     11	do { \
     12		char s_id_text[16]; \
     13		efc_node_fcid_display(ntoh24((hdr)->fh_s_id), \
     14			s_id_text, sizeof(s_id_text)); \
     15		efc_log_debug(efct, "[%06x.%s] %02x/%04x/%04x: " fmt, \
     16			ntoh24((hdr)->fh_d_id), s_id_text, \
     17			(hdr)->fh_r_ctl, be16_to_cpu((hdr)->fh_ox_id), \
     18			be16_to_cpu((hdr)->fh_rx_id), ##__VA_ARGS__); \
     19	} while (0)
     20
     21static struct efct_node *
     22efct_node_find(struct efct *efct, u32 port_id, u32 node_id)
     23{
     24	struct efct_node *node;
     25	u64 id = (u64)port_id << 32 | node_id;
     26
     27	/*
     28	 * During node shutdown, Lookup will be removed first,
     29	 * before announcing to backend. So, no new IOs will be allowed
     30	 */
     31	/* Find a target node, given s_id and d_id */
     32	node = xa_load(&efct->lookup, id);
     33	if (node)
     34		kref_get(&node->ref);
     35
     36	return node;
     37}
     38
     39static int
     40efct_dispatch_frame(struct efct *efct, struct efc_hw_sequence *seq)
     41{
     42	struct efct_node *node;
     43	struct fc_frame_header *hdr;
     44	u32 s_id, d_id;
     45
     46	hdr = seq->header->dma.virt;
     47
     48	/* extract the s_id and d_id */
     49	s_id = ntoh24(hdr->fh_s_id);
     50	d_id = ntoh24(hdr->fh_d_id);
     51
     52	if (!(hdr->fh_type == FC_TYPE_FCP || hdr->fh_type == FC_TYPE_BLS))
     53		return -EIO;
     54
     55	if (hdr->fh_type == FC_TYPE_FCP) {
     56		node = efct_node_find(efct, d_id, s_id);
     57		if (!node) {
     58			efc_log_err(efct,
     59				    "Node not found, drop cmd d_id:%x s_id:%x\n",
     60				    d_id, s_id);
     61			efct_hw_sequence_free(&efct->hw, seq);
     62			return 0;
     63		}
     64
     65		efct_dispatch_fcp_cmd(node, seq);
     66	} else {
     67		node = efct_node_find(efct, d_id, s_id);
     68		if (!node) {
     69			efc_log_err(efct, "ABTS: Node not found, d_id:%x s_id:%x\n",
     70				    d_id, s_id);
     71			return -EIO;
     72		}
     73
     74		efc_log_err(efct, "Received ABTS for Node:%p\n", node);
     75		efct_node_recv_abts_frame(node, seq);
     76	}
     77
     78	kref_put(&node->ref, node->release);
     79	efct_hw_sequence_free(&efct->hw, seq);
     80	return 0;
     81}
     82
     83int
     84efct_unsolicited_cb(void *arg, struct efc_hw_sequence *seq)
     85{
     86	struct efct *efct = arg;
     87
     88	/* Process FCP command */
     89	if (!efct_dispatch_frame(efct, seq))
     90		return 0;
     91
     92	/* Forward frame to discovery lib */
     93	efc_dispatch_frame(efct->efcport, seq);
     94	return 0;
     95}
     96
     97static int
     98efct_fc_tmf_rejected_cb(struct efct_io *io,
     99			enum efct_scsi_io_status scsi_status,
    100			u32 flags, void *arg)
    101{
    102	efct_scsi_io_free(io);
    103	return 0;
    104}
    105
    106static void
    107efct_dispatch_unsol_tmf(struct efct_io *io, u8 tm_flags, u32 lun)
    108{
    109	u32 i;
    110	struct {
    111		u32 mask;
    112		enum efct_scsi_tmf_cmd cmd;
    113	} tmflist[] = {
    114	{FCP_TMF_ABT_TASK_SET, EFCT_SCSI_TMF_ABORT_TASK_SET},
    115	{FCP_TMF_CLR_TASK_SET, EFCT_SCSI_TMF_CLEAR_TASK_SET},
    116	{FCP_TMF_LUN_RESET, EFCT_SCSI_TMF_LOGICAL_UNIT_RESET},
    117	{FCP_TMF_TGT_RESET, EFCT_SCSI_TMF_TARGET_RESET},
    118	{FCP_TMF_CLR_ACA, EFCT_SCSI_TMF_CLEAR_ACA} };
    119
    120	io->exp_xfer_len = 0;
    121
    122	for (i = 0; i < ARRAY_SIZE(tmflist); i++) {
    123		if (tmflist[i].mask & tm_flags) {
    124			io->tmf_cmd = tmflist[i].cmd;
    125			efct_scsi_recv_tmf(io, lun, tmflist[i].cmd, NULL, 0);
    126			break;
    127		}
    128	}
    129	if (i == ARRAY_SIZE(tmflist)) {
    130		/* Not handled */
    131		efc_log_err(io->node->efct, "TMF x%x rejected\n", tm_flags);
    132		efct_scsi_send_tmf_resp(io, EFCT_SCSI_TMF_FUNCTION_REJECTED,
    133					NULL, efct_fc_tmf_rejected_cb, NULL);
    134	}
    135}
    136
    137static int
    138efct_validate_fcp_cmd(struct efct *efct, struct efc_hw_sequence *seq)
    139{
    140	/*
    141	 * If we received less than FCP_CMND_IU bytes, assume that the frame is
    142	 * corrupted in some way and drop it.
    143	 * This was seen when jamming the FCTL
    144	 * fill bytes field.
    145	 */
    146	if (seq->payload->dma.len < sizeof(struct fcp_cmnd)) {
    147		struct fc_frame_header	*fchdr = seq->header->dma.virt;
    148
    149		efc_log_debug(efct,
    150			      "drop ox_id %04x payload (%zd) less than (%zd)\n",
    151			      be16_to_cpu(fchdr->fh_ox_id),
    152			      seq->payload->dma.len, sizeof(struct fcp_cmnd));
    153		return -EIO;
    154	}
    155	return 0;
    156}
    157
    158static void
    159efct_populate_io_fcp_cmd(struct efct_io *io, struct fcp_cmnd *cmnd,
    160			 struct fc_frame_header *fchdr, bool sit)
    161{
    162	io->init_task_tag = be16_to_cpu(fchdr->fh_ox_id);
    163	/* note, tgt_task_tag, hw_tag  set when HW io is allocated */
    164	io->exp_xfer_len = be32_to_cpu(cmnd->fc_dl);
    165	io->transferred = 0;
    166
    167	/* The upper 7 bits of CS_CTL is the frame priority thru the SAN.
    168	 * Our assertion here is, the priority given to a frame containing
    169	 * the FCP cmd should be the priority given to ALL frames contained
    170	 * in that IO. Thus we need to save the incoming CS_CTL here.
    171	 */
    172	if (ntoh24(fchdr->fh_f_ctl) & FC_FC_RES_B17)
    173		io->cs_ctl = fchdr->fh_cs_ctl;
    174	else
    175		io->cs_ctl = 0;
    176
    177	io->seq_init = sit;
    178}
    179
    180static u32
    181efct_get_flags_fcp_cmd(struct fcp_cmnd *cmnd)
    182{
    183	u32 flags = 0;
    184
    185	switch (cmnd->fc_pri_ta & FCP_PTA_MASK) {
    186	case FCP_PTA_SIMPLE:
    187		flags |= EFCT_SCSI_CMD_SIMPLE;
    188		break;
    189	case FCP_PTA_HEADQ:
    190		flags |= EFCT_SCSI_CMD_HEAD_OF_QUEUE;
    191		break;
    192	case FCP_PTA_ORDERED:
    193		flags |= EFCT_SCSI_CMD_ORDERED;
    194		break;
    195	case FCP_PTA_ACA:
    196		flags |= EFCT_SCSI_CMD_ACA;
    197		break;
    198	}
    199	if (cmnd->fc_flags & FCP_CFL_WRDATA)
    200		flags |= EFCT_SCSI_CMD_DIR_IN;
    201	if (cmnd->fc_flags & FCP_CFL_RDDATA)
    202		flags |= EFCT_SCSI_CMD_DIR_OUT;
    203
    204	return flags;
    205}
    206
    207static void
    208efct_sframe_common_send_cb(void *arg, u8 *cqe, int status)
    209{
    210	struct efct_hw_send_frame_context *ctx = arg;
    211	struct efct_hw *hw = ctx->hw;
    212
    213	/* Free WQ completion callback */
    214	efct_hw_reqtag_free(hw, ctx->wqcb);
    215
    216	/* Free sequence */
    217	efct_hw_sequence_free(hw, ctx->seq);
    218}
    219
    220static int
    221efct_sframe_common_send(struct efct_node *node,
    222			struct efc_hw_sequence *seq,
    223			enum fc_rctl r_ctl, u32 f_ctl,
    224			u8 type, void *payload, u32 payload_len)
    225{
    226	struct efct *efct = node->efct;
    227	struct efct_hw *hw = &efct->hw;
    228	int rc = 0;
    229	struct fc_frame_header *req_hdr = seq->header->dma.virt;
    230	struct fc_frame_header hdr;
    231	struct efct_hw_send_frame_context *ctx;
    232
    233	u32 heap_size = seq->payload->dma.size;
    234	uintptr_t heap_phys_base = seq->payload->dma.phys;
    235	u8 *heap_virt_base = seq->payload->dma.virt;
    236	u32 heap_offset = 0;
    237
    238	/* Build the FC header reusing the RQ header DMA buffer */
    239	memset(&hdr, 0, sizeof(hdr));
    240	hdr.fh_r_ctl = r_ctl;
    241	/* send it back to whomever sent it to us */
    242	memcpy(hdr.fh_d_id, req_hdr->fh_s_id, sizeof(hdr.fh_d_id));
    243	memcpy(hdr.fh_s_id, req_hdr->fh_d_id, sizeof(hdr.fh_s_id));
    244	hdr.fh_type = type;
    245	hton24(hdr.fh_f_ctl, f_ctl);
    246	hdr.fh_ox_id = req_hdr->fh_ox_id;
    247	hdr.fh_rx_id = req_hdr->fh_rx_id;
    248	hdr.fh_cs_ctl = 0;
    249	hdr.fh_df_ctl = 0;
    250	hdr.fh_seq_cnt = 0;
    251	hdr.fh_parm_offset = 0;
    252
    253	/*
    254	 * send_frame_seq_id is an atomic, we just let it increment,
    255	 * while storing only the low 8 bits to hdr->seq_id
    256	 */
    257	hdr.fh_seq_id = (u8)atomic_add_return(1, &hw->send_frame_seq_id);
    258	hdr.fh_seq_id--;
    259
    260	/* Allocate and fill in the send frame request context */
    261	ctx = (void *)(heap_virt_base + heap_offset);
    262	heap_offset += sizeof(*ctx);
    263	if (heap_offset > heap_size) {
    264		efc_log_err(efct, "Fill send frame failed offset %d size %d\n",
    265			    heap_offset, heap_size);
    266		return -EIO;
    267	}
    268
    269	memset(ctx, 0, sizeof(*ctx));
    270
    271	/* Save sequence */
    272	ctx->seq = seq;
    273
    274	/* Allocate a response payload DMA buffer from the heap */
    275	ctx->payload.phys = heap_phys_base + heap_offset;
    276	ctx->payload.virt = heap_virt_base + heap_offset;
    277	ctx->payload.size = payload_len;
    278	ctx->payload.len = payload_len;
    279	heap_offset += payload_len;
    280	if (heap_offset > heap_size) {
    281		efc_log_err(efct, "Fill send frame failed offset %d size %d\n",
    282			    heap_offset, heap_size);
    283		return -EIO;
    284	}
    285
    286	/* Copy the payload in */
    287	memcpy(ctx->payload.virt, payload, payload_len);
    288
    289	/* Send */
    290	rc = efct_hw_send_frame(&efct->hw, (void *)&hdr, FC_SOF_N3,
    291				FC_EOF_T, &ctx->payload, ctx,
    292				efct_sframe_common_send_cb, ctx);
    293	if (rc)
    294		efc_log_debug(efct, "efct_hw_send_frame failed: %d\n", rc);
    295
    296	return rc;
    297}
    298
    299static int
    300efct_sframe_send_fcp_rsp(struct efct_node *node, struct efc_hw_sequence *seq,
    301			 void *rsp, u32 rsp_len)
    302{
    303	return efct_sframe_common_send(node, seq, FC_RCTL_DD_CMD_STATUS,
    304				      FC_FC_EX_CTX |
    305				      FC_FC_LAST_SEQ |
    306				      FC_FC_END_SEQ |
    307				      FC_FC_SEQ_INIT,
    308				      FC_TYPE_FCP,
    309				      rsp, rsp_len);
    310}
    311
    312static int
    313efct_sframe_send_task_set_full_or_busy(struct efct_node *node,
    314				       struct efc_hw_sequence *seq)
    315{
    316	struct fcp_resp_with_ext fcprsp;
    317	struct fcp_cmnd *fcpcmd = seq->payload->dma.virt;
    318	int rc = 0;
    319	unsigned long flags = 0;
    320	struct efct *efct = node->efct;
    321
    322	/* construct task set full or busy response */
    323	memset(&fcprsp, 0, sizeof(fcprsp));
    324	spin_lock_irqsave(&node->active_ios_lock, flags);
    325	fcprsp.resp.fr_status = list_empty(&node->active_ios) ?
    326				SAM_STAT_BUSY : SAM_STAT_TASK_SET_FULL;
    327	spin_unlock_irqrestore(&node->active_ios_lock, flags);
    328	*((u32 *)&fcprsp.ext.fr_resid) = be32_to_cpu(fcpcmd->fc_dl);
    329
    330	/* send it using send_frame */
    331	rc = efct_sframe_send_fcp_rsp(node, seq, &fcprsp, sizeof(fcprsp));
    332	if (rc)
    333		efc_log_debug(efct, "efct_sframe_send_fcp_rsp failed %d\n", rc);
    334
    335	return rc;
    336}
    337
    338int
    339efct_dispatch_fcp_cmd(struct efct_node *node, struct efc_hw_sequence *seq)
    340{
    341	struct efct *efct = node->efct;
    342	struct fc_frame_header *fchdr = seq->header->dma.virt;
    343	struct fcp_cmnd	*cmnd = NULL;
    344	struct efct_io *io = NULL;
    345	u32 lun;
    346
    347	if (!seq->payload) {
    348		efc_log_err(efct, "Sequence payload is NULL.\n");
    349		return -EIO;
    350	}
    351
    352	cmnd = seq->payload->dma.virt;
    353
    354	/* perform FCP_CMND validation check(s) */
    355	if (efct_validate_fcp_cmd(efct, seq))
    356		return -EIO;
    357
    358	lun = scsilun_to_int(&cmnd->fc_lun);
    359	if (lun == U32_MAX)
    360		return -EIO;
    361
    362	io = efct_scsi_io_alloc(node);
    363	if (!io) {
    364		int rc;
    365
    366		/* Use SEND_FRAME to send task set full or busy */
    367		rc = efct_sframe_send_task_set_full_or_busy(node, seq);
    368		if (rc)
    369			efc_log_err(efct, "Failed to send busy task: %d\n", rc);
    370
    371		return rc;
    372	}
    373
    374	io->hw_priv = seq->hw_priv;
    375
    376	io->app_id = 0;
    377
    378	/* RQ pair, if we got here, SIT=1 */
    379	efct_populate_io_fcp_cmd(io, cmnd, fchdr, true);
    380
    381	if (cmnd->fc_tm_flags) {
    382		efct_dispatch_unsol_tmf(io, cmnd->fc_tm_flags, lun);
    383	} else {
    384		u32 flags = efct_get_flags_fcp_cmd(cmnd);
    385
    386		if (cmnd->fc_flags & FCP_CFL_LEN_MASK) {
    387			efc_log_err(efct, "Additional CDB not supported\n");
    388			return -EIO;
    389		}
    390		/*
    391		 * Can return failure for things like task set full and UAs,
    392		 * no need to treat as a dropped frame if rc != 0
    393		 */
    394		efct_scsi_recv_cmd(io, lun, cmnd->fc_cdb,
    395				   sizeof(cmnd->fc_cdb), flags);
    396	}
    397
    398	return 0;
    399}
    400
    401static int
    402efct_process_abts(struct efct_io *io, struct fc_frame_header *hdr)
    403{
    404	struct efct_node *node = io->node;
    405	struct efct *efct = io->efct;
    406	u16 ox_id = be16_to_cpu(hdr->fh_ox_id);
    407	u16 rx_id = be16_to_cpu(hdr->fh_rx_id);
    408	struct efct_io *abortio;
    409
    410	/* Find IO and attempt to take a reference on it */
    411	abortio = efct_io_find_tgt_io(efct, node, ox_id, rx_id);
    412
    413	if (abortio) {
    414		/* Got a reference on the IO. Hold it until backend
    415		 * is notified below
    416		 */
    417		efc_log_info(node->efct, "Abort ox_id [%04x] rx_id [%04x]\n",
    418			     ox_id, rx_id);
    419
    420		/*
    421		 * Save the ox_id for the ABTS as the init_task_tag in our
    422		 * manufactured
    423		 * TMF IO object
    424		 */
    425		io->display_name = "abts";
    426		io->init_task_tag = ox_id;
    427		/* don't set tgt_task_tag, don't want to confuse with XRI */
    428
    429		/*
    430		 * Save the rx_id from the ABTS as it is
    431		 * needed for the BLS response,
    432		 * regardless of the IO context's rx_id
    433		 */
    434		io->abort_rx_id = rx_id;
    435
    436		/* Call target server command abort */
    437		io->tmf_cmd = EFCT_SCSI_TMF_ABORT_TASK;
    438		efct_scsi_recv_tmf(io, abortio->tgt_io.lun,
    439				   EFCT_SCSI_TMF_ABORT_TASK, abortio, 0);
    440
    441		/*
    442		 * Backend will have taken an additional
    443		 * reference on the IO if needed;
    444		 * done with current reference.
    445		 */
    446		kref_put(&abortio->ref, abortio->release);
    447	} else {
    448		/*
    449		 * Either IO was not found or it has been
    450		 * freed between finding it
    451		 * and attempting to get the reference,
    452		 */
    453		efc_log_info(node->efct, "Abort: ox_id [%04x], IO not found\n",
    454			     ox_id);
    455
    456		/* Send a BA_RJT */
    457		efct_bls_send_rjt(io, hdr);
    458	}
    459	return 0;
    460}
    461
    462int
    463efct_node_recv_abts_frame(struct efct_node *node, struct efc_hw_sequence *seq)
    464{
    465	struct efct *efct = node->efct;
    466	struct fc_frame_header *hdr = seq->header->dma.virt;
    467	struct efct_io *io = NULL;
    468
    469	node->abort_cnt++;
    470	io = efct_scsi_io_alloc(node);
    471	if (io) {
    472		io->hw_priv = seq->hw_priv;
    473		/* If we got this far, SIT=1 */
    474		io->seq_init = 1;
    475
    476		/* fill out generic fields */
    477		io->efct = efct;
    478		io->node = node;
    479		io->cmd_tgt = true;
    480
    481		efct_process_abts(io, seq->header->dma.virt);
    482	} else {
    483		efc_log_err(efct,
    484			    "SCSI IO allocation failed for ABTS received ");
    485		efc_log_err(efct, "s_id %06x d_id %06x ox_id %04x rx_id %04x\n",
    486			    ntoh24(hdr->fh_s_id), ntoh24(hdr->fh_d_id),
    487			    be16_to_cpu(hdr->fh_ox_id),
    488			    be16_to_cpu(hdr->fh_rx_id));
    489	}
    490
    491	return 0;
    492}