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

adf_pfvf_pf_proto.c (10486B)


      1// SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0-only)
      2/* Copyright(c) 2015 - 2021 Intel Corporation */
      3#include <linux/bitfield.h>
      4#include <linux/spinlock.h>
      5#include <linux/types.h>
      6#include "adf_accel_devices.h"
      7#include "adf_common_drv.h"
      8#include "adf_pfvf_msg.h"
      9#include "adf_pfvf_pf_msg.h"
     10#include "adf_pfvf_pf_proto.h"
     11#include "adf_pfvf_utils.h"
     12
     13typedef u8 (*pf2vf_blkmsg_data_getter_fn)(u8 const *blkmsg, u8 byte);
     14
     15static const adf_pf2vf_blkmsg_provider pf2vf_blkmsg_providers[] = {
     16	NULL,				  /* no message type defined for value 0 */
     17	NULL,				  /* no message type defined for value 1 */
     18	adf_pf_capabilities_msg_provider, /* ADF_VF2PF_BLKMSG_REQ_CAP_SUMMARY */
     19	adf_pf_ring_to_svc_msg_provider,  /* ADF_VF2PF_BLKMSG_REQ_RING_SVC_MAP */
     20};
     21
     22/**
     23 * adf_send_pf2vf_msg() - send PF to VF message
     24 * @accel_dev:	Pointer to acceleration device
     25 * @vf_nr:	VF number to which the message will be sent
     26 * @msg:	Message to send
     27 *
     28 * This function allows the PF to send a message to a specific VF.
     29 *
     30 * Return: 0 on success, error code otherwise.
     31 */
     32int adf_send_pf2vf_msg(struct adf_accel_dev *accel_dev, u8 vf_nr, struct pfvf_message msg)
     33{
     34	struct adf_pfvf_ops *pfvf_ops = GET_PFVF_OPS(accel_dev);
     35	u32 pfvf_offset = pfvf_ops->get_pf2vf_offset(vf_nr);
     36
     37	return pfvf_ops->send_msg(accel_dev, msg, pfvf_offset,
     38				  &accel_dev->pf.vf_info[vf_nr].pf2vf_lock);
     39}
     40
     41/**
     42 * adf_recv_vf2pf_msg() - receive a VF to PF message
     43 * @accel_dev:	Pointer to acceleration device
     44 * @vf_nr:	Number of the VF from where the message will be received
     45 *
     46 * This function allows the PF to receive a message from a specific VF.
     47 *
     48 * Return: a valid message on success, zero otherwise.
     49 */
     50static struct pfvf_message adf_recv_vf2pf_msg(struct adf_accel_dev *accel_dev, u8 vf_nr)
     51{
     52	struct adf_accel_vf_info *vf_info = &accel_dev->pf.vf_info[vf_nr];
     53	struct adf_pfvf_ops *pfvf_ops = GET_PFVF_OPS(accel_dev);
     54	u32 pfvf_offset = pfvf_ops->get_vf2pf_offset(vf_nr);
     55
     56	return pfvf_ops->recv_msg(accel_dev, pfvf_offset, vf_info->vf_compat_ver);
     57}
     58
     59static adf_pf2vf_blkmsg_provider get_blkmsg_response_provider(u8 type)
     60{
     61	if (type >= ARRAY_SIZE(pf2vf_blkmsg_providers))
     62		return NULL;
     63
     64	return pf2vf_blkmsg_providers[type];
     65}
     66
     67/* Byte pf2vf_blkmsg_data_getter_fn callback */
     68static u8 adf_pf2vf_blkmsg_get_byte(u8 const *blkmsg, u8 index)
     69{
     70	return blkmsg[index];
     71}
     72
     73/* CRC pf2vf_blkmsg_data_getter_fn callback */
     74static u8 adf_pf2vf_blkmsg_get_crc(u8 const *blkmsg, u8 count)
     75{
     76	/* count is 0-based, turn it into a length */
     77	return adf_pfvf_calc_blkmsg_crc(blkmsg, count + 1);
     78}
     79
     80static int adf_pf2vf_blkmsg_get_data(struct adf_accel_vf_info *vf_info,
     81				     u8 type, u8 byte, u8 max_size, u8 *data,
     82				     pf2vf_blkmsg_data_getter_fn data_getter)
     83{
     84	u8 blkmsg[ADF_PFVF_BLKMSG_MSG_MAX_SIZE] = { 0 };
     85	struct adf_accel_dev *accel_dev = vf_info->accel_dev;
     86	adf_pf2vf_blkmsg_provider provider;
     87	u8 msg_size;
     88
     89	provider = get_blkmsg_response_provider(type);
     90
     91	if (unlikely(!provider)) {
     92		pr_err("QAT: No registered provider for message %d\n", type);
     93		*data = ADF_PF2VF_INVALID_BLOCK_TYPE;
     94		return -EINVAL;
     95	}
     96
     97	if (unlikely((*provider)(accel_dev, blkmsg, vf_info->vf_compat_ver))) {
     98		pr_err("QAT: unknown error from provider for message %d\n", type);
     99		*data = ADF_PF2VF_UNSPECIFIED_ERROR;
    100		return -EINVAL;
    101	}
    102
    103	msg_size = ADF_PFVF_BLKMSG_HEADER_SIZE + blkmsg[ADF_PFVF_BLKMSG_LEN_BYTE];
    104
    105	if (unlikely(msg_size >= max_size)) {
    106		pr_err("QAT: Invalid size %d provided for message type %d\n",
    107		       msg_size, type);
    108		*data = ADF_PF2VF_PAYLOAD_TRUNCATED;
    109		return -EINVAL;
    110	}
    111
    112	if (unlikely(byte >= msg_size)) {
    113		pr_err("QAT: Out-of-bound byte number %d (msg size %d)\n",
    114		       byte, msg_size);
    115		*data = ADF_PF2VF_INVALID_BYTE_NUM_REQ;
    116		return -EINVAL;
    117	}
    118
    119	*data = data_getter(blkmsg, byte);
    120	return 0;
    121}
    122
    123static struct pfvf_message handle_blkmsg_req(struct adf_accel_vf_info *vf_info,
    124					     struct pfvf_message req)
    125{
    126	u8 resp_type = ADF_PF2VF_BLKMSG_RESP_TYPE_ERROR;
    127	struct pfvf_message resp = { 0 };
    128	u8 resp_data = 0;
    129	u8 blk_type;
    130	u8 blk_byte;
    131	u8 byte_max;
    132
    133	switch (req.type) {
    134	case ADF_VF2PF_MSGTYPE_LARGE_BLOCK_REQ:
    135		blk_type = FIELD_GET(ADF_VF2PF_LARGE_BLOCK_TYPE_MASK, req.data)
    136			   + ADF_VF2PF_MEDIUM_BLOCK_TYPE_MAX + 1;
    137		blk_byte = FIELD_GET(ADF_VF2PF_LARGE_BLOCK_BYTE_MASK, req.data);
    138		byte_max = ADF_VF2PF_LARGE_BLOCK_BYTE_MAX;
    139		break;
    140	case ADF_VF2PF_MSGTYPE_MEDIUM_BLOCK_REQ:
    141		blk_type = FIELD_GET(ADF_VF2PF_MEDIUM_BLOCK_TYPE_MASK, req.data)
    142			   + ADF_VF2PF_SMALL_BLOCK_TYPE_MAX + 1;
    143		blk_byte = FIELD_GET(ADF_VF2PF_MEDIUM_BLOCK_BYTE_MASK, req.data);
    144		byte_max = ADF_VF2PF_MEDIUM_BLOCK_BYTE_MAX;
    145		break;
    146	case ADF_VF2PF_MSGTYPE_SMALL_BLOCK_REQ:
    147		blk_type = FIELD_GET(ADF_VF2PF_SMALL_BLOCK_TYPE_MASK, req.data);
    148		blk_byte = FIELD_GET(ADF_VF2PF_SMALL_BLOCK_BYTE_MASK, req.data);
    149		byte_max = ADF_VF2PF_SMALL_BLOCK_BYTE_MAX;
    150		break;
    151	}
    152
    153	/* Is this a request for CRC or data? */
    154	if (FIELD_GET(ADF_VF2PF_BLOCK_CRC_REQ_MASK, req.data)) {
    155		dev_dbg(&GET_DEV(vf_info->accel_dev),
    156			"BlockMsg of type %d for CRC over %d bytes received from VF%d\n",
    157			blk_type, blk_byte + 1, vf_info->vf_nr);
    158
    159		if (!adf_pf2vf_blkmsg_get_data(vf_info, blk_type, blk_byte,
    160					       byte_max, &resp_data,
    161					       adf_pf2vf_blkmsg_get_crc))
    162			resp_type = ADF_PF2VF_BLKMSG_RESP_TYPE_CRC;
    163	} else {
    164		dev_dbg(&GET_DEV(vf_info->accel_dev),
    165			"BlockMsg of type %d for data byte %d received from VF%d\n",
    166			blk_type, blk_byte, vf_info->vf_nr);
    167
    168		if (!adf_pf2vf_blkmsg_get_data(vf_info, blk_type, blk_byte,
    169					       byte_max, &resp_data,
    170					       adf_pf2vf_blkmsg_get_byte))
    171			resp_type = ADF_PF2VF_BLKMSG_RESP_TYPE_DATA;
    172	}
    173
    174	resp.type = ADF_PF2VF_MSGTYPE_BLKMSG_RESP;
    175	resp.data = FIELD_PREP(ADF_PF2VF_BLKMSG_RESP_TYPE_MASK, resp_type) |
    176		    FIELD_PREP(ADF_PF2VF_BLKMSG_RESP_DATA_MASK, resp_data);
    177
    178	return resp;
    179}
    180
    181static struct pfvf_message handle_rp_reset_req(struct adf_accel_dev *accel_dev, u8 vf_nr,
    182					       struct pfvf_message req)
    183{
    184	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
    185	struct pfvf_message resp = {
    186		.type = ADF_PF2VF_MSGTYPE_RP_RESET_RESP,
    187		.data = RPRESET_SUCCESS
    188	};
    189	u32 bank_number;
    190	u32 rsvd_field;
    191
    192	bank_number = FIELD_GET(ADF_VF2PF_RNG_RESET_RP_MASK, req.data);
    193	rsvd_field = FIELD_GET(ADF_VF2PF_RNG_RESET_RSVD_MASK, req.data);
    194
    195	dev_dbg(&GET_DEV(accel_dev),
    196		"Ring Pair Reset Message received from VF%d for bank 0x%x\n",
    197		vf_nr, bank_number);
    198
    199	if (!hw_data->ring_pair_reset || rsvd_field) {
    200		dev_dbg(&GET_DEV(accel_dev),
    201			"Ring Pair Reset for VF%d is not supported\n", vf_nr);
    202		resp.data = RPRESET_NOT_SUPPORTED;
    203		goto out;
    204	}
    205
    206	if (bank_number >= hw_data->num_banks_per_vf) {
    207		dev_err(&GET_DEV(accel_dev),
    208			"Invalid bank number (0x%x) from VF%d for Ring Reset\n",
    209			bank_number, vf_nr);
    210		resp.data = RPRESET_INVAL_BANK;
    211		goto out;
    212	}
    213
    214	/* Convert the VF provided value to PF bank number */
    215	bank_number = vf_nr * hw_data->num_banks_per_vf + bank_number;
    216	if (hw_data->ring_pair_reset(accel_dev, bank_number)) {
    217		dev_dbg(&GET_DEV(accel_dev),
    218			"Ring pair reset for VF%d failure\n", vf_nr);
    219		resp.data = RPRESET_TIMEOUT;
    220		goto out;
    221	}
    222
    223	dev_dbg(&GET_DEV(accel_dev),
    224		"Ring pair reset for VF%d successfully\n", vf_nr);
    225
    226out:
    227	return resp;
    228}
    229
    230static int adf_handle_vf2pf_msg(struct adf_accel_dev *accel_dev, u8 vf_nr,
    231				struct pfvf_message msg, struct pfvf_message *resp)
    232{
    233	struct adf_accel_vf_info *vf_info = &accel_dev->pf.vf_info[vf_nr];
    234
    235	switch (msg.type) {
    236	case ADF_VF2PF_MSGTYPE_COMPAT_VER_REQ:
    237		{
    238		u8 vf_compat_ver = msg.data;
    239		u8 compat;
    240
    241		dev_dbg(&GET_DEV(accel_dev),
    242			"VersionRequest received from VF%d (vers %d) to PF (vers %d)\n",
    243			vf_nr, vf_compat_ver, ADF_PFVF_COMPAT_THIS_VERSION);
    244
    245		if (vf_compat_ver == 0)
    246			compat = ADF_PF2VF_VF_INCOMPATIBLE;
    247		else if (vf_compat_ver <= ADF_PFVF_COMPAT_THIS_VERSION)
    248			compat = ADF_PF2VF_VF_COMPATIBLE;
    249		else
    250			compat = ADF_PF2VF_VF_COMPAT_UNKNOWN;
    251
    252		vf_info->vf_compat_ver = vf_compat_ver;
    253
    254		resp->type = ADF_PF2VF_MSGTYPE_VERSION_RESP;
    255		resp->data = FIELD_PREP(ADF_PF2VF_VERSION_RESP_VERS_MASK,
    256					ADF_PFVF_COMPAT_THIS_VERSION) |
    257			     FIELD_PREP(ADF_PF2VF_VERSION_RESP_RESULT_MASK, compat);
    258		}
    259		break;
    260	case ADF_VF2PF_MSGTYPE_VERSION_REQ:
    261		{
    262		u8 compat;
    263
    264		dev_dbg(&GET_DEV(accel_dev),
    265			"Legacy VersionRequest received from VF%d to PF (vers 1.1)\n",
    266			vf_nr);
    267
    268		/* legacy driver, VF compat_ver is 0 */
    269		vf_info->vf_compat_ver = 0;
    270
    271		/* PF always newer than legacy VF */
    272		compat = ADF_PF2VF_VF_COMPATIBLE;
    273
    274		/* Set legacy major and minor version to the latest, 1.1 */
    275		resp->type = ADF_PF2VF_MSGTYPE_VERSION_RESP;
    276		resp->data = FIELD_PREP(ADF_PF2VF_VERSION_RESP_VERS_MASK, 0x11) |
    277			     FIELD_PREP(ADF_PF2VF_VERSION_RESP_RESULT_MASK, compat);
    278		}
    279		break;
    280	case ADF_VF2PF_MSGTYPE_INIT:
    281		{
    282		dev_dbg(&GET_DEV(accel_dev),
    283			"Init message received from VF%d\n", vf_nr);
    284		vf_info->init = true;
    285		}
    286		break;
    287	case ADF_VF2PF_MSGTYPE_SHUTDOWN:
    288		{
    289		dev_dbg(&GET_DEV(accel_dev),
    290			"Shutdown message received from VF%d\n", vf_nr);
    291		vf_info->init = false;
    292		}
    293		break;
    294	case ADF_VF2PF_MSGTYPE_LARGE_BLOCK_REQ:
    295	case ADF_VF2PF_MSGTYPE_MEDIUM_BLOCK_REQ:
    296	case ADF_VF2PF_MSGTYPE_SMALL_BLOCK_REQ:
    297		*resp = handle_blkmsg_req(vf_info, msg);
    298		break;
    299	case ADF_VF2PF_MSGTYPE_RP_RESET:
    300		*resp = handle_rp_reset_req(accel_dev, vf_nr, msg);
    301		break;
    302	default:
    303		dev_dbg(&GET_DEV(accel_dev),
    304			"Unknown message from VF%d (type 0x%.4x, data: 0x%.4x)\n",
    305			vf_nr, msg.type, msg.data);
    306		return -ENOMSG;
    307	}
    308
    309	return 0;
    310}
    311
    312bool adf_recv_and_handle_vf2pf_msg(struct adf_accel_dev *accel_dev, u32 vf_nr)
    313{
    314	struct pfvf_message req;
    315	struct pfvf_message resp = {0};
    316
    317	req = adf_recv_vf2pf_msg(accel_dev, vf_nr);
    318	if (!req.type)  /* Legacy or no message */
    319		return true;
    320
    321	if (adf_handle_vf2pf_msg(accel_dev, vf_nr, req, &resp))
    322		return false;
    323
    324	if (resp.type && adf_send_pf2vf_msg(accel_dev, vf_nr, resp))
    325		dev_err(&GET_DEV(accel_dev),
    326			"Failed to send response to VF%d\n", vf_nr);
    327
    328	return true;
    329}
    330
    331/**
    332 * adf_enable_pf2vf_comms() - Function enables communication from pf to vf
    333 *
    334 * @accel_dev: Pointer to acceleration device virtual function.
    335 *
    336 * This function carries out the necessary steps to setup and start the PFVF
    337 * communication channel, if any.
    338 *
    339 * Return: 0 on success, error code otherwise.
    340 */
    341int adf_enable_pf2vf_comms(struct adf_accel_dev *accel_dev)
    342{
    343	adf_pfvf_crc_init();
    344	spin_lock_init(&accel_dev->pf.vf2pf_ints_lock);
    345
    346	return 0;
    347}
    348EXPORT_SYMBOL_GPL(adf_enable_pf2vf_comms);