1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
22
23#include <linux/firmware.h>
24#include <linux/pci_ids.h>
25#include <linux/uaccess.h>
26#include <linux/vmalloc.h>
27#include <linux/kernel.h>
28#include <linux/module.h>
29#include <linux/pci.h>
30
31#include <asm/microcode.h>
32#include <asm/processor.h>
33#include <asm/msr.h>
34#include <asm/microcode_amd.h>
35
36MODULE_DESCRIPTION("AMD Microcode Update Driver");
37MODULE_AUTHOR("Peter Oruba");
38MODULE_LICENSE("GPL v2");
39
40static struct equiv_cpu_entry *equiv_cpu_table;
41
42struct ucode_patch {
43 struct list_head plist;
44 void *data;
45 u32 patch_id;
46 u16 equiv_cpu;
47};
48
49static LIST_HEAD(pcache);
50
51static u16 __find_equiv_id(unsigned int cpu)
52{
53 struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
54 return find_equiv_id(equiv_cpu_table, uci->cpu_sig.sig);
55}
56
57static u32 find_cpu_family_by_equiv_cpu(u16 equiv_cpu)
58{
59 int i = 0;
60
61 BUG_ON(!equiv_cpu_table);
62
63 while (equiv_cpu_table[i].equiv_cpu != 0) {
64 if (equiv_cpu == equiv_cpu_table[i].equiv_cpu)
65 return equiv_cpu_table[i].installed_cpu;
66 i++;
67 }
68 return 0;
69}
70
71
72
73
74static struct ucode_patch *cache_find_patch(u16 equiv_cpu)
75{
76 struct ucode_patch *p;
77
78 list_for_each_entry(p, &pcache, plist)
79 if (p->equiv_cpu == equiv_cpu)
80 return p;
81 return NULL;
82}
83
84static void update_cache(struct ucode_patch *new_patch)
85{
86 struct ucode_patch *p;
87
88 list_for_each_entry(p, &pcache, plist) {
89 if (p->equiv_cpu == new_patch->equiv_cpu) {
90 if (p->patch_id >= new_patch->patch_id)
91
92 return;
93
94 list_replace(&p->plist, &new_patch->plist);
95 kfree(p->data);
96 kfree(p);
97 return;
98 }
99 }
100
101 list_add_tail(&new_patch->plist, &pcache);
102}
103
104static void free_cache(void)
105{
106 struct ucode_patch *p, *tmp;
107
108 list_for_each_entry_safe(p, tmp, &pcache, plist) {
109 __list_del(p->plist.prev, p->plist.next);
110 kfree(p->data);
111 kfree(p);
112 }
113}
114
115static struct ucode_patch *find_patch(unsigned int cpu)
116{
117 u16 equiv_id;
118
119 equiv_id = __find_equiv_id(cpu);
120 if (!equiv_id)
121 return NULL;
122
123 return cache_find_patch(equiv_id);
124}
125
126static int collect_cpu_info_amd(int cpu, struct cpu_signature *csig)
127{
128 struct cpuinfo_x86 *c = &cpu_data(cpu);
129 struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
130 struct ucode_patch *p;
131
132 csig->sig = cpuid_eax(0x00000001);
133 csig->rev = c->microcode;
134
135
136
137
138
139 p = find_patch(cpu);
140 if (p && (p->patch_id == csig->rev))
141 uci->mc = p->data;
142
143 pr_info("CPU%d: patch_level=0x%08x\n", cpu, csig->rev);
144
145 return 0;
146}
147
148static unsigned int verify_patch_size(u8 family, u32 patch_size,
149 unsigned int size)
150{
151 u32 max_size;
152
153#define F1XH_MPB_MAX_SIZE 2048
154#define F14H_MPB_MAX_SIZE 1824
155#define F15H_MPB_MAX_SIZE 4096
156#define F16H_MPB_MAX_SIZE 3458
157
158 switch (family) {
159 case 0x14:
160 max_size = F14H_MPB_MAX_SIZE;
161 break;
162 case 0x15:
163 max_size = F15H_MPB_MAX_SIZE;
164 break;
165 case 0x16:
166 max_size = F16H_MPB_MAX_SIZE;
167 break;
168 default:
169 max_size = F1XH_MPB_MAX_SIZE;
170 break;
171 }
172
173 if (patch_size > min_t(u32, size, max_size)) {
174 pr_err("patch size mismatch\n");
175 return 0;
176 }
177
178 return patch_size;
179}
180
181int __apply_microcode_amd(struct microcode_amd *mc_amd)
182{
183 u32 rev, dummy;
184
185 native_wrmsrl(MSR_AMD64_PATCH_LOADER, (u64)(long)&mc_amd->hdr.data_code);
186
187
188 native_rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
189 if (rev != mc_amd->hdr.patch_id)
190 return -1;
191
192 return 0;
193}
194
195int apply_microcode_amd(int cpu)
196{
197 struct cpuinfo_x86 *c = &cpu_data(cpu);
198 struct microcode_amd *mc_amd;
199 struct ucode_cpu_info *uci;
200 struct ucode_patch *p;
201 u32 rev, dummy;
202
203 BUG_ON(raw_smp_processor_id() != cpu);
204
205 uci = ucode_cpu_info + cpu;
206
207 p = find_patch(cpu);
208 if (!p)
209 return 0;
210
211 mc_amd = p->data;
212 uci->mc = p->data;
213
214 rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
215
216
217 if (rev >= mc_amd->hdr.patch_id) {
218 c->microcode = rev;
219 uci->cpu_sig.rev = rev;
220 return 0;
221 }
222
223 if (__apply_microcode_amd(mc_amd)) {
224 pr_err("CPU%d: update failed for patch_level=0x%08x\n",
225 cpu, mc_amd->hdr.patch_id);
226 return -1;
227 }
228 pr_info("CPU%d: new patch_level=0x%08x\n", cpu,
229 mc_amd->hdr.patch_id);
230
231 uci->cpu_sig.rev = mc_amd->hdr.patch_id;
232 c->microcode = mc_amd->hdr.patch_id;
233
234 return 0;
235}
236
237static int install_equiv_cpu_table(const u8 *buf)
238{
239 unsigned int *ibuf = (unsigned int *)buf;
240 unsigned int type = ibuf[1];
241 unsigned int size = ibuf[2];
242
243 if (type != UCODE_EQUIV_CPU_TABLE_TYPE || !size) {
244 pr_err("empty section/"
245 "invalid type field in container file section header\n");
246 return -EINVAL;
247 }
248
249 equiv_cpu_table = vmalloc(size);
250 if (!equiv_cpu_table) {
251 pr_err("failed to allocate equivalent CPU table\n");
252 return -ENOMEM;
253 }
254
255 memcpy(equiv_cpu_table, buf + CONTAINER_HDR_SZ, size);
256
257
258 return size + CONTAINER_HDR_SZ;
259}
260
261static void free_equiv_cpu_table(void)
262{
263 vfree(equiv_cpu_table);
264 equiv_cpu_table = NULL;
265}
266
267static void cleanup(void)
268{
269 free_equiv_cpu_table();
270 free_cache();
271}
272
273
274
275
276
277
278
279
280static int verify_and_add_patch(u8 family, u8 *fw, unsigned int leftover)
281{
282 struct microcode_header_amd *mc_hdr;
283 struct ucode_patch *patch;
284 unsigned int patch_size, crnt_size, ret;
285 u32 proc_fam;
286 u16 proc_id;
287
288 patch_size = *(u32 *)(fw + 4);
289 crnt_size = patch_size + SECTION_HDR_SIZE;
290 mc_hdr = (struct microcode_header_amd *)(fw + SECTION_HDR_SIZE);
291 proc_id = mc_hdr->processor_rev_id;
292
293 proc_fam = find_cpu_family_by_equiv_cpu(proc_id);
294 if (!proc_fam) {
295 pr_err("No patch family for equiv ID: 0x%04x\n", proc_id);
296 return crnt_size;
297 }
298
299
300 proc_fam = ((proc_fam >> 8) & 0xf) + ((proc_fam >> 20) & 0xff);
301 if (proc_fam != family)
302 return crnt_size;
303
304 if (mc_hdr->nb_dev_id || mc_hdr->sb_dev_id) {
305 pr_err("Patch-ID 0x%08x: chipset-specific code unsupported.\n",
306 mc_hdr->patch_id);
307 return crnt_size;
308 }
309
310 ret = verify_patch_size(family, patch_size, leftover);
311 if (!ret) {
312 pr_err("Patch-ID 0x%08x: size mismatch.\n", mc_hdr->patch_id);
313 return crnt_size;
314 }
315
316 patch = kzalloc(sizeof(*patch), GFP_KERNEL);
317 if (!patch) {
318 pr_err("Patch allocation failure.\n");
319 return -EINVAL;
320 }
321
322 patch->data = kzalloc(patch_size, GFP_KERNEL);
323 if (!patch->data) {
324 pr_err("Patch data allocation failure.\n");
325 kfree(patch);
326 return -EINVAL;
327 }
328
329
330 memcpy(patch->data, fw + SECTION_HDR_SIZE, patch_size);
331 INIT_LIST_HEAD(&patch->plist);
332 patch->patch_id = mc_hdr->patch_id;
333 patch->equiv_cpu = proc_id;
334
335 pr_debug("%s: Added patch_id: 0x%08x, proc_id: 0x%04x\n",
336 __func__, patch->patch_id, proc_id);
337
338
339 update_cache(patch);
340
341 return crnt_size;
342}
343
344static enum ucode_state __load_microcode_amd(u8 family, const u8 *data,
345 size_t size)
346{
347 enum ucode_state ret = UCODE_ERROR;
348 unsigned int leftover;
349 u8 *fw = (u8 *)data;
350 int crnt_size = 0;
351 int offset;
352
353 offset = install_equiv_cpu_table(data);
354 if (offset < 0) {
355 pr_err("failed to create equivalent cpu table\n");
356 return ret;
357 }
358 fw += offset;
359 leftover = size - offset;
360
361 if (*(u32 *)fw != UCODE_UCODE_TYPE) {
362 pr_err("invalid type field in container file section header\n");
363 free_equiv_cpu_table();
364 return ret;
365 }
366
367 while (leftover) {
368 crnt_size = verify_and_add_patch(family, fw, leftover);
369 if (crnt_size < 0)
370 return ret;
371
372 fw += crnt_size;
373 leftover -= crnt_size;
374 }
375
376 return UCODE_OK;
377}
378
379enum ucode_state load_microcode_amd(int cpu, u8 family, const u8 *data, size_t size)
380{
381 enum ucode_state ret;
382
383
384 free_equiv_cpu_table();
385
386 ret = __load_microcode_amd(family, data, size);
387
388 if (ret != UCODE_OK)
389 cleanup();
390
391#if defined(CONFIG_MICROCODE_AMD_EARLY) && defined(CONFIG_X86_32)
392
393 if (cpu_data(cpu).cpu_index == boot_cpu_data.cpu_index) {
394 struct ucode_patch *p = find_patch(cpu);
395 if (p) {
396 memset(amd_ucode_patch, 0, PATCH_MAX_SIZE);
397 memcpy(amd_ucode_patch, p->data, min_t(u32, ksize(p->data),
398 PATCH_MAX_SIZE));
399 }
400 }
401#endif
402 return ret;
403}
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421static enum ucode_state request_microcode_amd(int cpu, struct device *device,
422 bool refresh_fw)
423{
424 char fw_name[36] = "amd-ucode/microcode_amd.bin";
425 struct cpuinfo_x86 *c = &cpu_data(cpu);
426 enum ucode_state ret = UCODE_NFOUND;
427 const struct firmware *fw;
428
429
430 if (!refresh_fw || c->cpu_index != boot_cpu_data.cpu_index)
431 return UCODE_OK;
432
433 if (c->x86 >= 0x15)
434 snprintf(fw_name, sizeof(fw_name), "amd-ucode/microcode_amd_fam%.2xh.bin", c->x86);
435
436 if (request_firmware_direct(&fw, (const char *)fw_name, device)) {
437 pr_debug("failed to load file %s\n", fw_name);
438 goto out;
439 }
440
441 ret = UCODE_ERROR;
442 if (*(u32 *)fw->data != UCODE_MAGIC) {
443 pr_err("invalid magic value (0x%08x)\n", *(u32 *)fw->data);
444 goto fw_release;
445 }
446
447 ret = load_microcode_amd(cpu, c->x86, fw->data, fw->size);
448
449 fw_release:
450 release_firmware(fw);
451
452 out:
453 return ret;
454}
455
456static enum ucode_state
457request_microcode_user(int cpu, const void __user *buf, size_t size)
458{
459 return UCODE_ERROR;
460}
461
462static void microcode_fini_cpu_amd(int cpu)
463{
464 struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
465
466 uci->mc = NULL;
467}
468
469static struct microcode_ops microcode_amd_ops = {
470 .request_microcode_user = request_microcode_user,
471 .request_microcode_fw = request_microcode_amd,
472 .collect_cpu_info = collect_cpu_info_amd,
473 .apply_microcode = apply_microcode_amd,
474 .microcode_fini_cpu = microcode_fini_cpu_amd,
475};
476
477struct microcode_ops * __init init_amd_microcode(void)
478{
479 struct cpuinfo_x86 *c = &cpu_data(0);
480
481 if (c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10) {
482 pr_warning("AMD CPU family 0x%x not supported\n", c->x86);
483 return NULL;
484 }
485
486 return µcode_amd_ops;
487}
488
489void __exit exit_amd_microcode(void)
490{
491 cleanup();
492}
493