Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/amdgpu: added support for psp fw attestation

loaded fw can be queried from sys fs interface

Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com>
Signed-off-by: John Clements <john.clements@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

John Clements and committed by
Alex Deucher
19ae3330 0165b85c

+250 -20
+2 -1
drivers/gpu/drm/amd/amdgpu/Makefile
··· 55 55 amdgpu_vf_error.o amdgpu_sched.o amdgpu_debugfs.o amdgpu_ids.o \ 56 56 amdgpu_gmc.o amdgpu_mmhub.o amdgpu_xgmi.o amdgpu_csa.o amdgpu_ras.o amdgpu_vm_cpu.o \ 57 57 amdgpu_vm_sdma.o amdgpu_discovery.o amdgpu_ras_eeprom.o amdgpu_nbio.o \ 58 - amdgpu_umc.o smu_v11_0_i2c.o amdgpu_fru_eeprom.o amdgpu_rap.o 58 + amdgpu_umc.o smu_v11_0_i2c.o amdgpu_fru_eeprom.o amdgpu_rap.o \ 59 + amdgpu_fw_attestation.o 59 60 60 61 amdgpu-$(CONFIG_PERF_EVENTS) += amdgpu_pmu.o 61 62
+3
drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
··· 35 35 #include "amdgpu_dm_debugfs.h" 36 36 #include "amdgpu_ras.h" 37 37 #include "amdgpu_rap.h" 38 + #include "amdgpu_fw_attestation.h" 38 39 39 40 /** 40 41 * amdgpu_debugfs_add_files - Add simple debugfs entries ··· 1665 1664 amdgpu_debugfs_autodump_init(adev); 1666 1665 1667 1666 amdgpu_rap_debugfs_init(adev); 1667 + 1668 + amdgpu_fw_attestation_debugfs_init(adev); 1668 1669 1669 1670 return amdgpu_debugfs_add_files(adev, amdgpu_debugfs_list, 1670 1671 ARRAY_SIZE(amdgpu_debugfs_list));
+142
drivers/gpu/drm/amd/amdgpu/amdgpu_fw_attestation.c
··· 1 + /* 2 + * Copyright 2020 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 <linux/debugfs.h> 25 + #include <linux/firmware.h> 26 + #include <linux/dma-mapping.h> 27 + 28 + #include "amdgpu.h" 29 + #include "amdgpu_psp.h" 30 + #include "amdgpu_ucode.h" 31 + #include "soc15_common.h" 32 + 33 + #define FW_ATTESTATION_DB_COOKIE 0x143b6a37 34 + #define FW_ATTESTATION_RECORD_VALID 1 35 + #define FW_ATTESTATION_MAX_SIZE 4096 36 + 37 + typedef struct FW_ATT_DB_HEADER 38 + { 39 + uint32_t AttDbVersion; /* version of the fwar feature */ 40 + uint32_t AttDbCookie; /* cookie as an extra check for corrupt data */ 41 + } FW_ATT_DB_HEADER; 42 + 43 + typedef struct FW_ATT_RECORD 44 + { 45 + uint16_t AttFwIdV1; /* Legacy FW Type field */ 46 + uint16_t AttFwIdV2; /* V2 FW ID field */ 47 + uint32_t AttFWVersion; /* FW Version */ 48 + uint16_t AttFWActiveFunctionID; /* The VF ID (only in VF Attestation Table) */ 49 + uint16_t AttSource; /* FW source indicator */ 50 + uint16_t RecordValid; /* Indicates whether the record is a valid entry */ 51 + uint8_t AttFwTaId; /* Ta ID (only in TA Attestation Table) */ 52 + uint8_t Reserved; 53 + } FW_ATT_RECORD; 54 + 55 + static ssize_t amdgpu_fw_attestation_debugfs_read(struct file *f, 56 + char __user *buf, 57 + size_t size, 58 + loff_t *pos) 59 + { 60 + struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(f)->i_private; 61 + uint64_t records_addr = 0; 62 + uint64_t vram_pos = 0; 63 + FW_ATT_DB_HEADER fw_att_hdr = {0}; 64 + FW_ATT_RECORD fw_att_record = {0}; 65 + 66 + if (size < sizeof(FW_ATT_RECORD)) { 67 + DRM_WARN("FW attestation input buffer not enough memory"); 68 + return -EINVAL; 69 + } 70 + 71 + if ((*pos + sizeof(FW_ATT_DB_HEADER)) >= FW_ATTESTATION_MAX_SIZE) { 72 + DRM_WARN("FW attestation out of bounds"); 73 + return 0; 74 + } 75 + 76 + if (psp_get_fw_attestation_records_addr(&adev->psp, &records_addr)) { 77 + DRM_WARN("Failed to get FW attestation record address"); 78 + return -EINVAL; 79 + } 80 + 81 + vram_pos = records_addr - adev->gmc.vram_start; 82 + 83 + if (*pos == 0) { 84 + amdgpu_device_vram_access(adev, 85 + vram_pos, 86 + (uint32_t*)&fw_att_hdr, 87 + sizeof(FW_ATT_DB_HEADER), 88 + false); 89 + 90 + if (fw_att_hdr.AttDbCookie != FW_ATTESTATION_DB_COOKIE) { 91 + DRM_WARN("Invalid FW attestation cookie"); 92 + return -EINVAL; 93 + } 94 + 95 + DRM_INFO("FW attestation version = 0x%X", fw_att_hdr.AttDbVersion); 96 + } 97 + 98 + amdgpu_device_vram_access(adev, 99 + vram_pos + sizeof(FW_ATT_DB_HEADER) + *pos, 100 + (uint32_t*)&fw_att_record, 101 + sizeof(FW_ATT_RECORD), 102 + false); 103 + 104 + if (fw_att_record.RecordValid != FW_ATTESTATION_RECORD_VALID) 105 + return 0; 106 + 107 + if (copy_to_user(buf, (void*)&fw_att_record, sizeof(FW_ATT_RECORD))) 108 + return -EINVAL; 109 + 110 + *pos += sizeof(FW_ATT_RECORD); 111 + 112 + return sizeof(FW_ATT_RECORD); 113 + } 114 + 115 + static const struct file_operations amdgpu_fw_attestation_debugfs_ops = { 116 + .owner = THIS_MODULE, 117 + .read = amdgpu_fw_attestation_debugfs_read, 118 + .write = NULL, 119 + .llseek = default_llseek 120 + }; 121 + 122 + static int amdgpu_is_fw_attestation_supported(struct amdgpu_device *adev) 123 + { 124 + if (adev->asic_type >= CHIP_SIENNA_CICHLID) 125 + return 1; 126 + 127 + return 0; 128 + } 129 + 130 + void amdgpu_fw_attestation_debugfs_init(struct amdgpu_device *adev) 131 + { 132 + #if defined(CONFIG_DEBUG_FS) 133 + if (!amdgpu_is_fw_attestation_supported(adev)) 134 + return; 135 + 136 + debugfs_create_file("amdgpu_fw_attestation", 137 + S_IRUSR, 138 + adev_to_drm(adev)->primary->debugfs_root, 139 + adev, 140 + &amdgpu_fw_attestation_debugfs_ops); 141 + #endif 142 + }
+30
drivers/gpu/drm/amd/amdgpu/amdgpu_fw_attestation.h
··· 1 + /* 2 + * Copyright 2020 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 + #ifndef _AMDGPU_FW_ATTESTATION_H 25 + #define _AMDGPU_FW_ATTESTATION_H 26 + 27 + #include "amdgpu.h" 28 + 29 + void amdgpu_fw_attestation_debugfs_init(struct amdgpu_device *adev); 30 + #endif
+33 -3
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
··· 290 290 skip_unsupport = (psp->cmd_buf_mem->resp.status == TEE_ERROR_NOT_SUPPORTED || 291 291 psp->cmd_buf_mem->resp.status == PSP_ERR_UNKNOWN_COMMAND) && amdgpu_sriov_vf(psp->adev); 292 292 293 + memcpy((void*)&cmd->resp, (void*)&psp->cmd_buf_mem->resp, sizeof(struct psp_gfx_resp)); 294 + 293 295 /* In some cases, psp response status is not 0 even there is no 294 296 * problem while the command is submitted. Some version of PSP FW 295 297 * doesn't write 0 to that field. ··· 311 309 return -EINVAL; 312 310 } 313 311 } 314 - 315 - /* get xGMI session id from response buffer */ 316 - cmd->resp.session_id = psp->cmd_buf_mem->resp.session_id; 317 312 318 313 if (ucode) { 319 314 ucode->tmr_mc_addr_lo = psp->cmd_buf_mem->resp.fw_addr_lo; ··· 508 509 amdgpu_bo_free_kernel(&psp->tmr_bo, &psp->tmr_mc_addr, pptr); 509 510 510 511 return 0; 512 + } 513 + 514 + int psp_get_fw_attestation_records_addr(struct psp_context *psp, 515 + uint64_t *output_ptr) 516 + { 517 + int ret; 518 + struct psp_gfx_cmd_resp *cmd; 519 + 520 + if (!output_ptr) 521 + return -EINVAL; 522 + 523 + if (amdgpu_sriov_vf(psp->adev)) 524 + return 0; 525 + 526 + cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); 527 + if (!cmd) 528 + return -ENOMEM; 529 + 530 + cmd->cmd_id = GFX_CMD_ID_GET_FW_ATTESTATION; 531 + 532 + ret = psp_cmd_submit_buf(psp, NULL, cmd, 533 + psp->fence_buf_mc_addr); 534 + 535 + if (!ret) { 536 + *output_ptr = ((uint64_t)cmd->resp.uresp.fwar_db_info.fwar_db_addr_lo) + 537 + ((uint64_t)cmd->resp.uresp.fwar_db_info.fwar_db_addr_hi << 32); 538 + } 539 + 540 + kfree(cmd); 541 + 542 + return ret; 511 543 } 512 544 513 545 static void psp_prep_asd_load_cmd_buf(struct psp_gfx_cmd_resp *cmd,
+2
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h
··· 398 398 const char *chip_name); 399 399 int psp_init_ta_microcode(struct psp_context *psp, 400 400 const char *chip_name); 401 + int psp_get_fw_attestation_records_addr(struct psp_context *psp, 402 + uint64_t *output_ptr); 401 403 #endif
+38 -16
drivers/gpu/drm/amd/amdgpu/psp_gfx_if.h
··· 86 86 /* TEE Gfx Command IDs for the ring buffer interface. */ 87 87 enum psp_gfx_cmd_id 88 88 { 89 - GFX_CMD_ID_LOAD_TA = 0x00000001, /* load TA */ 90 - GFX_CMD_ID_UNLOAD_TA = 0x00000002, /* unload TA */ 91 - GFX_CMD_ID_INVOKE_CMD = 0x00000003, /* send command to TA */ 92 - GFX_CMD_ID_LOAD_ASD = 0x00000004, /* load ASD Driver */ 93 - GFX_CMD_ID_SETUP_TMR = 0x00000005, /* setup TMR region */ 94 - GFX_CMD_ID_LOAD_IP_FW = 0x00000006, /* load HW IP FW */ 95 - GFX_CMD_ID_DESTROY_TMR = 0x00000007, /* destroy TMR region */ 96 - GFX_CMD_ID_SAVE_RESTORE = 0x00000008, /* save/restore HW IP FW */ 97 - GFX_CMD_ID_SETUP_VMR = 0x00000009, /* setup VMR region */ 98 - GFX_CMD_ID_DESTROY_VMR = 0x0000000A, /* destroy VMR region */ 99 - GFX_CMD_ID_PROG_REG = 0x0000000B, /* program regs */ 100 - GFX_CMD_ID_CLEAR_VF_FW = 0x0000000D, /* Clear VF FW, to be used on VF shutdown. */ 89 + GFX_CMD_ID_LOAD_TA = 0x00000001, /* load TA */ 90 + GFX_CMD_ID_UNLOAD_TA = 0x00000002, /* unload TA */ 91 + GFX_CMD_ID_INVOKE_CMD = 0x00000003, /* send command to TA */ 92 + GFX_CMD_ID_LOAD_ASD = 0x00000004, /* load ASD Driver */ 93 + GFX_CMD_ID_SETUP_TMR = 0x00000005, /* setup TMR region */ 94 + GFX_CMD_ID_LOAD_IP_FW = 0x00000006, /* load HW IP FW */ 95 + GFX_CMD_ID_DESTROY_TMR = 0x00000007, /* destroy TMR region */ 96 + GFX_CMD_ID_SAVE_RESTORE = 0x00000008, /* save/restore HW IP FW */ 97 + GFX_CMD_ID_SETUP_VMR = 0x00000009, /* setup VMR region */ 98 + GFX_CMD_ID_DESTROY_VMR = 0x0000000A, /* destroy VMR region */ 99 + GFX_CMD_ID_PROG_REG = 0x0000000B, /* program regs */ 100 + GFX_CMD_ID_CLEAR_VF_FW = 0x0000000D, /* Clear VF FW, to be used on VF shutdown. */ 101 + GFX_CMD_ID_GET_FW_ATTESTATION = 0x0000000F, /* Query GPUVA of the Fw Attestation DB */ 101 102 /* IDs upto 0x1F are reserved for older programs (Raven, Vega 10/12/20) */ 102 - GFX_CMD_ID_LOAD_TOC = 0x00000020, /* Load TOC and obtain TMR size */ 103 - GFX_CMD_ID_AUTOLOAD_RLC = 0x00000021, /* Indicates all graphics fw loaded, start RLC autoload */ 103 + GFX_CMD_ID_LOAD_TOC = 0x00000020, /* Load TOC and obtain TMR size */ 104 + GFX_CMD_ID_AUTOLOAD_RLC = 0x00000021, /* Indicates all graphics fw loaded, start RLC autoload */ 104 105 }; 105 106 106 107 /* Command to load Trusted Application binary into PSP OS. */ ··· 286 285 struct psp_gfx_cmd_load_toc cmd_load_toc; 287 286 }; 288 287 288 + struct psp_gfx_uresp_reserved 289 + { 290 + uint32_t reserved[8]; 291 + }; 292 + 293 + /* Command-specific response for Fw Attestation Db */ 294 + struct psp_gfx_uresp_fwar_db_info 295 + { 296 + uint32_t fwar_db_addr_lo; 297 + uint32_t fwar_db_addr_hi; 298 + }; 299 + 300 + /* Union of command-specific responses for GPCOM ring. */ 301 + union psp_gfx_uresp 302 + { 303 + struct psp_gfx_uresp_reserved reserved; 304 + struct psp_gfx_uresp_fwar_db_info fwar_db_info; 305 + }; 306 + 289 307 /* Structure of GFX Response buffer. 290 308 * For GPCOM I/F it is part of GFX_CMD_RESP buffer, for RBI 291 309 * it is separate buffer. ··· 317 297 uint32_t fw_addr_hi; /* +12 bits [63:32] of FW address within TMR (in response to cmd_load_ip_fw command) */ 318 298 uint32_t tmr_size; /* +16 size of the TMR to be reserved including MM fw and Gfx fw in response to cmd_load_toc command */ 319 299 320 - uint32_t reserved[3]; 300 + uint32_t reserved[11]; 321 301 322 - /* total 32 bytes */ 302 + union psp_gfx_uresp uresp; /* +64 response union containing command-specific responses */ 303 + 304 + /* total 96 bytes */ 323 305 }; 324 306 325 307 /* Structure of Command buffer pointed by psp_gfx_rb_frame.cmd_buf_addr_hi