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

Configure Feed

Select the types of activity you want to include in your feed.

amd-pstate: Add support for CPPC_REQ2 and FLOOR_PERF

Some future AMD processors have feature named "CPPC Performance
Priority" which lets userspace specify different floor performance
levels for different CPUs. The platform firmware takes these different
floor performance levels into consideration while throttling the CPUs
under power/thermal constraints. The presence of this feature is
indicated by bit 16 of the EDX register for CPUID leaf
0x80000007. More details can be found in AMD Publication titled "AMD64
Collaborative Processor Performance Control (CPPC) Performance
Priority" Revision 1.10.

The number of distinct floor performance levels supported on the
platform will be advertised through the bits 32:39 of the
MSR_AMD_CPPC_CAP1. Bits 0:7 of a new MSR MSR_AMD_CPPC_REQ2
(0xc00102b5) will be used to specify the desired floor performance
level for that CPU.

Add support for the aforementioned MSR_AMD_CPPC_REQ2, and macros for
parsing and updating the relevant bits from MSR_AMD_CPPC_CAP1 and
MSR_AMD_CPPC_REQ2.

On boot if the default value of the MSR_AMD_CPPC_REQ2[7:0] (Floor
Perf) is lower than CPPC.lowest_perf, and thus invalid, initialize it
to MSR_AMD_CPPC_CAP1.nominal_perf which is a sane default value.

Save the boot-time floor_perf during amd_pstate_init_floor_perf(). In
a subsequent patch it will be restored in the suspend, offline, and
exit paths, mirroring how bios_min_perf is handled for
MSR_AMD_CPPC_REQ.

Link: https://docs.amd.com/v/u/en-US/69206_1.10_AMD64_CPPC_PUB
Reviewed-by: Mario Limonciello (AMD) <superm1@kernel.org>
Signed-off-by: Gautham R. Shenoy <gautham.shenoy@amd.com>
Signed-off-by: Mario Limonciello (AMD) <superm1@kernel.org>

authored by

Gautham R. Shenoy and committed by
Mario Limonciello (AMD)
97838281 17210008

+90 -1
+5
arch/x86/include/asm/msr-index.h
··· 765 765 #define MSR_AMD_CPPC_CAP2 0xc00102b2 766 766 #define MSR_AMD_CPPC_REQ 0xc00102b3 767 767 #define MSR_AMD_CPPC_STATUS 0xc00102b4 768 + #define MSR_AMD_CPPC_REQ2 0xc00102b5 768 769 769 770 /* Masks for use with MSR_AMD_CPPC_CAP1 */ 770 771 #define AMD_CPPC_LOWEST_PERF_MASK GENMASK(7, 0) 771 772 #define AMD_CPPC_LOWNONLIN_PERF_MASK GENMASK(15, 8) 772 773 #define AMD_CPPC_NOMINAL_PERF_MASK GENMASK(23, 16) 773 774 #define AMD_CPPC_HIGHEST_PERF_MASK GENMASK(31, 24) 775 + #define AMD_CPPC_FLOOR_PERF_CNT_MASK GENMASK_ULL(39, 32) 774 776 775 777 /* Masks for use with MSR_AMD_CPPC_REQ */ 776 778 #define AMD_CPPC_MAX_PERF_MASK GENMASK(7, 0) 777 779 #define AMD_CPPC_MIN_PERF_MASK GENMASK(15, 8) 778 780 #define AMD_CPPC_DES_PERF_MASK GENMASK(23, 16) 779 781 #define AMD_CPPC_EPP_PERF_MASK GENMASK(31, 24) 782 + 783 + /* Masks for use with MSR_AMD_CPPC_REQ2 */ 784 + #define AMD_CPPC_FLOOR_PERF_MASK GENMASK(7, 0) 780 785 781 786 /* AMD Performance Counter Global Status and Control MSRs */ 782 787 #define MSR_AMD64_PERF_CNTR_GLOBAL_STATUS 0xc0000300
+77 -1
drivers/cpufreq/amd-pstate.c
··· 329 329 return static_call(amd_pstate_set_epp)(policy, epp); 330 330 } 331 331 332 + static int amd_pstate_set_floor_perf(struct cpufreq_policy *policy, u8 perf) 333 + { 334 + struct amd_cpudata *cpudata = policy->driver_data; 335 + u64 value, prev; 336 + int ret; 337 + 338 + if (!cpu_feature_enabled(X86_FEATURE_CPPC_PERF_PRIO)) 339 + return 0; 340 + 341 + value = prev = READ_ONCE(cpudata->cppc_req2_cached); 342 + FIELD_MODIFY(AMD_CPPC_FLOOR_PERF_MASK, &value, perf); 343 + 344 + if (value == prev) 345 + return 0; 346 + 347 + ret = wrmsrq_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ2, value); 348 + if (ret) { 349 + pr_err("failed to set CPPC REQ2 value. Error (%d)\n", ret); 350 + return ret; 351 + } 352 + 353 + WRITE_ONCE(cpudata->cppc_req2_cached, value); 354 + 355 + return ret; 356 + } 357 + 358 + static int amd_pstate_init_floor_perf(struct cpufreq_policy *policy) 359 + { 360 + struct amd_cpudata *cpudata = policy->driver_data; 361 + u8 floor_perf; 362 + u64 value; 363 + int ret; 364 + 365 + if (!cpu_feature_enabled(X86_FEATURE_CPPC_PERF_PRIO)) 366 + return 0; 367 + 368 + ret = rdmsrq_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ2, &value); 369 + if (ret) { 370 + pr_err("failed to read CPPC REQ2 value. Error (%d)\n", ret); 371 + return ret; 372 + } 373 + 374 + WRITE_ONCE(cpudata->cppc_req2_cached, value); 375 + floor_perf = FIELD_GET(AMD_CPPC_FLOOR_PERF_MASK, 376 + cpudata->cppc_req2_cached); 377 + 378 + /* Set a sane value for floor_perf if the default value is invalid */ 379 + if (floor_perf < cpudata->perf.lowest_perf) { 380 + floor_perf = cpudata->perf.nominal_perf; 381 + ret = amd_pstate_set_floor_perf(policy, floor_perf); 382 + if (ret) 383 + return ret; 384 + } 385 + 386 + cpudata->bios_floor_perf = floor_perf; 387 + 388 + return 0; 389 + } 390 + 332 391 static int shmem_set_epp(struct cpufreq_policy *policy, u8 epp) 333 392 { 334 393 struct amd_cpudata *cpudata = policy->driver_data; ··· 485 426 perf.lowest_perf = FIELD_GET(AMD_CPPC_LOWEST_PERF_MASK, cap1); 486 427 WRITE_ONCE(cpudata->perf, perf); 487 428 WRITE_ONCE(cpudata->prefcore_ranking, FIELD_GET(AMD_CPPC_HIGHEST_PERF_MASK, cap1)); 429 + WRITE_ONCE(cpudata->floor_perf_cnt, FIELD_GET(AMD_CPPC_FLOOR_PERF_CNT_MASK, cap1)); 488 430 489 431 return 0; 490 432 } ··· 1084 1024 cpudata->nominal_freq, 1085 1025 perf.highest_perf); 1086 1026 1027 + policy->driver_data = cpudata; 1087 1028 ret = amd_pstate_cppc_enable(policy); 1088 1029 if (ret) 1089 1030 goto free_cpudata1; ··· 1096 1035 1097 1036 if (cpu_feature_enabled(X86_FEATURE_CPPC)) 1098 1037 policy->fast_switch_possible = true; 1038 + 1039 + ret = amd_pstate_init_floor_perf(policy); 1040 + if (ret) { 1041 + dev_err(dev, "Failed to initialize Floor Perf (%d)\n", ret); 1042 + goto free_cpudata1; 1043 + } 1099 1044 1100 1045 ret = freq_qos_add_request(&policy->constraints, &cpudata->req[0], 1101 1046 FREQ_QOS_MIN, FREQ_QOS_MIN_DEFAULT_VALUE); ··· 1117 1050 goto free_cpudata2; 1118 1051 } 1119 1052 1120 - policy->driver_data = cpudata; 1121 1053 1122 1054 if (!current_pstate_driver->adjust_perf) 1123 1055 current_pstate_driver->adjust_perf = amd_pstate_adjust_perf; ··· 1128 1062 free_cpudata1: 1129 1063 pr_warn("Failed to initialize CPU %d: %d\n", policy->cpu, ret); 1130 1064 kfree(cpudata); 1065 + policy->driver_data = NULL; 1131 1066 return ret; 1132 1067 } 1133 1068 ··· 1139 1072 1140 1073 /* Reset CPPC_REQ MSR to the BIOS value */ 1141 1074 amd_pstate_update_perf(policy, perf.bios_min_perf, 0U, 0U, 0U, false); 1075 + amd_pstate_set_floor_perf(policy, cpudata->bios_floor_perf); 1142 1076 1143 1077 freq_qos_remove_request(&cpudata->req[1]); 1144 1078 freq_qos_remove_request(&cpudata->req[0]); ··· 1666 1598 if (ret) 1667 1599 goto free_cpudata1; 1668 1600 1601 + ret = amd_pstate_init_floor_perf(policy); 1602 + if (ret) { 1603 + dev_err(dev, "Failed to initialize Floor Perf (%d)\n", ret); 1604 + goto free_cpudata1; 1605 + } 1606 + 1669 1607 current_pstate_driver->adjust_perf = NULL; 1670 1608 1671 1609 return 0; ··· 1679 1605 free_cpudata1: 1680 1606 pr_warn("Failed to initialize CPU %d: %d\n", policy->cpu, ret); 1681 1607 kfree(cpudata); 1608 + policy->driver_data = NULL; 1682 1609 return ret; 1683 1610 } 1684 1611 ··· 1692 1617 1693 1618 /* Reset CPPC_REQ MSR to the BIOS value */ 1694 1619 amd_pstate_update_perf(policy, perf.bios_min_perf, 0U, 0U, 0U, false); 1620 + amd_pstate_set_floor_perf(policy, cpudata->bios_floor_perf); 1695 1621 1696 1622 kfree(cpudata); 1697 1623 policy->driver_data = NULL;
+8
drivers/cpufreq/amd-pstate.h
··· 62 62 * @cpu: CPU number 63 63 * @req: constraint request to apply 64 64 * @cppc_req_cached: cached performance request hints 65 + * @cppc_req2_cached: cached value of MSR_AMD_CPPC_REQ2 65 66 * @perf: cached performance-related data 66 67 * @prefcore_ranking: the preferred core ranking, the higher value indicates a higher 67 68 * priority. 69 + * @floor_perf_cnt: Cached value of the number of distinct floor 70 + * performance levels supported 71 + * @bios_floor_perf: Cached value of the boot-time floor performance level from 72 + * MSR_AMD_CPPC_REQ2 68 73 * @min_limit_freq: Cached value of policy->min (in khz) 69 74 * @max_limit_freq: Cached value of policy->max (in khz) 70 75 * @nominal_freq: the frequency (in khz) that mapped to nominal_perf ··· 92 87 93 88 struct freq_qos_request req[2]; 94 89 u64 cppc_req_cached; 90 + u64 cppc_req2_cached; 95 91 96 92 union perf_cached perf; 97 93 98 94 u8 prefcore_ranking; 95 + u8 floor_perf_cnt; 96 + u8 bios_floor_perf; 99 97 u32 min_limit_freq; 100 98 u32 max_limit_freq; 101 99 u32 nominal_freq;