coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
model_2065x_init.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <assert.h>
4 #include <console/console.h>
5 #include <device/device.h>
6 #include <cpu/cpu.h>
7 #include <cpu/x86/mtrr.h>
8 #include <cpu/x86/msr.h>
9 #include <cpu/x86/lapic.h>
10 #include <cpu/x86/mp.h>
11 #include <cpu/intel/microcode.h>
12 #include <cpu/intel/speedstep.h>
13 #include <cpu/intel/turbo.h>
14 #include <cpu/x86/cache.h>
15 #include <cpu/x86/name.h>
16 #include "model_2065x.h"
17 #include "chip.h"
18 #include <cpu/intel/smm_reloc.h>
20 #include <smp/node.h>
21 #include <types.h>
22 
23 static void configure_thermal_target(void)
24 {
25  struct cpu_intel_model_2065x_config *conf;
26  struct device *lapic;
27  msr_t msr;
28 
29  /* Find pointer to CPU configuration */
31  if (!lapic || !lapic->chip_info)
32  return;
33  conf = lapic->chip_info;
34 
35  /* Set TCC activation offset if supported */
36  msr = rdmsr(MSR_PLATFORM_INFO);
37  if ((msr.lo & (1 << 30)) && conf->tcc_offset) {
39  msr.lo &= ~(0xf << 24); /* Bits 27:24 */
40  msr.lo |= (conf->tcc_offset & 0xf) << 24;
42  }
43 }
44 
45 static void configure_misc(void)
46 {
47  msr_t msr;
48 
49  msr = rdmsr(IA32_MISC_ENABLE);
50  msr.lo |= (1 << 0); /* Fast String enable */
51  msr.lo |= (1 << 3); /* TM1/TM2/EMTTM enable */
52  msr.lo |= (1 << 16); /* Enhanced SpeedStep Enable */
53  wrmsr(IA32_MISC_ENABLE, msr);
54 
55  /* Disable Thermal interrupts */
56  msr.lo = 0;
57  msr.hi = 0;
59 }
60 
61 static void set_max_ratio(void)
62 {
63  msr_t msr, perf_ctl;
64 
65  perf_ctl.hi = 0;
66 
67  /* Platform Info bits 15:8 give max ratio */
68  msr = rdmsr(MSR_PLATFORM_INFO);
69  perf_ctl.lo = msr.lo & 0xff00;
70  wrmsr(IA32_PERF_CTL, perf_ctl);
71 
72  printk(BIOS_DEBUG, "model_x065x: frequency set to %d\n",
73  ((perf_ctl.lo >> 8) & 0xff) * IRONLAKE_BCLK);
74 }
75 
76 static void model_2065x_init(struct device *cpu)
77 {
78  char processor_name[49];
79 
80  /* Clear out pending MCEs */
81  /* This should only be done on a cold boot */
83 
84  /* Print processor name */
86  printk(BIOS_INFO, "CPU: %s.\n", processor_name);
87  printk(BIOS_INFO, "CPU:lapic=%d, boot_cpu=%d\n", lapicid(),
88  boot_cpu());
89 
90  /* Setup Page Attribute Tables (PAT) */
91  // TODO set up PAT
92 
94 
95  /* Set virtualization based on Kconfig option */
97 
99 
100  /* Configure Enhanced SpeedStep and Thermal Sensors */
101  configure_misc();
102 
103  /* Thermal throttle activation offset */
105 
106  /* Set Max Ratio */
107  set_max_ratio();
108 
109  /* Enable Turbo */
110  enable_turbo();
111 }
112 
113 /* MP initialization support. */
114 static void pre_mp_init(void)
115 {
116  /* Setup MTRRs based on physical address size. */
118  x86_mtrr_check();
119 }
120 
121 static int get_cpu_count(void)
122 {
123  msr_t msr;
124  unsigned int num_threads;
125  unsigned int num_cores;
126 
128  num_threads = (msr.lo >> 0) & 0xffff;
129  num_cores = (msr.lo >> 16) & 0xffff;
130  printk(BIOS_DEBUG, "CPU has %u cores, %u threads enabled.\n",
131  num_cores, num_threads);
132 
133  return num_threads;
134 }
135 
136 static void get_microcode_info(const void **microcode, int *parallel)
137 {
139  *parallel = !intel_ht_supported();
140 }
141 
142 static void per_cpu_smm_trigger(void)
143 {
144  /* Relocate the SMM handler. */
145  smm_relocate();
146 
147  /* After SMM relocation a 2nd microcode load is required. */
148  const void *microcode_patch = intel_microcode_find();
150 }
151 
152 static void post_mp_init(void)
153 {
154  /* Now that all APs have been relocated as well as the BSP let SMIs
155  * start flowing. */
157 
158  /* Lock down the SMRAM space. */
159  smm_lock();
160 }
161 
162 static const struct mp_ops mp_ops = {
164  .get_cpu_count = get_cpu_count,
165  .get_smm_info = smm_info,
166  .get_microcode_info = get_microcode_info,
167  .pre_mp_smm_init = smm_initialize,
168  .per_cpu_smm_trigger = per_cpu_smm_trigger,
169  .relocation_handler = smm_relocation_handler,
170  .post_mp_init = post_mp_init,
171 };
172 
173 void mp_init_cpus(struct bus *cpu_bus)
174 {
175  /* TODO: Handle mp_init_with_smm failure? */
176  mp_init_with_smm(cpu_bus, &mp_ops);
177 }
178 
179 static struct device_operations cpu_dev_ops = {
181 };
182 
183 /* Arrandale / Clarkdale CPU IDs */
184 static const struct cpu_device_id cpu_table[] = {
185  { X86_VENDOR_INTEL, 0x20650 },
186  { X86_VENDOR_INTEL, 0x20651 },
187  { X86_VENDOR_INTEL, 0x20652 },
188  { X86_VENDOR_INTEL, 0x20654 },
189  { X86_VENDOR_INTEL, 0x20655 },
190  { 0, 0 },
191 };
192 
193 static const struct cpu_driver driver __cpu_driver = {
194  .ops = &cpu_dev_ops,
195  .id_table = cpu_table,
196 };
#define X86_VENDOR_INTEL
Definition: cpu.h:138
int boot_cpu(void)
Definition: psp.c:5
#define printk(level,...)
Definition: stdlib.h:16
void set_aesni_lock(void)
Definition: common_init.c:146
void enable_lapic_tpr(void)
Definition: common_init.c:167
void set_vmx_and_lock(void)
Definition: common_init.c:15
bool intel_ht_supported(void)
Definition: hyperthreading.c:7
#define SPEEDSTEP_APIC_MAGIC
Definition: chip.h:4
#define MSR_TEMPERATURE_TARGET
Definition: haswell.h:50
#define MSR_CORE_THREAD_COUNT
Definition: haswell.h:37
void smm_relocate(void)
Definition: smmrelocate.c:247
void smm_relocation_handler(int cpu, uintptr_t curr_smbase, uintptr_t staggered_smbase)
Definition: smmrelocate.c:90
void smm_initialize(void)
Definition: smmrelocate.c:227
void smm_lock(void)
Definition: smmrelocate.c:261
void smm_info(uintptr_t *perm_smbase, size_t *perm_smsize, size_t *smm_save_state_size)
Definition: smmrelocate.c:213
static char processor_name[49]
Definition: mp_init.c:37
enum cb_err mp_init_with_smm(struct bus *cpu_bus, const struct mp_ops *mp_ops)
Definition: mp_init.c:1145
void x86_mtrr_check(void)
Definition: mtrr.c:836
void x86_setup_mtrrs_with_detect(void)
Definition: mtrr.c:823
struct device * dev_find_lapic(unsigned int apic_id)
Given a Local APIC ID, find the device structure.
Definition: device_util.c:17
#define MSR_PLATFORM_INFO
Definition: fsb.c:16
static const void * microcode_patch
Definition: haswell_init.c:567
static __always_inline msr_t rdmsr(unsigned int index)
Definition: msr.h:146
#define IA32_MISC_ENABLE
Definition: msr.h:45
static void mca_clear_status(void)
Definition: msr.h:176
#define IA32_PERF_CTL
Definition: msr.h:43
static __always_inline void wrmsr(unsigned int index, msr_t msr)
Definition: msr.h:157
#define IA32_THERM_INTERRUPT
Definition: msr.h:44
void global_smi_enable(void)
Set the EOS bit and enable SMI generation from southbridge.
Definition: smi_util.c:60
static __always_inline unsigned int lapicid(void)
Definition: lapic.h:136
#define BIOS_INFO
BIOS_INFO - Expected events.
Definition: loglevel.h:113
#define BIOS_DEBUG
BIOS_DEBUG - Verbose output.
Definition: loglevel.h:128
void intel_microcode_load_unlocked(const void *microcode_patch)
Definition: microcode.c:71
const void * intel_microcode_find(void)
Definition: microcode.c:223
#define IRONLAKE_BCLK
Definition: model_2065x.h:7
static void get_microcode_info(const void **microcode, int *parallel)
void mp_init_cpus(struct bus *cpu_bus)
static const struct cpu_driver driver __cpu_driver
static void set_max_ratio(void)
static void configure_misc(void)
static void pre_mp_init(void)
static void per_cpu_smm_trigger(void)
static void model_2065x_init(struct device *cpu)
static void configure_thermal_target(void)
static const struct cpu_device_id cpu_table[]
static int get_cpu_count(void)
static struct device_operations cpu_dev_ops
static void post_mp_init(void)
void fill_processor_name(char *processor_name)
Definition: name.c:8
Definition: device.h:76
Definition: cpu.h:13
struct device_operations * ops
Definition: cpu.h:14
void(* init)(struct device *dev)
Definition: device.h:42
Definition: device.h:107
DEVTREE_CONST void * chip_info
Definition: device.h:164
Definition: mp.h:20
void(* pre_mp_init)(void)
Definition: mp.h:27
unsigned int hi
Definition: msr.h:112
unsigned int lo
Definition: msr.h:111
void enable_turbo(void)
Definition: turbo.c:89