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

vega12_smumgr.c (14576B)


      1/*
      2 * Copyright 2017 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 "smumgr.h"
     25#include "vega12_inc.h"
     26#include "soc15_common.h"
     27#include "smu9_smumgr.h"
     28#include "vega12_smumgr.h"
     29#include "vega12_ppsmc.h"
     30#include "vega12/smu9_driver_if.h"
     31#include "ppatomctrl.h"
     32#include "pp_debug.h"
     33
     34
     35/*
     36 * Copy table from SMC into driver FB
     37 * @param   hwmgr    the address of the HW manager
     38 * @param   table_id    the driver's table ID to copy from
     39 */
     40static int vega12_copy_table_from_smc(struct pp_hwmgr *hwmgr,
     41				      uint8_t *table, int16_t table_id)
     42{
     43	struct vega12_smumgr *priv =
     44			(struct vega12_smumgr *)(hwmgr->smu_backend);
     45	struct amdgpu_device *adev = hwmgr->adev;
     46
     47	PP_ASSERT_WITH_CODE(table_id < TABLE_COUNT,
     48			"Invalid SMU Table ID!", return -EINVAL);
     49	PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0,
     50			"Invalid SMU Table version!", return -EINVAL);
     51	PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0,
     52			"Invalid SMU Table Length!", return -EINVAL);
     53	PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr,
     54			PPSMC_MSG_SetDriverDramAddrHigh,
     55			upper_32_bits(priv->smu_tables.entry[table_id].mc_addr),
     56			NULL) == 0,
     57			"[CopyTableFromSMC] Attempt to Set Dram Addr High Failed!", return -EINVAL);
     58	PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr,
     59			PPSMC_MSG_SetDriverDramAddrLow,
     60			lower_32_bits(priv->smu_tables.entry[table_id].mc_addr),
     61			NULL) == 0,
     62			"[CopyTableFromSMC] Attempt to Set Dram Addr Low Failed!",
     63			return -EINVAL);
     64	PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr,
     65			PPSMC_MSG_TransferTableSmu2Dram,
     66			table_id,
     67			NULL) == 0,
     68			"[CopyTableFromSMC] Attempt to Transfer Table From SMU Failed!",
     69			return -EINVAL);
     70
     71	amdgpu_asic_invalidate_hdp(adev, NULL);
     72
     73	memcpy(table, priv->smu_tables.entry[table_id].table,
     74			priv->smu_tables.entry[table_id].size);
     75
     76	return 0;
     77}
     78
     79/*
     80 * Copy table from Driver FB into SMC
     81 * @param   hwmgr    the address of the HW manager
     82 * @param   table_id    the table to copy from
     83 */
     84static int vega12_copy_table_to_smc(struct pp_hwmgr *hwmgr,
     85				    uint8_t *table, int16_t table_id)
     86{
     87	struct vega12_smumgr *priv =
     88			(struct vega12_smumgr *)(hwmgr->smu_backend);
     89	struct amdgpu_device *adev = hwmgr->adev;
     90
     91	PP_ASSERT_WITH_CODE(table_id < TABLE_COUNT,
     92			"Invalid SMU Table ID!", return -EINVAL);
     93	PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0,
     94			"Invalid SMU Table version!", return -EINVAL);
     95	PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0,
     96			"Invalid SMU Table Length!", return -EINVAL);
     97
     98	memcpy(priv->smu_tables.entry[table_id].table, table,
     99			priv->smu_tables.entry[table_id].size);
    100
    101	amdgpu_asic_flush_hdp(adev, NULL);
    102
    103	PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr,
    104			PPSMC_MSG_SetDriverDramAddrHigh,
    105			upper_32_bits(priv->smu_tables.entry[table_id].mc_addr),
    106			NULL) == 0,
    107			"[CopyTableToSMC] Attempt to Set Dram Addr High Failed!",
    108			return -EINVAL;);
    109	PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr,
    110			PPSMC_MSG_SetDriverDramAddrLow,
    111			lower_32_bits(priv->smu_tables.entry[table_id].mc_addr),
    112			NULL) == 0,
    113			"[CopyTableToSMC] Attempt to Set Dram Addr Low Failed!",
    114			return -EINVAL);
    115	PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr,
    116			PPSMC_MSG_TransferTableDram2Smu,
    117			table_id,
    118			NULL) == 0,
    119			"[CopyTableToSMC] Attempt to Transfer Table To SMU Failed!",
    120			return -EINVAL);
    121
    122	return 0;
    123}
    124
    125int vega12_enable_smc_features(struct pp_hwmgr *hwmgr,
    126		bool enable, uint64_t feature_mask)
    127{
    128	uint32_t smu_features_low, smu_features_high;
    129
    130	smu_features_low = (uint32_t)((feature_mask & SMU_FEATURES_LOW_MASK) >> SMU_FEATURES_LOW_SHIFT);
    131	smu_features_high = (uint32_t)((feature_mask & SMU_FEATURES_HIGH_MASK) >> SMU_FEATURES_HIGH_SHIFT);
    132
    133	if (enable) {
    134		PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr,
    135				PPSMC_MSG_EnableSmuFeaturesLow, smu_features_low, NULL) == 0,
    136				"[EnableDisableSMCFeatures] Attempt to enable SMU features Low failed!",
    137				return -EINVAL);
    138		PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr,
    139				PPSMC_MSG_EnableSmuFeaturesHigh, smu_features_high, NULL) == 0,
    140				"[EnableDisableSMCFeatures] Attempt to enable SMU features High failed!",
    141				return -EINVAL);
    142	} else {
    143		PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr,
    144				PPSMC_MSG_DisableSmuFeaturesLow, smu_features_low, NULL) == 0,
    145				"[EnableDisableSMCFeatures] Attempt to disable SMU features Low failed!",
    146				return -EINVAL);
    147		PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr,
    148				PPSMC_MSG_DisableSmuFeaturesHigh, smu_features_high, NULL) == 0,
    149				"[EnableDisableSMCFeatures] Attempt to disable SMU features High failed!",
    150				return -EINVAL);
    151	}
    152
    153	return 0;
    154}
    155
    156int vega12_get_enabled_smc_features(struct pp_hwmgr *hwmgr,
    157		uint64_t *features_enabled)
    158{
    159	uint32_t smc_features_low, smc_features_high;
    160
    161	if (features_enabled == NULL)
    162		return -EINVAL;
    163
    164	PP_ASSERT_WITH_CODE(smum_send_msg_to_smc(hwmgr,
    165			PPSMC_MSG_GetEnabledSmuFeaturesLow,
    166			&smc_features_low) == 0,
    167			"[GetEnabledSMCFeatures] Attempt to get SMU features Low failed!",
    168			return -EINVAL);
    169
    170	PP_ASSERT_WITH_CODE(smum_send_msg_to_smc(hwmgr,
    171			PPSMC_MSG_GetEnabledSmuFeaturesHigh,
    172			&smc_features_high) == 0,
    173			"[GetEnabledSMCFeatures] Attempt to get SMU features High failed!",
    174			return -EINVAL);
    175
    176	*features_enabled = ((((uint64_t)smc_features_low << SMU_FEATURES_LOW_SHIFT) & SMU_FEATURES_LOW_MASK) |
    177			(((uint64_t)smc_features_high << SMU_FEATURES_HIGH_SHIFT) & SMU_FEATURES_HIGH_MASK));
    178
    179	return 0;
    180}
    181
    182static bool vega12_is_dpm_running(struct pp_hwmgr *hwmgr)
    183{
    184	uint64_t features_enabled = 0;
    185
    186	vega12_get_enabled_smc_features(hwmgr, &features_enabled);
    187
    188	if (features_enabled & SMC_DPM_FEATURES)
    189		return true;
    190	else
    191		return false;
    192}
    193
    194static int vega12_set_tools_address(struct pp_hwmgr *hwmgr)
    195{
    196	struct vega12_smumgr *priv =
    197			(struct vega12_smumgr *)(hwmgr->smu_backend);
    198
    199	if (priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr) {
    200		if (!smum_send_msg_to_smc_with_parameter(hwmgr,
    201				PPSMC_MSG_SetToolsDramAddrHigh,
    202				upper_32_bits(priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr),
    203				NULL))
    204			smum_send_msg_to_smc_with_parameter(hwmgr,
    205					PPSMC_MSG_SetToolsDramAddrLow,
    206					lower_32_bits(priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr),
    207					NULL);
    208	}
    209	return 0;
    210}
    211
    212static int vega12_smu_init(struct pp_hwmgr *hwmgr)
    213{
    214	struct vega12_smumgr *priv;
    215	unsigned long tools_size;
    216	struct cgs_firmware_info info = {0};
    217	int ret;
    218
    219	ret = cgs_get_firmware_info(hwmgr->device, CGS_UCODE_ID_SMU,
    220				&info);
    221	if (ret || !info.kptr)
    222		return -EINVAL;
    223
    224	priv = kzalloc(sizeof(struct vega12_smumgr), GFP_KERNEL);
    225	if (!priv)
    226		return -ENOMEM;
    227
    228	hwmgr->smu_backend = priv;
    229
    230	/* allocate space for pptable */
    231	ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
    232			sizeof(PPTable_t),
    233			PAGE_SIZE,
    234			AMDGPU_GEM_DOMAIN_VRAM,
    235			&priv->smu_tables.entry[TABLE_PPTABLE].handle,
    236			&priv->smu_tables.entry[TABLE_PPTABLE].mc_addr,
    237			&priv->smu_tables.entry[TABLE_PPTABLE].table);
    238	if (ret)
    239		goto free_backend;
    240
    241	priv->smu_tables.entry[TABLE_PPTABLE].version = 0x01;
    242	priv->smu_tables.entry[TABLE_PPTABLE].size = sizeof(PPTable_t);
    243
    244	/* allocate space for watermarks table */
    245	ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
    246				      sizeof(Watermarks_t),
    247				      PAGE_SIZE,
    248				      AMDGPU_GEM_DOMAIN_VRAM,
    249				      &priv->smu_tables.entry[TABLE_WATERMARKS].handle,
    250				      &priv->smu_tables.entry[TABLE_WATERMARKS].mc_addr,
    251				      &priv->smu_tables.entry[TABLE_WATERMARKS].table);
    252
    253	if (ret)
    254		goto err0;
    255
    256	priv->smu_tables.entry[TABLE_WATERMARKS].version = 0x01;
    257	priv->smu_tables.entry[TABLE_WATERMARKS].size = sizeof(Watermarks_t);
    258
    259	tools_size = 0x19000;
    260	if (tools_size) {
    261		ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
    262					      tools_size,
    263					      PAGE_SIZE,
    264					      AMDGPU_GEM_DOMAIN_VRAM,
    265					      &priv->smu_tables.entry[TABLE_PMSTATUSLOG].handle,
    266					      &priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr,
    267					      &priv->smu_tables.entry[TABLE_PMSTATUSLOG].table);
    268		if (ret)
    269			goto err1;
    270
    271		priv->smu_tables.entry[TABLE_PMSTATUSLOG].version = 0x01;
    272		priv->smu_tables.entry[TABLE_PMSTATUSLOG].size = tools_size;
    273	}
    274
    275	/* allocate space for AVFS Fuse table */
    276	ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
    277				      sizeof(AvfsFuseOverride_t),
    278				      PAGE_SIZE,
    279				      AMDGPU_GEM_DOMAIN_VRAM,
    280				      &priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].handle,
    281				      &priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].mc_addr,
    282				      &priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].table);
    283
    284	if (ret)
    285		goto err2;
    286
    287	priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].version = 0x01;
    288	priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].size = sizeof(AvfsFuseOverride_t);
    289
    290	/* allocate space for OverDrive table */
    291	ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
    292				      sizeof(OverDriveTable_t),
    293				      PAGE_SIZE,
    294				      AMDGPU_GEM_DOMAIN_VRAM,
    295				      &priv->smu_tables.entry[TABLE_OVERDRIVE].handle,
    296				      &priv->smu_tables.entry[TABLE_OVERDRIVE].mc_addr,
    297				      &priv->smu_tables.entry[TABLE_OVERDRIVE].table);
    298	if (ret)
    299		goto err3;
    300
    301	priv->smu_tables.entry[TABLE_OVERDRIVE].version = 0x01;
    302	priv->smu_tables.entry[TABLE_OVERDRIVE].size = sizeof(OverDriveTable_t);
    303
    304	/* allocate space for SMU_METRICS table */
    305	ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
    306				      sizeof(SmuMetrics_t),
    307				      PAGE_SIZE,
    308				      AMDGPU_GEM_DOMAIN_VRAM,
    309				      &priv->smu_tables.entry[TABLE_SMU_METRICS].handle,
    310				      &priv->smu_tables.entry[TABLE_SMU_METRICS].mc_addr,
    311				      &priv->smu_tables.entry[TABLE_SMU_METRICS].table);
    312	if (ret)
    313		goto err4;
    314
    315	priv->smu_tables.entry[TABLE_SMU_METRICS].version = 0x01;
    316	priv->smu_tables.entry[TABLE_SMU_METRICS].size = sizeof(SmuMetrics_t);
    317
    318	return 0;
    319
    320err4:
    321	amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_OVERDRIVE].handle,
    322				&priv->smu_tables.entry[TABLE_OVERDRIVE].mc_addr,
    323				&priv->smu_tables.entry[TABLE_OVERDRIVE].table);
    324err3:
    325	amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].handle,
    326				&priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].mc_addr,
    327				&priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].table);
    328err2:
    329	if (priv->smu_tables.entry[TABLE_PMSTATUSLOG].table)
    330		amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_PMSTATUSLOG].handle,
    331				&priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr,
    332				&priv->smu_tables.entry[TABLE_PMSTATUSLOG].table);
    333err1:
    334	amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_WATERMARKS].handle,
    335				&priv->smu_tables.entry[TABLE_WATERMARKS].mc_addr,
    336				&priv->smu_tables.entry[TABLE_WATERMARKS].table);
    337err0:
    338	amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_PPTABLE].handle,
    339			&priv->smu_tables.entry[TABLE_PPTABLE].mc_addr,
    340			&priv->smu_tables.entry[TABLE_PPTABLE].table);
    341free_backend:
    342	kfree(hwmgr->smu_backend);
    343
    344	return -EINVAL;
    345}
    346
    347static int vega12_smu_fini(struct pp_hwmgr *hwmgr)
    348{
    349	struct vega12_smumgr *priv =
    350			(struct vega12_smumgr *)(hwmgr->smu_backend);
    351
    352	if (priv) {
    353		amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_PPTABLE].handle,
    354				      &priv->smu_tables.entry[TABLE_PPTABLE].mc_addr,
    355				      &priv->smu_tables.entry[TABLE_PPTABLE].table);
    356		amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_WATERMARKS].handle,
    357				      &priv->smu_tables.entry[TABLE_WATERMARKS].mc_addr,
    358				      &priv->smu_tables.entry[TABLE_WATERMARKS].table);
    359		if (priv->smu_tables.entry[TABLE_PMSTATUSLOG].table)
    360			amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_PMSTATUSLOG].handle,
    361					      &priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr,
    362					      &priv->smu_tables.entry[TABLE_PMSTATUSLOG].table);
    363		amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].handle,
    364				      &priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].mc_addr,
    365				      &priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].table);
    366		amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_OVERDRIVE].handle,
    367				      &priv->smu_tables.entry[TABLE_OVERDRIVE].mc_addr,
    368				      &priv->smu_tables.entry[TABLE_OVERDRIVE].table);
    369		amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_SMU_METRICS].handle,
    370				      &priv->smu_tables.entry[TABLE_SMU_METRICS].mc_addr,
    371				      &priv->smu_tables.entry[TABLE_SMU_METRICS].table);
    372		kfree(hwmgr->smu_backend);
    373		hwmgr->smu_backend = NULL;
    374	}
    375	return 0;
    376}
    377
    378static int vega12_start_smu(struct pp_hwmgr *hwmgr)
    379{
    380	PP_ASSERT_WITH_CODE(smu9_is_smc_ram_running(hwmgr),
    381			"SMC is not running!",
    382			return -EINVAL);
    383
    384	vega12_set_tools_address(hwmgr);
    385
    386	return 0;
    387}
    388
    389static int vega12_smc_table_manager(struct pp_hwmgr *hwmgr, uint8_t *table,
    390				    uint16_t table_id, bool rw)
    391{
    392	int ret;
    393
    394	if (rw)
    395		ret = vega12_copy_table_from_smc(hwmgr, table, table_id);
    396	else
    397		ret = vega12_copy_table_to_smc(hwmgr, table, table_id);
    398
    399	return ret;
    400}
    401
    402const struct pp_smumgr_func vega12_smu_funcs = {
    403	.name = "vega12_smu",
    404	.smu_init = &vega12_smu_init,
    405	.smu_fini = &vega12_smu_fini,
    406	.start_smu = &vega12_start_smu,
    407	.request_smu_load_specific_fw = NULL,
    408	.send_msg_to_smc = &smu9_send_msg_to_smc,
    409	.send_msg_to_smc_with_parameter = &smu9_send_msg_to_smc_with_parameter,
    410	.download_pptable_settings = NULL,
    411	.upload_pptable_settings = NULL,
    412	.is_dpm_running = vega12_is_dpm_running,
    413	.get_argument = smu9_get_argument,
    414	.smc_table_manager = vega12_smc_table_manager,
    415};