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

otx2_cptpf_mbox.c (9753B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/* Copyright (C) 2020 Marvell. */
      3
      4#include "otx2_cpt_common.h"
      5#include "otx2_cptpf.h"
      6#include "rvu_reg.h"
      7
      8/*
      9 * CPT PF driver version, It will be incremented by 1 for every feature
     10 * addition in CPT mailbox messages.
     11 */
     12#define OTX2_CPT_PF_DRV_VERSION 0x1
     13
     14static int forward_to_af(struct otx2_cptpf_dev *cptpf,
     15			 struct otx2_cptvf_info *vf,
     16			 struct mbox_msghdr *req, int size)
     17{
     18	struct mbox_msghdr *msg;
     19	int ret;
     20
     21	mutex_lock(&cptpf->lock);
     22	msg = otx2_mbox_alloc_msg(&cptpf->afpf_mbox, 0, size);
     23	if (msg == NULL) {
     24		mutex_unlock(&cptpf->lock);
     25		return -ENOMEM;
     26	}
     27
     28	memcpy((uint8_t *)msg + sizeof(struct mbox_msghdr),
     29	       (uint8_t *)req + sizeof(struct mbox_msghdr), size);
     30	msg->id = req->id;
     31	msg->pcifunc = req->pcifunc;
     32	msg->sig = req->sig;
     33	msg->ver = req->ver;
     34
     35	ret = otx2_cpt_sync_mbox_msg(&cptpf->afpf_mbox);
     36	/* Error code -EIO indicate there is a communication failure
     37	 * to the AF. Rest of the error codes indicate that AF processed
     38	 * VF messages and set the error codes in response messages
     39	 * (if any) so simply forward responses to VF.
     40	 */
     41	if (ret == -EIO) {
     42		dev_warn(&cptpf->pdev->dev,
     43			 "AF not responding to VF%d messages\n", vf->vf_id);
     44		mutex_unlock(&cptpf->lock);
     45		return ret;
     46	}
     47	mutex_unlock(&cptpf->lock);
     48	return 0;
     49}
     50
     51static int handle_msg_get_caps(struct otx2_cptpf_dev *cptpf,
     52			       struct otx2_cptvf_info *vf,
     53			       struct mbox_msghdr *req)
     54{
     55	struct otx2_cpt_caps_rsp *rsp;
     56
     57	rsp = (struct otx2_cpt_caps_rsp *)
     58	      otx2_mbox_alloc_msg(&cptpf->vfpf_mbox, vf->vf_id,
     59				  sizeof(*rsp));
     60	if (!rsp)
     61		return -ENOMEM;
     62
     63	rsp->hdr.id = MBOX_MSG_GET_CAPS;
     64	rsp->hdr.sig = OTX2_MBOX_RSP_SIG;
     65	rsp->hdr.pcifunc = req->pcifunc;
     66	rsp->cpt_pf_drv_version = OTX2_CPT_PF_DRV_VERSION;
     67	rsp->cpt_revision = cptpf->pdev->revision;
     68	memcpy(&rsp->eng_caps, &cptpf->eng_caps, sizeof(rsp->eng_caps));
     69
     70	return 0;
     71}
     72
     73static int handle_msg_get_eng_grp_num(struct otx2_cptpf_dev *cptpf,
     74				      struct otx2_cptvf_info *vf,
     75				      struct mbox_msghdr *req)
     76{
     77	struct otx2_cpt_egrp_num_msg *grp_req;
     78	struct otx2_cpt_egrp_num_rsp *rsp;
     79
     80	grp_req = (struct otx2_cpt_egrp_num_msg *)req;
     81	rsp = (struct otx2_cpt_egrp_num_rsp *)
     82	       otx2_mbox_alloc_msg(&cptpf->vfpf_mbox, vf->vf_id, sizeof(*rsp));
     83	if (!rsp)
     84		return -ENOMEM;
     85
     86	rsp->hdr.id = MBOX_MSG_GET_ENG_GRP_NUM;
     87	rsp->hdr.sig = OTX2_MBOX_RSP_SIG;
     88	rsp->hdr.pcifunc = req->pcifunc;
     89	rsp->eng_type = grp_req->eng_type;
     90	rsp->eng_grp_num = otx2_cpt_get_eng_grp(&cptpf->eng_grps,
     91						grp_req->eng_type);
     92
     93	return 0;
     94}
     95
     96static int handle_msg_kvf_limits(struct otx2_cptpf_dev *cptpf,
     97				 struct otx2_cptvf_info *vf,
     98				 struct mbox_msghdr *req)
     99{
    100	struct otx2_cpt_kvf_limits_rsp *rsp;
    101
    102	rsp = (struct otx2_cpt_kvf_limits_rsp *)
    103	      otx2_mbox_alloc_msg(&cptpf->vfpf_mbox, vf->vf_id, sizeof(*rsp));
    104	if (!rsp)
    105		return -ENOMEM;
    106
    107	rsp->hdr.id = MBOX_MSG_GET_KVF_LIMITS;
    108	rsp->hdr.sig = OTX2_MBOX_RSP_SIG;
    109	rsp->hdr.pcifunc = req->pcifunc;
    110	rsp->kvf_limits = cptpf->kvf_limits;
    111
    112	return 0;
    113}
    114
    115static int cptpf_handle_vf_req(struct otx2_cptpf_dev *cptpf,
    116			       struct otx2_cptvf_info *vf,
    117			       struct mbox_msghdr *req, int size)
    118{
    119	int err = 0;
    120
    121	/* Check if msg is valid, if not reply with an invalid msg */
    122	if (req->sig != OTX2_MBOX_REQ_SIG)
    123		goto inval_msg;
    124
    125	switch (req->id) {
    126	case MBOX_MSG_GET_ENG_GRP_NUM:
    127		err = handle_msg_get_eng_grp_num(cptpf, vf, req);
    128		break;
    129	case MBOX_MSG_GET_CAPS:
    130		err = handle_msg_get_caps(cptpf, vf, req);
    131		break;
    132	case MBOX_MSG_GET_KVF_LIMITS:
    133		err = handle_msg_kvf_limits(cptpf, vf, req);
    134		break;
    135	default:
    136		err = forward_to_af(cptpf, vf, req, size);
    137		break;
    138	}
    139	return err;
    140
    141inval_msg:
    142	otx2_reply_invalid_msg(&cptpf->vfpf_mbox, vf->vf_id, 0, req->id);
    143	otx2_mbox_msg_send(&cptpf->vfpf_mbox, vf->vf_id);
    144	return err;
    145}
    146
    147irqreturn_t otx2_cptpf_vfpf_mbox_intr(int __always_unused irq, void *arg)
    148{
    149	struct otx2_cptpf_dev *cptpf = arg;
    150	struct otx2_cptvf_info *vf;
    151	int i, vf_idx;
    152	u64 intr;
    153
    154	/*
    155	 * Check which VF has raised an interrupt and schedule
    156	 * corresponding work queue to process the messages
    157	 */
    158	for (i = 0; i < 2; i++) {
    159		/* Read the interrupt bits */
    160		intr = otx2_cpt_read64(cptpf->reg_base, BLKADDR_RVUM, 0,
    161				       RVU_PF_VFPF_MBOX_INTX(i));
    162
    163		for (vf_idx = i * 64; vf_idx < cptpf->enabled_vfs; vf_idx++) {
    164			vf = &cptpf->vf[vf_idx];
    165			if (intr & (1ULL << vf->intr_idx)) {
    166				queue_work(cptpf->vfpf_mbox_wq,
    167					   &vf->vfpf_mbox_work);
    168				/* Clear the interrupt */
    169				otx2_cpt_write64(cptpf->reg_base, BLKADDR_RVUM,
    170						 0, RVU_PF_VFPF_MBOX_INTX(i),
    171						 BIT_ULL(vf->intr_idx));
    172			}
    173		}
    174	}
    175	return IRQ_HANDLED;
    176}
    177
    178void otx2_cptpf_vfpf_mbox_handler(struct work_struct *work)
    179{
    180	struct otx2_cptpf_dev *cptpf;
    181	struct otx2_cptvf_info *vf;
    182	struct otx2_mbox_dev *mdev;
    183	struct mbox_hdr *req_hdr;
    184	struct mbox_msghdr *msg;
    185	struct otx2_mbox *mbox;
    186	int offset, i, err;
    187
    188	vf = container_of(work, struct otx2_cptvf_info, vfpf_mbox_work);
    189	cptpf = vf->cptpf;
    190	mbox = &cptpf->vfpf_mbox;
    191	/* sync with mbox memory region */
    192	smp_rmb();
    193	mdev = &mbox->dev[vf->vf_id];
    194	/* Process received mbox messages */
    195	req_hdr = (struct mbox_hdr *)(mdev->mbase + mbox->rx_start);
    196	offset = mbox->rx_start + ALIGN(sizeof(*req_hdr), MBOX_MSG_ALIGN);
    197
    198	for (i = 0; i < req_hdr->num_msgs; i++) {
    199		msg = (struct mbox_msghdr *)(mdev->mbase + offset);
    200
    201		/* Set which VF sent this message based on mbox IRQ */
    202		msg->pcifunc = ((u16)cptpf->pf_id << RVU_PFVF_PF_SHIFT) |
    203				((vf->vf_id + 1) & RVU_PFVF_FUNC_MASK);
    204
    205		err = cptpf_handle_vf_req(cptpf, vf, msg,
    206					  msg->next_msgoff - offset);
    207		/*
    208		 * Behave as the AF, drop the msg if there is
    209		 * no memory, timeout handling also goes here
    210		 */
    211		if (err == -ENOMEM || err == -EIO)
    212			break;
    213		offset = msg->next_msgoff;
    214		/* Write barrier required for VF responses which are handled by
    215		 * PF driver and not forwarded to AF.
    216		 */
    217		smp_wmb();
    218	}
    219	/* Send mbox responses to VF */
    220	if (mdev->num_msgs)
    221		otx2_mbox_msg_send(mbox, vf->vf_id);
    222}
    223
    224irqreturn_t otx2_cptpf_afpf_mbox_intr(int __always_unused irq, void *arg)
    225{
    226	struct otx2_cptpf_dev *cptpf = arg;
    227	u64 intr;
    228
    229	/* Read the interrupt bits */
    230	intr = otx2_cpt_read64(cptpf->reg_base, BLKADDR_RVUM, 0, RVU_PF_INT);
    231
    232	if (intr & 0x1ULL) {
    233		/* Schedule work queue function to process the MBOX request */
    234		queue_work(cptpf->afpf_mbox_wq, &cptpf->afpf_mbox_work);
    235		/* Clear and ack the interrupt */
    236		otx2_cpt_write64(cptpf->reg_base, BLKADDR_RVUM, 0, RVU_PF_INT,
    237				 0x1ULL);
    238	}
    239	return IRQ_HANDLED;
    240}
    241
    242static void process_afpf_mbox_msg(struct otx2_cptpf_dev *cptpf,
    243				  struct mbox_msghdr *msg)
    244{
    245	struct device *dev = &cptpf->pdev->dev;
    246	struct cpt_rd_wr_reg_msg *rsp_rd_wr;
    247
    248	if (msg->id >= MBOX_MSG_MAX) {
    249		dev_err(dev, "MBOX msg with unknown ID %d\n", msg->id);
    250		return;
    251	}
    252	if (msg->sig != OTX2_MBOX_RSP_SIG) {
    253		dev_err(dev, "MBOX msg with wrong signature %x, ID %d\n",
    254			msg->sig, msg->id);
    255		return;
    256	}
    257
    258	switch (msg->id) {
    259	case MBOX_MSG_READY:
    260		cptpf->pf_id = (msg->pcifunc >> RVU_PFVF_PF_SHIFT) &
    261				RVU_PFVF_PF_MASK;
    262		break;
    263	case MBOX_MSG_CPT_RD_WR_REGISTER:
    264		rsp_rd_wr = (struct cpt_rd_wr_reg_msg *)msg;
    265		if (msg->rc) {
    266			dev_err(dev, "Reg %llx rd/wr(%d) failed %d\n",
    267				rsp_rd_wr->reg_offset, rsp_rd_wr->is_write,
    268				msg->rc);
    269			return;
    270		}
    271		if (!rsp_rd_wr->is_write)
    272			*rsp_rd_wr->ret_val = rsp_rd_wr->val;
    273		break;
    274	case MBOX_MSG_ATTACH_RESOURCES:
    275		if (!msg->rc)
    276			cptpf->lfs.are_lfs_attached = 1;
    277		break;
    278	case MBOX_MSG_DETACH_RESOURCES:
    279		if (!msg->rc)
    280			cptpf->lfs.are_lfs_attached = 0;
    281		break;
    282
    283	default:
    284		dev_err(dev,
    285			"Unsupported msg %d received.\n", msg->id);
    286		break;
    287	}
    288}
    289
    290static void forward_to_vf(struct otx2_cptpf_dev *cptpf, struct mbox_msghdr *msg,
    291			  int vf_id, int size)
    292{
    293	struct otx2_mbox *vfpf_mbox;
    294	struct mbox_msghdr *fwd;
    295
    296	if (msg->id >= MBOX_MSG_MAX) {
    297		dev_err(&cptpf->pdev->dev,
    298			"MBOX msg with unknown ID %d\n", msg->id);
    299		return;
    300	}
    301	if (msg->sig != OTX2_MBOX_RSP_SIG) {
    302		dev_err(&cptpf->pdev->dev,
    303			"MBOX msg with wrong signature %x, ID %d\n",
    304			msg->sig, msg->id);
    305		return;
    306	}
    307	vfpf_mbox = &cptpf->vfpf_mbox;
    308	vf_id--;
    309	if (vf_id >= cptpf->enabled_vfs) {
    310		dev_err(&cptpf->pdev->dev,
    311			"MBOX msg to unknown VF: %d >= %d\n",
    312			vf_id, cptpf->enabled_vfs);
    313		return;
    314	}
    315	if (msg->id == MBOX_MSG_VF_FLR)
    316		return;
    317
    318	fwd = otx2_mbox_alloc_msg(vfpf_mbox, vf_id, size);
    319	if (!fwd) {
    320		dev_err(&cptpf->pdev->dev,
    321			"Forwarding to VF%d failed.\n", vf_id);
    322		return;
    323	}
    324	memcpy((uint8_t *)fwd + sizeof(struct mbox_msghdr),
    325		(uint8_t *)msg + sizeof(struct mbox_msghdr), size);
    326	fwd->id = msg->id;
    327	fwd->pcifunc = msg->pcifunc;
    328	fwd->sig = msg->sig;
    329	fwd->ver = msg->ver;
    330	fwd->rc = msg->rc;
    331}
    332
    333/* Handle mailbox messages received from AF */
    334void otx2_cptpf_afpf_mbox_handler(struct work_struct *work)
    335{
    336	struct otx2_cptpf_dev *cptpf;
    337	struct otx2_mbox *afpf_mbox;
    338	struct otx2_mbox_dev *mdev;
    339	struct mbox_hdr *rsp_hdr;
    340	struct mbox_msghdr *msg;
    341	int offset, vf_id, i;
    342
    343	cptpf = container_of(work, struct otx2_cptpf_dev, afpf_mbox_work);
    344	afpf_mbox = &cptpf->afpf_mbox;
    345	mdev = &afpf_mbox->dev[0];
    346	/* Sync mbox data into memory */
    347	smp_wmb();
    348
    349	rsp_hdr = (struct mbox_hdr *)(mdev->mbase + afpf_mbox->rx_start);
    350	offset = ALIGN(sizeof(*rsp_hdr), MBOX_MSG_ALIGN);
    351
    352	for (i = 0; i < rsp_hdr->num_msgs; i++) {
    353		msg = (struct mbox_msghdr *)(mdev->mbase + afpf_mbox->rx_start +
    354					     offset);
    355		vf_id = (msg->pcifunc >> RVU_PFVF_FUNC_SHIFT) &
    356			 RVU_PFVF_FUNC_MASK;
    357		if (vf_id > 0)
    358			forward_to_vf(cptpf, msg, vf_id,
    359				      msg->next_msgoff - offset);
    360		else
    361			process_afpf_mbox_msg(cptpf, msg);
    362
    363		offset = msg->next_msgoff;
    364		/* Sync VF response ready to be sent */
    365		smp_wmb();
    366		mdev->msgs_acked++;
    367	}
    368	otx2_mbox_reset(afpf_mbox, 0);
    369}