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 29 static ssize_t ta_if_load_debugfs_write(struct file *fp, const char *buf, 30 size_t len, loff_t *off); 31 static ssize_t ta_if_unload_debugfs_write(struct file *fp, const char *buf, 32 size_t len, loff_t *off); 33 static ssize_t ta_if_invoke_debugfs_write(struct file *fp, const char *buf, 34 size_t len, loff_t *off); 35 36 static 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 44 static int prep_ta_mem_context(struct ta_mem_context *mem_context, 45 uint8_t *shared_buf, 46 uint32_t shared_buf_len) 47 { 48 if (mem_context->shared_mem_size < shared_buf_len) 49 return -EINVAL; 50 memset(mem_context->shared_buf, 0, mem_context->shared_mem_size); 51 memcpy((void *)mem_context->shared_buf, shared_buf, shared_buf_len); 52 53 return 0; 54 } 55 56 static bool is_ta_type_valid(enum ta_type_id ta_type) 57 { 58 switch (ta_type) { 59 case TA_TYPE_RAS: 60 return true; 61 default: 62 return false; 63 } 64 } 65 66 static const struct ta_funcs ras_ta_funcs = { 67 .fn_ta_initialize = psp_ras_initialize, 68 .fn_ta_invoke = psp_ras_invoke, 69 .fn_ta_terminate = psp_ras_terminate 70 }; 71 72 static void set_ta_context_funcs(struct psp_context *psp, 73 enum ta_type_id ta_type, 74 struct ta_context **pcontext) 75 { 76 switch (ta_type) { 77 case TA_TYPE_RAS: 78 *pcontext = &psp->ras_context.context; 79 psp->ta_funcs = &ras_ta_funcs; 80 break; 81 default: 82 break; 83 } 84 } 85 86 static const struct file_operations ta_load_debugfs_fops = { 87 .write = ta_if_load_debugfs_write, 88 .llseek = default_llseek, 89 .owner = THIS_MODULE 90 }; 91 92 static const struct file_operations ta_unload_debugfs_fops = { 93 .write = ta_if_unload_debugfs_write, 94 .llseek = default_llseek, 95 .owner = THIS_MODULE 96 }; 97 98 static const struct file_operations ta_invoke_debugfs_fops = { 99 .write = ta_if_invoke_debugfs_write, 100 .llseek = default_llseek, 101 .owner = THIS_MODULE 102 }; 103 104 /* 105 * DOC: AMDGPU TA debugfs interfaces 106 * 107 * Three debugfs interfaces can be opened by a program to 108 * load/invoke/unload TA, 109 * 110 * - /sys/kernel/debug/dri/<N>/ta_if/ta_load 111 * - /sys/kernel/debug/dri/<N>/ta_if/ta_invoke 112 * - /sys/kernel/debug/dri/<N>/ta_if/ta_unload 113 * 114 * How to use the interfaces in a program? 115 * 116 * A program needs to provide transmit buffer to the interfaces 117 * and will receive buffer from the interfaces below, 118 * 119 * - For TA load debugfs interface: 120 * Transmit buffer: 121 * - TA type (4bytes) 122 * - TA bin length (4bytes) 123 * - TA bin 124 * Receive buffer: 125 * - TA ID (4bytes) 126 * 127 * - For TA invoke debugfs interface: 128 * Transmit buffer: 129 * - TA type (4bytes) 130 * - TA ID (4bytes) 131 * - TA CMD ID (4bytes) 132 * - TA shard buf length 133 * (4bytes, value not beyond TA shared memory size) 134 * - TA shared buf 135 * Receive buffer: 136 * - TA shared buf 137 * 138 * - For TA unload debugfs interface: 139 * Transmit buffer: 140 * - TA type (4bytes) 141 * - TA ID (4bytes) 142 */ 143 144 static ssize_t ta_if_load_debugfs_write(struct file *fp, const char *buf, size_t len, loff_t *off) 145 { 146 uint32_t ta_type = 0; 147 uint32_t ta_bin_len = 0; 148 uint8_t *ta_bin = NULL; 149 uint32_t copy_pos = 0; 150 int ret = 0; 151 152 struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(fp)->i_private; 153 struct psp_context *psp = &adev->psp; 154 struct ta_context *context = NULL; 155 156 if (!buf) 157 return -EINVAL; 158 159 ret = copy_from_user((void *)&ta_type, &buf[copy_pos], sizeof(uint32_t)); 160 if (ret || (!is_ta_type_valid(ta_type))) 161 return -EFAULT; 162 163 copy_pos += sizeof(uint32_t); 164 165 ret = copy_from_user((void *)&ta_bin_len, &buf[copy_pos], sizeof(uint32_t)); 166 if (ret) 167 return -EFAULT; 168 169 copy_pos += sizeof(uint32_t); 170 171 ta_bin = kzalloc(ta_bin_len, GFP_KERNEL); 172 if (!ta_bin) 173 return -ENOMEM; 174 if (copy_from_user((void *)ta_bin, &buf[copy_pos], ta_bin_len)) { 175 ret = -EFAULT; 176 goto err_free_bin; 177 } 178 179 /* Set TA context and functions */ 180 set_ta_context_funcs(psp, ta_type, &context); 181 182 if (!psp->ta_funcs || !psp->ta_funcs->fn_ta_terminate) { 183 dev_err(adev->dev, "Unsupported function to terminate TA\n"); 184 ret = -EOPNOTSUPP; 185 goto err_free_bin; 186 } 187 188 /* 189 * Allocate TA shared buf in case shared buf was freed 190 * due to loading TA failed before. 191 */ 192 if (!context->mem_context.shared_buf) { 193 ret = psp_ta_init_shared_buf(psp, &context->mem_context); 194 if (ret) { 195 ret = -ENOMEM; 196 goto err_free_bin; 197 } 198 } 199 200 ret = psp_fn_ta_terminate(psp); 201 if (ret || context->resp_status) { 202 dev_err(adev->dev, 203 "Failed to unload embedded TA (%d) and status (0x%X)\n", 204 ret, context->resp_status); 205 if (!ret) 206 ret = -EINVAL; 207 goto err_free_ta_shared_buf; 208 } 209 210 /* Prepare TA context for TA initialization */ 211 context->ta_type = ta_type; 212 context->bin_desc.fw_version = get_bin_version(ta_bin); 213 context->bin_desc.size_bytes = ta_bin_len; 214 context->bin_desc.start_addr = ta_bin; 215 216 if (!psp->ta_funcs->fn_ta_initialize) { 217 dev_err(adev->dev, "Unsupported function to initialize TA\n"); 218 ret = -EOPNOTSUPP; 219 goto err_free_ta_shared_buf; 220 } 221 222 ret = psp_fn_ta_initialize(psp); 223 if (ret || context->resp_status) { 224 dev_err(adev->dev, "Failed to load TA via debugfs (%d) and status (0x%X)\n", 225 ret, context->resp_status); 226 if (!ret) 227 ret = -EINVAL; 228 goto err_free_ta_shared_buf; 229 } 230 231 if (copy_to_user((char *)buf, (void *)&context->session_id, sizeof(uint32_t))) 232 ret = -EFAULT; 233 234 err_free_ta_shared_buf: 235 /* Only free TA shared buf when returns error code */ 236 if (ret && context->mem_context.shared_buf) 237 psp_ta_free_shared_buf(&context->mem_context); 238 err_free_bin: 239 kfree(ta_bin); 240 241 return ret; 242 } 243 244 static ssize_t ta_if_unload_debugfs_write(struct file *fp, const char *buf, size_t len, loff_t *off) 245 { 246 uint32_t ta_type = 0; 247 uint32_t ta_id = 0; 248 uint32_t copy_pos = 0; 249 int ret = 0; 250 251 struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(fp)->i_private; 252 struct psp_context *psp = &adev->psp; 253 struct ta_context *context = NULL; 254 255 if (!buf) 256 return -EINVAL; 257 258 ret = copy_from_user((void *)&ta_type, &buf[copy_pos], sizeof(uint32_t)); 259 if (ret || (!is_ta_type_valid(ta_type))) 260 return -EFAULT; 261 262 copy_pos += sizeof(uint32_t); 263 264 ret = copy_from_user((void *)&ta_id, &buf[copy_pos], sizeof(uint32_t)); 265 if (ret) 266 return -EFAULT; 267 268 set_ta_context_funcs(psp, ta_type, &context); 269 context->session_id = ta_id; 270 271 if (!psp->ta_funcs || !psp->ta_funcs->fn_ta_terminate) { 272 dev_err(adev->dev, "Unsupported function to terminate TA\n"); 273 return -EOPNOTSUPP; 274 } 275 276 ret = psp_fn_ta_terminate(psp); 277 if (ret || context->resp_status) { 278 dev_err(adev->dev, "Failed to unload TA via debugfs (%d) and status (0x%X)\n", 279 ret, context->resp_status); 280 if (!ret) 281 ret = -EINVAL; 282 } 283 284 if (context->mem_context.shared_buf) 285 psp_ta_free_shared_buf(&context->mem_context); 286 287 return ret; 288 } 289 290 static ssize_t ta_if_invoke_debugfs_write(struct file *fp, const char *buf, size_t len, loff_t *off) 291 { 292 uint32_t ta_type = 0; 293 uint32_t ta_id = 0; 294 uint32_t cmd_id = 0; 295 uint32_t shared_buf_len = 0; 296 uint8_t *shared_buf = NULL; 297 uint32_t copy_pos = 0; 298 int ret = 0; 299 300 struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(fp)->i_private; 301 struct psp_context *psp = &adev->psp; 302 struct ta_context *context = NULL; 303 304 if (!buf) 305 return -EINVAL; 306 307 ret = copy_from_user((void *)&ta_type, &buf[copy_pos], sizeof(uint32_t)); 308 if (ret) 309 return -EFAULT; 310 copy_pos += sizeof(uint32_t); 311 312 ret = copy_from_user((void *)&ta_id, &buf[copy_pos], sizeof(uint32_t)); 313 if (ret) 314 return -EFAULT; 315 copy_pos += sizeof(uint32_t); 316 317 ret = copy_from_user((void *)&cmd_id, &buf[copy_pos], sizeof(uint32_t)); 318 if (ret) 319 return -EFAULT; 320 copy_pos += sizeof(uint32_t); 321 322 ret = copy_from_user((void *)&shared_buf_len, &buf[copy_pos], sizeof(uint32_t)); 323 if (ret) 324 return -EFAULT; 325 copy_pos += sizeof(uint32_t); 326 327 shared_buf = kzalloc(shared_buf_len, GFP_KERNEL); 328 if (!shared_buf) 329 return -ENOMEM; 330 if (copy_from_user((void *)shared_buf, &buf[copy_pos], shared_buf_len)) { 331 ret = -EFAULT; 332 goto err_free_shared_buf; 333 } 334 335 set_ta_context_funcs(psp, ta_type, &context); 336 337 if (!context->initialized) { 338 dev_err(adev->dev, "TA is not initialized\n"); 339 ret = -EINVAL; 340 goto err_free_shared_buf; 341 } 342 343 if (!psp->ta_funcs || !psp->ta_funcs->fn_ta_invoke) { 344 dev_err(adev->dev, "Unsupported function to invoke TA\n"); 345 ret = -EOPNOTSUPP; 346 goto err_free_shared_buf; 347 } 348 349 context->session_id = ta_id; 350 351 ret = prep_ta_mem_context(&context->mem_context, shared_buf, shared_buf_len); 352 if (ret) 353 goto err_free_shared_buf; 354 355 ret = psp_fn_ta_invoke(psp, cmd_id); 356 if (ret || context->resp_status) { 357 dev_err(adev->dev, "Failed to invoke TA via debugfs (%d) and status (0x%X)\n", 358 ret, context->resp_status); 359 if (!ret) { 360 ret = -EINVAL; 361 goto err_free_shared_buf; 362 } 363 } 364 365 if (copy_to_user((char *)&buf[copy_pos], context->mem_context.shared_buf, shared_buf_len)) 366 ret = -EFAULT; 367 368 err_free_shared_buf: 369 kfree(shared_buf); 370 371 return ret; 372 } 373 374 void amdgpu_ta_if_debugfs_init(struct amdgpu_device *adev) 375 { 376 struct drm_minor *minor = adev_to_drm(adev)->primary; 377 378 struct dentry *dir = debugfs_create_dir("ta_if", minor->debugfs_root); 379 380 debugfs_create_file("ta_load", 0200, dir, adev, 381 &ta_load_debugfs_fops); 382 383 debugfs_create_file("ta_unload", 0200, dir, 384 adev, &ta_unload_debugfs_fops); 385 386 debugfs_create_file("ta_invoke", 0200, dir, 387 adev, &ta_invoke_debugfs_fops); 388 } 389 390 #else 391 void amdgpu_ta_if_debugfs_init(struct amdgpu_device *adev) 392 { 393 394 } 395 #endif 396