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

amdgpu_psp_ta.c (8101B)


      1/*
      2 * Copyright 2022 Advanced Micro Devices, Inc.
      3 *
      4 * Permission is hereby granted, free of charge, to any person obtaining a
      5 * copy of this software and associated documentation files (the "Software"),
      6 * to deal in the Software without restriction, including without limitation
      7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8 * and/or sell copies of the Software, and to permit persons to whom the
      9 * Software is furnished to do so, subject to the following conditions:
     10 *
     11 * The above copyright notice and this permission notice shall be included in
     12 * all copies or substantial portions of the Software.
     13 *
     14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
     18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     20 * OTHER DEALINGS IN THE SOFTWARE.
     21 *
     22 */
     23
     24#include "amdgpu.h"
     25#include "amdgpu_psp_ta.h"
     26
     27#if defined(CONFIG_DEBUG_FS)
     28
     29static ssize_t ta_if_load_debugfs_write(struct file *fp, const char *buf,
     30					    size_t len, loff_t *off);
     31static ssize_t ta_if_unload_debugfs_write(struct file *fp, const char *buf,
     32					    size_t len, loff_t *off);
     33static ssize_t ta_if_invoke_debugfs_write(struct file *fp, const char *buf,
     34					    size_t len, loff_t *off);
     35
     36static uint32_t get_bin_version(const uint8_t *bin)
     37{
     38	const struct common_firmware_header *hdr =
     39			     (const struct common_firmware_header *)bin;
     40
     41	return hdr->ucode_version;
     42}
     43
     44static void prep_ta_mem_context(struct psp_context *psp,
     45					     struct ta_context *context,
     46					     uint8_t *shared_buf,
     47					     uint32_t shared_buf_len)
     48{
     49	context->mem_context.shared_mem_size = PAGE_ALIGN(shared_buf_len);
     50	psp_ta_init_shared_buf(psp, &context->mem_context);
     51
     52	memcpy((void *)context->mem_context.shared_buf, shared_buf, shared_buf_len);
     53}
     54
     55static bool is_ta_type_valid(enum ta_type_id ta_type)
     56{
     57	bool ret = false;
     58
     59	switch (ta_type) {
     60	case TA_TYPE_RAS:
     61		ret = true;
     62		break;
     63	default:
     64		break;
     65	}
     66
     67	return ret;
     68}
     69
     70static const struct file_operations ta_load_debugfs_fops = {
     71	.write  = ta_if_load_debugfs_write,
     72	.llseek = default_llseek,
     73	.owner  = THIS_MODULE
     74};
     75
     76static const struct file_operations ta_unload_debugfs_fops = {
     77	.write  = ta_if_unload_debugfs_write,
     78	.llseek = default_llseek,
     79	.owner  = THIS_MODULE
     80};
     81
     82static const struct file_operations ta_invoke_debugfs_fops = {
     83	.write  = ta_if_invoke_debugfs_write,
     84	.llseek = default_llseek,
     85	.owner  = THIS_MODULE
     86};
     87
     88
     89/**
     90 * DOC: AMDGPU TA debugfs interfaces
     91 *
     92 * Three debugfs interfaces can be opened by a program to
     93 * load/invoke/unload TA,
     94 *
     95 * - /sys/kernel/debug/dri/<N>/ta_if/ta_load
     96 * - /sys/kernel/debug/dri/<N>/ta_if/ta_invoke
     97 * - /sys/kernel/debug/dri/<N>/ta_if/ta_unload
     98 *
     99 * How to use the interfaces in a program?
    100 *
    101 * A program needs to provide transmit buffer to the interfaces
    102 * and will receive buffer from the interfaces below,
    103 *
    104 * - For TA load debugfs interface:
    105 *   Transmit buffer:
    106 *    - TA type (4bytes)
    107 *    - TA bin length (4bytes)
    108 *    - TA bin
    109 *   Receive buffer:
    110 *    - TA ID (4bytes)
    111 *
    112 * - For TA invoke debugfs interface:
    113 *   Transmit buffer:
    114 *    - TA ID (4bytes)
    115 *    - TA CMD ID (4bytes)
    116 *    - TA shard buf length (4bytes)
    117 *    - TA shared buf
    118 *   Receive buffer:
    119 *    - TA shared buf
    120 *
    121 * - For TA unload debugfs interface:
    122 *   Transmit buffer:
    123 *    - TA ID (4bytes)
    124 */
    125
    126static ssize_t ta_if_load_debugfs_write(struct file *fp, const char *buf, size_t len, loff_t *off)
    127{
    128	uint32_t ta_type    = 0;
    129	uint32_t ta_bin_len = 0;
    130	uint8_t  *ta_bin    = NULL;
    131	uint32_t copy_pos   = 0;
    132	int      ret        = 0;
    133
    134	struct amdgpu_device *adev   = (struct amdgpu_device *)file_inode(fp)->i_private;
    135	struct psp_context   *psp    = &adev->psp;
    136	struct ta_context    context = {0};
    137
    138	if (!buf)
    139		return -EINVAL;
    140
    141	ret = copy_from_user((void *)&ta_type, &buf[copy_pos], sizeof(uint32_t));
    142	if (ret || (!is_ta_type_valid(ta_type)))
    143		return -EINVAL;
    144
    145	copy_pos += sizeof(uint32_t);
    146
    147	ret = copy_from_user((void *)&ta_bin_len, &buf[copy_pos], sizeof(uint32_t));
    148	if (ret)
    149		return -EINVAL;
    150
    151	copy_pos += sizeof(uint32_t);
    152
    153	ta_bin = kzalloc(ta_bin_len, GFP_KERNEL);
    154	if (!ta_bin)
    155		ret = -ENOMEM;
    156	if (copy_from_user((void *)ta_bin, &buf[copy_pos], ta_bin_len)) {
    157		ret = -EFAULT;
    158		goto err_free_bin;
    159	}
    160
    161	ret = psp_ras_terminate(psp);
    162	if (ret) {
    163		dev_err(adev->dev, "Failed to unload embedded RAS TA\n");
    164		goto err_free_bin;
    165	}
    166
    167	context.ta_type             = ta_type;
    168	context.ta_load_type        = GFX_CMD_ID_LOAD_TA;
    169	context.bin_desc.fw_version = get_bin_version(ta_bin);
    170	context.bin_desc.size_bytes = ta_bin_len;
    171	context.bin_desc.start_addr = ta_bin;
    172
    173	ret = psp_ta_load(psp, &context);
    174
    175	if (ret || context.resp_status) {
    176		dev_err(adev->dev, "TA load via debugfs failed (%d) status %d\n",
    177			 ret, context.resp_status);
    178		if (!ret)
    179			ret = -EINVAL;
    180		goto err_free_bin;
    181	}
    182
    183	context.initialized = true;
    184	if (copy_to_user((char *)buf, (void *)&context.session_id, sizeof(uint32_t)))
    185		ret = -EFAULT;
    186
    187err_free_bin:
    188	kfree(ta_bin);
    189
    190	return ret;
    191}
    192
    193static ssize_t ta_if_unload_debugfs_write(struct file *fp, const char *buf, size_t len, loff_t *off)
    194{
    195	uint32_t ta_id  = 0;
    196	int      ret    = 0;
    197
    198	struct amdgpu_device *adev   = (struct amdgpu_device *)file_inode(fp)->i_private;
    199	struct psp_context   *psp    = &adev->psp;
    200	struct ta_context    context = {0};
    201
    202	if (!buf)
    203		return -EINVAL;
    204
    205	ret = copy_from_user((void *)&ta_id, buf, sizeof(uint32_t));
    206	if (ret)
    207		return -EINVAL;
    208
    209	context.session_id = ta_id;
    210
    211	ret = psp_ta_unload(psp, &context);
    212	if (!ret)
    213		context.initialized = false;
    214
    215	return ret;
    216}
    217
    218static ssize_t ta_if_invoke_debugfs_write(struct file *fp, const char *buf, size_t len, loff_t *off)
    219{
    220	uint32_t ta_id          = 0;
    221	uint32_t cmd_id         = 0;
    222	uint32_t shared_buf_len = 0;
    223	uint8_t	 *shared_buf    = NULL;
    224	uint32_t copy_pos       = 0;
    225	int      ret            = 0;
    226
    227	struct amdgpu_device *adev   = (struct amdgpu_device *)file_inode(fp)->i_private;
    228	struct psp_context   *psp    = &adev->psp;
    229	struct ta_context    context = {0};
    230
    231	if (!buf)
    232		return -EINVAL;
    233
    234	ret = copy_from_user((void *)&ta_id, &buf[copy_pos], sizeof(uint32_t));
    235	if (ret)
    236		return -EINVAL;
    237	copy_pos += sizeof(uint32_t);
    238
    239	ret = copy_from_user((void *)&cmd_id, &buf[copy_pos], sizeof(uint32_t));
    240	if (ret)
    241		return -EINVAL;
    242	copy_pos += sizeof(uint32_t);
    243
    244	ret = copy_from_user((void *)&shared_buf_len, &buf[copy_pos], sizeof(uint32_t));
    245	if (ret)
    246		return -EINVAL;
    247	copy_pos += sizeof(uint32_t);
    248
    249	shared_buf = kzalloc(shared_buf_len, GFP_KERNEL);
    250	if (!shared_buf)
    251		return -ENOMEM;
    252	if (copy_from_user((void *)shared_buf, &buf[copy_pos], shared_buf_len)) {
    253		ret = -EFAULT;
    254		goto err_free_shared_buf;
    255	}
    256
    257	context.session_id = ta_id;
    258
    259	prep_ta_mem_context(psp, &context, shared_buf, shared_buf_len);
    260
    261	ret = psp_ta_invoke_indirect(psp, cmd_id, &context);
    262
    263	if (ret || context.resp_status) {
    264		dev_err(adev->dev, "TA invoke via debugfs failed (%d) status %d\n",
    265			 ret, context.resp_status);
    266		if (!ret)
    267			ret = -EINVAL;
    268		goto err_free_ta_shared_buf;
    269	}
    270
    271	if (copy_to_user((char *)buf, context.mem_context.shared_buf, shared_buf_len))
    272		ret = -EFAULT;
    273
    274err_free_ta_shared_buf:
    275	psp_ta_free_shared_buf(&context.mem_context);
    276
    277err_free_shared_buf:
    278	kfree(shared_buf);
    279
    280	return ret;
    281}
    282
    283void amdgpu_ta_if_debugfs_init(struct amdgpu_device *adev)
    284{
    285	struct drm_minor *minor = adev_to_drm(adev)->primary;
    286
    287	struct dentry *dir = debugfs_create_dir("ta_if", minor->debugfs_root);
    288
    289	debugfs_create_file("ta_load", 0200, dir, adev,
    290				     &ta_load_debugfs_fops);
    291
    292	debugfs_create_file("ta_unload", 0200, dir,
    293				     adev, &ta_unload_debugfs_fops);
    294
    295	debugfs_create_file("ta_invoke", 0200, dir,
    296				     adev, &ta_invoke_debugfs_fops);
    297}
    298
    299#else
    300void amdgpu_ta_if_debugfs_init(struct amdgpu_device *adev)
    301{
    302
    303}
    304#endif