142 lines
4.5 KiB
Diff
142 lines
4.5 KiB
Diff
|
Index: xen-3.3.0-testing/xen/arch/x86/microcode.c
|
||
|
===================================================================
|
||
|
--- xen-3.3.0-testing.orig/xen/arch/x86/microcode.c
|
||
|
+++ xen-3.3.0-testing/xen/arch/x86/microcode.c
|
||
|
@@ -98,7 +98,7 @@ MODULE_LICENSE("GPL");
|
||
|
static int verbose;
|
||
|
boolean_param("microcode.verbose", verbose);
|
||
|
|
||
|
-#define MICROCODE_VERSION "1.14a"
|
||
|
+#define MICROCODE_VERSION "1.14b"
|
||
|
|
||
|
#define DEFAULT_UCODE_DATASIZE (2000) /* 2000 bytes */
|
||
|
#define MC_HEADER_SIZE (sizeof (microcode_header_t)) /* 48 bytes */
|
||
|
@@ -118,9 +118,6 @@ boolean_param("microcode.verbose", verbo
|
||
|
|
||
|
#define exttable_size(et) ((et)->count * EXT_SIGNATURE_SIZE + EXT_HEADER_SIZE)
|
||
|
|
||
|
-/* serialize access to the physical write to MSR 0x79 */
|
||
|
-static DEFINE_SPINLOCK(microcode_update_lock);
|
||
|
-
|
||
|
/* no concurrent ->write()s are allowed on /dev/cpu/microcode */
|
||
|
static DEFINE_MUTEX(microcode_mutex);
|
||
|
|
||
|
@@ -376,25 +373,10 @@ out:
|
||
|
|
||
|
static void do_update_one (void * unused)
|
||
|
{
|
||
|
- unsigned long flags;
|
||
|
unsigned int val[2];
|
||
|
int cpu_num = smp_processor_id();
|
||
|
struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
|
||
|
|
||
|
- if (uci->mc == NULL) {
|
||
|
- if (verbose) {
|
||
|
- if (uci->err == MC_SUCCESS)
|
||
|
- printk(KERN_INFO "microcode: CPU%d already at revision 0x%x\n",
|
||
|
- cpu_num, uci->rev);
|
||
|
- else
|
||
|
- printk(KERN_INFO "microcode: No new microcode data for CPU%d\n", cpu_num);
|
||
|
- }
|
||
|
- return;
|
||
|
- }
|
||
|
-
|
||
|
- /* serialize access to the physical write to MSR 0x79 */
|
||
|
- spin_lock_irqsave(µcode_update_lock, flags);
|
||
|
-
|
||
|
/* write microcode via MSR 0x79 */
|
||
|
wrmsr(MSR_IA32_UCODE_WRITE,
|
||
|
(unsigned long) uci->mc->bits,
|
||
|
@@ -409,7 +391,6 @@ static void do_update_one (void * unused
|
||
|
|
||
|
/* notify the caller of success on this cpu */
|
||
|
uci->err = MC_SUCCESS;
|
||
|
- spin_unlock_irqrestore(µcode_update_lock, flags);
|
||
|
printk(KERN_INFO "microcode: CPU%d updated from revision "
|
||
|
"0x%x to 0x%x, date = %08x \n",
|
||
|
cpu_num, uci->rev, val[1], uci->mc->hdr.date);
|
||
|
@@ -418,40 +399,65 @@ static void do_update_one (void * unused
|
||
|
|
||
|
static int do_microcode_update (void)
|
||
|
{
|
||
|
- int i, error;
|
||
|
+ int i, j, error;
|
||
|
+ cpumask_t cpu_mask = cpu_online_map;
|
||
|
|
||
|
- if (on_each_cpu(collect_cpu_info, NULL, 1, 1) != 0) {
|
||
|
- printk(KERN_ERR "microcode: Error! Could not run on all processors\n");
|
||
|
- error = -EIO;
|
||
|
- goto out;
|
||
|
+ for_each_cpu_mask(i, cpu_mask) {
|
||
|
+ if (on_selected_cpus(cpumask_of_cpu(i), collect_cpu_info, NULL, 1, 1) != 0) {
|
||
|
+ printk(KERN_ERR "microcode: Error! Could not run on all processors\n");
|
||
|
+ return -EIO;
|
||
|
+ }
|
||
|
}
|
||
|
|
||
|
if ((error = find_matching_ucodes())) {
|
||
|
printk(KERN_ERR "microcode: Error in the microcode data\n");
|
||
|
- goto out_free;
|
||
|
+ cpus_clear(cpu_mask);
|
||
|
}
|
||
|
|
||
|
- if (on_each_cpu(do_update_one, NULL, 1, 1) != 0) {
|
||
|
- printk(KERN_ERR "microcode: Error! Could not run on all processors\n");
|
||
|
- error = -EIO;
|
||
|
+ for (; (i = any_online_cpu(cpu_mask)) < NR_CPUS; cpu_clear(i, cpu_mask)) {
|
||
|
+ if (ucode_cpu_info[i].mc == NULL) {
|
||
|
+ if (verbose) {
|
||
|
+ switch (ucode_cpu_info[i].err) {
|
||
|
+ case MC_SUCCESS:
|
||
|
+ printk(KERN_INFO "microcode: CPU%d already at revision 0x%x\n",
|
||
|
+ i, ucode_cpu_info[i].rev);
|
||
|
+ break;
|
||
|
+ case MC_IGNORED:
|
||
|
+ printk(KERN_WARNING "microcode: CPU%d not 'upgrading' to earlier revision"
|
||
|
+ " 0x%x (current=0x%x)\n", i, ucode_cpu_info[i].cksum, ucode_cpu_info[i].rev);
|
||
|
+ break;
|
||
|
+ default:
|
||
|
+ printk(KERN_INFO "microcode: No new microcode data for CPU%d\n", i);
|
||
|
+ break;
|
||
|
+ }
|
||
|
+ }
|
||
|
+ } else if (on_selected_cpus(cpumask_of_cpu(i), do_update_one, NULL, 1, 1) != 0) {
|
||
|
+ printk(KERN_ERR "microcode: Error! Could not run on processor %d\n", i);
|
||
|
+ error = -EIO;
|
||
|
+ } else if (ucode_cpu_info[i].err == MC_SUCCESS) {
|
||
|
+ cpus_andnot(cpu_mask, cpu_mask, cpu_sibling_map[i]);
|
||
|
+ for_each_cpu_mask(j, cpu_sibling_map[i]) {
|
||
|
+ if (j != i) {
|
||
|
+ ucode_cpu_info[j].err = MC_SUCCESS;
|
||
|
+ ASSERT(ucode_cpu_info[j].mc == ucode_cpu_info[i].mc);
|
||
|
+ ucode_cpu_info[j].mc = NULL;
|
||
|
+ }
|
||
|
+ }
|
||
|
+ }
|
||
|
}
|
||
|
|
||
|
-out_free:
|
||
|
- for_each_online_cpu(i) {
|
||
|
+ for (i = 0; i < NR_CPUS; i++) {
|
||
|
if (ucode_cpu_info[i].mc) {
|
||
|
- int j;
|
||
|
void *tmp = ucode_cpu_info[i].mc;
|
||
|
- vfree(tmp);
|
||
|
- for_each_online_cpu(j) {
|
||
|
+
|
||
|
+ for (j = 0; j < NR_CPUS; j++) {
|
||
|
if (ucode_cpu_info[j].mc == tmp)
|
||
|
ucode_cpu_info[j].mc = NULL;
|
||
|
}
|
||
|
+ vfree(tmp);
|
||
|
}
|
||
|
- if (ucode_cpu_info[i].err == MC_IGNORED && verbose)
|
||
|
- printk(KERN_WARNING "microcode: CPU%d not 'upgrading' to earlier revision"
|
||
|
- " 0x%x (current=0x%x)\n", i, ucode_cpu_info[i].cksum, ucode_cpu_info[i].rev);
|
||
|
}
|
||
|
-out:
|
||
|
+
|
||
|
return error;
|
||
|
}
|
||
|
|