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 if (ta_bin_len > PSP_1_MEG) 170 return -EINVAL; 171 172 copy_pos += sizeof(uint32_t); 173 174 ta_bin = kzalloc(ta_bin_len, GFP_KERNEL); 175 if (!ta_bin) 176 return -ENOMEM; 177 if (copy_from_user((void *)ta_bin, &buf[copy_pos], ta_bin_len)) { 178 ret = -EFAULT; 179 goto err_free_bin; 180 } 181 182 /* Set TA context and functions */ 183 set_ta_context_funcs(psp, ta_type, &context); 184 185 if (!psp->ta_funcs || !psp->ta_funcs->fn_ta_terminate) { 186 dev_err(adev->dev, "Unsupported function to terminate TA\n"); 187 ret = -EOPNOTSUPP; 188 goto err_free_bin; 189 } 190 191 /* 192 * Allocate TA shared buf in case shared buf was freed 193 * due to loading TA failed before. 194 */ 195 if (!context->mem_context.shared_buf) { 196 ret = psp_ta_init_shared_buf(psp, &context->mem_context); 197 if (ret) { 198 ret = -ENOMEM; 199 goto err_free_bin; 200 } 201 } 202 203 ret = psp_fn_ta_terminate(psp); 204 if (ret || context->resp_status) { 205 dev_err(adev->dev, 206 "Failed to unload embedded TA (%d) and status (0x%X)\n", 207 ret, context->resp_status); 208 if (!ret) 209 ret = -EINVAL; 210 goto err_free_ta_shared_buf; 211 } 212 213 /* Prepare TA context for TA initialization */ 214 context->ta_type = ta_type; 215 context->bin_desc.fw_version = get_bin_version(ta_bin); 216 context->bin_desc.size_bytes = ta_bin_len; 217 context->bin_desc.start_addr = ta_bin; 218 219 if (!psp->ta_funcs->fn_ta_initialize) { 220 dev_err(adev->dev, "Unsupported function to initialize TA\n"); 221 ret = -EOPNOTSUPP; 222 goto err_free_ta_shared_buf; 223 } 224 225 ret = psp_fn_ta_initialize(psp); 226 if (ret || context->resp_status) { 227 dev_err(adev->dev, "Failed to load TA via debugfs (%d) and status (0x%X)\n", 228 ret, context->resp_status); 229 if (!ret) 230 ret = -EINVAL; 231 goto err_free_ta_shared_buf; 232 } 233 234 if (copy_to_user((char *)buf, (void *)&context->session_id, sizeof(uint32_t))) 235 ret = -EFAULT; 236 237 err_free_ta_shared_buf: 238 /* Only free TA shared buf when returns error code */ 239 if (ret && context->mem_context.shared_buf) 240 psp_ta_free_shared_buf(&context->mem_context); 241 err_free_bin: 242 kfree(ta_bin); 243 244 return ret; 245 } 246 247 static ssize_t ta_if_unload_debugfs_write(struct file *fp, const char *buf, size_t len, loff_t *off) 248 { 249 uint32_t ta_type = 0; 250 uint32_t ta_id = 0; 251 uint32_t copy_pos = 0; 252 int ret = 0; 253 254 struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(fp)->i_private; 255 struct psp_context *psp = &adev->psp; 256 struct ta_context *context = NULL; 257 258 if (!buf) 259 return -EINVAL; 260 261 ret = copy_from_user((void *)&ta_type, &buf[copy_pos], sizeof(uint32_t)); 262 if (ret || (!is_ta_type_valid(ta_type))) 263 return -EFAULT; 264 265 copy_pos += sizeof(uint32_t); 266 267 ret = copy_from_user((void *)&ta_id, &buf[copy_pos], sizeof(uint32_t)); 268 if (ret) 269 return -EFAULT; 270 271 set_ta_context_funcs(psp, ta_type, &context); 272 context->session_id = ta_id; 273 274 if (!psp->ta_funcs || !psp->ta_funcs->fn_ta_terminate) { 275 dev_err(adev->dev, "Unsupported function to terminate TA\n"); 276 return -EOPNOTSUPP; 277 } 278 279 ret = psp_fn_ta_terminate(psp); 280 if (ret || context->resp_status) { 281 dev_err(adev->dev, "Failed to unload TA via debugfs (%d) and status (0x%X)\n", 282 ret, context->resp_status); 283 if (!ret) 284 ret = -EINVAL; 285 } 286 287 if (context->mem_context.shared_buf) 288 psp_ta_free_shared_buf(&context->mem_context); 289 290 return ret; 291 } 292 293 static ssize_t ta_if_invoke_debugfs_write(struct file *fp, const char *buf, size_t len, loff_t *off) 294 { 295 uint32_t ta_type = 0; 296 uint32_t ta_id = 0; 297 uint32_t cmd_id = 0; 298 uint32_t shared_buf_len = 0; 299 uint8_t *shared_buf = NULL; 300 uint32_t copy_pos = 0; 301 int ret = 0; 302 303 struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(fp)->i_private; 304 struct psp_context *psp = &adev->psp; 305 struct ta_context *context = NULL; 306 307 if (!buf) 308 return -EINVAL; 309 310 ret = copy_from_user((void *)&ta_type, &buf[copy_pos], sizeof(uint32_t)); 311 if (ret) 312 return -EFAULT; 313 copy_pos += sizeof(uint32_t); 314 315 ret = copy_from_user((void *)&ta_id, &buf[copy_pos], sizeof(uint32_t)); 316 if (ret) 317 return -EFAULT; 318 copy_pos += sizeof(uint32_t); 319 320 ret = copy_from_user((void *)&cmd_id, &buf[copy_pos], sizeof(uint32_t)); 321 if (ret) 322 return -EFAULT; 323 copy_pos += sizeof(uint32_t); 324 325 ret = copy_from_user((void *)&shared_buf_len, &buf[copy_pos], sizeof(uint32_t)); 326 if (ret) 327 return -EFAULT; 328 copy_pos += sizeof(uint32_t); 329 330 shared_buf = kzalloc(shared_buf_len, GFP_KERNEL); 331 if (!shared_buf) 332 return -ENOMEM; 333 if (copy_from_user((void *)shared_buf, &buf[copy_pos], shared_buf_len)) { 334 ret = -EFAULT; 335 goto err_free_shared_buf; 336 } 337 338 set_ta_context_funcs(psp, ta_type, &context); 339 340 if (!context || !context->initialized) { 341 dev_err(adev->dev, "TA is not initialized\n"); 342 ret = -EINVAL; 343 goto err_free_shared_buf; 344 } 345 346 if (!psp->ta_funcs || !psp->ta_funcs->fn_ta_invoke) { 347 dev_err(adev->dev, "Unsupported function to invoke TA\n"); 348 ret = -EOPNOTSUPP; 349 goto err_free_shared_buf; 350 } 351 352 context->session_id = ta_id; 353 354 ret = prep_ta_mem_context(&context->mem_context, shared_buf, shared_buf_len); 355 if (ret) 356 goto err_free_shared_buf; 357 358 ret = psp_fn_ta_invoke(psp, cmd_id); 359 if (ret || context->resp_status) { 360 dev_err(adev->dev, "Failed to invoke TA via debugfs (%d) and status (0x%X)\n", 361 ret, context->resp_status); 362 if (!ret) { 363 ret = -EINVAL; 364 goto err_free_shared_buf; 365 } 366 } 367 368 if (copy_to_user((char *)&buf[copy_pos], context->mem_context.shared_buf, shared_buf_len)) 369 ret = -EFAULT; 370 371 err_free_shared_buf: 372 kfree(shared_buf); 373 374 return ret; 375 } 376 377 void amdgpu_ta_if_debugfs_init(struct amdgpu_device *adev) 378 { 379 struct drm_minor *minor = adev_to_drm(adev)->primary; 380 381 struct dentry *dir = debugfs_create_dir("ta_if", minor->debugfs_root); 382 383 debugfs_create_file("ta_load", 0200, dir, adev, 384 &ta_load_debugfs_fops); 385 386 debugfs_create_file("ta_unload", 0200, dir, 387 adev, &ta_unload_debugfs_fops); 388 389 debugfs_create_file("ta_invoke", 0200, dir, 390 adev, &ta_invoke_debugfs_fops); 391 } 392 393 #else 394 void amdgpu_ta_if_debugfs_init(struct amdgpu_device *adev) 395 { 396 397 } 398 #endif 399