xen/x86-microcode.patch

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(&microcode_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(&microcode_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;
}