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

isst-core.c (25171B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Intel Speed Select -- Enumerate and control features
      4 * Copyright (c) 2019 Intel Corporation.
      5 */
      6
      7#include "isst.h"
      8
      9int isst_write_pm_config(int cpu, int cp_state)
     10{
     11	unsigned int req, resp;
     12	int ret;
     13
     14	if (cp_state)
     15		req = BIT(16);
     16	else
     17		req = 0;
     18
     19	ret = isst_send_mbox_command(cpu, WRITE_PM_CONFIG, PM_FEATURE, 0, req,
     20				     &resp);
     21	if (ret)
     22		return ret;
     23
     24	debug_printf("cpu:%d WRITE_PM_CONFIG resp:%x\n", cpu, resp);
     25
     26	return 0;
     27}
     28
     29int isst_read_pm_config(int cpu, int *cp_state, int *cp_cap)
     30{
     31	unsigned int resp;
     32	int ret;
     33
     34	ret = isst_send_mbox_command(cpu, READ_PM_CONFIG, PM_FEATURE, 0, 0,
     35				     &resp);
     36	if (ret)
     37		return ret;
     38
     39	debug_printf("cpu:%d READ_PM_CONFIG resp:%x\n", cpu, resp);
     40
     41	*cp_state = resp & BIT(16);
     42	*cp_cap = resp & BIT(0) ? 1 : 0;
     43
     44	return 0;
     45}
     46
     47int isst_get_ctdp_levels(int cpu, struct isst_pkg_ctdp *pkg_dev)
     48{
     49	unsigned int resp;
     50	int ret;
     51
     52	ret = isst_send_mbox_command(cpu, CONFIG_TDP,
     53				     CONFIG_TDP_GET_LEVELS_INFO, 0, 0, &resp);
     54	if (ret) {
     55		pkg_dev->levels = 0;
     56		pkg_dev->locked = 1;
     57		pkg_dev->current_level = 0;
     58		pkg_dev->version = 0;
     59		pkg_dev->enabled = 0;
     60		return 0;
     61	}
     62
     63	debug_printf("cpu:%d CONFIG_TDP_GET_LEVELS_INFO resp:%x\n", cpu, resp);
     64
     65	pkg_dev->version = resp & 0xff;
     66	pkg_dev->levels = (resp >> 8) & 0xff;
     67	pkg_dev->current_level = (resp >> 16) & 0xff;
     68	pkg_dev->locked = !!(resp & BIT(24));
     69	pkg_dev->enabled = !!(resp & BIT(31));
     70
     71	return 0;
     72}
     73
     74int isst_get_ctdp_control(int cpu, int config_index,
     75			  struct isst_pkg_ctdp_level_info *ctdp_level)
     76{
     77	int cp_state, cp_cap;
     78	unsigned int resp;
     79	int ret;
     80
     81	ret = isst_send_mbox_command(cpu, CONFIG_TDP,
     82				     CONFIG_TDP_GET_TDP_CONTROL, 0,
     83				     config_index, &resp);
     84	if (ret)
     85		return ret;
     86
     87	ctdp_level->fact_support = resp & BIT(0);
     88	ctdp_level->pbf_support = !!(resp & BIT(1));
     89	ctdp_level->fact_enabled = !!(resp & BIT(16));
     90	ctdp_level->pbf_enabled = !!(resp & BIT(17));
     91
     92	ret = isst_read_pm_config(cpu, &cp_state, &cp_cap);
     93	if (ret) {
     94		debug_printf("cpu:%d pm_config is not supported \n", cpu);
     95	} else {
     96		debug_printf("cpu:%d pm_config SST-CP state:%d cap:%d \n", cpu, cp_state, cp_cap);
     97		ctdp_level->sst_cp_support = cp_cap;
     98		ctdp_level->sst_cp_enabled = cp_state;
     99	}
    100
    101	debug_printf(
    102		"cpu:%d CONFIG_TDP_GET_TDP_CONTROL resp:%x fact_support:%d pbf_support: %d fact_enabled:%d pbf_enabled:%d\n",
    103		cpu, resp, ctdp_level->fact_support, ctdp_level->pbf_support,
    104		ctdp_level->fact_enabled, ctdp_level->pbf_enabled);
    105
    106	return 0;
    107}
    108
    109int isst_get_tdp_info(int cpu, int config_index,
    110		      struct isst_pkg_ctdp_level_info *ctdp_level)
    111{
    112	unsigned int resp;
    113	int ret;
    114
    115	ret = isst_send_mbox_command(cpu, CONFIG_TDP, CONFIG_TDP_GET_TDP_INFO,
    116				     0, config_index, &resp);
    117	if (ret) {
    118		isst_display_error_info_message(1, "Invalid level, Can't get TDP information at level", 1, config_index);
    119		return ret;
    120	}
    121
    122	ctdp_level->pkg_tdp = resp & GENMASK(14, 0);
    123	ctdp_level->tdp_ratio = (resp & GENMASK(23, 16)) >> 16;
    124
    125	debug_printf(
    126		"cpu:%d ctdp:%d CONFIG_TDP_GET_TDP_INFO resp:%x tdp_ratio:%d pkg_tdp:%d\n",
    127		cpu, config_index, resp, ctdp_level->tdp_ratio,
    128		ctdp_level->pkg_tdp);
    129	return 0;
    130}
    131
    132int isst_get_pwr_info(int cpu, int config_index,
    133		      struct isst_pkg_ctdp_level_info *ctdp_level)
    134{
    135	unsigned int resp;
    136	int ret;
    137
    138	ret = isst_send_mbox_command(cpu, CONFIG_TDP, CONFIG_TDP_GET_PWR_INFO,
    139				     0, config_index, &resp);
    140	if (ret)
    141		return ret;
    142
    143	ctdp_level->pkg_max_power = resp & GENMASK(14, 0);
    144	ctdp_level->pkg_min_power = (resp & GENMASK(30, 16)) >> 16;
    145
    146	debug_printf(
    147		"cpu:%d ctdp:%d CONFIG_TDP_GET_PWR_INFO resp:%x pkg_max_power:%d pkg_min_power:%d\n",
    148		cpu, config_index, resp, ctdp_level->pkg_max_power,
    149		ctdp_level->pkg_min_power);
    150
    151	return 0;
    152}
    153
    154void isst_get_uncore_p0_p1_info(int cpu, int config_index,
    155				struct isst_pkg_ctdp_level_info *ctdp_level)
    156{
    157	unsigned int resp;
    158	int ret;
    159	ret = isst_send_mbox_command(cpu, CONFIG_TDP,
    160				     CONFIG_TDP_GET_UNCORE_P0_P1_INFO, 0,
    161				     config_index, &resp);
    162	if (ret) {
    163		ctdp_level->uncore_p0 = 0;
    164		ctdp_level->uncore_p1 = 0;
    165		return;
    166	}
    167
    168	ctdp_level->uncore_p0 = resp & GENMASK(7, 0);
    169	ctdp_level->uncore_p1 = (resp & GENMASK(15, 8)) >> 8;
    170	debug_printf(
    171		"cpu:%d ctdp:%d CONFIG_TDP_GET_UNCORE_P0_P1_INFO resp:%x uncore p0:%d uncore p1:%d\n",
    172		cpu, config_index, resp, ctdp_level->uncore_p0,
    173		ctdp_level->uncore_p1);
    174}
    175
    176void isst_get_p1_info(int cpu, int config_index,
    177		      struct isst_pkg_ctdp_level_info *ctdp_level)
    178{
    179	unsigned int resp;
    180	int ret;
    181	ret = isst_send_mbox_command(cpu, CONFIG_TDP, CONFIG_TDP_GET_P1_INFO, 0,
    182				     config_index, &resp);
    183	if (ret) {
    184		ctdp_level->sse_p1 = 0;
    185		ctdp_level->avx2_p1 = 0;
    186		ctdp_level->avx512_p1 = 0;
    187		return;
    188	}
    189
    190	ctdp_level->sse_p1 = resp & GENMASK(7, 0);
    191	ctdp_level->avx2_p1 = (resp & GENMASK(15, 8)) >> 8;
    192	ctdp_level->avx512_p1 = (resp & GENMASK(23, 16)) >> 16;
    193	debug_printf(
    194		"cpu:%d ctdp:%d CONFIG_TDP_GET_P1_INFO resp:%x sse_p1:%d avx2_p1:%d avx512_p1:%d\n",
    195		cpu, config_index, resp, ctdp_level->sse_p1,
    196		ctdp_level->avx2_p1, ctdp_level->avx512_p1);
    197}
    198
    199void isst_get_uncore_mem_freq(int cpu, int config_index,
    200			      struct isst_pkg_ctdp_level_info *ctdp_level)
    201{
    202	unsigned int resp;
    203	int ret;
    204
    205	ret = isst_send_mbox_command(cpu, CONFIG_TDP, CONFIG_TDP_GET_MEM_FREQ,
    206				     0, config_index, &resp);
    207	if (ret) {
    208		ctdp_level->mem_freq = 0;
    209		return;
    210	}
    211
    212	ctdp_level->mem_freq = resp & GENMASK(7, 0);
    213	if (is_spr_platform()) {
    214		ctdp_level->mem_freq *= 200;
    215	} else if (is_icx_platform()) {
    216		if (ctdp_level->mem_freq < 7) {
    217			ctdp_level->mem_freq = (12 - ctdp_level->mem_freq) * 133.33 * 2 * 10;
    218			ctdp_level->mem_freq /= 10;
    219			if (ctdp_level->mem_freq % 10 > 5)
    220				ctdp_level->mem_freq++;
    221		} else {
    222			ctdp_level->mem_freq = 0;
    223		}
    224	} else {
    225		ctdp_level->mem_freq = 0;
    226	}
    227	debug_printf(
    228		"cpu:%d ctdp:%d CONFIG_TDP_GET_MEM_FREQ resp:%x uncore mem_freq:%d\n",
    229		cpu, config_index, resp, ctdp_level->mem_freq);
    230}
    231
    232int isst_get_tjmax_info(int cpu, int config_index,
    233			struct isst_pkg_ctdp_level_info *ctdp_level)
    234{
    235	unsigned int resp;
    236	int ret;
    237
    238	ret = isst_send_mbox_command(cpu, CONFIG_TDP, CONFIG_TDP_GET_TJMAX_INFO,
    239				     0, config_index, &resp);
    240	if (ret)
    241		return ret;
    242
    243	ctdp_level->t_proc_hot = resp & GENMASK(7, 0);
    244
    245	debug_printf(
    246		"cpu:%d ctdp:%d CONFIG_TDP_GET_TJMAX_INFO resp:%x t_proc_hot:%d\n",
    247		cpu, config_index, resp, ctdp_level->t_proc_hot);
    248
    249	return 0;
    250}
    251
    252int isst_get_coremask_info(int cpu, int config_index,
    253			   struct isst_pkg_ctdp_level_info *ctdp_level)
    254{
    255	unsigned int resp;
    256	int i, ret;
    257
    258	ctdp_level->cpu_count = 0;
    259	for (i = 0; i < 2; ++i) {
    260		unsigned long long mask;
    261		int cpu_count = 0;
    262
    263		ret = isst_send_mbox_command(cpu, CONFIG_TDP,
    264					     CONFIG_TDP_GET_CORE_MASK, 0,
    265					     (i << 8) | config_index, &resp);
    266		if (ret)
    267			return ret;
    268
    269		debug_printf(
    270			"cpu:%d ctdp:%d mask:%d CONFIG_TDP_GET_CORE_MASK resp:%x\n",
    271			cpu, config_index, i, resp);
    272
    273		mask = (unsigned long long)resp << (32 * i);
    274		set_cpu_mask_from_punit_coremask(cpu, mask,
    275						 ctdp_level->core_cpumask_size,
    276						 ctdp_level->core_cpumask,
    277						 &cpu_count);
    278		ctdp_level->cpu_count += cpu_count;
    279		debug_printf("cpu:%d ctdp:%d mask:%d cpu count:%d\n", cpu,
    280			     config_index, i, ctdp_level->cpu_count);
    281	}
    282
    283	return 0;
    284}
    285
    286int isst_get_get_trl_from_msr(int cpu, int *trl)
    287{
    288	unsigned long long msr_trl;
    289	int ret;
    290
    291	ret = isst_send_msr_command(cpu, 0x1AD, 0, &msr_trl);
    292	if (ret)
    293		return ret;
    294
    295	trl[0] = msr_trl & GENMASK(7, 0);
    296	trl[1] = (msr_trl & GENMASK(15, 8)) >> 8;
    297	trl[2] = (msr_trl & GENMASK(23, 16)) >> 16;
    298	trl[3] = (msr_trl & GENMASK(31, 24)) >> 24;
    299	trl[4] = (msr_trl & GENMASK(39, 32)) >> 32;
    300	trl[5] = (msr_trl & GENMASK(47, 40)) >> 40;
    301	trl[6] = (msr_trl & GENMASK(55, 48)) >> 48;
    302	trl[7] = (msr_trl & GENMASK(63, 56)) >> 56;
    303
    304	return 0;
    305}
    306
    307int isst_get_get_trl(int cpu, int level, int avx_level, int *trl)
    308{
    309	unsigned int req, resp;
    310	int ret;
    311
    312	req = level | (avx_level << 16);
    313	ret = isst_send_mbox_command(cpu, CONFIG_TDP,
    314				     CONFIG_TDP_GET_TURBO_LIMIT_RATIOS, 0, req,
    315				     &resp);
    316	if (ret)
    317		return ret;
    318
    319	debug_printf(
    320		"cpu:%d CONFIG_TDP_GET_TURBO_LIMIT_RATIOS req:%x resp:%x\n",
    321		cpu, req, resp);
    322
    323	trl[0] = resp & GENMASK(7, 0);
    324	trl[1] = (resp & GENMASK(15, 8)) >> 8;
    325	trl[2] = (resp & GENMASK(23, 16)) >> 16;
    326	trl[3] = (resp & GENMASK(31, 24)) >> 24;
    327
    328	req = level | BIT(8) | (avx_level << 16);
    329	ret = isst_send_mbox_command(cpu, CONFIG_TDP,
    330				     CONFIG_TDP_GET_TURBO_LIMIT_RATIOS, 0, req,
    331				     &resp);
    332	if (ret)
    333		return ret;
    334
    335	debug_printf("cpu:%d CONFIG_TDP_GET_TURBO_LIMIT req:%x resp:%x\n", cpu,
    336		     req, resp);
    337
    338	trl[4] = resp & GENMASK(7, 0);
    339	trl[5] = (resp & GENMASK(15, 8)) >> 8;
    340	trl[6] = (resp & GENMASK(23, 16)) >> 16;
    341	trl[7] = (resp & GENMASK(31, 24)) >> 24;
    342
    343	return 0;
    344}
    345
    346int isst_get_trl_bucket_info(int cpu, unsigned long long *buckets_info)
    347{
    348	int ret;
    349
    350	debug_printf("cpu:%d bucket info via MSR\n", cpu);
    351
    352	*buckets_info = 0;
    353
    354	ret = isst_send_msr_command(cpu, 0x1ae, 0, buckets_info);
    355	if (ret)
    356		return ret;
    357
    358	debug_printf("cpu:%d bucket info via MSR successful 0x%llx\n", cpu,
    359		     *buckets_info);
    360
    361	return 0;
    362}
    363
    364int isst_set_tdp_level_msr(int cpu, int tdp_level)
    365{
    366	unsigned long long level = tdp_level;
    367	int ret;
    368
    369	debug_printf("cpu: tdp_level via MSR %d\n", cpu, tdp_level);
    370
    371	if (isst_get_config_tdp_lock_status(cpu)) {
    372		isst_display_error_info_message(1, "tdp_locked", 0, 0);
    373		return -1;
    374	}
    375
    376	if (tdp_level > 2)
    377		return -1; /* invalid value */
    378
    379	ret = isst_send_msr_command(cpu, 0x64b, 1, &level);
    380	if (ret)
    381		return ret;
    382
    383	debug_printf("cpu: tdp_level via MSR successful %d\n", cpu, tdp_level);
    384
    385	return 0;
    386}
    387
    388int isst_set_tdp_level(int cpu, int tdp_level)
    389{
    390	unsigned int resp;
    391	int ret;
    392
    393
    394	if (isst_get_config_tdp_lock_status(cpu)) {
    395		isst_display_error_info_message(1, "TDP is locked", 0, 0);
    396		return -1;
    397
    398	}
    399
    400	ret = isst_send_mbox_command(cpu, CONFIG_TDP, CONFIG_TDP_SET_LEVEL, 0,
    401				     tdp_level, &resp);
    402	if (ret) {
    403		isst_display_error_info_message(1, "Set TDP level failed for level", 1, tdp_level);
    404		return ret;
    405	}
    406
    407	return 0;
    408}
    409
    410int isst_get_pbf_info(int cpu, int level, struct isst_pbf_info *pbf_info)
    411{
    412	struct isst_pkg_ctdp_level_info ctdp_level;
    413	struct isst_pkg_ctdp pkg_dev;
    414	int i, ret, max_punit_core, max_mask_index;
    415	unsigned int req, resp;
    416
    417	ret = isst_get_ctdp_levels(cpu, &pkg_dev);
    418	if (ret) {
    419		isst_display_error_info_message(1, "Failed to get number of levels", 0, 0);
    420		return ret;
    421	}
    422
    423	if (level > pkg_dev.levels) {
    424		isst_display_error_info_message(1, "Invalid level", 1, level);
    425		return -1;
    426	}
    427
    428	ret = isst_get_ctdp_control(cpu, level, &ctdp_level);
    429	if (ret)
    430		return ret;
    431
    432	if (!ctdp_level.pbf_support) {
    433		isst_display_error_info_message(1, "base-freq feature is not present at this level", 1, level);
    434		return -1;
    435	}
    436
    437	pbf_info->core_cpumask_size = alloc_cpu_set(&pbf_info->core_cpumask);
    438
    439	max_punit_core = get_max_punit_core_id(get_physical_package_id(cpu), get_physical_die_id(cpu));
    440	max_mask_index = max_punit_core > 32 ? 2 : 1;
    441
    442	for (i = 0; i < max_mask_index; ++i) {
    443		unsigned long long mask;
    444		int count;
    445
    446		ret = isst_send_mbox_command(cpu, CONFIG_TDP,
    447					     CONFIG_TDP_PBF_GET_CORE_MASK_INFO,
    448					     0, (i << 8) | level, &resp);
    449		if (ret)
    450			break;
    451
    452		debug_printf(
    453			"cpu:%d CONFIG_TDP_PBF_GET_CORE_MASK_INFO resp:%x\n",
    454			cpu, resp);
    455
    456		mask = (unsigned long long)resp << (32 * i);
    457		set_cpu_mask_from_punit_coremask(cpu, mask,
    458						 pbf_info->core_cpumask_size,
    459						 pbf_info->core_cpumask,
    460						 &count);
    461	}
    462
    463	req = level;
    464	ret = isst_send_mbox_command(cpu, CONFIG_TDP,
    465				     CONFIG_TDP_PBF_GET_P1HI_P1LO_INFO, 0, req,
    466				     &resp);
    467	if (ret)
    468		return ret;
    469
    470	debug_printf("cpu:%d CONFIG_TDP_PBF_GET_P1HI_P1LO_INFO resp:%x\n", cpu,
    471		     resp);
    472
    473	pbf_info->p1_low = resp & 0xff;
    474	pbf_info->p1_high = (resp & GENMASK(15, 8)) >> 8;
    475
    476	req = level;
    477	ret = isst_send_mbox_command(
    478		cpu, CONFIG_TDP, CONFIG_TDP_PBF_GET_TDP_INFO, 0, req, &resp);
    479	if (ret)
    480		return ret;
    481
    482	debug_printf("cpu:%d CONFIG_TDP_PBF_GET_TDP_INFO resp:%x\n", cpu, resp);
    483
    484	pbf_info->tdp = resp & 0xffff;
    485
    486	req = level;
    487	ret = isst_send_mbox_command(
    488		cpu, CONFIG_TDP, CONFIG_TDP_PBF_GET_TJ_MAX_INFO, 0, req, &resp);
    489	if (ret)
    490		return ret;
    491
    492	debug_printf("cpu:%d CONFIG_TDP_PBF_GET_TJ_MAX_INFO resp:%x\n", cpu,
    493		     resp);
    494	pbf_info->t_control = (resp >> 8) & 0xff;
    495	pbf_info->t_prochot = resp & 0xff;
    496
    497	return 0;
    498}
    499
    500void isst_get_pbf_info_complete(struct isst_pbf_info *pbf_info)
    501{
    502	free_cpu_set(pbf_info->core_cpumask);
    503}
    504
    505int isst_set_pbf_fact_status(int cpu, int pbf, int enable)
    506{
    507	struct isst_pkg_ctdp pkg_dev;
    508	struct isst_pkg_ctdp_level_info ctdp_level;
    509	int current_level;
    510	unsigned int req = 0, resp;
    511	int ret;
    512
    513	ret = isst_get_ctdp_levels(cpu, &pkg_dev);
    514	if (ret)
    515		debug_printf("cpu:%d No support for dynamic ISST\n", cpu);
    516
    517	current_level = pkg_dev.current_level;
    518
    519	ret = isst_get_ctdp_control(cpu, current_level, &ctdp_level);
    520	if (ret)
    521		return ret;
    522
    523	if (pbf) {
    524		if (ctdp_level.fact_enabled)
    525			req = BIT(16);
    526
    527		if (enable)
    528			req |= BIT(17);
    529		else
    530			req &= ~BIT(17);
    531	} else {
    532
    533		if (enable && !ctdp_level.sst_cp_enabled)
    534			isst_display_error_info_message(0, "Make sure to execute before: core-power enable", 0, 0);
    535
    536		if (ctdp_level.pbf_enabled)
    537			req = BIT(17);
    538
    539		if (enable)
    540			req |= BIT(16);
    541		else
    542			req &= ~BIT(16);
    543	}
    544
    545	ret = isst_send_mbox_command(cpu, CONFIG_TDP,
    546				     CONFIG_TDP_SET_TDP_CONTROL, 0, req, &resp);
    547	if (ret)
    548		return ret;
    549
    550	debug_printf("cpu:%d CONFIG_TDP_SET_TDP_CONTROL pbf/fact:%d req:%x\n",
    551		     cpu, pbf, req);
    552
    553	return 0;
    554}
    555
    556int isst_get_fact_bucket_info(int cpu, int level,
    557			      struct isst_fact_bucket_info *bucket_info)
    558{
    559	unsigned int resp;
    560	int i, k, ret;
    561
    562	for (i = 0; i < 2; ++i) {
    563		int j;
    564
    565		ret = isst_send_mbox_command(
    566			cpu, CONFIG_TDP,
    567			CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_NUMCORES, 0,
    568			(i << 8) | level, &resp);
    569		if (ret)
    570			return ret;
    571
    572		debug_printf(
    573			"cpu:%d CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_NUMCORES index:%d level:%d resp:%x\n",
    574			cpu, i, level, resp);
    575
    576		for (j = 0; j < 4; ++j) {
    577			bucket_info[j + (i * 4)].high_priority_cores_count =
    578				(resp >> (j * 8)) & 0xff;
    579		}
    580	}
    581
    582	for (k = 0; k < 3; ++k) {
    583		for (i = 0; i < 2; ++i) {
    584			int j;
    585
    586			ret = isst_send_mbox_command(
    587				cpu, CONFIG_TDP,
    588				CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_RATIOS, 0,
    589				(k << 16) | (i << 8) | level, &resp);
    590			if (ret)
    591				return ret;
    592
    593			debug_printf(
    594				"cpu:%d CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_RATIOS index:%d level:%d avx:%d resp:%x\n",
    595				cpu, i, level, k, resp);
    596
    597			for (j = 0; j < 4; ++j) {
    598				switch (k) {
    599				case 0:
    600					bucket_info[j + (i * 4)].sse_trl =
    601						(resp >> (j * 8)) & 0xff;
    602					break;
    603				case 1:
    604					bucket_info[j + (i * 4)].avx_trl =
    605						(resp >> (j * 8)) & 0xff;
    606					break;
    607				case 2:
    608					bucket_info[j + (i * 4)].avx512_trl =
    609						(resp >> (j * 8)) & 0xff;
    610					break;
    611				default:
    612					break;
    613				}
    614			}
    615		}
    616	}
    617
    618	return 0;
    619}
    620
    621int isst_get_fact_info(int cpu, int level, int fact_bucket, struct isst_fact_info *fact_info)
    622{
    623	struct isst_pkg_ctdp_level_info ctdp_level;
    624	struct isst_pkg_ctdp pkg_dev;
    625	unsigned int resp;
    626	int j, ret, print;
    627
    628	ret = isst_get_ctdp_levels(cpu, &pkg_dev);
    629	if (ret) {
    630		isst_display_error_info_message(1, "Failed to get number of levels", 0, 0);
    631		return ret;
    632	}
    633
    634	if (level > pkg_dev.levels) {
    635		isst_display_error_info_message(1, "Invalid level", 1, level);
    636		return -1;
    637	}
    638
    639	ret = isst_get_ctdp_control(cpu, level, &ctdp_level);
    640	if (ret)
    641		return ret;
    642
    643	if (!ctdp_level.fact_support) {
    644		isst_display_error_info_message(1, "turbo-freq feature is not present at this level", 1, level);
    645		return -1;
    646	}
    647
    648	ret = isst_send_mbox_command(cpu, CONFIG_TDP,
    649				     CONFIG_TDP_GET_FACT_LP_CLIPPING_RATIO, 0,
    650				     level, &resp);
    651	if (ret)
    652		return ret;
    653
    654	debug_printf("cpu:%d CONFIG_TDP_GET_FACT_LP_CLIPPING_RATIO resp:%x\n",
    655		     cpu, resp);
    656
    657	fact_info->lp_clipping_ratio_license_sse = resp & 0xff;
    658	fact_info->lp_clipping_ratio_license_avx2 = (resp >> 8) & 0xff;
    659	fact_info->lp_clipping_ratio_license_avx512 = (resp >> 16) & 0xff;
    660
    661	ret = isst_get_fact_bucket_info(cpu, level, fact_info->bucket_info);
    662	if (ret)
    663		return ret;
    664
    665	print = 0;
    666	for (j = 0; j < ISST_FACT_MAX_BUCKETS; ++j) {
    667		if (fact_bucket != 0xff && fact_bucket != j)
    668			continue;
    669
    670		if (!fact_info->bucket_info[j].high_priority_cores_count)
    671			break;
    672
    673		print = 1;
    674	}
    675	if (!print) {
    676		isst_display_error_info_message(1, "Invalid bucket", 0, 0);
    677		return -1;
    678	}
    679
    680	return 0;
    681}
    682
    683int isst_get_trl(int cpu, unsigned long long *trl)
    684{
    685	int ret;
    686
    687	ret = isst_send_msr_command(cpu, 0x1AD, 0, trl);
    688	if (ret)
    689		return ret;
    690
    691	return 0;
    692}
    693
    694int isst_set_trl(int cpu, unsigned long long trl)
    695{
    696	int ret;
    697
    698	if (!trl)
    699		trl = 0xFFFFFFFFFFFFFFFFULL;
    700
    701	ret = isst_send_msr_command(cpu, 0x1AD, 1, &trl);
    702	if (ret)
    703		return ret;
    704
    705	return 0;
    706}
    707
    708int isst_set_trl_from_current_tdp(int cpu, unsigned long long trl)
    709{
    710	unsigned long long msr_trl;
    711	int ret;
    712
    713	if (trl) {
    714		msr_trl = trl;
    715	} else {
    716		struct isst_pkg_ctdp pkg_dev;
    717		int trl[8];
    718		int i;
    719
    720		ret = isst_get_ctdp_levels(cpu, &pkg_dev);
    721		if (ret)
    722			return ret;
    723
    724		ret = isst_get_get_trl(cpu, pkg_dev.current_level, 0, trl);
    725		if (ret)
    726			return ret;
    727
    728		msr_trl = 0;
    729		for (i = 0; i < 8; ++i) {
    730			unsigned long long _trl = trl[i];
    731
    732			msr_trl |= (_trl << (i * 8));
    733		}
    734	}
    735	ret = isst_send_msr_command(cpu, 0x1AD, 1, &msr_trl);
    736	if (ret)
    737		return ret;
    738
    739	return 0;
    740}
    741
    742/* Return 1 if locked */
    743int isst_get_config_tdp_lock_status(int cpu)
    744{
    745	unsigned long long tdp_control = 0;
    746	int ret;
    747
    748	ret = isst_send_msr_command(cpu, 0x64b, 0, &tdp_control);
    749	if (ret)
    750		return ret;
    751
    752	ret = !!(tdp_control & BIT(31));
    753
    754	return ret;
    755}
    756
    757void isst_get_process_ctdp_complete(int cpu, struct isst_pkg_ctdp *pkg_dev)
    758{
    759	int i;
    760
    761	if (!pkg_dev->processed)
    762		return;
    763
    764	for (i = 0; i < pkg_dev->levels; ++i) {
    765		struct isst_pkg_ctdp_level_info *ctdp_level;
    766
    767		ctdp_level = &pkg_dev->ctdp_level[i];
    768		if (ctdp_level->pbf_support)
    769			free_cpu_set(ctdp_level->pbf_info.core_cpumask);
    770		free_cpu_set(ctdp_level->core_cpumask);
    771	}
    772}
    773
    774int isst_get_process_ctdp(int cpu, int tdp_level, struct isst_pkg_ctdp *pkg_dev)
    775{
    776	int i, ret, valid = 0;
    777
    778	if (pkg_dev->processed)
    779		return 0;
    780
    781	ret = isst_get_ctdp_levels(cpu, pkg_dev);
    782	if (ret)
    783		return ret;
    784
    785	debug_printf("cpu: %d ctdp enable:%d current level: %d levels:%d\n",
    786		     cpu, pkg_dev->enabled, pkg_dev->current_level,
    787		     pkg_dev->levels);
    788
    789	if (tdp_level != 0xff && tdp_level > pkg_dev->levels) {
    790		isst_display_error_info_message(1, "Invalid level", 0, 0);
    791		return -1;
    792	}
    793
    794	if (!pkg_dev->enabled)
    795		isst_display_error_info_message(0, "perf-profile feature is not supported, just base-config level 0 is valid", 0, 0);
    796
    797	for (i = 0; i <= pkg_dev->levels; ++i) {
    798		struct isst_pkg_ctdp_level_info *ctdp_level;
    799
    800		if (tdp_level != 0xff && i != tdp_level)
    801			continue;
    802
    803		debug_printf("cpu:%d Get Information for TDP level:%d\n", cpu,
    804			     i);
    805		ctdp_level = &pkg_dev->ctdp_level[i];
    806
    807		ctdp_level->level = i;
    808		ctdp_level->control_cpu = cpu;
    809		ctdp_level->pkg_id = get_physical_package_id(cpu);
    810		ctdp_level->die_id = get_physical_die_id(cpu);
    811
    812		ret = isst_get_ctdp_control(cpu, i, ctdp_level);
    813		if (ret)
    814			continue;
    815
    816		valid = 1;
    817		pkg_dev->processed = 1;
    818		ctdp_level->processed = 1;
    819
    820		if (ctdp_level->pbf_support) {
    821			ret = isst_get_pbf_info(cpu, i, &ctdp_level->pbf_info);
    822			if (!ret)
    823				ctdp_level->pbf_found = 1;
    824		}
    825
    826		if (ctdp_level->fact_support) {
    827			ret = isst_get_fact_info(cpu, i, 0xff,
    828						 &ctdp_level->fact_info);
    829			if (ret)
    830				return ret;
    831		}
    832
    833		if (!pkg_dev->enabled && is_skx_based_platform()) {
    834			int freq;
    835
    836			freq = get_cpufreq_base_freq(cpu);
    837			if (freq > 0) {
    838				ctdp_level->sse_p1 = freq / 100000;
    839				ctdp_level->tdp_ratio = ctdp_level->sse_p1;
    840			}
    841
    842			isst_get_get_trl_from_msr(cpu, ctdp_level->trl_sse_active_cores);
    843			isst_get_trl_bucket_info(cpu, &ctdp_level->buckets_info);
    844			continue;
    845		}
    846
    847		ret = isst_get_tdp_info(cpu, i, ctdp_level);
    848		if (ret)
    849			return ret;
    850
    851		ret = isst_get_pwr_info(cpu, i, ctdp_level);
    852		if (ret)
    853			return ret;
    854
    855		ret = isst_get_tjmax_info(cpu, i, ctdp_level);
    856		if (ret)
    857			return ret;
    858
    859		ctdp_level->core_cpumask_size =
    860			alloc_cpu_set(&ctdp_level->core_cpumask);
    861		ret = isst_get_coremask_info(cpu, i, ctdp_level);
    862		if (ret)
    863			return ret;
    864
    865		ret = isst_get_trl_bucket_info(cpu, &ctdp_level->buckets_info);
    866		if (ret)
    867			return ret;
    868
    869		ret = isst_get_get_trl(cpu, i, 0,
    870				       ctdp_level->trl_sse_active_cores);
    871		if (ret)
    872			return ret;
    873
    874		ret = isst_get_get_trl(cpu, i, 1,
    875				       ctdp_level->trl_avx_active_cores);
    876		if (ret)
    877			return ret;
    878
    879		ret = isst_get_get_trl(cpu, i, 2,
    880				       ctdp_level->trl_avx_512_active_cores);
    881		if (ret)
    882			return ret;
    883
    884		isst_get_uncore_p0_p1_info(cpu, i, ctdp_level);
    885		isst_get_p1_info(cpu, i, ctdp_level);
    886		isst_get_uncore_mem_freq(cpu, i, ctdp_level);
    887	}
    888
    889	if (!valid)
    890		isst_display_error_info_message(0, "Invalid level, Can't get TDP control information at specified levels on cpu", 1, cpu);
    891
    892	return 0;
    893}
    894
    895int isst_clos_get_clos_information(int cpu, int *enable, int *type)
    896{
    897	unsigned int resp;
    898	int ret;
    899
    900	ret = isst_send_mbox_command(cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG, 0, 0,
    901				     &resp);
    902	if (ret)
    903		return ret;
    904
    905	debug_printf("cpu:%d CLOS_PM_QOS_CONFIG resp:%x\n", cpu, resp);
    906
    907	if (resp & BIT(1))
    908		*enable = 1;
    909	else
    910		*enable = 0;
    911
    912	if (resp & BIT(2))
    913		*type = 1;
    914	else
    915		*type = 0;
    916
    917	return 0;
    918}
    919
    920int isst_pm_qos_config(int cpu, int enable_clos, int priority_type)
    921{
    922	unsigned int req, resp;
    923	int ret;
    924
    925	if (!enable_clos) {
    926		struct isst_pkg_ctdp pkg_dev;
    927		struct isst_pkg_ctdp_level_info ctdp_level;
    928
    929		ret = isst_get_ctdp_levels(cpu, &pkg_dev);
    930		if (ret) {
    931			debug_printf("isst_get_ctdp_levels\n");
    932			return ret;
    933		}
    934
    935		ret = isst_get_ctdp_control(cpu, pkg_dev.current_level,
    936					    &ctdp_level);
    937		if (ret)
    938			return ret;
    939
    940		if (ctdp_level.fact_enabled) {
    941			isst_display_error_info_message(1, "Ignoring request, turbo-freq feature is still enabled", 0, 0);
    942			return -EINVAL;
    943		}
    944		ret = isst_write_pm_config(cpu, 0);
    945		if (ret)
    946			isst_display_error_info_message(0, "WRITE_PM_CONFIG command failed, ignoring error", 0, 0);
    947	} else {
    948		ret = isst_write_pm_config(cpu, 1);
    949		if (ret)
    950			isst_display_error_info_message(0, "WRITE_PM_CONFIG command failed, ignoring error", 0, 0);
    951	}
    952
    953	ret = isst_send_mbox_command(cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG, 0, 0,
    954				     &resp);
    955	if (ret) {
    956		isst_display_error_info_message(1, "CLOS_PM_QOS_CONFIG command failed", 0, 0);
    957		return ret;
    958	}
    959
    960	debug_printf("cpu:%d CLOS_PM_QOS_CONFIG resp:%x\n", cpu, resp);
    961
    962	req = resp;
    963
    964	if (enable_clos)
    965		req = req | BIT(1);
    966	else
    967		req = req & ~BIT(1);
    968
    969	if (priority_type > 1)
    970		isst_display_error_info_message(1, "Invalid priority type: Changing type to ordered", 0, 0);
    971
    972	if (priority_type)
    973		req = req | BIT(2);
    974	else
    975		req = req & ~BIT(2);
    976
    977	ret = isst_send_mbox_command(cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG,
    978				     BIT(MBOX_CMD_WRITE_BIT), req, &resp);
    979	if (ret)
    980		return ret;
    981
    982	debug_printf("cpu:%d CLOS_PM_QOS_CONFIG priority type:%d req:%x\n", cpu,
    983		     priority_type, req);
    984
    985	return 0;
    986}
    987
    988int isst_pm_get_clos(int cpu, int clos, struct isst_clos_config *clos_config)
    989{
    990	unsigned int resp;
    991	int ret;
    992
    993	ret = isst_send_mbox_command(cpu, CONFIG_CLOS, CLOS_PM_CLOS, clos, 0,
    994				     &resp);
    995	if (ret)
    996		return ret;
    997
    998	clos_config->pkg_id = get_physical_package_id(cpu);
    999	clos_config->die_id = get_physical_die_id(cpu);
   1000
   1001	clos_config->epp = resp & 0x0f;
   1002	clos_config->clos_prop_prio = (resp >> 4) & 0x0f;
   1003	clos_config->clos_min = (resp >> 8) & 0xff;
   1004	clos_config->clos_max = (resp >> 16) & 0xff;
   1005	clos_config->clos_desired = (resp >> 24) & 0xff;
   1006
   1007	return 0;
   1008}
   1009
   1010int isst_set_clos(int cpu, int clos, struct isst_clos_config *clos_config)
   1011{
   1012	unsigned int req, resp;
   1013	unsigned int param;
   1014	int ret;
   1015
   1016	req = clos_config->epp & 0x0f;
   1017	req |= (clos_config->clos_prop_prio & 0x0f) << 4;
   1018	req |= (clos_config->clos_min & 0xff) << 8;
   1019	req |= (clos_config->clos_max & 0xff) << 16;
   1020	req |= (clos_config->clos_desired & 0xff) << 24;
   1021
   1022	param = BIT(MBOX_CMD_WRITE_BIT) | clos;
   1023
   1024	ret = isst_send_mbox_command(cpu, CONFIG_CLOS, CLOS_PM_CLOS, param, req,
   1025				     &resp);
   1026	if (ret)
   1027		return ret;
   1028
   1029	debug_printf("cpu:%d CLOS_PM_CLOS param:%x req:%x\n", cpu, param, req);
   1030
   1031	return 0;
   1032}
   1033
   1034int isst_clos_get_assoc_status(int cpu, int *clos_id)
   1035{
   1036	unsigned int resp;
   1037	unsigned int param;
   1038	int core_id, ret;
   1039
   1040	core_id = find_phy_core_num(cpu);
   1041	param = core_id;
   1042
   1043	ret = isst_send_mbox_command(cpu, CONFIG_CLOS, CLOS_PQR_ASSOC, param, 0,
   1044				     &resp);
   1045	if (ret)
   1046		return ret;
   1047
   1048	debug_printf("cpu:%d CLOS_PQR_ASSOC param:%x resp:%x\n", cpu, param,
   1049		     resp);
   1050	*clos_id = (resp >> 16) & 0x03;
   1051
   1052	return 0;
   1053}
   1054
   1055int isst_clos_associate(int cpu, int clos_id)
   1056{
   1057	unsigned int req, resp;
   1058	unsigned int param;
   1059	int core_id, ret;
   1060
   1061	req = (clos_id & 0x03) << 16;
   1062	core_id = find_phy_core_num(cpu);
   1063	param = BIT(MBOX_CMD_WRITE_BIT) | core_id;
   1064
   1065	ret = isst_send_mbox_command(cpu, CONFIG_CLOS, CLOS_PQR_ASSOC, param,
   1066				     req, &resp);
   1067	if (ret)
   1068		return ret;
   1069
   1070	debug_printf("cpu:%d CLOS_PQR_ASSOC param:%x req:%x\n", cpu, param,
   1071		     req);
   1072
   1073	return 0;
   1074}