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 static const char *TA_IF_FS_NAME = "ta_if"; 28 29 struct dentry *dir; 30 static struct dentry *ta_load_debugfs_dentry; 31 static struct dentry *ta_unload_debugfs_dentry; 32 static struct dentry *ta_invoke_debugfs_dentry; 33 34 static ssize_t ta_if_load_debugfs_write(struct file *fp, const char *buf, 35 size_t len, loff_t *off); 36 static ssize_t ta_if_unload_debugfs_write(struct file *fp, const char *buf, 37 size_t len, loff_t *off); 38 static ssize_t ta_if_invoke_debugfs_write(struct file *fp, const char *buf, 39 size_t len, loff_t *off); 40 41 42 static uint32_t get_bin_version(const uint8_t *bin) 43 { 44 const struct common_firmware_header *hdr = 45 (const struct common_firmware_header *)bin; 46 47 return hdr->ucode_version; 48 } 49 50 static void prep_ta_mem_context(struct psp_context *psp, 51 struct ta_context *context, 52 uint8_t *shared_buf, 53 uint32_t shared_buf_len) 54 { 55 context->mem_context.shared_mem_size = PAGE_ALIGN(shared_buf_len); 56 psp_ta_init_shared_buf(psp, &context->mem_context); 57 58 memcpy((void *)context->mem_context.shared_buf, shared_buf, shared_buf_len); 59 } 60 61 static bool is_ta_type_valid(enum ta_type_id ta_type) 62 { 63 bool ret = false; 64 65 switch (ta_type) { 66 case TA_TYPE_RAS: 67 ret = true; 68 break; 69 default: 70 break; 71 } 72 73 return ret; 74 } 75 76 static const struct file_operations ta_load_debugfs_fops = { 77 .write = ta_if_load_debugfs_write, 78 .llseek = default_llseek, 79 .owner = THIS_MODULE 80 }; 81 82 static const struct file_operations ta_unload_debugfs_fops = { 83 .write = ta_if_unload_debugfs_write, 84 .llseek = default_llseek, 85 .owner = THIS_MODULE 86 }; 87 88 static const struct file_operations ta_invoke_debugfs_fops = { 89 .write = ta_if_invoke_debugfs_write, 90 .llseek = default_llseek, 91 .owner = THIS_MODULE 92 }; 93 94 95 /** 96 * DOC: AMDGPU TA debugfs interfaces 97 * 98 * Three debugfs interfaces can be opened by a program to 99 * load/invoke/unload TA, 100 * 101 * - /sys/kernel/debug/dri/<N>/ta_if/ta_load 102 * - /sys/kernel/debug/dri/<N>/ta_if/ta_invoke 103 * - /sys/kernel/debug/dri/<N>/ta_if/ta_unload 104 * 105 * How to use the interfaces in a program? 106 * 107 * A program needs to provide transmit buffer to the interfaces 108 * and will receive buffer from the interfaces below, 109 * 110 * - For TA load debugfs interface: 111 * Transmit buffer: 112 * - TA type (4bytes) 113 * - TA bin length (4bytes) 114 * - TA bin 115 * Receive buffer: 116 * - TA ID (4bytes) 117 * 118 * - For TA invoke debugfs interface: 119 * Transmit buffer: 120 * - TA ID (4bytes) 121 * - TA CMD ID (4bytes) 122 * - TA shard buf length (4bytes) 123 * - TA shared buf 124 * Receive buffer: 125 * - TA shared buf 126 * 127 * - For TA unload debugfs interface: 128 * Transmit buffer: 129 * - TA ID (4bytes) 130 */ 131 132 static ssize_t ta_if_load_debugfs_write(struct file *fp, const char *buf, size_t len, loff_t *off) 133 { 134 uint32_t ta_type = 0; 135 uint32_t ta_bin_len = 0; 136 uint8_t *ta_bin = NULL; 137 uint32_t copy_pos = 0; 138 int ret = 0; 139 140 struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(fp)->i_private; 141 struct psp_context *psp = &adev->psp; 142 struct ta_context context = {0}; 143 144 if (!buf) 145 return -EINVAL; 146 147 ret = copy_from_user((void *)&ta_type, &buf[copy_pos], sizeof(uint32_t)); 148 if (ret || (!is_ta_type_valid(ta_type))) 149 return -EINVAL; 150 151 copy_pos += sizeof(uint32_t); 152 153 ret = copy_from_user((void *)&ta_bin_len, &buf[copy_pos], sizeof(uint32_t)); 154 if (ret) 155 return -EINVAL; 156 157 copy_pos += sizeof(uint32_t); 158 159 ta_bin = kzalloc(ta_bin_len, GFP_KERNEL); 160 if (!ta_bin) 161 ret = -ENOMEM; 162 if (copy_from_user((void *)ta_bin, &buf[copy_pos], ta_bin_len)) { 163 ret = -EFAULT; 164 goto err_free_bin; 165 } 166 167 ret = psp_ras_terminate(psp); 168 if (ret) { 169 dev_err(adev->dev, "Failed to unload embedded RAS TA\n"); 170 goto err_free_bin; 171 } 172 173 context.ta_type = ta_type; 174 context.ta_load_type = GFX_CMD_ID_LOAD_TA; 175 context.bin_desc.fw_version = get_bin_version(ta_bin); 176 context.bin_desc.size_bytes = ta_bin_len; 177 context.bin_desc.start_addr = ta_bin; 178 179 ret = psp_ta_load(psp, &context); 180 181 if (ret || context.resp_status) { 182 dev_err(adev->dev, "TA load via debugfs failed (%d) status %d\n", 183 ret, context.resp_status); 184 if (!ret) 185 ret = -EINVAL; 186 goto err_free_bin; 187 } 188 189 context.initialized = true; 190 if (copy_to_user((char *)buf, (void *)&context.session_id, sizeof(uint32_t))) 191 ret = -EFAULT; 192 193 err_free_bin: 194 kfree(ta_bin); 195 196 return ret; 197 } 198 199 static ssize_t ta_if_unload_debugfs_write(struct file *fp, const char *buf, size_t len, loff_t *off) 200 { 201 uint32_t ta_id = 0; 202 int ret = 0; 203 204 struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(fp)->i_private; 205 struct psp_context *psp = &adev->psp; 206 struct ta_context context = {0}; 207 208 if (!buf) 209 return -EINVAL; 210 211 ret = copy_from_user((void *)&ta_id, buf, sizeof(uint32_t)); 212 if (ret) 213 return -EINVAL; 214 215 context.session_id = ta_id; 216 217 ret = psp_ta_unload(psp, &context); 218 if (!ret) 219 context.initialized = false; 220 221 return ret; 222 } 223 224 static ssize_t ta_if_invoke_debugfs_write(struct file *fp, const char *buf, size_t len, loff_t *off) 225 { 226 uint32_t ta_id = 0; 227 uint32_t cmd_id = 0; 228 uint32_t shared_buf_len = 0; 229 uint8_t *shared_buf = NULL; 230 uint32_t copy_pos = 0; 231 int ret = 0; 232 233 struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(fp)->i_private; 234 struct psp_context *psp = &adev->psp; 235 struct ta_context context = {0}; 236 237 if (!buf) 238 return -EINVAL; 239 240 ret = copy_from_user((void *)&ta_id, &buf[copy_pos], sizeof(uint32_t)); 241 if (ret) 242 return -EINVAL; 243 copy_pos += sizeof(uint32_t); 244 245 ret = copy_from_user((void *)&cmd_id, &buf[copy_pos], sizeof(uint32_t)); 246 if (ret) 247 return -EINVAL; 248 copy_pos += sizeof(uint32_t); 249 250 ret = copy_from_user((void *)&shared_buf_len, &buf[copy_pos], sizeof(uint32_t)); 251 if (ret) 252 return -EINVAL; 253 copy_pos += sizeof(uint32_t); 254 255 shared_buf = kzalloc(shared_buf_len, GFP_KERNEL); 256 if (!shared_buf) 257 return -ENOMEM; 258 if (copy_from_user((void *)shared_buf, &buf[copy_pos], shared_buf_len)) { 259 ret = -EFAULT; 260 goto err_free_shared_buf; 261 } 262 263 context.session_id = ta_id; 264 265 prep_ta_mem_context(psp, &context, shared_buf, shared_buf_len); 266 267 ret = psp_ta_invoke_indirect(psp, cmd_id, &context); 268 269 if (ret || context.resp_status) { 270 dev_err(adev->dev, "TA invoke via debugfs failed (%d) status %d\n", 271 ret, context.resp_status); 272 if (!ret) 273 ret = -EINVAL; 274 goto err_free_ta_shared_buf; 275 } 276 277 if (copy_to_user((char *)buf, context.mem_context.shared_buf, shared_buf_len)) 278 ret = -EFAULT; 279 280 err_free_ta_shared_buf: 281 psp_ta_free_shared_buf(&context.mem_context); 282 283 err_free_shared_buf: 284 kfree(shared_buf); 285 286 return ret; 287 } 288 289 static struct dentry *amdgpu_ta_if_debugfs_create(struct amdgpu_device *adev) 290 { 291 struct drm_minor *minor = adev_to_drm(adev)->primary; 292 293 dir = debugfs_create_dir(TA_IF_FS_NAME, minor->debugfs_root); 294 295 ta_load_debugfs_dentry = debugfs_create_file("ta_load", 0200, dir, adev, 296 &ta_load_debugfs_fops); 297 298 ta_unload_debugfs_dentry = debugfs_create_file("ta_unload", 0200, dir, 299 adev, &ta_unload_debugfs_fops); 300 301 ta_invoke_debugfs_dentry = debugfs_create_file("ta_invoke", 0200, dir, 302 adev, &ta_invoke_debugfs_fops); 303 return dir; 304 } 305 306 void amdgpu_ta_if_debugfs_init(struct amdgpu_device *adev) 307 { 308 #if defined(CONFIG_DEBUG_FS) 309 dir = amdgpu_ta_if_debugfs_create(adev); 310 #endif 311 } 312 313 void amdgpu_ta_if_debugfs_remove(void) 314 { 315 debugfs_remove_recursive(dir); 316 } 317