|
65 | 65 | #include <asm/mwait.h> |
66 | 66 | #include <asm/msr.h> |
67 | 67 |
|
68 | | -#define INTEL_IDLE_VERSION "0.4" |
| 68 | +#define INTEL_IDLE_VERSION "0.4.1" |
69 | 69 | #define PREFIX "intel_idle: " |
70 | 70 |
|
71 | 71 | static struct cpuidle_driver intel_idle_driver = { |
@@ -994,36 +994,92 @@ static void intel_idle_cpuidle_devices_uninit(void) |
994 | 994 | } |
995 | 995 |
|
996 | 996 | /* |
997 | | - * intel_idle_state_table_update() |
998 | | - * |
999 | | - * Update the default state_table for this CPU-id |
| 997 | + * ivt_idle_state_table_update(void) |
1000 | 998 | * |
1001 | | - * Currently used to access tuned IVT multi-socket targets |
| 999 | + * Tune IVT multi-socket targets |
1002 | 1000 | * Assumption: num_sockets == (max_package_num + 1) |
1003 | 1001 | */ |
1004 | | -void intel_idle_state_table_update(void) |
| 1002 | +static void ivt_idle_state_table_update(void) |
1005 | 1003 | { |
1006 | 1004 | /* IVT uses a different table for 1-2, 3-4, and > 4 sockets */ |
1007 | | - if (boot_cpu_data.x86_model == 0x3e) { /* IVT */ |
1008 | | - int cpu, package_num, num_sockets = 1; |
1009 | | - |
1010 | | - for_each_online_cpu(cpu) { |
1011 | | - package_num = topology_physical_package_id(cpu); |
1012 | | - if (package_num + 1 > num_sockets) { |
1013 | | - num_sockets = package_num + 1; |
1014 | | - |
1015 | | - if (num_sockets > 4) { |
1016 | | - cpuidle_state_table = ivt_cstates_8s; |
1017 | | - return; |
1018 | | - } |
| 1005 | + int cpu, package_num, num_sockets = 1; |
| 1006 | + |
| 1007 | + for_each_online_cpu(cpu) { |
| 1008 | + package_num = topology_physical_package_id(cpu); |
| 1009 | + if (package_num + 1 > num_sockets) { |
| 1010 | + num_sockets = package_num + 1; |
| 1011 | + |
| 1012 | + if (num_sockets > 4) { |
| 1013 | + cpuidle_state_table = ivt_cstates_8s; |
| 1014 | + return; |
1019 | 1015 | } |
1020 | 1016 | } |
| 1017 | + } |
| 1018 | + |
| 1019 | + if (num_sockets > 2) |
| 1020 | + cpuidle_state_table = ivt_cstates_4s; |
| 1021 | + |
| 1022 | + /* else, 1 and 2 socket systems use default ivt_cstates */ |
| 1023 | +} |
| 1024 | +/* |
| 1025 | + * sklh_idle_state_table_update(void) |
| 1026 | + * |
| 1027 | + * On SKL-H (model 0x5e) disable C8 and C9 if: |
| 1028 | + * C10 is enabled and SGX disabled |
| 1029 | + */ |
| 1030 | +static void sklh_idle_state_table_update(void) |
| 1031 | +{ |
| 1032 | + unsigned long long msr; |
| 1033 | + unsigned int eax, ebx, ecx, edx; |
| 1034 | + |
| 1035 | + |
| 1036 | + /* if PC10 disabled via cmdline intel_idle.max_cstate=7 or shallower */ |
| 1037 | + if (max_cstate <= 7) |
| 1038 | + return; |
| 1039 | + |
| 1040 | + /* if PC10 not present in CPUID.MWAIT.EDX */ |
| 1041 | + if ((mwait_substates & (0xF << 28)) == 0) |
| 1042 | + return; |
| 1043 | + |
| 1044 | + rdmsrl(MSR_NHM_SNB_PKG_CST_CFG_CTL, msr); |
| 1045 | + |
| 1046 | + /* PC10 is not enabled in PKG C-state limit */ |
| 1047 | + if ((msr & 0xF) != 8) |
| 1048 | + return; |
| 1049 | + |
| 1050 | + ecx = 0; |
| 1051 | + cpuid(7, &eax, &ebx, &ecx, &edx); |
| 1052 | + |
| 1053 | + /* if SGX is present */ |
| 1054 | + if (ebx & (1 << 2)) { |
1021 | 1055 |
|
1022 | | - if (num_sockets > 2) |
1023 | | - cpuidle_state_table = ivt_cstates_4s; |
1024 | | - /* else, 1 and 2 socket systems use default ivt_cstates */ |
| 1056 | + rdmsrl(MSR_IA32_FEATURE_CONTROL, msr); |
| 1057 | + |
| 1058 | + /* if SGX is enabled */ |
| 1059 | + if (msr & (1 << 18)) |
| 1060 | + return; |
| 1061 | + } |
| 1062 | + |
| 1063 | + skl_cstates[5].disabled = 1; /* C8-SKL */ |
| 1064 | + skl_cstates[6].disabled = 1; /* C9-SKL */ |
| 1065 | +} |
| 1066 | +/* |
| 1067 | + * intel_idle_state_table_update() |
| 1068 | + * |
| 1069 | + * Update the default state_table for this CPU-id |
| 1070 | + */ |
| 1071 | + |
| 1072 | +static void intel_idle_state_table_update(void) |
| 1073 | +{ |
| 1074 | + switch (boot_cpu_data.x86_model) { |
| 1075 | + |
| 1076 | + case 0x3e: /* IVT */ |
| 1077 | + ivt_idle_state_table_update(); |
| 1078 | + break; |
| 1079 | + case 0x5e: /* SKL-H */ |
| 1080 | + sklh_idle_state_table_update(); |
| 1081 | + break; |
1025 | 1082 | } |
1026 | | - return; |
1027 | 1083 | } |
1028 | 1084 |
|
1029 | 1085 | /* |
@@ -1063,6 +1119,14 @@ static int __init intel_idle_cpuidle_driver_init(void) |
1063 | 1119 | if (num_substates == 0) |
1064 | 1120 | continue; |
1065 | 1121 |
|
| 1122 | + /* if state marked as disabled, skip it */ |
| 1123 | + if (cpuidle_state_table[cstate].disabled != 0) { |
| 1124 | + pr_debug(PREFIX "state %s is disabled", |
| 1125 | + cpuidle_state_table[cstate].name); |
| 1126 | + continue; |
| 1127 | + } |
| 1128 | + |
| 1129 | + |
1066 | 1130 | if (((mwait_cstate + 1) > 2) && |
1067 | 1131 | !boot_cpu_has(X86_FEATURE_NONSTOP_TSC)) |
1068 | 1132 | mark_tsc_unstable("TSC halts in idle" |
|
0 commit comments