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