diff options
| -rw-r--r-- | arch/x86/kernel/microcode_intel.c | 46 | ||||
| -rw-r--r-- | include/asm-x86/microcode.h | 10 |
2 files changed, 30 insertions, 26 deletions
diff --git a/arch/x86/kernel/microcode_intel.c b/arch/x86/kernel/microcode_intel.c index eded0a154ea8..ca9861bf067e 100644 --- a/arch/x86/kernel/microcode_intel.c +++ b/arch/x86/kernel/microcode_intel.c | |||
| @@ -100,17 +100,19 @@ MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>"); | |||
| 100 | MODULE_LICENSE("GPL"); | 100 | MODULE_LICENSE("GPL"); |
| 101 | 101 | ||
| 102 | #define DEFAULT_UCODE_DATASIZE (2000) /* 2000 bytes */ | 102 | #define DEFAULT_UCODE_DATASIZE (2000) /* 2000 bytes */ |
| 103 | #define MC_HEADER_SIZE (sizeof(struct microcode_header)) /* 48 bytes */ | 103 | #define MC_HEADER_SIZE (sizeof(struct microcode_header_intel)) /* 48 bytes */ |
| 104 | #define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE) /* 2048 bytes */ | 104 | #define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE) /* 2048 bytes */ |
| 105 | #define EXT_HEADER_SIZE (sizeof(struct extended_sigtable)) /* 20 bytes */ | 105 | #define EXT_HEADER_SIZE (sizeof(struct extended_sigtable)) /* 20 bytes */ |
| 106 | #define EXT_SIGNATURE_SIZE (sizeof(struct extended_signature)) /* 12 bytes */ | 106 | #define EXT_SIGNATURE_SIZE (sizeof(struct extended_signature)) /* 12 bytes */ |
| 107 | #define DWSIZE (sizeof(u32)) | 107 | #define DWSIZE (sizeof(u32)) |
| 108 | #define get_totalsize(mc) \ | 108 | #define get_totalsize(mc) \ |
| 109 | (((struct microcode *)mc)->hdr.totalsize ? \ | 109 | (((struct microcode_intel *)mc)->hdr.totalsize ? \ |
| 110 | ((struct microcode *)mc)->hdr.totalsize : DEFAULT_UCODE_TOTALSIZE) | 110 | ((struct microcode_intel *)mc)->hdr.totalsize : \ |
| 111 | DEFAULT_UCODE_TOTALSIZE) | ||
| 112 | |||
| 111 | #define get_datasize(mc) \ | 113 | #define get_datasize(mc) \ |
| 112 | (((struct microcode *)mc)->hdr.datasize ? \ | 114 | (((struct microcode_intel *)mc)->hdr.datasize ? \ |
| 113 | ((struct microcode *)mc)->hdr.datasize : DEFAULT_UCODE_DATASIZE) | 115 | ((struct microcode_intel *)mc)->hdr.datasize : DEFAULT_UCODE_DATASIZE) |
| 114 | 116 | ||
| 115 | #define sigmatch(s1, s2, p1, p2) \ | 117 | #define sigmatch(s1, s2, p1, p2) \ |
| 116 | (((s1) == (s2)) && (((p1) & (p2)) || (((p1) == 0) && ((p2) == 0)))) | 118 | (((s1) == (s2)) && (((p1) & (p2)) || (((p1) == 0) && ((p2) == 0)))) |
| @@ -134,7 +136,7 @@ void collect_cpu_info(int cpu_num) | |||
| 134 | /* We should bind the task to the CPU */ | 136 | /* We should bind the task to the CPU */ |
| 135 | BUG_ON(raw_smp_processor_id() != cpu_num); | 137 | BUG_ON(raw_smp_processor_id() != cpu_num); |
| 136 | uci->pf = uci->rev = 0; | 138 | uci->pf = uci->rev = 0; |
| 137 | uci->mc = NULL; | 139 | uci->mc.mc_intel = NULL; |
| 138 | uci->valid = 1; | 140 | uci->valid = 1; |
| 139 | 141 | ||
| 140 | if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 || | 142 | if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 || |
| @@ -163,7 +165,7 @@ void collect_cpu_info(int cpu_num) | |||
| 163 | } | 165 | } |
| 164 | 166 | ||
| 165 | static inline int microcode_update_match(int cpu_num, | 167 | static inline int microcode_update_match(int cpu_num, |
| 166 | struct microcode_header *mc_header, int sig, int pf) | 168 | struct microcode_header_intel *mc_header, int sig, int pf) |
| 167 | { | 169 | { |
| 168 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; | 170 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; |
| 169 | 171 | ||
| @@ -175,7 +177,7 @@ static inline int microcode_update_match(int cpu_num, | |||
| 175 | 177 | ||
| 176 | int microcode_sanity_check(void *mc) | 178 | int microcode_sanity_check(void *mc) |
| 177 | { | 179 | { |
| 178 | struct microcode_header *mc_header = mc; | 180 | struct microcode_header_intel *mc_header = mc; |
| 179 | struct extended_sigtable *ext_header = NULL; | 181 | struct extended_sigtable *ext_header = NULL; |
| 180 | struct extended_signature *ext_sig; | 182 | struct extended_signature *ext_sig; |
| 181 | unsigned long total_size, data_size, ext_table_size; | 183 | unsigned long total_size, data_size, ext_table_size; |
| @@ -260,7 +262,7 @@ int microcode_sanity_check(void *mc) | |||
| 260 | int get_matching_microcode(void *mc, int cpu) | 262 | int get_matching_microcode(void *mc, int cpu) |
| 261 | { | 263 | { |
| 262 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; | 264 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; |
| 263 | struct microcode_header *mc_header = mc; | 265 | struct microcode_header_intel *mc_header = mc; |
| 264 | struct extended_sigtable *ext_header; | 266 | struct extended_sigtable *ext_header; |
| 265 | unsigned long total_size = get_totalsize(mc_header); | 267 | unsigned long total_size = get_totalsize(mc_header); |
| 266 | int ext_sigcount, i; | 268 | int ext_sigcount, i; |
| @@ -294,10 +296,10 @@ find: | |||
| 294 | } | 296 | } |
| 295 | 297 | ||
| 296 | /* free previous update file */ | 298 | /* free previous update file */ |
| 297 | vfree(uci->mc); | 299 | vfree(uci->mc.mc_intel); |
| 298 | 300 | ||
| 299 | memcpy(new_mc, mc, total_size); | 301 | memcpy(new_mc, mc, total_size); |
| 300 | uci->mc = new_mc; | 302 | uci->mc.mc_intel = new_mc; |
| 301 | return 1; | 303 | return 1; |
| 302 | } | 304 | } |
| 303 | 305 | ||
| @@ -311,7 +313,7 @@ void apply_microcode(int cpu) | |||
| 311 | /* We should bind the task to the CPU */ | 313 | /* We should bind the task to the CPU */ |
| 312 | BUG_ON(cpu_num != cpu); | 314 | BUG_ON(cpu_num != cpu); |
| 313 | 315 | ||
| 314 | if (uci->mc == NULL) | 316 | if (uci->mc.mc_intel == NULL) |
| 315 | return; | 317 | return; |
| 316 | 318 | ||
| 317 | /* serialize access to the physical write to MSR 0x79 */ | 319 | /* serialize access to the physical write to MSR 0x79 */ |
| @@ -319,8 +321,8 @@ void apply_microcode(int cpu) | |||
| 319 | 321 | ||
| 320 | /* write microcode via MSR 0x79 */ | 322 | /* write microcode via MSR 0x79 */ |
| 321 | wrmsr(MSR_IA32_UCODE_WRITE, | 323 | wrmsr(MSR_IA32_UCODE_WRITE, |
| 322 | (unsigned long) uci->mc->bits, | 324 | (unsigned long) uci->mc.mc_intel->bits, |
| 323 | (unsigned long) uci->mc->bits >> 16 >> 16); | 325 | (unsigned long) uci->mc.mc_intel->bits >> 16 >> 16); |
| 324 | wrmsr(MSR_IA32_UCODE_REV, 0, 0); | 326 | wrmsr(MSR_IA32_UCODE_REV, 0, 0); |
| 325 | 327 | ||
| 326 | /* see notes above for revision 1.07. Apparent chip bug */ | 328 | /* see notes above for revision 1.07. Apparent chip bug */ |
| @@ -330,14 +332,14 @@ void apply_microcode(int cpu) | |||
| 330 | rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]); | 332 | rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]); |
| 331 | 333 | ||
| 332 | spin_unlock_irqrestore(µcode_update_lock, flags); | 334 | spin_unlock_irqrestore(µcode_update_lock, flags); |
| 333 | if (val[1] != uci->mc->hdr.rev) { | 335 | if (val[1] != uci->mc.mc_intel->hdr.rev) { |
| 334 | printk(KERN_ERR "microcode: CPU%d update from revision " | 336 | printk(KERN_ERR "microcode: CPU%d update from revision " |
| 335 | "0x%x to 0x%x failed\n", cpu_num, uci->rev, val[1]); | 337 | "0x%x to 0x%x failed\n", cpu_num, uci->rev, val[1]); |
| 336 | return; | 338 | return; |
| 337 | } | 339 | } |
| 338 | printk(KERN_INFO "microcode: CPU%d updated from revision " | 340 | printk(KERN_INFO "microcode: CPU%d updated from revision " |
| 339 | "0x%x to 0x%x, date = %08x \n", | 341 | "0x%x to 0x%x, date = %08x \n", |
| 340 | cpu_num, uci->rev, val[1], uci->mc->hdr.date); | 342 | cpu_num, uci->rev, val[1], uci->mc.mc_intel->hdr.date); |
| 341 | uci->rev = val[1]; | 343 | uci->rev = val[1]; |
| 342 | } | 344 | } |
| 343 | 345 | ||
| @@ -347,7 +349,7 @@ extern unsigned int user_buffer_size; /* it's size */ | |||
| 347 | 349 | ||
| 348 | long get_next_ucode(void **mc, long offset) | 350 | long get_next_ucode(void **mc, long offset) |
| 349 | { | 351 | { |
| 350 | struct microcode_header mc_header; | 352 | struct microcode_header_intel mc_header; |
| 351 | unsigned long total_size; | 353 | unsigned long total_size; |
| 352 | 354 | ||
| 353 | /* No more data */ | 355 | /* No more data */ |
| @@ -378,13 +380,13 @@ long get_next_ucode(void **mc, long offset) | |||
| 378 | static long get_next_ucode_from_buffer(void **mc, const u8 *buf, | 380 | static long get_next_ucode_from_buffer(void **mc, const u8 *buf, |
| 379 | unsigned long size, long offset) | 381 | unsigned long size, long offset) |
| 380 | { | 382 | { |
| 381 | struct microcode_header *mc_header; | 383 | struct microcode_header_intel *mc_header; |
| 382 | unsigned long total_size; | 384 | unsigned long total_size; |
| 383 | 385 | ||
| 384 | /* No more data */ | 386 | /* No more data */ |
| 385 | if (offset >= size) | 387 | if (offset >= size) |
| 386 | return 0; | 388 | return 0; |
| 387 | mc_header = (struct microcode_header *)(buf + offset); | 389 | mc_header = (struct microcode_header_intel *)(buf + offset); |
| 388 | total_size = get_totalsize(mc_header); | 390 | total_size = get_totalsize(mc_header); |
| 389 | 391 | ||
| 390 | if (offset + total_size > size) { | 392 | if (offset + total_size > size) { |
| @@ -463,7 +465,7 @@ int apply_microcode_check_cpu(int cpu) | |||
| 463 | int err = 0; | 465 | int err = 0; |
| 464 | 466 | ||
| 465 | /* Check if the microcode is available */ | 467 | /* Check if the microcode is available */ |
| 466 | if (!uci->mc) | 468 | if (!uci->mc.mc_intel) |
| 467 | return 0; | 469 | return 0; |
| 468 | 470 | ||
| 469 | old = current->cpus_allowed; | 471 | old = current->cpus_allowed; |
| @@ -508,7 +510,7 @@ void microcode_fini_cpu(int cpu) | |||
| 508 | 510 | ||
| 509 | mutex_lock(µcode_mutex); | 511 | mutex_lock(µcode_mutex); |
| 510 | uci->valid = 0; | 512 | uci->valid = 0; |
| 511 | kfree(uci->mc); | 513 | kfree(uci->mc.mc_intel); |
| 512 | uci->mc = NULL; | 514 | uci->mc.mc_intel = NULL; |
| 513 | mutex_unlock(µcode_mutex); | 515 | mutex_unlock(µcode_mutex); |
| 514 | } | 516 | } |
diff --git a/include/asm-x86/microcode.h b/include/asm-x86/microcode.h index d34a1fc1b173..ef77c6f438bf 100644 --- a/include/asm-x86/microcode.h +++ b/include/asm-x86/microcode.h | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | struct microcode_header { | 1 | struct microcode_header_intel { |
| 2 | unsigned int hdrver; | 2 | unsigned int hdrver; |
| 3 | unsigned int rev; | 3 | unsigned int rev; |
| 4 | unsigned int date; | 4 | unsigned int date; |
| @@ -11,8 +11,8 @@ struct microcode_header { | |||
| 11 | unsigned int reserved[3]; | 11 | unsigned int reserved[3]; |
| 12 | }; | 12 | }; |
| 13 | 13 | ||
| 14 | struct microcode { | 14 | struct microcode_intel { |
| 15 | struct microcode_header hdr; | 15 | struct microcode_header_intel hdr; |
| 16 | unsigned int bits[0]; | 16 | unsigned int bits[0]; |
| 17 | }; | 17 | }; |
| 18 | 18 | ||
| @@ -35,5 +35,7 @@ struct ucode_cpu_info { | |||
| 35 | unsigned int sig; | 35 | unsigned int sig; |
| 36 | unsigned int pf; | 36 | unsigned int pf; |
| 37 | unsigned int rev; | 37 | unsigned int rev; |
| 38 | struct microcode *mc; | 38 | union { |
| 39 | struct microcode_intel *mc_intel; | ||
| 40 | } mc; | ||
| 39 | }; | 41 | }; |
