2 * This file is part of the coreboot project.
4 * Copyright (C) 2007-2009 coresystems GmbH
5 * Copyright (C) 2011 The ChromiumOS Authors. All rights reserved.
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; version 2 of
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.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
23 #include <console/console.h>
24 #include <device/device.h>
25 #include <device/pci.h>
27 #include <arch/acpi.h>
29 #include <cpu/x86/mtrr.h>
30 #include <cpu/x86/msr.h>
31 #include <cpu/x86/lapic.h>
32 #include <cpu/intel/microcode.h>
33 #include <cpu/intel/speedstep.h>
34 #include <cpu/intel/turbo.h>
35 #include <cpu/x86/cache.h>
36 #include <cpu/x86/name.h>
37 #include <pc80/mc146818rtc.h>
38 #include "model_2065x.h"
42 * List of supported C-states in this processor
44 * Latencies are typical worst-case package exit time in uS
45 * taken from the SandyBridge BIOS specification.
47 static acpi_cstate_t cstate_map
[] = {
53 .addrl
= 0x00, /* MWAIT State 0 */
54 .space_id
= ACPI_ADDRESS_SPACE_FIXED
,
55 .bit_width
= ACPI_FFIXEDHW_VENDOR_INTEL
,
56 .bit_offset
= ACPI_FFIXEDHW_CLASS_MWAIT
,
57 .resv
= ACPI_FFIXEDHW_FLAG_HW_COORD
,
64 .addrl
= 0x01, /* MWAIT State 0 Sub-state 1 */
65 .space_id
= ACPI_ADDRESS_SPACE_FIXED
,
66 .bit_width
= ACPI_FFIXEDHW_VENDOR_INTEL
,
67 .bit_offset
= ACPI_FFIXEDHW_CLASS_MWAIT
,
68 .resv
= ACPI_FFIXEDHW_FLAG_HW_COORD
,
75 .addrl
= 0x10, /* MWAIT State 1 */
76 .space_id
= ACPI_ADDRESS_SPACE_FIXED
,
77 .bit_width
= ACPI_FFIXEDHW_VENDOR_INTEL
,
78 .bit_offset
= ACPI_FFIXEDHW_CLASS_MWAIT
,
79 .resv
= ACPI_FFIXEDHW_FLAG_HW_COORD
,
86 .addrl
= 0x20, /* MWAIT State 2 */
87 .space_id
= ACPI_ADDRESS_SPACE_FIXED
,
88 .bit_width
= ACPI_FFIXEDHW_VENDOR_INTEL
,
89 .bit_offset
= ACPI_FFIXEDHW_CLASS_MWAIT
,
90 .resv
= ACPI_FFIXEDHW_FLAG_HW_COORD
,
97 .addrl
= 0x30, /* MWAIT State 3 */
98 .space_id
= ACPI_ADDRESS_SPACE_FIXED
,
99 .bit_width
= ACPI_FFIXEDHW_VENDOR_INTEL
,
100 .bit_offset
= ACPI_FFIXEDHW_CLASS_MWAIT
,
101 .resv
= ACPI_FFIXEDHW_FLAG_HW_COORD
,
108 .addrl
= 0x31, /* MWAIT State 3 Sub-state 1 */
109 .space_id
= ACPI_ADDRESS_SPACE_FIXED
,
110 .bit_width
= ACPI_FFIXEDHW_VENDOR_INTEL
,
111 .bit_offset
= ACPI_FFIXEDHW_CLASS_MWAIT
,
112 .resv
= ACPI_FFIXEDHW_FLAG_HW_COORD
,
118 static void enable_vmx(void)
120 struct cpuid_result regs
;
122 int enable
= CONFIG_ENABLE_VMX
;
125 /* Check that the VMX is supported before reading or writing the MSR. */
126 if (!((regs
.ecx
& CPUID_VMX
) || (regs
.ecx
& CPUID_SMX
)))
129 msr
= rdmsr(IA32_FEATURE_CONTROL
);
131 if (msr
.lo
& (1 << 0)) {
132 printk(BIOS_ERR
, "VMX is locked, so %s will do nothing\n", __func__
);
133 /* VMX locked. If we set it again we get an illegal
139 /* The IA32_FEATURE_CONTROL MSR may initialize with random values.
140 * It must be cleared regardless of VMX config setting.
144 printk(BIOS_DEBUG
, "%s VMX\n", enable
? "Enabling" : "Disabling");
146 /* Even though the Intel manual says you must set the lock bit in addition
147 * to the VMX bit in order for VMX to work, it is incorrect. Thus we leave
148 * it unlocked for the OS to manage things itself. This is good for a few
150 * - No need to reflash the bios just to toggle the lock bit.
151 * - The VMX bits really really should match each other across cores, so
152 * hard locking it on one while another has the opposite setting can
153 * easily lead to crashes as code using VMX migrates between them.
154 * - Vendors that want to "upsell" from a bios that disables+locks to
155 * one that doesn't is sleazy.
156 * By leaving this to the OS (e.g. Linux), people can do exactly what they
157 * want on the fly, and do it correctly (e.g. across multiple cores).
161 if (regs
.ecx
& CPUID_SMX
)
165 wrmsr(IA32_FEATURE_CONTROL
, msr
);
168 /* Convert time in seconds to POWER_LIMIT_1_TIME MSR value */
169 static const u8 power_limit_time_sec_to_msr
[] = {
197 /* Convert POWER_LIMIT_1_TIME MSR value to seconds */
198 static const u8 power_limit_time_msr_to_sec
[] = {
226 int cpu_config_tdp_levels(void)
230 /* Minimum CPU revision */
231 if (cpuid_eax(1) < IVB_CONFIG_TDP_MIN_CPUID
)
234 /* Bits 34:33 indicate how many levels supported */
235 platform_info
= rdmsr(MSR_PLATFORM_INFO
);
236 return (platform_info
.hi
>> 1) & 3;
240 static void configure_thermal_target(void)
242 struct cpu_intel_model_2065x_config
*conf
;
246 /* Find pointer to CPU configuration */
247 lapic
= dev_find_lapic(SPEEDSTEP_APIC_MAGIC
);
248 if (!lapic
|| !lapic
->chip_info
)
250 conf
= lapic
->chip_info
;
252 /* Set TCC activation offset if supported */
253 msr
= rdmsr(MSR_PLATFORM_INFO
);
254 if ((msr
.lo
& (1 << 30)) && conf
->tcc_offset
) {
255 msr
= rdmsr(MSR_TEMPERATURE_TARGET
);
256 msr
.lo
&= ~(0xf << 24); /* Bits 27:24 */
257 msr
.lo
|= (conf
->tcc_offset
& 0xf) << 24;
258 wrmsr(MSR_TEMPERATURE_TARGET
, msr
);
262 static void configure_misc(void)
266 msr
= rdmsr(IA32_MISC_ENABLE
);
267 msr
.lo
|= (1 << 0); /* Fast String enable */
268 msr
.lo
|= (1 << 3); /* TM1/TM2/EMTTM enable */
269 msr
.lo
|= (1 << 16); /* Enhanced SpeedStep Enable */
270 wrmsr(IA32_MISC_ENABLE
, msr
);
272 /* Disable Thermal interrupts */
275 wrmsr(IA32_THERM_INTERRUPT
, msr
);
278 /* Enable package critical interrupt only */
281 wrmsr(IA32_PACKAGE_THERM_INTERRUPT
, msr
);
285 static void enable_lapic_tpr(void)
289 msr
= rdmsr(MSR_PIC_MSG_CONTROL
);
290 msr
.lo
&= ~(1 << 10); /* Enable APIC TPR updates */
291 wrmsr(MSR_PIC_MSG_CONTROL
, msr
);
295 static void set_max_ratio(void)
301 /* Check for configurable TDP option */
302 if (cpu_config_tdp_levels()) {
303 /* Set to nominal TDP ratio */
304 msr
= rdmsr(MSR_CONFIG_TDP_NOMINAL
);
305 perf_ctl
.lo
= (msr
.lo
& 0xff) << 8;
307 /* Platform Info bits 15:8 give max ratio */
308 msr
= rdmsr(MSR_PLATFORM_INFO
);
309 perf_ctl
.lo
= msr
.lo
& 0xff00;
311 wrmsr(IA32_PERF_CTL
, perf_ctl
);
313 printk(BIOS_DEBUG
, "model_x06ax: frequency set to %d\n",
314 ((perf_ctl
.lo
>> 8) & 0xff) * NEHALEM_BCLK
);
317 static void set_energy_perf_bias(u8 policy
)
322 /* Energy Policy is bits 3:0 */
323 msr
= rdmsr(IA32_ENERGY_PERFORMANCE_BIAS
);
325 msr
.lo
|= policy
& 0xf;
326 wrmsr(IA32_ENERGY_PERFORMANCE_BIAS
, msr
);
328 printk(BIOS_DEBUG
, "model_x06ax: energy policy set to %u\n",
333 static void configure_mca(void)
339 /* This should only be done on a cold boot */
340 for (i
= 0; i
< 7; i
++)
341 wrmsr(IA32_MC0_STATUS
+ (i
* 4), msr
);
345 * Initialize any extra cores/threads in this package.
347 static void intel_cores_init(device_t cpu
)
349 struct cpuid_result result
;
350 unsigned threads_per_package
, threads_per_core
, i
;
352 /* Logical processors (threads) per core */
353 result
= cpuid_ext(0xb, 0);
354 threads_per_core
= result
.ebx
& 0xffff;
356 /* Logical processors (threads) per package */
357 result
= cpuid_ext(0xb, 1);
358 threads_per_package
= result
.ebx
& 0xffff;
360 /* Only initialize extra cores from BSP */
361 if (cpu
->path
.apic
.apic_id
)
364 printk(BIOS_DEBUG
, "CPU: %u has %u cores, %u threads per core\n",
365 cpu
->path
.apic
.apic_id
, threads_per_package
/threads_per_core
,
368 for (i
= 1; i
< threads_per_package
; ++i
) {
369 struct device_path cpu_path
;
372 /* Build the cpu device path */
373 cpu_path
.type
= DEVICE_PATH_APIC
;
374 cpu_path
.apic
.apic_id
=
375 cpu
->path
.apic
.apic_id
+ (i
& 1) + ((i
& 2) << 1);
377 /* Update APIC ID if no hyperthreading */
378 if (threads_per_core
== 1)
379 cpu_path
.apic
.apic_id
<<= 1;
381 /* Allocate the new cpu device structure */
382 new = alloc_dev(cpu
->bus
, &cpu_path
);
386 printk(BIOS_DEBUG
, "CPU: %u has core %u\n",
387 cpu
->path
.apic
.apic_id
,
388 new->path
.apic
.apic_id
);
390 #if CONFIG_SMP && CONFIG_MAX_CPUS > 1
391 /* Start the new cpu */
392 if (!start_cpu(new)) {
393 /* Record the error in cpu? */
394 printk(BIOS_ERR
, "CPU %u would not start!\n",
395 new->path
.apic
.apic_id
);
401 static void model_2065x_init(device_t cpu
)
403 char processor_name
[49];
404 struct cpuid_result cpuid_regs
;
406 /* Turn on caching if we haven't already */
409 intel_update_microcode_from_cbfs();
411 /* Clear out pending MCEs */
414 /* Print processor name */
415 fill_processor_name(processor_name
);
416 printk(BIOS_INFO
, "CPU: %s.\n", processor_name
);
417 printk(BIOS_INFO
, "CPU:lapic=%ld, boot_cpu=%d\n", lapicid (), boot_cpu ());
419 /* Setup MTRRs based on physical address size */
420 cpuid_regs
= cpuid(0x80000008);
421 x86_setup_fixed_mtrrs();
422 x86_setup_var_mtrrs(cpuid_regs
.eax
& 0xff, 2);
425 /* Setup Page Attribute Tables (PAT) */
428 /* Enable the local cpu apics */
432 /* Enable virtualization if enabled in CMOS */
435 /* Configure Enhanced SpeedStep and Thermal Sensors */
438 /* Thermal throttle activation offset */
439 configure_thermal_target();
441 /* Set energy policy */
442 set_energy_perf_bias(ENERGY_POLICY_NORMAL
);
450 /* Start up extra cores */
451 intel_cores_init(cpu
);
454 static struct device_operations cpu_dev_ops
= {
455 .init
= model_2065x_init
,
458 static struct cpu_device_id cpu_table
[] = {
459 { X86_VENDOR_INTEL
, 0x20652 }, /* Intel Nehalem */
460 { X86_VENDOR_INTEL
, 0x20655 }, /* Intel Nehalem */
464 static const struct cpu_driver driver __cpu_driver
= {
466 .id_table
= cpu_table
,
467 .cstates
= cstate_map
,