aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/i386/kernel/microcode.c73
1 files changed, 49 insertions, 24 deletions
diff --git a/arch/i386/kernel/microcode.c b/arch/i386/kernel/microcode.c
index e7c138f66c5a..0a865889b2a9 100644
--- a/arch/i386/kernel/microcode.c
+++ b/arch/i386/kernel/microcode.c
@@ -91,7 +91,10 @@ MODULE_DESCRIPTION("Intel CPU (IA-32) Microcode Update Driver");
91MODULE_AUTHOR("Tigran Aivazian <tigran@veritas.com>"); 91MODULE_AUTHOR("Tigran Aivazian <tigran@veritas.com>");
92MODULE_LICENSE("GPL"); 92MODULE_LICENSE("GPL");
93 93
94#define MICROCODE_VERSION "1.14" 94static int verbose;
95module_param(verbose, int, 0644);
96
97#define MICROCODE_VERSION "1.14a"
95 98
96#define DEFAULT_UCODE_DATASIZE (2000) /* 2000 bytes */ 99#define DEFAULT_UCODE_DATASIZE (2000) /* 2000 bytes */
97#define MC_HEADER_SIZE (sizeof (microcode_header_t)) /* 48 bytes */ 100#define MC_HEADER_SIZE (sizeof (microcode_header_t)) /* 48 bytes */
@@ -122,14 +125,15 @@ static unsigned int user_buffer_size; /* it's size */
122 125
123typedef enum mc_error_code { 126typedef enum mc_error_code {
124 MC_SUCCESS = 0, 127 MC_SUCCESS = 0,
125 MC_NOTFOUND = 1, 128 MC_IGNORED = 1,
126 MC_MARKED = 2, 129 MC_NOTFOUND = 2,
127 MC_ALLOCATED = 3, 130 MC_MARKED = 3,
131 MC_ALLOCATED = 4,
128} mc_error_code_t; 132} mc_error_code_t;
129 133
130static struct ucode_cpu_info { 134static struct ucode_cpu_info {
131 unsigned int sig; 135 unsigned int sig;
132 unsigned int pf; 136 unsigned int pf, orig_pf;
133 unsigned int rev; 137 unsigned int rev;
134 unsigned int cksum; 138 unsigned int cksum;
135 mc_error_code_t err; 139 mc_error_code_t err;
@@ -164,6 +168,7 @@ static void collect_cpu_info (void *unused)
164 rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]); 168 rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
165 uci->pf = 1 << ((val[1] >> 18) & 7); 169 uci->pf = 1 << ((val[1] >> 18) & 7);
166 } 170 }
171 uci->orig_pf = uci->pf;
167 } 172 }
168 173
169 wrmsr(MSR_IA32_UCODE_REV, 0, 0); 174 wrmsr(MSR_IA32_UCODE_REV, 0, 0);
@@ -197,21 +202,34 @@ static inline void mark_microcode_update (int cpu_num, microcode_header_t *mc_he
197 pr_debug(" Checksum 0x%x\n", cksum); 202 pr_debug(" Checksum 0x%x\n", cksum);
198 203
199 if (mc_header->rev < uci->rev) { 204 if (mc_header->rev < uci->rev) {
200 printk(KERN_ERR "microcode: CPU%d not 'upgrading' to earlier revision" 205 if (uci->err == MC_NOTFOUND) {
201 " 0x%x (current=0x%x)\n", cpu_num, mc_header->rev, uci->rev); 206 uci->err = MC_IGNORED;
202 goto out; 207 uci->cksum = mc_header->rev;
208 } else if (uci->err == MC_IGNORED && uci->cksum < mc_header->rev)
209 uci->cksum = mc_header->rev;
203 } else if (mc_header->rev == uci->rev) { 210 } else if (mc_header->rev == uci->rev) {
204 /* notify the caller of success on this cpu */ 211 if (uci->err < MC_MARKED) {
205 uci->err = MC_SUCCESS; 212 /* notify the caller of success on this cpu */
206 goto out; 213 uci->err = MC_SUCCESS;
214 }
215 } else if (uci->err != MC_ALLOCATED || mc_header->rev > uci->mc->hdr.rev) {
216 pr_debug("microcode: CPU%d found a matching microcode update with "
217 " revision 0x%x (current=0x%x)\n", cpu_num, mc_header->rev, uci->rev);
218 uci->cksum = cksum;
219 uci->pf = pf; /* keep the original mc pf for cksum calculation */
220 uci->err = MC_MARKED; /* found the match */
221 for_each_online_cpu(cpu_num) {
222 if (ucode_cpu_info + cpu_num != uci
223 && ucode_cpu_info[cpu_num].mc == uci->mc) {
224 uci->mc = NULL;
225 break;
226 }
227 }
228 if (uci->mc != NULL) {
229 vfree(uci->mc);
230 uci->mc = NULL;
231 }
207 } 232 }
208
209 pr_debug("microcode: CPU%d found a matching microcode update with "
210 " revision 0x%x (current=0x%x)\n", cpu_num, mc_header->rev, uci->rev);
211 uci->cksum = cksum;
212 uci->pf = pf; /* keep the original mc pf for cksum calculation */
213 uci->err = MC_MARKED; /* found the match */
214out:
215 return; 233 return;
216} 234}
217 235
@@ -253,10 +271,8 @@ static int find_matching_ucodes (void)
253 271
254 for_each_online_cpu(cpu_num) { 272 for_each_online_cpu(cpu_num) {
255 struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; 273 struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
256 if (uci->err != MC_NOTFOUND) /* already found a match or not an online cpu*/
257 continue;
258 274
259 if (sigmatch(mc_header.sig, uci->sig, mc_header.pf, uci->pf)) 275 if (sigmatch(mc_header.sig, uci->sig, mc_header.pf, uci->orig_pf))
260 mark_microcode_update(cpu_num, &mc_header, mc_header.sig, mc_header.pf, mc_header.cksum); 276 mark_microcode_update(cpu_num, &mc_header, mc_header.sig, mc_header.pf, mc_header.cksum);
261 } 277 }
262 278
@@ -295,9 +311,8 @@ static int find_matching_ucodes (void)
295 } 311 }
296 for_each_online_cpu(cpu_num) { 312 for_each_online_cpu(cpu_num) {
297 struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; 313 struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
298 if (uci->err != MC_NOTFOUND) /* already found a match or not an online cpu*/ 314
299 continue; 315 if (sigmatch(ext_sig.sig, uci->sig, ext_sig.pf, uci->orig_pf)) {
300 if (sigmatch(ext_sig.sig, uci->sig, ext_sig.pf, uci->pf)) {
301 mark_microcode_update(cpu_num, &mc_header, ext_sig.sig, ext_sig.pf, ext_sig.cksum); 316 mark_microcode_update(cpu_num, &mc_header, ext_sig.sig, ext_sig.pf, ext_sig.cksum);
302 } 317 }
303 } 318 }
@@ -368,6 +383,13 @@ static void do_update_one (void * unused)
368 struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; 383 struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
369 384
370 if (uci->mc == NULL) { 385 if (uci->mc == NULL) {
386 if (verbose) {
387 if (uci->err == MC_SUCCESS)
388 printk(KERN_INFO "microcode: CPU%d already at revision 0x%x\n",
389 cpu_num, uci->rev);
390 else
391 printk(KERN_INFO "microcode: No new microcode data for CPU%d\n", cpu_num);
392 }
371 return; 393 return;
372 } 394 }
373 395
@@ -426,6 +448,9 @@ out_free:
426 ucode_cpu_info[j].mc = NULL; 448 ucode_cpu_info[j].mc = NULL;
427 } 449 }
428 } 450 }
451 if (ucode_cpu_info[i].err == MC_IGNORED && verbose)
452 printk(KERN_WARNING "microcode: CPU%d not 'upgrading' to earlier revision"
453 " 0x%x (current=0x%x)\n", i, ucode_cpu_info[i].cksum, ucode_cpu_info[i].rev);
429 } 454 }
430out: 455out:
431 return error; 456 return error;