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

cptpf_mbox.c (4482B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (C) 2016 Cavium, Inc.
      4 */
      5#include <linux/module.h>
      6#include "cptpf.h"
      7
      8static void cpt_send_msg_to_vf(struct cpt_device *cpt, int vf,
      9			       struct cpt_mbox *mbx)
     10{
     11	/* Writing mbox(0) causes interrupt */
     12	cpt_write_csr64(cpt->reg_base, CPTX_PF_VFX_MBOXX(0, vf, 1),
     13			mbx->data);
     14	cpt_write_csr64(cpt->reg_base, CPTX_PF_VFX_MBOXX(0, vf, 0), mbx->msg);
     15}
     16
     17/* ACKs VF's mailbox message
     18 * @vf: VF to which ACK to be sent
     19 */
     20static void cpt_mbox_send_ack(struct cpt_device *cpt, int vf,
     21			      struct cpt_mbox *mbx)
     22{
     23	mbx->data = 0ull;
     24	mbx->msg = CPT_MBOX_MSG_TYPE_ACK;
     25	cpt_send_msg_to_vf(cpt, vf, mbx);
     26}
     27
     28static void cpt_clear_mbox_intr(struct cpt_device *cpt, u32 vf)
     29{
     30	/* W1C for the VF */
     31	cpt_write_csr64(cpt->reg_base, CPTX_PF_MBOX_INTX(0, 0), (1 << vf));
     32}
     33
     34/*
     35 *  Configure QLEN/Chunk sizes for VF
     36 */
     37static void cpt_cfg_qlen_for_vf(struct cpt_device *cpt, int vf, u32 size)
     38{
     39	union cptx_pf_qx_ctl pf_qx_ctl;
     40
     41	pf_qx_ctl.u = cpt_read_csr64(cpt->reg_base, CPTX_PF_QX_CTL(0, vf));
     42	pf_qx_ctl.s.size = size;
     43	pf_qx_ctl.s.cont_err = true;
     44	cpt_write_csr64(cpt->reg_base, CPTX_PF_QX_CTL(0, vf), pf_qx_ctl.u);
     45}
     46
     47/*
     48 * Configure VQ priority
     49 */
     50static void cpt_cfg_vq_priority(struct cpt_device *cpt, int vf, u32 pri)
     51{
     52	union cptx_pf_qx_ctl pf_qx_ctl;
     53
     54	pf_qx_ctl.u = cpt_read_csr64(cpt->reg_base, CPTX_PF_QX_CTL(0, vf));
     55	pf_qx_ctl.s.pri = pri;
     56	cpt_write_csr64(cpt->reg_base, CPTX_PF_QX_CTL(0, vf), pf_qx_ctl.u);
     57}
     58
     59static int cpt_bind_vq_to_grp(struct cpt_device *cpt, u8 q, u8 grp)
     60{
     61	struct microcode *mcode = cpt->mcode;
     62	union cptx_pf_qx_ctl pf_qx_ctl;
     63	struct device *dev = &cpt->pdev->dev;
     64
     65	if (q >= CPT_MAX_VF_NUM) {
     66		dev_err(dev, "Queues are more than cores in the group");
     67		return -EINVAL;
     68	}
     69	if (grp >= CPT_MAX_CORE_GROUPS) {
     70		dev_err(dev, "Request group is more than possible groups");
     71		return -EINVAL;
     72	}
     73	if (grp >= cpt->next_mc_idx) {
     74		dev_err(dev, "Request group is higher than available functional groups");
     75		return -EINVAL;
     76	}
     77	pf_qx_ctl.u = cpt_read_csr64(cpt->reg_base, CPTX_PF_QX_CTL(0, q));
     78	pf_qx_ctl.s.grp = mcode[grp].group;
     79	cpt_write_csr64(cpt->reg_base, CPTX_PF_QX_CTL(0, q), pf_qx_ctl.u);
     80	dev_dbg(dev, "VF %d TYPE %s", q, (mcode[grp].is_ae ? "AE" : "SE"));
     81
     82	return mcode[grp].is_ae ? AE_TYPES : SE_TYPES;
     83}
     84
     85/* Interrupt handler to handle mailbox messages from VFs */
     86static void cpt_handle_mbox_intr(struct cpt_device *cpt, int vf)
     87{
     88	struct cpt_vf_info *vfx = &cpt->vfinfo[vf];
     89	struct cpt_mbox mbx = {};
     90	int vftype;
     91	struct device *dev = &cpt->pdev->dev;
     92	/*
     93	 * MBOX[0] contains msg
     94	 * MBOX[1] contains data
     95	 */
     96	mbx.msg  = cpt_read_csr64(cpt->reg_base, CPTX_PF_VFX_MBOXX(0, vf, 0));
     97	mbx.data = cpt_read_csr64(cpt->reg_base, CPTX_PF_VFX_MBOXX(0, vf, 1));
     98	dev_dbg(dev, "%s: Mailbox msg 0x%llx from VF%d", __func__, mbx.msg, vf);
     99	switch (mbx.msg) {
    100	case CPT_MSG_VF_UP:
    101		vfx->state = VF_STATE_UP;
    102		try_module_get(THIS_MODULE);
    103		cpt_mbox_send_ack(cpt, vf, &mbx);
    104		break;
    105	case CPT_MSG_READY:
    106		mbx.msg  = CPT_MSG_READY;
    107		mbx.data = vf;
    108		cpt_send_msg_to_vf(cpt, vf, &mbx);
    109		break;
    110	case CPT_MSG_VF_DOWN:
    111		/* First msg in VF teardown sequence */
    112		vfx->state = VF_STATE_DOWN;
    113		module_put(THIS_MODULE);
    114		cpt_mbox_send_ack(cpt, vf, &mbx);
    115		break;
    116	case CPT_MSG_QLEN:
    117		vfx->qlen = mbx.data;
    118		cpt_cfg_qlen_for_vf(cpt, vf, vfx->qlen);
    119		cpt_mbox_send_ack(cpt, vf, &mbx);
    120		break;
    121	case CPT_MSG_QBIND_GRP:
    122		vftype = cpt_bind_vq_to_grp(cpt, vf, (u8)mbx.data);
    123		if ((vftype != AE_TYPES) && (vftype != SE_TYPES))
    124			dev_err(dev, "Queue %d binding to group %llu failed",
    125				vf, mbx.data);
    126		else {
    127			dev_dbg(dev, "Queue %d binding to group %llu successful",
    128				vf, mbx.data);
    129			mbx.msg = CPT_MSG_QBIND_GRP;
    130			mbx.data = vftype;
    131			cpt_send_msg_to_vf(cpt, vf, &mbx);
    132		}
    133		break;
    134	case CPT_MSG_VQ_PRIORITY:
    135		vfx->priority = mbx.data;
    136		cpt_cfg_vq_priority(cpt, vf, vfx->priority);
    137		cpt_mbox_send_ack(cpt, vf, &mbx);
    138		break;
    139	default:
    140		dev_err(&cpt->pdev->dev, "Invalid msg from VF%d, msg 0x%llx\n",
    141			vf, mbx.msg);
    142		break;
    143	}
    144}
    145
    146void cpt_mbox_intr_handler (struct cpt_device *cpt, int mbx)
    147{
    148	u64 intr;
    149	u8  vf;
    150
    151	intr = cpt_read_csr64(cpt->reg_base, CPTX_PF_MBOX_INTX(0, 0));
    152	dev_dbg(&cpt->pdev->dev, "PF interrupt Mbox%d 0x%llx\n", mbx, intr);
    153	for (vf = 0; vf < CPT_MAX_VF_NUM; vf++) {
    154		if (intr & (1ULL << vf)) {
    155			dev_dbg(&cpt->pdev->dev, "Intr from VF %d\n", vf);
    156			cpt_handle_mbox_intr(cpt, vf);
    157			cpt_clear_mbox_intr(cpt, vf);
    158		}
    159	}
    160}