aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJacob Shin <jacob.shin@amd.com>2013-05-30 15:09:18 -0400
committerH. Peter Anvin <hpa@linux.intel.com>2013-05-30 23:19:25 -0400
commita76096a6571d5389376753c2e18b30a9791fa072 (patch)
tree1ca270330019b9d46ad6f499a7fa5bb69f56ba40
parentf2b3ee820a9f2368d7f8842ad7da062dfe86e199 (diff)
x86, microcode, amd: Refactor functions to prepare for early loading
In preparation work for early loading, refactor some common functions that will be shared, and move some struct defines to a common header file. Signed-off-by: Jacob Shin <jacob.shin@amd.com> Link: http://lkml.kernel.org/r/1369940959-2077-4-git-send-email-jacob.shin@amd.com Signed-off-by: H. Peter Anvin <hpa@linux.intel.com> Cc: Fenghua Yu <fenghua.yu@intel.com>
-rw-r--r--arch/x86/include/asm/microcode_amd.h64
-rw-r--r--arch/x86/kernel/microcode_amd.c111
2 files changed, 106 insertions, 69 deletions
diff --git a/arch/x86/include/asm/microcode_amd.h b/arch/x86/include/asm/microcode_amd.h
new file mode 100644
index 000000000000..a57d9b75f30b
--- /dev/null
+++ b/arch/x86/include/asm/microcode_amd.h
@@ -0,0 +1,64 @@
1#ifndef _ASM_X86_MICROCODE_AMD_H
2#define _ASM_X86_MICROCODE_AMD_H
3
4#include <asm/microcode.h>
5
6#define UCODE_MAGIC 0x00414d44
7#define UCODE_EQUIV_CPU_TABLE_TYPE 0x00000000
8#define UCODE_UCODE_TYPE 0x00000001
9
10#define SECTION_HDR_SIZE 8
11#define CONTAINER_HDR_SZ 12
12
13struct equiv_cpu_entry {
14 u32 installed_cpu;
15 u32 fixed_errata_mask;
16 u32 fixed_errata_compare;
17 u16 equiv_cpu;
18 u16 res;
19} __attribute__((packed));
20
21struct microcode_header_amd {
22 u32 data_code;
23 u32 patch_id;
24 u16 mc_patch_data_id;
25 u8 mc_patch_data_len;
26 u8 init_flag;
27 u32 mc_patch_data_checksum;
28 u32 nb_dev_id;
29 u32 sb_dev_id;
30 u16 processor_rev_id;
31 u8 nb_rev_id;
32 u8 sb_rev_id;
33 u8 bios_api_rev;
34 u8 reserved1[3];
35 u32 match_reg[8];
36} __attribute__((packed));
37
38struct microcode_amd {
39 struct microcode_header_amd hdr;
40 unsigned int mpb[0];
41};
42
43static inline u16 find_equiv_id(struct equiv_cpu_entry *equiv_cpu_table,
44 unsigned int sig)
45{
46 int i = 0;
47
48 if (!equiv_cpu_table)
49 return 0;
50
51 while (equiv_cpu_table[i].installed_cpu != 0) {
52 if (sig == equiv_cpu_table[i].installed_cpu)
53 return equiv_cpu_table[i].equiv_cpu;
54
55 i++;
56 }
57 return 0;
58}
59
60extern int __apply_microcode_amd(struct microcode_amd *mc_amd);
61extern int apply_microcode_amd(int cpu);
62extern enum ucode_state load_microcode_amd(int cpu, const u8 *data, size_t size);
63
64#endif /* _ASM_X86_MICROCODE_AMD_H */
diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c
index efdec7cd8e01..8f11f8f90e98 100644
--- a/arch/x86/kernel/microcode_amd.c
+++ b/arch/x86/kernel/microcode_amd.c
@@ -31,48 +31,12 @@
31#include <asm/microcode.h> 31#include <asm/microcode.h>
32#include <asm/processor.h> 32#include <asm/processor.h>
33#include <asm/msr.h> 33#include <asm/msr.h>
34#include <asm/microcode_amd.h>
34 35
35MODULE_DESCRIPTION("AMD Microcode Update Driver"); 36MODULE_DESCRIPTION("AMD Microcode Update Driver");
36MODULE_AUTHOR("Peter Oruba"); 37MODULE_AUTHOR("Peter Oruba");
37MODULE_LICENSE("GPL v2"); 38MODULE_LICENSE("GPL v2");
38 39
39#define UCODE_MAGIC 0x00414d44
40#define UCODE_EQUIV_CPU_TABLE_TYPE 0x00000000
41#define UCODE_UCODE_TYPE 0x00000001
42
43struct equiv_cpu_entry {
44 u32 installed_cpu;
45 u32 fixed_errata_mask;
46 u32 fixed_errata_compare;
47 u16 equiv_cpu;
48 u16 res;
49} __attribute__((packed));
50
51struct microcode_header_amd {
52 u32 data_code;
53 u32 patch_id;
54 u16 mc_patch_data_id;
55 u8 mc_patch_data_len;
56 u8 init_flag;
57 u32 mc_patch_data_checksum;
58 u32 nb_dev_id;
59 u32 sb_dev_id;
60 u16 processor_rev_id;
61 u8 nb_rev_id;
62 u8 sb_rev_id;
63 u8 bios_api_rev;
64 u8 reserved1[3];
65 u32 match_reg[8];
66} __attribute__((packed));
67
68struct microcode_amd {
69 struct microcode_header_amd hdr;
70 unsigned int mpb[0];
71};
72
73#define SECTION_HDR_SIZE 8
74#define CONTAINER_HDR_SZ 12
75
76static struct equiv_cpu_entry *equiv_cpu_table; 40static struct equiv_cpu_entry *equiv_cpu_table;
77 41
78struct ucode_patch { 42struct ucode_patch {
@@ -84,21 +48,10 @@ struct ucode_patch {
84 48
85static LIST_HEAD(pcache); 49static LIST_HEAD(pcache);
86 50
87static u16 find_equiv_id(unsigned int cpu) 51static u16 __find_equiv_id(unsigned int cpu)
88{ 52{
89 struct ucode_cpu_info *uci = ucode_cpu_info + cpu; 53 struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
90 int i = 0; 54 return find_equiv_id(equiv_cpu_table, uci->cpu_sig.sig);
91
92 if (!equiv_cpu_table)
93 return 0;
94
95 while (equiv_cpu_table[i].installed_cpu != 0) {
96 if (uci->cpu_sig.sig == equiv_cpu_table[i].installed_cpu)
97 return equiv_cpu_table[i].equiv_cpu;
98
99 i++;
100 }
101 return 0;
102} 55}
103 56
104static u32 find_cpu_family_by_equiv_cpu(u16 equiv_cpu) 57static u32 find_cpu_family_by_equiv_cpu(u16 equiv_cpu)
@@ -163,7 +116,7 @@ static struct ucode_patch *find_patch(unsigned int cpu)
163{ 116{
164 u16 equiv_id; 117 u16 equiv_id;
165 118
166 equiv_id = find_equiv_id(cpu); 119 equiv_id = __find_equiv_id(cpu);
167 if (!equiv_id) 120 if (!equiv_id)
168 return NULL; 121 return NULL;
169 122
@@ -215,7 +168,21 @@ static unsigned int verify_patch_size(int cpu, u32 patch_size,
215 return patch_size; 168 return patch_size;
216} 169}
217 170
218static int apply_microcode_amd(int cpu) 171int __apply_microcode_amd(struct microcode_amd *mc_amd)
172{
173 u32 rev, dummy;
174
175 wrmsrl(MSR_AMD64_PATCH_LOADER, (u64)(long)&mc_amd->hdr.data_code);
176
177 /* verify patch application was successful */
178 rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
179 if (rev != mc_amd->hdr.patch_id)
180 return -1;
181
182 return 0;
183}
184
185int apply_microcode_amd(int cpu)
219{ 186{
220 struct cpuinfo_x86 *c = &cpu_data(cpu); 187 struct cpuinfo_x86 *c = &cpu_data(cpu);
221 struct microcode_amd *mc_amd; 188 struct microcode_amd *mc_amd;
@@ -242,19 +209,15 @@ static int apply_microcode_amd(int cpu)
242 return 0; 209 return 0;
243 } 210 }
244 211
245 wrmsrl(MSR_AMD64_PATCH_LOADER, (u64)(long)&mc_amd->hdr.data_code); 212 if (__apply_microcode_amd(mc_amd))
246
247 /* verify patch application was successful */
248 rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
249 if (rev != mc_amd->hdr.patch_id) {
250 pr_err("CPU%d: update failed for patch_level=0x%08x\n", 213 pr_err("CPU%d: update failed for patch_level=0x%08x\n",
251 cpu, mc_amd->hdr.patch_id); 214 cpu, mc_amd->hdr.patch_id);
252 return -1; 215 else
253 } 216 pr_info("CPU%d: new patch_level=0x%08x\n", cpu,
217 mc_amd->hdr.patch_id);
254 218
255 pr_info("CPU%d: new patch_level=0x%08x\n", cpu, rev); 219 uci->cpu_sig.rev = mc_amd->hdr.patch_id;
256 uci->cpu_sig.rev = rev; 220 c->microcode = mc_amd->hdr.patch_id;
257 c->microcode = rev;
258 221
259 return 0; 222 return 0;
260} 223}
@@ -364,7 +327,7 @@ static int verify_and_add_patch(unsigned int cpu, u8 *fw, unsigned int leftover)
364 return crnt_size; 327 return crnt_size;
365} 328}
366 329
367static enum ucode_state load_microcode_amd(int cpu, const u8 *data, size_t size) 330static enum ucode_state __load_microcode_amd(int cpu, const u8 *data, size_t size)
368{ 331{
369 enum ucode_state ret = UCODE_ERROR; 332 enum ucode_state ret = UCODE_ERROR;
370 unsigned int leftover; 333 unsigned int leftover;
@@ -398,6 +361,21 @@ static enum ucode_state load_microcode_amd(int cpu, const u8 *data, size_t size)
398 return UCODE_OK; 361 return UCODE_OK;
399} 362}
400 363
364enum ucode_state load_microcode_amd(int cpu, const u8 *data, size_t size)
365{
366 enum ucode_state ret;
367
368 /* free old equiv table */
369 free_equiv_cpu_table();
370
371 ret = __load_microcode_amd(cpu, data, size);
372
373 if (ret != UCODE_OK)
374 cleanup();
375
376 return ret;
377}
378
401/* 379/*
402 * AMD microcode firmware naming convention, up to family 15h they are in 380 * AMD microcode firmware naming convention, up to family 15h they are in
403 * the legacy file: 381 * the legacy file:
@@ -440,12 +418,7 @@ static enum ucode_state request_microcode_amd(int cpu, struct device *device,
440 goto fw_release; 418 goto fw_release;
441 } 419 }
442 420
443 /* free old equiv table */
444 free_equiv_cpu_table();
445
446 ret = load_microcode_amd(cpu, fw->data, fw->size); 421 ret = load_microcode_amd(cpu, fw->data, fw->size);
447 if (ret != UCODE_OK)
448 cleanup();
449 422
450 fw_release: 423 fw_release:
451 release_firmware(fw); 424 release_firmware(fw);