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; }