]>
git.ipfire.org Git - thirdparty/u-boot.git/blob - arch/x86/cpu/intel_common/microcode.c
1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2014 Google, Inc
4 * Copyright (C) 2000 Ronald G. Minnich
6 * Microcode update for Intel PIII and later CPUs
12 #include <linux/libfdt.h>
14 #include <asm/microcode.h>
16 #include <asm/msr-index.h>
17 #include <asm/processor.h>
19 DECLARE_GLOBAL_DATA_PTR
;
22 * struct microcode_update - standard microcode header from Intel
24 * We read this information out of the device tree and use it to determine
25 * whether the update is applicable or not. We also use the same structure
26 * to read information from the CPU.
28 struct microcode_update
{
32 uint processor_signature
;
40 static int microcode_decode_node(const void *blob
, int node
,
41 struct microcode_update
*update
)
43 update
->data
= fdt_getprop(blob
, node
, "data", &update
->size
);
46 update
->data
+= UCODE_HEADER_LEN
;
47 update
->size
-= UCODE_HEADER_LEN
;
49 update
->header_version
= fdtdec_get_int(blob
, node
,
50 "intel,header-version", 0);
51 update
->update_revision
= fdtdec_get_int(blob
, node
,
52 "intel,update-revision", 0);
53 update
->date_code
= fdtdec_get_int(blob
, node
,
54 "intel,date-code", 0);
55 update
->processor_signature
= fdtdec_get_int(blob
, node
,
56 "intel,processor-signature", 0);
57 update
->checksum
= fdtdec_get_int(blob
, node
, "intel,checksum", 0);
58 update
->loader_revision
= fdtdec_get_int(blob
, node
,
59 "intel,loader-revision", 0);
60 update
->processor_flags
= fdtdec_get_int(blob
, node
,
61 "intel,processor-flags", 0);
66 int microcode_read_rev(void)
68 /* Quark does not have microcode MSRs */
69 #ifdef CONFIG_INTEL_QUARK
73 * Some Intel CPUs can be very finicky about the CPUID sequence used.
74 * So this is implemented in assembly so that it works reliably.
88 "=a" (low
), "=d" (high
)
90 "i" (MSR_IA32_UCODE_REV
)
99 static void microcode_read_cpu(struct microcode_update
*cpu
)
101 /* CPUID sets MSR 0x8B iff a microcode update has been loaded. */
102 unsigned int x86_model
, x86_family
;
103 struct cpuid_result result
;
106 wrmsr(MSR_IA32_UCODE_REV
, 0, 0);
108 rdmsr(MSR_IA32_UCODE_REV
, low
, cpu
->update_revision
);
109 x86_model
= (result
.eax
>> 4) & 0x0f;
110 x86_family
= (result
.eax
>> 8) & 0x0f;
111 cpu
->processor_signature
= result
.eax
;
113 cpu
->processor_flags
= 0;
114 if ((x86_model
>= 5) || (x86_family
> 6)) {
115 rdmsr(0x17, low
, high
);
116 cpu
->processor_flags
= 1 << ((high
>> 18) & 7);
118 debug("microcode: sig=%#x pf=%#x revision=%#x\n",
119 cpu
->processor_signature
, cpu
->processor_flags
,
120 cpu
->update_revision
);
123 /* Get a microcode update from the device tree and apply it */
124 int microcode_update_intel(void)
126 struct microcode_update cpu
, update
;
127 const void *blob
= gd
->fdt_blob
;
134 microcode_read_cpu(&cpu
);
139 node
= fdtdec_next_compatible(blob
, node
,
140 COMPAT_INTEL_MICROCODE
);
142 debug("%s: Found %d updates\n", __func__
, count
);
143 return count
? 0 : skipped
? -EEXIST
: -ENOENT
;
146 ret
= microcode_decode_node(blob
, node
, &update
);
147 if (ret
== -ENOENT
&& ucode_base
) {
149 * The microcode has been removed from the device tree
150 * in the build system. In that case it will have
151 * already been updated in car_init().
153 debug("%s: Microcode data not available\n", __func__
);
158 debug("%s: Unable to decode update: %d\n", __func__
,
162 if (!(update
.processor_signature
== cpu
.processor_signature
&&
163 (update
.processor_flags
& cpu
.processor_flags
))) {
164 debug("%s: Skipping non-matching update, sig=%x, pf=%x\n",
165 __func__
, update
.processor_signature
,
166 update
.processor_flags
);
170 wrmsr(MSR_IA32_UCODE_WRITE
, (ulong
)update
.data
, 0);
171 rev
= microcode_read_rev();
172 debug("microcode: updated to revision 0x%x date=%04x-%02x-%02x\n",
173 rev
, update
.date_code
& 0xffff,
174 (update
.date_code
>> 24) & 0xff,
175 (update
.date_code
>> 16) & 0xff);
176 if (update
.update_revision
!= rev
) {
177 printf("Microcode update failed\n");