blob: 910dcb88c90ba833a0d9545f0c1a857246ee41e5 [file] [log] [blame]
Lee Leahyb0005132015-05-12 18:19:47 -07001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2007-2009 coresystems GmbH
5 * Copyright (C) 2014 Google Inc.
Pratik Prajapati07cbd762019-01-11 14:00:40 -08006 * Copyright (C) 2015-2019 Intel Corporation.
Lee Leahyb0005132015-05-12 18:19:47 -07007 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2 of the License.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
Lee Leahyb0005132015-05-12 18:19:47 -070016 */
17
Subrata Banika4b11e5c2017-02-03 18:57:49 +053018#include <assert.h>
Subrata Banik53b08c32018-12-10 14:11:35 +053019#include <arch/cpu.h>
Subrata Banika4b11e5c2017-02-03 18:57:49 +053020#include <bootstate.h>
Lee Leahyb0005132015-05-12 18:19:47 -070021#include <console/console.h>
22#include <device/device.h>
23#include <device/pci.h>
24#include <string.h>
Lee Leahy1d14b3e2015-05-12 18:23:27 -070025#include <chip.h>
Lee Leahyb0005132015-05-12 18:19:47 -070026#include <cpu/x86/mtrr.h>
27#include <cpu/x86/msr.h>
28#include <cpu/x86/lapic.h>
29#include <cpu/x86/mp.h>
Nico Huber6275e342018-11-21 00:11:35 +010030#include <cpu/intel/common/common.h>
Lee Leahyb0005132015-05-12 18:19:47 -070031#include <cpu/intel/microcode.h>
32#include <cpu/intel/speedstep.h>
33#include <cpu/intel/turbo.h>
34#include <cpu/x86/cache.h>
35#include <cpu/x86/name.h>
36#include <cpu/x86/smm.h>
37#include <delay.h>
Barnali Sarkar0a203d12017-05-04 18:02:17 +053038#include <intelblocks/cpulib.h>
Aaron Durbin93d5f402017-06-08 11:00:23 -050039#include <intelblocks/fast_spi.h>
Barnali Sarkar73273862017-06-13 20:22:33 +053040#include <intelblocks/mp_init.h>
Pratik Prajapatia04aa3d2017-06-12 23:02:36 -070041#include <intelblocks/sgx.h>
Subrata Banikece173c2017-12-14 18:18:34 +053042#include <intelblocks/smm.h>
Lee Leahyb0005132015-05-12 18:19:47 -070043#include <soc/cpu.h>
44#include <soc/msr.h>
45#include <soc/pci_devs.h>
Subrata Banikf004f662017-02-03 19:05:27 +053046#include <soc/pm.h>
Lee Leahyb0005132015-05-12 18:19:47 -070047#include <soc/ramstage.h>
Lee Leahyb0005132015-05-12 18:19:47 -070048#include <soc/smm.h>
49#include <soc/systemagent.h>
Subrata Banik1c9d8632018-05-15 13:31:28 +053050#include <timer.h>
Lee Leahyb0005132015-05-12 18:19:47 -070051
52/* Convert time in seconds to POWER_LIMIT_1_TIME MSR value */
53static const u8 power_limit_time_sec_to_msr[] = {
54 [0] = 0x00,
55 [1] = 0x0a,
56 [2] = 0x0b,
57 [3] = 0x4b,
58 [4] = 0x0c,
59 [5] = 0x2c,
60 [6] = 0x4c,
61 [7] = 0x6c,
62 [8] = 0x0d,
63 [10] = 0x2d,
64 [12] = 0x4d,
65 [14] = 0x6d,
66 [16] = 0x0e,
67 [20] = 0x2e,
68 [24] = 0x4e,
69 [28] = 0x6e,
70 [32] = 0x0f,
71 [40] = 0x2f,
72 [48] = 0x4f,
73 [56] = 0x6f,
74 [64] = 0x10,
75 [80] = 0x30,
76 [96] = 0x50,
77 [112] = 0x70,
78 [128] = 0x11,
79};
80
81/* Convert POWER_LIMIT_1_TIME MSR value to seconds */
82static const u8 power_limit_time_msr_to_sec[] = {
83 [0x00] = 0,
84 [0x0a] = 1,
85 [0x0b] = 2,
86 [0x4b] = 3,
87 [0x0c] = 4,
88 [0x2c] = 5,
89 [0x4c] = 6,
90 [0x6c] = 7,
91 [0x0d] = 8,
92 [0x2d] = 10,
93 [0x4d] = 12,
94 [0x6d] = 14,
95 [0x0e] = 16,
96 [0x2e] = 20,
97 [0x4e] = 24,
98 [0x6e] = 28,
99 [0x0f] = 32,
100 [0x2f] = 40,
101 [0x4f] = 48,
102 [0x6f] = 56,
103 [0x10] = 64,
104 [0x30] = 80,
105 [0x50] = 96,
106 [0x70] = 112,
107 [0x11] = 128,
108};
109
Lee Leahyb0005132015-05-12 18:19:47 -0700110/*
111 * Configure processor power limits if possible
112 * This must be done AFTER set of BIOS_RESET_CPL
113 */
114void set_power_limits(u8 power_limit_1_time)
115{
116 msr_t msr = rdmsr(MSR_PLATFORM_INFO);
117 msr_t limit;
Lee Leahy573564c2017-03-16 16:38:26 -0700118 unsigned int power_unit;
Wei Shun Changb54d1542018-04-09 11:46:43 +0800119 unsigned int tdp, min_power, max_power, max_time, tdp_pl2, tdp_pl1;
Lee Leahyb0005132015-05-12 18:19:47 -0700120 u8 power_limit_1_val;
Elyes HAOUAS143fb462018-05-25 12:56:45 +0200121 struct device *dev = SA_DEV_ROOT;
pchandrif9495ea2016-01-11 15:22:45 -0800122 config_t *conf = dev->chip_info;
Lee Leahyb0005132015-05-12 18:19:47 -0700123
124 if (power_limit_1_time > ARRAY_SIZE(power_limit_time_sec_to_msr))
125 power_limit_1_time = 28;
126
127 if (!(msr.lo & PLATFORM_INFO_SET_TDP))
128 return;
129
130 /* Get units */
131 msr = rdmsr(MSR_PKG_POWER_SKU_UNIT);
pchandrif9495ea2016-01-11 15:22:45 -0800132 power_unit = 1 << (msr.lo & 0xf);
Lee Leahyb0005132015-05-12 18:19:47 -0700133
134 /* Get power defaults for this SKU */
135 msr = rdmsr(MSR_PKG_POWER_SKU);
136 tdp = msr.lo & 0x7fff;
137 min_power = (msr.lo >> 16) & 0x7fff;
138 max_power = msr.hi & 0x7fff;
139 max_time = (msr.hi >> 16) & 0x7f;
140
141 printk(BIOS_DEBUG, "CPU TDP: %u Watts\n", tdp / power_unit);
142
143 if (power_limit_time_msr_to_sec[max_time] > power_limit_1_time)
144 power_limit_1_time = power_limit_time_msr_to_sec[max_time];
145
146 if (min_power > 0 && tdp < min_power)
147 tdp = min_power;
148
149 if (max_power > 0 && tdp > max_power)
150 tdp = max_power;
151
152 power_limit_1_val = power_limit_time_sec_to_msr[power_limit_1_time];
153
154 /* Set long term power limit to TDP */
155 limit.lo = 0;
Wei Shun Changb54d1542018-04-09 11:46:43 +0800156 tdp_pl1 = ((conf->tdp_pl1_override == 0) ?
157 tdp : (conf->tdp_pl1_override * power_unit));
158 limit.lo |= (tdp_pl1 & PKG_POWER_LIMIT_MASK);
Rizwan Qureshi0dd72e82015-10-15 21:38:21 +0530159
160 /* Set PL1 Pkg Power clamp bit */
161 limit.lo |= PKG_POWER_LIMIT_CLAMP;
162
Lee Leahyb0005132015-05-12 18:19:47 -0700163 limit.lo |= PKG_POWER_LIMIT_EN;
164 limit.lo |= (power_limit_1_val & PKG_POWER_LIMIT_TIME_MASK) <<
165 PKG_POWER_LIMIT_TIME_SHIFT;
166
Shelley Chen20c3ea52017-06-29 11:31:16 -0700167 /* Set short term power limit to 1.25 * TDP if no config given */
Lee Leahyb0005132015-05-12 18:19:47 -0700168 limit.hi = 0;
pchandrif9495ea2016-01-11 15:22:45 -0800169 tdp_pl2 = (conf->tdp_pl2_override == 0) ?
170 (tdp * 125) / 100 : (conf->tdp_pl2_override * power_unit);
Shelley Chen20c3ea52017-06-29 11:31:16 -0700171 printk(BIOS_DEBUG, "CPU PL2 = %u Watts\n", tdp_pl2 / power_unit);
pchandrif9495ea2016-01-11 15:22:45 -0800172 limit.hi |= (tdp_pl2) & PKG_POWER_LIMIT_MASK;
Rizwan Qureshi0dd72e82015-10-15 21:38:21 +0530173 limit.hi |= PKG_POWER_LIMIT_CLAMP;
Lee Leahyb0005132015-05-12 18:19:47 -0700174 limit.hi |= PKG_POWER_LIMIT_EN;
Lee Leahyb0005132015-05-12 18:19:47 -0700175
Lee Leahy1d14b3e2015-05-12 18:23:27 -0700176 /* Power limit 2 time is only programmable on server SKU */
Lee Leahyb0005132015-05-12 18:19:47 -0700177 wrmsr(MSR_PKG_POWER_LIMIT, limit);
178
pchandrif9495ea2016-01-11 15:22:45 -0800179 /* Set PL2 power limit values in MCHBAR and disable PL1 */
180 MCHBAR32(MCH_PKG_POWER_LIMIT_LO) = limit.lo & (~(PKG_POWER_LIMIT_EN));
Lee Leahyb0005132015-05-12 18:19:47 -0700181 MCHBAR32(MCH_PKG_POWER_LIMIT_HI) = limit.hi;
182
Shelley Chen20c3ea52017-06-29 11:31:16 -0700183 /* Set PsysPl2 */
184 if (conf->tdp_psyspl2) {
185 limit = rdmsr(MSR_PLATFORM_POWER_LIMIT);
186 limit.hi = 0;
187 printk(BIOS_DEBUG, "CPU PsysPL2 = %u Watts\n",
188 conf->tdp_psyspl2);
189 limit.hi |= (conf->tdp_psyspl2 * power_unit) &
190 PKG_POWER_LIMIT_MASK;
191 limit.hi |= PKG_POWER_LIMIT_CLAMP;
192 limit.hi |= PKG_POWER_LIMIT_EN;
193
194 wrmsr(MSR_PLATFORM_POWER_LIMIT, limit);
195 }
196
Shelley Chen50db9a22018-01-31 15:55:50 -0800197 /* Set PsysPl3 */
198 if (conf->tdp_psyspl3) {
199 limit = rdmsr(MSR_PL3_CONTROL);
200 limit.lo = 0;
201 printk(BIOS_DEBUG, "CPU PsysPL3 = %u Watts\n",
202 conf->tdp_psyspl3);
203 limit.lo |= (conf->tdp_psyspl3 * power_unit) &
204 PKG_POWER_LIMIT_MASK;
205 /* Enable PsysPl3 */
206 limit.lo |= PKG_POWER_LIMIT_EN;
207 /* set PsysPl3 time window */
208 limit.lo |= (conf->tdp_psyspl3_time &
209 PKG_POWER_LIMIT_TIME_MASK) <<
210 PKG_POWER_LIMIT_TIME_SHIFT;
211 /* set PsysPl3 duty cycle */
212 limit.lo |= (conf->tdp_psyspl3_dutycycle &
213 PKG_POWER_LIMIT_DUTYCYCLE_MASK) <<
214 PKG_POWER_LIMIT_DUTYCYCLE_SHIFT;
215 wrmsr(MSR_PL3_CONTROL, limit);
216 }
217
218 /* Set Pl4 */
219 if (conf->tdp_pl4) {
220 limit = rdmsr(MSR_VR_CURRENT_CONFIG);
221 limit.lo = 0;
222 printk(BIOS_DEBUG, "CPU PL4 = %u Watts\n",
223 conf->tdp_pl4);
224 limit.lo |= (conf->tdp_pl4 * power_unit) &
225 PKG_POWER_LIMIT_MASK;
226 wrmsr(MSR_VR_CURRENT_CONFIG, limit);
227 }
228
Lee Leahyb0005132015-05-12 18:19:47 -0700229 /* Set DDR RAPL power limit by copying from MMIO to MSR */
230 msr.lo = MCHBAR32(MCH_DDR_POWER_LIMIT_LO);
231 msr.hi = MCHBAR32(MCH_DDR_POWER_LIMIT_HI);
232 wrmsr(MSR_DDR_RAPL_LIMIT, msr);
233
234 /* Use nominal TDP values for CPUs with configurable TDP */
235 if (cpu_config_tdp_levels()) {
236 msr = rdmsr(MSR_CONFIG_TDP_NOMINAL);
237 limit.hi = 0;
Barnali Sarkar0a203d12017-05-04 18:02:17 +0530238 limit.lo = cpu_get_tdp_nominal_ratio();
Lee Leahyb0005132015-05-12 18:19:47 -0700239 wrmsr(MSR_TURBO_ACTIVATION_RATIO, limit);
240 }
241}
242
Lee Leahyb0005132015-05-12 18:19:47 -0700243static void configure_thermal_target(void)
244{
Elyes HAOUAS143fb462018-05-25 12:56:45 +0200245 struct device *dev = SA_DEV_ROOT;
Lee Leahyb0005132015-05-12 18:19:47 -0700246 config_t *conf = dev->chip_info;
247 msr_t msr;
248
Sumeet Pawnikar9d2f3de2016-12-22 13:48:46 +0530249 /* Set TCC activation offset if supported */
Lee Leahyb0005132015-05-12 18:19:47 -0700250 msr = rdmsr(MSR_PLATFORM_INFO);
Pratik Prajapati07cbd762019-01-11 14:00:40 -0800251 if ((msr.lo & (1 << 30)) && conf && conf->tcc_offset) {
Lee Leahyb0005132015-05-12 18:19:47 -0700252 msr = rdmsr(MSR_TEMPERATURE_TARGET);
253 msr.lo &= ~(0xf << 24); /* Bits 27:24 */
254 msr.lo |= (conf->tcc_offset & 0xf) << 24;
255 wrmsr(MSR_TEMPERATURE_TARGET, msr);
256 }
Sumeet Pawnikar8b3004e2016-11-11 17:11:28 +0530257 msr = rdmsr(MSR_TEMPERATURE_TARGET);
258 msr.lo &= ~0x7f; /* Bits 6:0 */
259 msr.lo |= 0xe6; /* setting 100ms thermal time window */
260 wrmsr(MSR_TEMPERATURE_TARGET, msr);
Lee Leahyb0005132015-05-12 18:19:47 -0700261}
262
Subrata Banikb7e69a22016-02-08 17:15:29 +0530263static void configure_isst(void)
264{
Elyes HAOUAS143fb462018-05-25 12:56:45 +0200265 struct device *dev = SA_DEV_ROOT;
Subrata Banikb7e69a22016-02-08 17:15:29 +0530266 config_t *conf = dev->chip_info;
267 msr_t msr;
268
269 if (conf->speed_shift_enable) {
270 /*
271 * Kernel driver checks CPUID.06h:EAX[Bit 7] to determine if HWP
Martin Rothe18e6422017-06-03 20:03:18 -0600272 is supported or not. coreboot needs to configure MSR 0x1AA
Subrata Banikb7e69a22016-02-08 17:15:29 +0530273 which is then reflected in the CPUID register.
274 */
275 msr = rdmsr(MSR_MISC_PWR_MGMT);
276 msr.lo |= MISC_PWR_MGMT_ISST_EN; /* Enable Speed Shift */
277 msr.lo |= MISC_PWR_MGMT_ISST_EN_INT; /* Enable Interrupt */
278 msr.lo |= MISC_PWR_MGMT_ISST_EN_EPP; /* Enable EPP */
279 wrmsr(MSR_MISC_PWR_MGMT, msr);
280 } else {
281 msr = rdmsr(MSR_MISC_PWR_MGMT);
282 msr.lo &= ~MISC_PWR_MGMT_ISST_EN; /* Disable Speed Shift */
283 msr.lo &= ~MISC_PWR_MGMT_ISST_EN_INT; /* Disable Interrupt */
284 msr.lo &= ~MISC_PWR_MGMT_ISST_EN_EPP; /* Disable EPP */
285 wrmsr(MSR_MISC_PWR_MGMT, msr);
286 }
287}
288
Lee Leahyb0005132015-05-12 18:19:47 -0700289static void configure_misc(void)
290{
Elyes HAOUAS143fb462018-05-25 12:56:45 +0200291 struct device *dev = SA_DEV_ROOT;
Subrata Banik834543c2018-10-06 13:58:33 +0530292 if (!dev) {
293 printk(BIOS_ERR, "SA_DEV_ROOT device not found!\n");
294 return;
295 }
Subrata Banik6b45ee42017-05-12 11:43:57 +0530296 config_t *conf = dev->chip_info;
Lee Leahyb0005132015-05-12 18:19:47 -0700297 msr_t msr;
298
299 msr = rdmsr(IA32_MISC_ENABLE);
Lee Leahy1d14b3e2015-05-12 18:23:27 -0700300 msr.lo |= (1 << 0); /* Fast String enable */
301 msr.lo |= (1 << 3); /* TM1/TM2/EMTTM enable */
Subrata Banik6b45ee42017-05-12 11:43:57 +0530302 if (conf->eist_enable)
Matt DeVillier6dd4f762018-03-02 14:22:14 -0500303 msr.lo |= (1 << 16); /* Enhanced SpeedStep Enable */
Subrata Banik6b45ee42017-05-12 11:43:57 +0530304 else
Matt DeVillier6dd4f762018-03-02 14:22:14 -0500305 msr.lo &= ~(1 << 16); /* Enhanced SpeedStep Disable */
Lee Leahyb0005132015-05-12 18:19:47 -0700306 wrmsr(IA32_MISC_ENABLE, msr);
307
308 /* Disable Thermal interrupts */
309 msr.lo = 0;
310 msr.hi = 0;
311 wrmsr(IA32_THERM_INTERRUPT, msr);
312
313 /* Enable package critical interrupt only */
314 msr.lo = 1 << 4;
315 msr.hi = 0;
316 wrmsr(IA32_PACKAGE_THERM_INTERRUPT, msr);
Pratik Prajapati79cfcde2016-03-08 12:34:06 -0800317
Pratik Prajapati79cfcde2016-03-08 12:34:06 -0800318 msr = rdmsr(MSR_POWER_CTL);
319 msr.lo |= (1 << 0); /* Enable Bi-directional PROCHOT as an input*/
Cole Nelson63b6fea2018-06-15 15:51:54 -0700320 msr.lo &= ~POWER_CTL_C1E_MASK; /* Disable C1E */
Pratik Prajapati79cfcde2016-03-08 12:34:06 -0800321 msr.lo |= (1 << 23); /* Lock it */
322 wrmsr(MSR_POWER_CTL, msr);
Lee Leahyb0005132015-05-12 18:19:47 -0700323}
324
325static void enable_lapic_tpr(void)
326{
327 msr_t msr;
328
329 msr = rdmsr(MSR_PIC_MSG_CONTROL);
330 msr.lo &= ~(1 << 10); /* Enable APIC TPR updates */
331 wrmsr(MSR_PIC_MSG_CONTROL, msr);
332}
333
334static void configure_dca_cap(void)
335{
Subrata Banik53b08c32018-12-10 14:11:35 +0530336 uint32_t feature_flag;
Lee Leahyb0005132015-05-12 18:19:47 -0700337 msr_t msr;
338
339 /* Check feature flag in CPUID.(EAX=1):ECX[18]==1 */
Subrata Banik53b08c32018-12-10 14:11:35 +0530340 feature_flag = cpu_get_feature_flags_ecx();
341 if (feature_flag & CPUID_DCA) {
Lee Leahyb0005132015-05-12 18:19:47 -0700342 msr = rdmsr(IA32_PLATFORM_DCA_CAP);
343 msr.lo |= 1;
344 wrmsr(IA32_PLATFORM_DCA_CAP, msr);
345 }
346}
347
Lee Leahyb0005132015-05-12 18:19:47 -0700348static void set_energy_perf_bias(u8 policy)
349{
350 msr_t msr;
351 int ecx;
352
353 /* Determine if energy efficient policy is supported. */
354 ecx = cpuid_ecx(0x6);
355 if (!(ecx & (1 << 3)))
356 return;
357
358 /* Energy Policy is bits 3:0 */
Elyes HAOUAS419bfbc2018-10-01 08:47:51 +0200359 msr = rdmsr(IA32_ENERGY_PERF_BIAS);
Lee Leahyb0005132015-05-12 18:19:47 -0700360 msr.lo &= ~0xf;
361 msr.lo |= policy & 0xf;
Elyes HAOUAS419bfbc2018-10-01 08:47:51 +0200362 wrmsr(IA32_ENERGY_PERF_BIAS, msr);
Lee Leahyb0005132015-05-12 18:19:47 -0700363
364 printk(BIOS_DEBUG, "cpu: energy policy set to %u\n", policy);
365}
366
Subrata Banik481b3642017-05-12 11:29:43 +0530367static void configure_c_states(void)
368{
369 msr_t msr;
370
371 /* C-state Interrupt Response Latency Control 0 - package C3 latency */
372 msr.hi = 0;
373 msr.lo = IRTL_VALID | IRTL_1024_NS | C_STATE_LATENCY_CONTROL_0_LIMIT;
374 wrmsr(MSR_C_STATE_LATENCY_CONTROL_0, msr);
375
376 /* C-state Interrupt Response Latency Control 1 - package C6/C7 short */
377 msr.hi = 0;
378 msr.lo = IRTL_VALID | IRTL_1024_NS | C_STATE_LATENCY_CONTROL_1_LIMIT;
379 wrmsr(MSR_C_STATE_LATENCY_CONTROL_1, msr);
380
381 /* C-state Interrupt Response Latency Control 2 - package C6/C7 long */
382 msr.hi = 0;
383 msr.lo = IRTL_VALID | IRTL_1024_NS | C_STATE_LATENCY_CONTROL_2_LIMIT;
384 wrmsr(MSR_C_STATE_LATENCY_CONTROL_2, msr);
385
386 /* C-state Interrupt Response Latency Control 3 - package C8 */
387 msr.hi = 0;
388 msr.lo = IRTL_VALID | IRTL_1024_NS |
389 C_STATE_LATENCY_CONTROL_3_LIMIT;
390 wrmsr(MSR_C_STATE_LATENCY_CONTROL_3, msr);
391
392 /* C-state Interrupt Response Latency Control 4 - package C9 */
393 msr.hi = 0;
394 msr.lo = IRTL_VALID | IRTL_1024_NS |
395 C_STATE_LATENCY_CONTROL_4_LIMIT;
396 wrmsr(MSR_C_STATE_LATENCY_CONTROL_4, msr);
397
398 /* C-state Interrupt Response Latency Control 5 - package C10 */
399 msr.hi = 0;
400 msr.lo = IRTL_VALID | IRTL_1024_NS |
401 C_STATE_LATENCY_CONTROL_5_LIMIT;
402 wrmsr(MSR_C_STATE_LATENCY_CONTROL_5, msr);
403}
404
Subrata Banikf004f662017-02-03 19:05:27 +0530405/*
406 * The emulated ACPI timer allows disabling of the ACPI timer
407 * (PM1_TMR) to have no impart on the system.
408 */
409static void enable_pm_timer_emulation(void)
410{
411 /* ACPI PM timer emulation */
412 msr_t msr;
413 /*
414 * The derived frequency is calculated as follows:
415 * (CTC_FREQ * msr[63:32]) >> 32 = target frequency.
416 * Back solve the multiplier so the 3.579545MHz ACPI timer
417 * frequency is used.
418 */
419 msr.hi = (3579545ULL << 32) / CTC_FREQ;
420 /* Set PM1 timer IO port and enable*/
421 msr.lo = (EMULATE_DELAY_VALUE << EMULATE_DELAY_OFFSET_VALUE) |
422 EMULATE_PM_TMR_EN | (ACPI_BASE_ADDRESS + PM1_TMR);
Elyes HAOUASf212cf32018-12-18 10:24:55 +0100423 wrmsr(MSR_EMULATE_PM_TIMER, msr);
Subrata Banikf004f662017-02-03 19:05:27 +0530424}
425
Lee Leahyb0005132015-05-12 18:19:47 -0700426/* All CPUs including BSP will run the following function. */
Elyes HAOUAS143fb462018-05-25 12:56:45 +0200427void soc_core_init(struct device *cpu)
Lee Leahyb0005132015-05-12 18:19:47 -0700428{
429 /* Clear out pending MCEs */
Pratik Prajapatie8163152017-08-28 12:27:57 -0700430 /* TODO(adurbin): This should only be done on a cold boot. Also, some
431 * of these banks are core vs package scope. For now every CPU clears
432 * every bank. */
Pratik Prajapati35cb7852018-05-18 18:05:18 -0700433 mca_configure(NULL);
Lee Leahyb0005132015-05-12 18:19:47 -0700434
Elyes HAOUAS038e7242016-07-29 18:31:16 +0200435 /* Enable the local CPU apics */
Lee Leahyb0005132015-05-12 18:19:47 -0700436 enable_lapic_tpr();
437 setup_lapic();
438
Subrata Banik481b3642017-05-12 11:29:43 +0530439 /* Configure c-state interrupt response time */
440 configure_c_states();
441
Lee Leahyb0005132015-05-12 18:19:47 -0700442 /* Configure Enhanced SpeedStep and Thermal Sensors */
443 configure_misc();
444
Subrata Banikb7e69a22016-02-08 17:15:29 +0530445 /* Configure Intel Speed Shift */
446 configure_isst();
447
Subrata Banikf004f662017-02-03 19:05:27 +0530448 /* Enable ACPI Timer Emulation via MSR 0x121 */
449 enable_pm_timer_emulation();
450
Lee Leahyb0005132015-05-12 18:19:47 -0700451 /* Enable Direct Cache Access */
452 configure_dca_cap();
453
454 /* Set energy policy */
455 set_energy_perf_bias(ENERGY_POLICY_NORMAL);
456
457 /* Enable Turbo */
458 enable_turbo();
Robbie Zhang7de03172017-02-21 14:00:31 -0800459
Pratik Prajapati7a357eb2017-08-14 12:18:38 -0700460 /* Configure Core PRMRR for SGX. */
461 prmrr_core_configure();
Aaron Durbin58225822016-05-03 17:45:59 -0500462}
Lee Leahyb0005132015-05-12 18:19:47 -0700463
Aaron Durbin58225822016-05-03 17:45:59 -0500464static void per_cpu_smm_trigger(void)
465{
466 /* Relocate the SMM handler. */
467 smm_relocate();
Aaron Durbin58225822016-05-03 17:45:59 -0500468}
Lee Leahyb0005132015-05-12 18:19:47 -0700469
Nico Huber6275e342018-11-21 00:11:35 +0100470static void vmx_configure(void *unused)
471{
472 set_feature_ctrl_vmx();
473}
474
475static void fc_lock_configure(void *unused)
476{
477 set_feature_ctrl_lock();
478}
479
Aaron Durbin58225822016-05-03 17:45:59 -0500480static void post_mp_init(void)
481{
Lee Leahyb0005132015-05-12 18:19:47 -0700482 /* Set Max Ratio */
Barnali Sarkar0a203d12017-05-04 18:02:17 +0530483 cpu_set_max_ratio();
Lee Leahyb0005132015-05-12 18:19:47 -0700484
Aaron Durbin58225822016-05-03 17:45:59 -0500485 /*
486 * Now that all APs have been relocated as well as the BSP let SMIs
487 * start flowing.
488 */
Subrata Banikece173c2017-12-14 18:18:34 +0530489 smm_southbridge_enable(GBL_EN);
Aaron Durbin58225822016-05-03 17:45:59 -0500490
491 /* Lock down the SMRAM space. */
492#if IS_ENABLED(CONFIG_HAVE_SMI_HANDLER)
493 smm_lock();
494#endif
Pratik Prajapati7a357eb2017-08-14 12:18:38 -0700495
Subrata Banik1c9d8632018-05-15 13:31:28 +0530496 mp_run_on_all_cpus(vmx_configure, NULL, 2 * USECS_PER_MSEC);
Matt DeVillier969ef102018-03-21 20:47:52 -0500497
Subrata Banik1c9d8632018-05-15 13:31:28 +0530498 mp_run_on_all_cpus(sgx_configure, NULL, 14 * USECS_PER_MSEC);
Nico Huber6275e342018-11-21 00:11:35 +0100499
500 mp_run_on_all_cpus(fc_lock_configure, NULL, 2 * USECS_PER_MSEC);
Aaron Durbin58225822016-05-03 17:45:59 -0500501}
502
503static const struct mp_ops mp_ops = {
Subrata Banika4b11e5c2017-02-03 18:57:49 +0530504 /*
505 * Skip Pre MP init MTRR programming as MTRRs are mirrored from BSP,
506 * that are set prior to ramstage.
507 * Real MTRRs programming are being done after resource allocation.
508 */
Furquan Shaikhc2480442017-02-20 13:41:56 -0800509 .pre_mp_init = soc_fsp_load,
Aaron Durbin58225822016-05-03 17:45:59 -0500510 .get_cpu_count = get_cpu_count,
511 .get_smm_info = smm_info,
512 .get_microcode_info = get_microcode_info,
Aaron Durbin58225822016-05-03 17:45:59 -0500513 .pre_mp_smm_init = smm_initialize,
514 .per_cpu_smm_trigger = per_cpu_smm_trigger,
515 .relocation_handler = smm_relocation_handler,
516 .post_mp_init = post_mp_init,
517};
518
Pratik Prajapati9cd6a262017-08-14 13:57:46 -0700519void soc_init_cpus(struct bus *cpu_bus)
Aaron Durbin58225822016-05-03 17:45:59 -0500520{
Lee Leahyf4c4ab92017-03-16 17:08:03 -0700521 if (mp_init_with_smm(cpu_bus, &mp_ops))
Aaron Durbin58225822016-05-03 17:45:59 -0500522 printk(BIOS_ERR, "MP initialization failure.\n");
Sumeet Pawnikar9d2f3de2016-12-22 13:48:46 +0530523
524 /* Thermal throttle activation offset */
525 configure_thermal_target();
Lee Leahyb0005132015-05-12 18:19:47 -0700526}
Rizwan Qureshia7ff4532015-07-23 22:40:53 +0530527
528int soc_skip_ucode_update(u32 current_patch_id, u32 new_patch_id)
529{
Robbie Zhang7de03172017-02-21 14:00:31 -0800530 msr_t msr1;
531 msr_t msr2;
532
533 /*
534 * If PRMRR/SGX is supported the FIT microcode load will set the msr
Rizwan Qureshia7ff4532015-07-23 22:40:53 +0530535 * 0x08b with the Patch revision id one less than the id in the
536 * microcode binary. The PRMRR support is indicated in the MSR
Robbie Zhang7de03172017-02-21 14:00:31 -0800537 * MTRRCAP[12]. If SGX is not enabled, check and avoid reloading the
538 * same microcode during CPU initialization. If SGX is enabled, as
539 * part of SGX BIOS initialization steps, the same microcode needs to
540 * be reloaded after the core PRMRR MSRs are programmed.
Rizwan Qureshia7ff4532015-07-23 22:40:53 +0530541 */
Robbie Zhang7de03172017-02-21 14:00:31 -0800542 msr1 = rdmsr(MTRR_CAP_MSR);
Elyes HAOUASf212cf32018-12-18 10:24:55 +0100543 msr2 = rdmsr(MSR_PRMRR_PHYS_BASE);
Robbie Zhang7de03172017-02-21 14:00:31 -0800544 if (msr2.lo && (current_patch_id == new_patch_id - 1))
545 return 0;
546 else
547 return (msr1.lo & PRMRR_SUPPORTED) &&
548 (current_patch_id == new_patch_id - 1);
Rizwan Qureshia7ff4532015-07-23 22:40:53 +0530549}
Pratik Prajapatia04aa3d2017-06-12 23:02:36 -0700550
551void cpu_lock_sgx_memory(void)
552{
553 msr_t msr;
554
555 msr = rdmsr(MSR_LT_LOCK_MEMORY);
556 if ((msr.lo & 1) == 0) {
557 msr.lo |= 1; /* Lock it */
558 wrmsr(MSR_LT_LOCK_MEMORY, msr);
559 }
560}
Pratik Prajapatib45b22f2017-09-13 13:45:31 -0700561
562int soc_fill_sgx_param(struct sgx_param *sgx_param)
563{
Elyes HAOUAS143fb462018-05-25 12:56:45 +0200564 struct device *dev = SA_DEV_ROOT;
Pratik Prajapati645064a2018-10-02 17:10:52 -0700565 config_t *conf;
Pratik Prajapatib45b22f2017-09-13 13:45:31 -0700566
Pratik Prajapati645064a2018-10-02 17:10:52 -0700567 if (!dev) {
568 printk(BIOS_ERR, "Failed to get root dev for checking SGX param\n");
569 return -1;
570 }
571
572 conf = dev->chip_info;
Pratik Prajapatib45b22f2017-09-13 13:45:31 -0700573 if (!conf) {
574 printk(BIOS_ERR, "Failed to get chip_info for SGX param\n");
575 return -1;
576 }
577
578 sgx_param->enable = conf->sgx_enable;
579 return 0;
580}