Commit 19ae3330 authored by John Clements's avatar John Clements Committed by Alex Deucher

drm/amdgpu: added support for psp fw attestation

loaded fw can be queried from sys fs interface
Reviewed-by: default avatarHawking Zhang <Hawking.Zhang@amd.com>
Signed-off-by: default avatarJohn Clements <john.clements@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 0165b85c
...@@ -55,7 +55,8 @@ amdgpu-y += amdgpu_device.o amdgpu_kms.o \ ...@@ -55,7 +55,8 @@ amdgpu-y += amdgpu_device.o amdgpu_kms.o \
amdgpu_vf_error.o amdgpu_sched.o amdgpu_debugfs.o amdgpu_ids.o \ amdgpu_vf_error.o amdgpu_sched.o amdgpu_debugfs.o amdgpu_ids.o \
amdgpu_gmc.o amdgpu_mmhub.o amdgpu_xgmi.o amdgpu_csa.o amdgpu_ras.o amdgpu_vm_cpu.o \ amdgpu_gmc.o amdgpu_mmhub.o amdgpu_xgmi.o amdgpu_csa.o amdgpu_ras.o amdgpu_vm_cpu.o \
amdgpu_vm_sdma.o amdgpu_discovery.o amdgpu_ras_eeprom.o amdgpu_nbio.o \ amdgpu_vm_sdma.o amdgpu_discovery.o amdgpu_ras_eeprom.o amdgpu_nbio.o \
amdgpu_umc.o smu_v11_0_i2c.o amdgpu_fru_eeprom.o amdgpu_rap.o amdgpu_umc.o smu_v11_0_i2c.o amdgpu_fru_eeprom.o amdgpu_rap.o \
amdgpu_fw_attestation.o
amdgpu-$(CONFIG_PERF_EVENTS) += amdgpu_pmu.o amdgpu-$(CONFIG_PERF_EVENTS) += amdgpu_pmu.o
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include "amdgpu_dm_debugfs.h" #include "amdgpu_dm_debugfs.h"
#include "amdgpu_ras.h" #include "amdgpu_ras.h"
#include "amdgpu_rap.h" #include "amdgpu_rap.h"
#include "amdgpu_fw_attestation.h"
/** /**
* amdgpu_debugfs_add_files - Add simple debugfs entries * amdgpu_debugfs_add_files - Add simple debugfs entries
...@@ -1665,6 +1666,8 @@ int amdgpu_debugfs_init(struct amdgpu_device *adev) ...@@ -1665,6 +1666,8 @@ int amdgpu_debugfs_init(struct amdgpu_device *adev)
amdgpu_rap_debugfs_init(adev); amdgpu_rap_debugfs_init(adev);
amdgpu_fw_attestation_debugfs_init(adev);
return amdgpu_debugfs_add_files(adev, amdgpu_debugfs_list, return amdgpu_debugfs_add_files(adev, amdgpu_debugfs_list,
ARRAY_SIZE(amdgpu_debugfs_list)); ARRAY_SIZE(amdgpu_debugfs_list));
} }
......
/*
* Copyright 2020 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
*/
#include <linux/debugfs.h>
#include <linux/firmware.h>
#include <linux/dma-mapping.h>
#include "amdgpu.h"
#include "amdgpu_psp.h"
#include "amdgpu_ucode.h"
#include "soc15_common.h"
#define FW_ATTESTATION_DB_COOKIE 0x143b6a37
#define FW_ATTESTATION_RECORD_VALID 1
#define FW_ATTESTATION_MAX_SIZE 4096
typedef struct FW_ATT_DB_HEADER
{
uint32_t AttDbVersion; /* version of the fwar feature */
uint32_t AttDbCookie; /* cookie as an extra check for corrupt data */
} FW_ATT_DB_HEADER;
typedef struct FW_ATT_RECORD
{
uint16_t AttFwIdV1; /* Legacy FW Type field */
uint16_t AttFwIdV2; /* V2 FW ID field */
uint32_t AttFWVersion; /* FW Version */
uint16_t AttFWActiveFunctionID; /* The VF ID (only in VF Attestation Table) */
uint16_t AttSource; /* FW source indicator */
uint16_t RecordValid; /* Indicates whether the record is a valid entry */
uint8_t AttFwTaId; /* Ta ID (only in TA Attestation Table) */
uint8_t Reserved;
} FW_ATT_RECORD;
static ssize_t amdgpu_fw_attestation_debugfs_read(struct file *f,
char __user *buf,
size_t size,
loff_t *pos)
{
struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(f)->i_private;
uint64_t records_addr = 0;
uint64_t vram_pos = 0;
FW_ATT_DB_HEADER fw_att_hdr = {0};
FW_ATT_RECORD fw_att_record = {0};
if (size < sizeof(FW_ATT_RECORD)) {
DRM_WARN("FW attestation input buffer not enough memory");
return -EINVAL;
}
if ((*pos + sizeof(FW_ATT_DB_HEADER)) >= FW_ATTESTATION_MAX_SIZE) {
DRM_WARN("FW attestation out of bounds");
return 0;
}
if (psp_get_fw_attestation_records_addr(&adev->psp, &records_addr)) {
DRM_WARN("Failed to get FW attestation record address");
return -EINVAL;
}
vram_pos = records_addr - adev->gmc.vram_start;
if (*pos == 0) {
amdgpu_device_vram_access(adev,
vram_pos,
(uint32_t*)&fw_att_hdr,
sizeof(FW_ATT_DB_HEADER),
false);
if (fw_att_hdr.AttDbCookie != FW_ATTESTATION_DB_COOKIE) {
DRM_WARN("Invalid FW attestation cookie");
return -EINVAL;
}
DRM_INFO("FW attestation version = 0x%X", fw_att_hdr.AttDbVersion);
}
amdgpu_device_vram_access(adev,
vram_pos + sizeof(FW_ATT_DB_HEADER) + *pos,
(uint32_t*)&fw_att_record,
sizeof(FW_ATT_RECORD),
false);
if (fw_att_record.RecordValid != FW_ATTESTATION_RECORD_VALID)
return 0;
if (copy_to_user(buf, (void*)&fw_att_record, sizeof(FW_ATT_RECORD)))
return -EINVAL;
*pos += sizeof(FW_ATT_RECORD);
return sizeof(FW_ATT_RECORD);
}
static const struct file_operations amdgpu_fw_attestation_debugfs_ops = {
.owner = THIS_MODULE,
.read = amdgpu_fw_attestation_debugfs_read,
.write = NULL,
.llseek = default_llseek
};
static int amdgpu_is_fw_attestation_supported(struct amdgpu_device *adev)
{
if (adev->asic_type >= CHIP_SIENNA_CICHLID)
return 1;
return 0;
}
void amdgpu_fw_attestation_debugfs_init(struct amdgpu_device *adev)
{
#if defined(CONFIG_DEBUG_FS)
if (!amdgpu_is_fw_attestation_supported(adev))
return;
debugfs_create_file("amdgpu_fw_attestation",
S_IRUSR,
adev_to_drm(adev)->primary->debugfs_root,
adev,
&amdgpu_fw_attestation_debugfs_ops);
#endif
}
\ No newline at end of file
/*
* Copyright 2020 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
*
*/
#ifndef _AMDGPU_FW_ATTESTATION_H
#define _AMDGPU_FW_ATTESTATION_H
#include "amdgpu.h"
void amdgpu_fw_attestation_debugfs_init(struct amdgpu_device *adev);
#endif
...@@ -290,6 +290,8 @@ psp_cmd_submit_buf(struct psp_context *psp, ...@@ -290,6 +290,8 @@ psp_cmd_submit_buf(struct psp_context *psp,
skip_unsupport = (psp->cmd_buf_mem->resp.status == TEE_ERROR_NOT_SUPPORTED || skip_unsupport = (psp->cmd_buf_mem->resp.status == TEE_ERROR_NOT_SUPPORTED ||
psp->cmd_buf_mem->resp.status == PSP_ERR_UNKNOWN_COMMAND) && amdgpu_sriov_vf(psp->adev); psp->cmd_buf_mem->resp.status == PSP_ERR_UNKNOWN_COMMAND) && amdgpu_sriov_vf(psp->adev);
memcpy((void*)&cmd->resp, (void*)&psp->cmd_buf_mem->resp, sizeof(struct psp_gfx_resp));
/* In some cases, psp response status is not 0 even there is no /* In some cases, psp response status is not 0 even there is no
* problem while the command is submitted. Some version of PSP FW * problem while the command is submitted. Some version of PSP FW
* doesn't write 0 to that field. * doesn't write 0 to that field.
...@@ -310,9 +312,6 @@ psp_cmd_submit_buf(struct psp_context *psp, ...@@ -310,9 +312,6 @@ psp_cmd_submit_buf(struct psp_context *psp,
} }
} }
/* get xGMI session id from response buffer */
cmd->resp.session_id = psp->cmd_buf_mem->resp.session_id;
if (ucode) { if (ucode) {
ucode->tmr_mc_addr_lo = psp->cmd_buf_mem->resp.fw_addr_lo; ucode->tmr_mc_addr_lo = psp->cmd_buf_mem->resp.fw_addr_lo;
ucode->tmr_mc_addr_hi = psp->cmd_buf_mem->resp.fw_addr_hi; ucode->tmr_mc_addr_hi = psp->cmd_buf_mem->resp.fw_addr_hi;
...@@ -511,6 +510,37 @@ static int psp_tmr_terminate(struct psp_context *psp) ...@@ -511,6 +510,37 @@ static int psp_tmr_terminate(struct psp_context *psp)
return 0; return 0;
} }
int psp_get_fw_attestation_records_addr(struct psp_context *psp,
uint64_t *output_ptr)
{
int ret;
struct psp_gfx_cmd_resp *cmd;
if (!output_ptr)
return -EINVAL;
if (amdgpu_sriov_vf(psp->adev))
return 0;
cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
if (!cmd)
return -ENOMEM;
cmd->cmd_id = GFX_CMD_ID_GET_FW_ATTESTATION;
ret = psp_cmd_submit_buf(psp, NULL, cmd,
psp->fence_buf_mc_addr);
if (!ret) {
*output_ptr = ((uint64_t)cmd->resp.uresp.fwar_db_info.fwar_db_addr_lo) +
((uint64_t)cmd->resp.uresp.fwar_db_info.fwar_db_addr_hi << 32);
}
kfree(cmd);
return ret;
}
static void psp_prep_asd_load_cmd_buf(struct psp_gfx_cmd_resp *cmd, static void psp_prep_asd_load_cmd_buf(struct psp_gfx_cmd_resp *cmd,
uint64_t asd_mc, uint32_t size) uint64_t asd_mc, uint32_t size)
{ {
......
...@@ -398,4 +398,6 @@ int psp_init_sos_microcode(struct psp_context *psp, ...@@ -398,4 +398,6 @@ int psp_init_sos_microcode(struct psp_context *psp,
const char *chip_name); const char *chip_name);
int psp_init_ta_microcode(struct psp_context *psp, int psp_init_ta_microcode(struct psp_context *psp,
const char *chip_name); const char *chip_name);
int psp_get_fw_attestation_records_addr(struct psp_context *psp,
uint64_t *output_ptr);
#endif #endif
...@@ -98,6 +98,7 @@ enum psp_gfx_cmd_id ...@@ -98,6 +98,7 @@ enum psp_gfx_cmd_id
GFX_CMD_ID_DESTROY_VMR = 0x0000000A, /* destroy VMR region */ GFX_CMD_ID_DESTROY_VMR = 0x0000000A, /* destroy VMR region */
GFX_CMD_ID_PROG_REG = 0x0000000B, /* program regs */ GFX_CMD_ID_PROG_REG = 0x0000000B, /* program regs */
GFX_CMD_ID_CLEAR_VF_FW = 0x0000000D, /* Clear VF FW, to be used on VF shutdown. */ GFX_CMD_ID_CLEAR_VF_FW = 0x0000000D, /* Clear VF FW, to be used on VF shutdown. */
GFX_CMD_ID_GET_FW_ATTESTATION = 0x0000000F, /* Query GPUVA of the Fw Attestation DB */
/* IDs upto 0x1F are reserved for older programs (Raven, Vega 10/12/20) */ /* IDs upto 0x1F are reserved for older programs (Raven, Vega 10/12/20) */
GFX_CMD_ID_LOAD_TOC = 0x00000020, /* Load TOC and obtain TMR size */ GFX_CMD_ID_LOAD_TOC = 0x00000020, /* Load TOC and obtain TMR size */
GFX_CMD_ID_AUTOLOAD_RLC = 0x00000021, /* Indicates all graphics fw loaded, start RLC autoload */ GFX_CMD_ID_AUTOLOAD_RLC = 0x00000021, /* Indicates all graphics fw loaded, start RLC autoload */
...@@ -285,6 +286,25 @@ union psp_gfx_commands ...@@ -285,6 +286,25 @@ union psp_gfx_commands
struct psp_gfx_cmd_load_toc cmd_load_toc; struct psp_gfx_cmd_load_toc cmd_load_toc;
}; };
struct psp_gfx_uresp_reserved
{
uint32_t reserved[8];
};
/* Command-specific response for Fw Attestation Db */
struct psp_gfx_uresp_fwar_db_info
{
uint32_t fwar_db_addr_lo;
uint32_t fwar_db_addr_hi;
};
/* Union of command-specific responses for GPCOM ring. */
union psp_gfx_uresp
{
struct psp_gfx_uresp_reserved reserved;
struct psp_gfx_uresp_fwar_db_info fwar_db_info;
};
/* Structure of GFX Response buffer. /* Structure of GFX Response buffer.
* For GPCOM I/F it is part of GFX_CMD_RESP buffer, for RBI * For GPCOM I/F it is part of GFX_CMD_RESP buffer, for RBI
* it is separate buffer. * it is separate buffer.
...@@ -297,9 +317,11 @@ struct psp_gfx_resp ...@@ -297,9 +317,11 @@ struct psp_gfx_resp
uint32_t fw_addr_hi; /* +12 bits [63:32] of FW address within TMR (in response to cmd_load_ip_fw command) */ uint32_t fw_addr_hi; /* +12 bits [63:32] of FW address within TMR (in response to cmd_load_ip_fw command) */
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 */ 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 */
uint32_t reserved[3]; uint32_t reserved[11];
union psp_gfx_uresp uresp; /* +64 response union containing command-specific responses */
/* total 32 bytes */ /* total 96 bytes */
}; };
/* Structure of Command buffer pointed by psp_gfx_rb_frame.cmd_buf_addr_hi /* Structure of Command buffer pointed by psp_gfx_rb_frame.cmd_buf_addr_hi
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment