@@ -89,6 +89,83 @@ EXPORT_SYMBOL_GPL(get_llc_id);
8989/* L2 cache ID of each logical CPU */
9090DEFINE_PER_CPU_READ_MOSTLY (u16 , cpu_l2c_id ) = BAD_APICID ;
9191
92+ static struct ppin_info {
93+ int feature ;
94+ int msr_ppin_ctl ;
95+ int msr_ppin ;
96+ } ppin_info [] = {
97+ [X86_VENDOR_INTEL ] = {
98+ .feature = X86_FEATURE_INTEL_PPIN ,
99+ .msr_ppin_ctl = MSR_PPIN_CTL ,
100+ .msr_ppin = MSR_PPIN
101+ },
102+ [X86_VENDOR_AMD ] = {
103+ .feature = X86_FEATURE_AMD_PPIN ,
104+ .msr_ppin_ctl = MSR_AMD_PPIN_CTL ,
105+ .msr_ppin = MSR_AMD_PPIN
106+ },
107+ };
108+
109+ static const struct x86_cpu_id ppin_cpuids [] = {
110+ X86_MATCH_FEATURE (X86_FEATURE_AMD_PPIN , & ppin_info [X86_VENDOR_AMD ]),
111+ X86_MATCH_FEATURE (X86_FEATURE_INTEL_PPIN , & ppin_info [X86_VENDOR_INTEL ]),
112+
113+ /* Legacy models without CPUID enumeration */
114+ X86_MATCH_INTEL_FAM6_MODEL (IVYBRIDGE_X , & ppin_info [X86_VENDOR_INTEL ]),
115+ X86_MATCH_INTEL_FAM6_MODEL (HASWELL_X , & ppin_info [X86_VENDOR_INTEL ]),
116+ X86_MATCH_INTEL_FAM6_MODEL (BROADWELL_D , & ppin_info [X86_VENDOR_INTEL ]),
117+ X86_MATCH_INTEL_FAM6_MODEL (BROADWELL_X , & ppin_info [X86_VENDOR_INTEL ]),
118+ X86_MATCH_INTEL_FAM6_MODEL (SKYLAKE_X , & ppin_info [X86_VENDOR_INTEL ]),
119+ X86_MATCH_INTEL_FAM6_MODEL (ICELAKE_X , & ppin_info [X86_VENDOR_INTEL ]),
120+ X86_MATCH_INTEL_FAM6_MODEL (ICELAKE_D , & ppin_info [X86_VENDOR_INTEL ]),
121+ X86_MATCH_INTEL_FAM6_MODEL (SAPPHIRERAPIDS_X , & ppin_info [X86_VENDOR_INTEL ]),
122+ X86_MATCH_INTEL_FAM6_MODEL (XEON_PHI_KNL , & ppin_info [X86_VENDOR_INTEL ]),
123+ X86_MATCH_INTEL_FAM6_MODEL (XEON_PHI_KNM , & ppin_info [X86_VENDOR_INTEL ]),
124+
125+ {}
126+ };
127+
128+ static void ppin_init (struct cpuinfo_x86 * c )
129+ {
130+ const struct x86_cpu_id * id ;
131+ unsigned long long val ;
132+ struct ppin_info * info ;
133+
134+ id = x86_match_cpu (ppin_cpuids );
135+ if (!id )
136+ return ;
137+
138+ /*
139+ * Testing the presence of the MSR is not enough. Need to check
140+ * that the PPIN_CTL allows reading of the PPIN.
141+ */
142+ info = (struct ppin_info * )id -> driver_data ;
143+
144+ if (rdmsrl_safe (info -> msr_ppin_ctl , & val ))
145+ goto clear_ppin ;
146+
147+ if ((val & 3UL ) == 1UL ) {
148+ /* PPIN locked in disabled mode */
149+ goto clear_ppin ;
150+ }
151+
152+ /* If PPIN is disabled, try to enable */
153+ if (!(val & 2UL )) {
154+ wrmsrl_safe (info -> msr_ppin_ctl , val | 2UL );
155+ rdmsrl_safe (info -> msr_ppin_ctl , & val );
156+ }
157+
158+ /* Is the enable bit set? */
159+ if (val & 2UL ) {
160+ c -> ppin = __rdmsr (info -> msr_ppin );
161+ set_cpu_cap (c , info -> feature );
162+ return ;
163+ }
164+
165+ clear_ppin :
166+ clear_cpu_cap (c , info -> feature );
167+ }
168+
92169/* correctly size the local cpu masks */
93170void __init setup_cpu_local_masks (void )
94171{
@@ -1710,6 +1787,8 @@ static void identify_cpu(struct cpuinfo_x86 *c)
17101787 c -> x86_capability [i ] |= boot_cpu_data .x86_capability [i ];
17111788 }
17121789
1790+ ppin_init (c );
1791+
17131792 /* Init Machine Check Exception if available. */
17141793 mcheck_cpu_init (c );
17151794
0 commit comments