cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

amdgpu_cgs.c (14541B)


      1/*
      2 * Copyright 2015 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/list.h>
     25#include <linux/pci.h>
     26#include <linux/slab.h>
     27
     28#include <linux/firmware.h>
     29#include <drm/amdgpu_drm.h>
     30#include "amdgpu.h"
     31#include "atom.h"
     32#include "amdgpu_ucode.h"
     33
     34struct amdgpu_cgs_device {
     35	struct cgs_device base;
     36	struct amdgpu_device *adev;
     37};
     38
     39#define CGS_FUNC_ADEV							\
     40	struct amdgpu_device *adev =					\
     41		((struct amdgpu_cgs_device *)cgs_device)->adev
     42
     43
     44static uint32_t amdgpu_cgs_read_register(struct cgs_device *cgs_device, unsigned offset)
     45{
     46	CGS_FUNC_ADEV;
     47	return RREG32(offset);
     48}
     49
     50static void amdgpu_cgs_write_register(struct cgs_device *cgs_device, unsigned offset,
     51				      uint32_t value)
     52{
     53	CGS_FUNC_ADEV;
     54	WREG32(offset, value);
     55}
     56
     57static uint32_t amdgpu_cgs_read_ind_register(struct cgs_device *cgs_device,
     58					     enum cgs_ind_reg space,
     59					     unsigned index)
     60{
     61	CGS_FUNC_ADEV;
     62	switch (space) {
     63	case CGS_IND_REG__PCIE:
     64		return RREG32_PCIE(index);
     65	case CGS_IND_REG__SMC:
     66		return RREG32_SMC(index);
     67	case CGS_IND_REG__UVD_CTX:
     68		return RREG32_UVD_CTX(index);
     69	case CGS_IND_REG__DIDT:
     70		return RREG32_DIDT(index);
     71	case CGS_IND_REG_GC_CAC:
     72		return RREG32_GC_CAC(index);
     73	case CGS_IND_REG_SE_CAC:
     74		return RREG32_SE_CAC(index);
     75	case CGS_IND_REG__AUDIO_ENDPT:
     76		DRM_ERROR("audio endpt register access not implemented.\n");
     77		return 0;
     78	default:
     79		BUG();
     80	}
     81	WARN(1, "Invalid indirect register space");
     82	return 0;
     83}
     84
     85static void amdgpu_cgs_write_ind_register(struct cgs_device *cgs_device,
     86					  enum cgs_ind_reg space,
     87					  unsigned index, uint32_t value)
     88{
     89	CGS_FUNC_ADEV;
     90	switch (space) {
     91	case CGS_IND_REG__PCIE:
     92		return WREG32_PCIE(index, value);
     93	case CGS_IND_REG__SMC:
     94		return WREG32_SMC(index, value);
     95	case CGS_IND_REG__UVD_CTX:
     96		return WREG32_UVD_CTX(index, value);
     97	case CGS_IND_REG__DIDT:
     98		return WREG32_DIDT(index, value);
     99	case CGS_IND_REG_GC_CAC:
    100		return WREG32_GC_CAC(index, value);
    101	case CGS_IND_REG_SE_CAC:
    102		return WREG32_SE_CAC(index, value);
    103	case CGS_IND_REG__AUDIO_ENDPT:
    104		DRM_ERROR("audio endpt register access not implemented.\n");
    105		return;
    106	default:
    107		BUG();
    108	}
    109	WARN(1, "Invalid indirect register space");
    110}
    111
    112static uint32_t fw_type_convert(struct cgs_device *cgs_device, uint32_t fw_type)
    113{
    114	CGS_FUNC_ADEV;
    115	enum AMDGPU_UCODE_ID result = AMDGPU_UCODE_ID_MAXIMUM;
    116
    117	switch (fw_type) {
    118	case CGS_UCODE_ID_SDMA0:
    119		result = AMDGPU_UCODE_ID_SDMA0;
    120		break;
    121	case CGS_UCODE_ID_SDMA1:
    122		result = AMDGPU_UCODE_ID_SDMA1;
    123		break;
    124	case CGS_UCODE_ID_CP_CE:
    125		result = AMDGPU_UCODE_ID_CP_CE;
    126		break;
    127	case CGS_UCODE_ID_CP_PFP:
    128		result = AMDGPU_UCODE_ID_CP_PFP;
    129		break;
    130	case CGS_UCODE_ID_CP_ME:
    131		result = AMDGPU_UCODE_ID_CP_ME;
    132		break;
    133	case CGS_UCODE_ID_CP_MEC:
    134	case CGS_UCODE_ID_CP_MEC_JT1:
    135		result = AMDGPU_UCODE_ID_CP_MEC1;
    136		break;
    137	case CGS_UCODE_ID_CP_MEC_JT2:
    138		/* for VI. JT2 should be the same as JT1, because:
    139			1, MEC2 and MEC1 use exactly same FW.
    140			2, JT2 is not pached but JT1 is.
    141		*/
    142		if (adev->asic_type >= CHIP_TOPAZ)
    143			result = AMDGPU_UCODE_ID_CP_MEC1;
    144		else
    145			result = AMDGPU_UCODE_ID_CP_MEC2;
    146		break;
    147	case CGS_UCODE_ID_RLC_G:
    148		result = AMDGPU_UCODE_ID_RLC_G;
    149		break;
    150	case CGS_UCODE_ID_STORAGE:
    151		result = AMDGPU_UCODE_ID_STORAGE;
    152		break;
    153	default:
    154		DRM_ERROR("Firmware type not supported\n");
    155	}
    156	return result;
    157}
    158
    159static uint16_t amdgpu_get_firmware_version(struct cgs_device *cgs_device,
    160					enum cgs_ucode_id type)
    161{
    162	CGS_FUNC_ADEV;
    163	uint16_t fw_version = 0;
    164
    165	switch (type) {
    166		case CGS_UCODE_ID_SDMA0:
    167			fw_version = adev->sdma.instance[0].fw_version;
    168			break;
    169		case CGS_UCODE_ID_SDMA1:
    170			fw_version = adev->sdma.instance[1].fw_version;
    171			break;
    172		case CGS_UCODE_ID_CP_CE:
    173			fw_version = adev->gfx.ce_fw_version;
    174			break;
    175		case CGS_UCODE_ID_CP_PFP:
    176			fw_version = adev->gfx.pfp_fw_version;
    177			break;
    178		case CGS_UCODE_ID_CP_ME:
    179			fw_version = adev->gfx.me_fw_version;
    180			break;
    181		case CGS_UCODE_ID_CP_MEC:
    182			fw_version = adev->gfx.mec_fw_version;
    183			break;
    184		case CGS_UCODE_ID_CP_MEC_JT1:
    185			fw_version = adev->gfx.mec_fw_version;
    186			break;
    187		case CGS_UCODE_ID_CP_MEC_JT2:
    188			fw_version = adev->gfx.mec_fw_version;
    189			break;
    190		case CGS_UCODE_ID_RLC_G:
    191			fw_version = adev->gfx.rlc_fw_version;
    192			break;
    193		case CGS_UCODE_ID_STORAGE:
    194			break;
    195		default:
    196			DRM_ERROR("firmware type %d do not have version\n", type);
    197			break;
    198	}
    199	return fw_version;
    200}
    201
    202static int amdgpu_cgs_get_firmware_info(struct cgs_device *cgs_device,
    203					enum cgs_ucode_id type,
    204					struct cgs_firmware_info *info)
    205{
    206	CGS_FUNC_ADEV;
    207
    208	if ((CGS_UCODE_ID_SMU != type) && (CGS_UCODE_ID_SMU_SK != type)) {
    209		uint64_t gpu_addr;
    210		uint32_t data_size;
    211		const struct gfx_firmware_header_v1_0 *header;
    212		enum AMDGPU_UCODE_ID id;
    213		struct amdgpu_firmware_info *ucode;
    214
    215		id = fw_type_convert(cgs_device, type);
    216		ucode = &adev->firmware.ucode[id];
    217		if (ucode->fw == NULL)
    218			return -EINVAL;
    219
    220		gpu_addr  = ucode->mc_addr;
    221		header = (const struct gfx_firmware_header_v1_0 *)ucode->fw->data;
    222		data_size = le32_to_cpu(header->header.ucode_size_bytes);
    223
    224		if ((type == CGS_UCODE_ID_CP_MEC_JT1) ||
    225		    (type == CGS_UCODE_ID_CP_MEC_JT2)) {
    226			gpu_addr += ALIGN(le32_to_cpu(header->header.ucode_size_bytes), PAGE_SIZE);
    227			data_size = le32_to_cpu(header->jt_size) << 2;
    228		}
    229
    230		info->kptr = ucode->kaddr;
    231		info->image_size = data_size;
    232		info->mc_addr = gpu_addr;
    233		info->version = (uint16_t)le32_to_cpu(header->header.ucode_version);
    234
    235		if (CGS_UCODE_ID_CP_MEC == type)
    236			info->image_size = le32_to_cpu(header->jt_offset) << 2;
    237
    238		info->fw_version = amdgpu_get_firmware_version(cgs_device, type);
    239		info->feature_version = (uint16_t)le32_to_cpu(header->ucode_feature_version);
    240	} else {
    241		char fw_name[30] = {0};
    242		int err = 0;
    243		uint32_t ucode_size;
    244		uint32_t ucode_start_address;
    245		const uint8_t *src;
    246		const struct smc_firmware_header_v1_0 *hdr;
    247		const struct common_firmware_header *header;
    248		struct amdgpu_firmware_info *ucode = NULL;
    249
    250		if (!adev->pm.fw) {
    251			switch (adev->asic_type) {
    252			case CHIP_TAHITI:
    253				strcpy(fw_name, "radeon/tahiti_smc.bin");
    254				break;
    255			case CHIP_PITCAIRN:
    256				if ((adev->pdev->revision == 0x81) &&
    257				    ((adev->pdev->device == 0x6810) ||
    258				    (adev->pdev->device == 0x6811))) {
    259					info->is_kicker = true;
    260					strcpy(fw_name, "radeon/pitcairn_k_smc.bin");
    261				} else {
    262					strcpy(fw_name, "radeon/pitcairn_smc.bin");
    263				}
    264				break;
    265			case CHIP_VERDE:
    266				if (((adev->pdev->device == 0x6820) &&
    267					((adev->pdev->revision == 0x81) ||
    268					(adev->pdev->revision == 0x83))) ||
    269				    ((adev->pdev->device == 0x6821) &&
    270					((adev->pdev->revision == 0x83) ||
    271					(adev->pdev->revision == 0x87))) ||
    272				    ((adev->pdev->revision == 0x87) &&
    273					((adev->pdev->device == 0x6823) ||
    274					(adev->pdev->device == 0x682b)))) {
    275					info->is_kicker = true;
    276					strcpy(fw_name, "radeon/verde_k_smc.bin");
    277				} else {
    278					strcpy(fw_name, "radeon/verde_smc.bin");
    279				}
    280				break;
    281			case CHIP_OLAND:
    282				if (((adev->pdev->revision == 0x81) &&
    283					((adev->pdev->device == 0x6600) ||
    284					(adev->pdev->device == 0x6604) ||
    285					(adev->pdev->device == 0x6605) ||
    286					(adev->pdev->device == 0x6610))) ||
    287				    ((adev->pdev->revision == 0x83) &&
    288					(adev->pdev->device == 0x6610))) {
    289					info->is_kicker = true;
    290					strcpy(fw_name, "radeon/oland_k_smc.bin");
    291				} else {
    292					strcpy(fw_name, "radeon/oland_smc.bin");
    293				}
    294				break;
    295			case CHIP_HAINAN:
    296				if (((adev->pdev->revision == 0x81) &&
    297					(adev->pdev->device == 0x6660)) ||
    298				    ((adev->pdev->revision == 0x83) &&
    299					((adev->pdev->device == 0x6660) ||
    300					(adev->pdev->device == 0x6663) ||
    301					(adev->pdev->device == 0x6665) ||
    302					 (adev->pdev->device == 0x6667)))) {
    303					info->is_kicker = true;
    304					strcpy(fw_name, "radeon/hainan_k_smc.bin");
    305				} else if ((adev->pdev->revision == 0xc3) &&
    306					 (adev->pdev->device == 0x6665)) {
    307					info->is_kicker = true;
    308					strcpy(fw_name, "radeon/banks_k_2_smc.bin");
    309				} else {
    310					strcpy(fw_name, "radeon/hainan_smc.bin");
    311				}
    312				break;
    313			case CHIP_BONAIRE:
    314				if ((adev->pdev->revision == 0x80) ||
    315					(adev->pdev->revision == 0x81) ||
    316					(adev->pdev->device == 0x665f)) {
    317					info->is_kicker = true;
    318					strcpy(fw_name, "amdgpu/bonaire_k_smc.bin");
    319				} else {
    320					strcpy(fw_name, "amdgpu/bonaire_smc.bin");
    321				}
    322				break;
    323			case CHIP_HAWAII:
    324				if (adev->pdev->revision == 0x80) {
    325					info->is_kicker = true;
    326					strcpy(fw_name, "amdgpu/hawaii_k_smc.bin");
    327				} else {
    328					strcpy(fw_name, "amdgpu/hawaii_smc.bin");
    329				}
    330				break;
    331			case CHIP_TOPAZ:
    332				if (((adev->pdev->device == 0x6900) && (adev->pdev->revision == 0x81)) ||
    333				    ((adev->pdev->device == 0x6900) && (adev->pdev->revision == 0x83)) ||
    334				    ((adev->pdev->device == 0x6907) && (adev->pdev->revision == 0x87)) ||
    335				    ((adev->pdev->device == 0x6900) && (adev->pdev->revision == 0xD1)) ||
    336				    ((adev->pdev->device == 0x6900) && (adev->pdev->revision == 0xD3))) {
    337					info->is_kicker = true;
    338					strcpy(fw_name, "amdgpu/topaz_k_smc.bin");
    339				} else
    340					strcpy(fw_name, "amdgpu/topaz_smc.bin");
    341				break;
    342			case CHIP_TONGA:
    343				if (((adev->pdev->device == 0x6939) && (adev->pdev->revision == 0xf1)) ||
    344				    ((adev->pdev->device == 0x6938) && (adev->pdev->revision == 0xf1))) {
    345					info->is_kicker = true;
    346					strcpy(fw_name, "amdgpu/tonga_k_smc.bin");
    347				} else
    348					strcpy(fw_name, "amdgpu/tonga_smc.bin");
    349				break;
    350			case CHIP_FIJI:
    351				strcpy(fw_name, "amdgpu/fiji_smc.bin");
    352				break;
    353			case CHIP_POLARIS11:
    354				if (type == CGS_UCODE_ID_SMU) {
    355					if (ASICID_IS_P21(adev->pdev->device, adev->pdev->revision)) {
    356						info->is_kicker = true;
    357						strcpy(fw_name, "amdgpu/polaris11_k_smc.bin");
    358					} else if (ASICID_IS_P31(adev->pdev->device, adev->pdev->revision)) {
    359						info->is_kicker = true;
    360						strcpy(fw_name, "amdgpu/polaris11_k2_smc.bin");
    361					} else {
    362						strcpy(fw_name, "amdgpu/polaris11_smc.bin");
    363					}
    364				} else if (type == CGS_UCODE_ID_SMU_SK) {
    365					strcpy(fw_name, "amdgpu/polaris11_smc_sk.bin");
    366				}
    367				break;
    368			case CHIP_POLARIS10:
    369				if (type == CGS_UCODE_ID_SMU) {
    370					if (ASICID_IS_P20(adev->pdev->device, adev->pdev->revision)) {
    371						info->is_kicker = true;
    372						strcpy(fw_name, "amdgpu/polaris10_k_smc.bin");
    373					} else if (ASICID_IS_P30(adev->pdev->device, adev->pdev->revision)) {
    374						info->is_kicker = true;
    375						strcpy(fw_name, "amdgpu/polaris10_k2_smc.bin");
    376					} else {
    377						strcpy(fw_name, "amdgpu/polaris10_smc.bin");
    378					}
    379				} else if (type == CGS_UCODE_ID_SMU_SK) {
    380					strcpy(fw_name, "amdgpu/polaris10_smc_sk.bin");
    381				}
    382				break;
    383			case CHIP_POLARIS12:
    384				if (ASICID_IS_P23(adev->pdev->device, adev->pdev->revision)) {
    385					info->is_kicker = true;
    386					strcpy(fw_name, "amdgpu/polaris12_k_smc.bin");
    387				} else {
    388					strcpy(fw_name, "amdgpu/polaris12_smc.bin");
    389				}
    390				break;
    391			case CHIP_VEGAM:
    392				strcpy(fw_name, "amdgpu/vegam_smc.bin");
    393				break;
    394			case CHIP_VEGA10:
    395				if ((adev->pdev->device == 0x687f) &&
    396					((adev->pdev->revision == 0xc0) ||
    397					(adev->pdev->revision == 0xc1) ||
    398					(adev->pdev->revision == 0xc3)))
    399					strcpy(fw_name, "amdgpu/vega10_acg_smc.bin");
    400				else
    401					strcpy(fw_name, "amdgpu/vega10_smc.bin");
    402				break;
    403			case CHIP_VEGA12:
    404				strcpy(fw_name, "amdgpu/vega12_smc.bin");
    405				break;
    406			case CHIP_VEGA20:
    407				strcpy(fw_name, "amdgpu/vega20_smc.bin");
    408				break;
    409			default:
    410				DRM_ERROR("SMC firmware not supported\n");
    411				return -EINVAL;
    412			}
    413
    414			err = request_firmware(&adev->pm.fw, fw_name, adev->dev);
    415			if (err) {
    416				DRM_ERROR("Failed to request firmware\n");
    417				return err;
    418			}
    419
    420			err = amdgpu_ucode_validate(adev->pm.fw);
    421			if (err) {
    422				DRM_ERROR("Failed to load firmware \"%s\"", fw_name);
    423				release_firmware(adev->pm.fw);
    424				adev->pm.fw = NULL;
    425				return err;
    426			}
    427
    428			if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
    429				ucode = &adev->firmware.ucode[AMDGPU_UCODE_ID_SMC];
    430				ucode->ucode_id = AMDGPU_UCODE_ID_SMC;
    431				ucode->fw = adev->pm.fw;
    432				header = (const struct common_firmware_header *)ucode->fw->data;
    433				adev->firmware.fw_size +=
    434					ALIGN(le32_to_cpu(header->ucode_size_bytes), PAGE_SIZE);
    435			}
    436		}
    437
    438		hdr = (const struct smc_firmware_header_v1_0 *)	adev->pm.fw->data;
    439		amdgpu_ucode_print_smc_hdr(&hdr->header);
    440		adev->pm.fw_version = le32_to_cpu(hdr->header.ucode_version);
    441		ucode_size = le32_to_cpu(hdr->header.ucode_size_bytes);
    442		ucode_start_address = le32_to_cpu(hdr->ucode_start_addr);
    443		src = (const uint8_t *)(adev->pm.fw->data +
    444		       le32_to_cpu(hdr->header.ucode_array_offset_bytes));
    445
    446		info->version = adev->pm.fw_version;
    447		info->image_size = ucode_size;
    448		info->ucode_start_address = ucode_start_address;
    449		info->kptr = (void *)src;
    450	}
    451	return 0;
    452}
    453
    454static const struct cgs_ops amdgpu_cgs_ops = {
    455	.read_register = amdgpu_cgs_read_register,
    456	.write_register = amdgpu_cgs_write_register,
    457	.read_ind_register = amdgpu_cgs_read_ind_register,
    458	.write_ind_register = amdgpu_cgs_write_ind_register,
    459	.get_firmware_info = amdgpu_cgs_get_firmware_info,
    460};
    461
    462struct cgs_device *amdgpu_cgs_create_device(struct amdgpu_device *adev)
    463{
    464	struct amdgpu_cgs_device *cgs_device =
    465		kmalloc(sizeof(*cgs_device), GFP_KERNEL);
    466
    467	if (!cgs_device) {
    468		DRM_ERROR("Couldn't allocate CGS device structure\n");
    469		return NULL;
    470	}
    471
    472	cgs_device->base.ops = &amdgpu_cgs_ops;
    473	cgs_device->adev = adev;
    474
    475	return (struct cgs_device *)cgs_device;
    476}
    477
    478void amdgpu_cgs_destroy_device(struct cgs_device *cgs_device)
    479{
    480	kfree(cgs_device);
    481}