1 /* SPDX-License-Identifier: GPL-2.0-only */
3 /* Microcode update for Intel PIII and later CPUs */
6 #include <console/console.h>
8 #include <cpu/intel/microcode.h>
9 #include <cpu/x86/msr.h>
10 #include <smp/spinlock.h>
13 DECLARE_SPIN_LOCK(microcode_lock
)
16 u32 hdrver
; /* Header Version */
17 u32 rev
; /* Update Revision */
19 u32 sig
; /* Processor Signature */
21 u32 cksum
; /* Checksum */
22 u32 ldrver
; /* Loader Revision */
23 u32 pf
; /* Processor Flags */
25 u32 data_size
; /* Data Size */
26 u32 total_size
; /* Total Size */
31 struct ext_sig_table
{
37 struct ext_sig_entry
{
43 static inline u32
read_microcode_rev(void)
45 /* Some Intel CPUs can be very finicky about the
46 * CPUID sequence used. So this is implemented in
47 * assembly so that it works reliably.
51 "xorl %%eax, %%eax\n\t"
52 "xorl %%edx, %%edx\n\t"
53 "movl $0x8b, %%ecx\n\t"
55 "movl $0x01, %%eax\n\t"
57 "movl $0x08b, %%ecx\n\t"
60 "=a" (msr
.lo
), "=d" (msr
.hi
)
68 #define MICROCODE_CBFS_FILE "cpu_microcode_blob.bin"
70 static int load_microcode(const struct microcode
*ucode_patch
)
75 msr
.lo
= (unsigned long)ucode_patch
+ sizeof(struct microcode
);
77 wrmsr(IA32_BIOS_UPDT_TRIG
, msr
);
79 current_rev
= read_microcode_rev();
80 if (current_rev
== ucode_patch
->rev
) {
81 printk(BIOS_INFO
, "microcode: updated to revision "
82 "0x%x date=%04x-%02x-%02x\n", read_microcode_rev(),
83 ucode_patch
->date
& 0xffff, (ucode_patch
->date
>> 24) & 0xff,
84 (ucode_patch
->date
>> 16) & 0xff);
91 void intel_microcode_load_unlocked(const void *microcode_patch
)
94 const struct microcode
*m
= microcode_patch
;
97 printk(BIOS_WARNING
, "microcode: failed because no ucode was found\n");
101 current_rev
= read_microcode_rev();
103 /* No use loading the same revision. */
104 if (current_rev
== m
->rev
) {
105 printk(BIOS_INFO
, "microcode: Update skipped, already up-to-date\n");
110 /*SoC specific check to update microcode*/
111 if (soc_skip_ucode_update(current_rev
, m
->rev
)) {
112 printk(BIOS_DEBUG
, "Skip microcode update\n");
117 printk(BIOS_INFO
, "microcode: load microcode patch\n");
118 if (load_microcode(m
) < 0)
119 printk(BIOS_ERR
, "microcode: Update failed\n");
122 uint32_t get_current_microcode_rev(void)
124 return read_microcode_rev();
127 uint32_t get_microcode_rev(const void *microcode
)
129 return ((struct microcode
*)microcode
)->rev
;
132 uint32_t get_microcode_size(const void *microcode
)
134 return ((struct microcode
*)microcode
)->total_size
;
137 uint32_t get_microcode_checksum(const void *microcode
)
139 return ((struct microcode
*)microcode
)->cksum
;
143 static struct ext_sig_table
*ucode_get_ext_sig_table(const struct microcode
*ucode
)
145 struct ext_sig_table
*ext_tbl
;
146 /* header + ucode data blob size */
147 u32 size
= ucode
->data_size
+ sizeof(struct microcode
);
149 ssize_t ext_tbl_len
= ucode
->total_size
- size
;
151 if (ext_tbl_len
< (ssize_t
)sizeof(struct ext_sig_table
))
154 ext_tbl
= (struct ext_sig_table
*)((uintptr_t)ucode
+ size
);
156 if (ext_tbl_len
< (sizeof(struct ext_sig_table
) +
157 ext_tbl
->ext_sig_cnt
* sizeof(struct ext_sig_entry
)))
163 static const void *find_cbfs_microcode(void)
165 const struct microcode
*ucode_updates
;
166 struct ext_sig_table
*ext_tbl
;
167 size_t microcode_len
;
169 u32 pf
, rev
, sig
, update_size
;
171 struct cpuinfo_x86 c
;
173 ucode_updates
= cbfs_map(MICROCODE_CBFS_FILE
, µcode_len
);
174 if (ucode_updates
== NULL
)
177 rev
= read_microcode_rev();
183 if ((c
.x86_model
>= 5) || (c
.x86
> 6)) {
184 msr
= rdmsr(IA32_PLATFORM_ID
);
185 pf
= 1 << ((msr
.hi
>> 18) & 7);
188 printk(BIOS_DEBUG
, "microcode: sig=0x%x pf=0x%x revision=0x%x\n",
191 while (microcode_len
>= sizeof(*ucode_updates
)) {
192 /* Newer microcode updates include a size field, whereas older
193 * containers set it at 0 and are exactly 2048 bytes long */
194 if (ucode_updates
->total_size
) {
195 update_size
= ucode_updates
->total_size
;
197 printk(BIOS_SPEW
, "Microcode size field is 0\n");
201 /* Checkpoint 1: The microcode update falls within CBFS */
202 if (update_size
> microcode_len
) {
203 printk(BIOS_WARNING
, "Microcode header corrupted!\n");
207 if ((ucode_updates
->sig
== sig
) && (ucode_updates
->pf
& pf
))
208 return ucode_updates
;
211 /* Check if there is extended signature table */
212 ext_tbl
= ucode_get_ext_sig_table(ucode_updates
);
214 if (ext_tbl
!= NULL
) {
216 struct ext_sig_entry
*entry
= (struct ext_sig_entry
*)(ext_tbl
+ 1);
218 for (i
= 0; i
< ext_tbl
->ext_sig_cnt
; i
++, entry
++) {
219 if ((sig
== entry
->sig
) && (pf
& entry
->pf
)) {
220 return ucode_updates
;
225 ucode_updates
= (void *)((char *)ucode_updates
+ update_size
);
226 microcode_len
-= update_size
;
232 const void *intel_microcode_find(void)
234 static bool microcode_checked
;
235 static const void *ucode_update
;
237 if (microcode_checked
)
241 * Since this function caches the found microcode (NULL or a valid
242 * microcode pointer), it is expected to be run from BSP before starting
243 * any other APs. This sequence is not multithread safe otherwise.
245 ucode_update
= find_cbfs_microcode();
246 microcode_checked
= true;
251 void intel_update_microcode_from_cbfs(void)
253 const void *patch
= intel_microcode_find();
255 spin_lock(µcode_lock
);
257 intel_microcode_load_unlocked(patch
);
259 spin_unlock(µcode_lock
);
262 void intel_reload_microcode(void)
264 if (!CONFIG(RELOAD_MICROCODE_PATCH
))
267 const struct microcode
*m
= intel_microcode_find();
270 printk(BIOS_WARNING
, "microcode: failed because no ucode was found\n");
274 printk(BIOS_INFO
, "microcode: Re-load microcode patch\n");
276 if (load_microcode(m
) < 0)
277 printk(BIOS_ERR
, "microcode: Re-load failed\n");
281 __weak
int soc_skip_ucode_update(u32 current_patch_id
,