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 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 55 static 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 70 static 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 76 static 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 82 static 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 126 static 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 187 err_free_bin: 188 kfree(ta_bin); 189 190 return ret; 191 } 192 193 static 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 218 static 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 274 err_free_ta_shared_buf: 275 psp_ta_free_shared_buf(&context.mem_context); 276 277 err_free_shared_buf: 278 kfree(shared_buf); 279 280 return ret; 281 } 282 283 void 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 300 void amdgpu_ta_if_debugfs_init(struct amdgpu_device *adev) 301 { 302 303 } 304 #endif 305