# HG changeset patch # User Keir Fraser # Date 1221568859 -3600 # Node ID 879330497672d96ee966c9774d21c437895f6839 # Parent 88445b184dc666fc196cffab19eac75cd9c10b87 x86, microcode: Do not run microcode update in IRQ context. It's unnecessary, and also invalid since the update process tries to allocate memory. Signed-off-by: Keir Fraser Index: xen-3.3.1-testing/xen/arch/x86/microcode.c =================================================================== --- xen-3.3.1-testing.orig/xen/arch/x86/microcode.c +++ xen-3.3.1-testing/xen/arch/x86/microcode.c @@ -45,14 +45,13 @@ static DEFINE_SPINLOCK(microcode_mutex); struct ucode_cpu_info ucode_cpu_info[NR_CPUS]; -struct microcode_buffer { - void *buf; - size_t size; +struct microcode_info { + unsigned int cpu; + uint32_t buffer_size; + int error; + char buffer[1]; }; -static struct microcode_buffer microcode_buffer; -static bool_t microcode_error; - static void microcode_fini_cpu(int cpu) { struct ucode_cpu_info *uci = ucode_cpu_info + cpu; @@ -110,14 +109,12 @@ static int microcode_resume_cpu(int cpu) return err; } -static int microcode_update_cpu(int cpu, const void *buf, size_t size) +static int microcode_update_cpu(const void *buf, size_t size) { - int err = 0; + int err; + unsigned int cpu = smp_processor_id(); struct ucode_cpu_info *uci = ucode_cpu_info + cpu; - /* We should bind the task to the CPU */ - BUG_ON(raw_smp_processor_id() != cpu); - spin_lock(µcode_mutex); /* @@ -140,72 +137,50 @@ static int microcode_update_cpu(int cpu, return err; } -static void do_microcode_update_one(void *info) +static long do_microcode_update(void *_info) { + struct microcode_info *info = _info; int error; - error = microcode_update_cpu( - smp_processor_id(), microcode_buffer.buf, microcode_buffer.size); + BUG_ON(info->cpu != smp_processor_id()); - if ( error ) - microcode_error = error; -} + error = microcode_update_cpu(info->buffer, info->buffer_size); -static int do_microcode_update(void) -{ - int error = 0; - - microcode_error = 0; - - if ( on_each_cpu(do_microcode_update_one, NULL, 1, 1) != 0 ) - { - printk(KERN_ERR "microcode: Error! Could not run on all processors\n"); - error = -EIO; - goto out; - } + if ( error ) + info->error = error; - if ( microcode_error ) - { - error = microcode_error; - goto out; - } + info->cpu = next_cpu(info->cpu, cpu_online_map); + if ( info->cpu >= NR_CPUS ) + return info->error; - out: - return error; + return continue_hypercall_on_cpu(info->cpu, do_microcode_update, info); } int microcode_update(XEN_GUEST_HANDLE(const_void) buf, unsigned long len) { int ret; + struct microcode_info *info; - /* XXX FIXME: No allocations in interrupt context. */ - return -EINVAL; - - if ( len != (typeof(microcode_buffer.size))len ) - { - printk(KERN_ERR "microcode: too much data\n"); + if ( len != (uint32_t)len ) return -E2BIG; - } if (microcode_ops == NULL) return -EINVAL; - microcode_buffer.buf = xmalloc_array(uint8_t, len); - if ( microcode_buffer.buf == NULL ) + info = xmalloc_bytes(sizeof(*info) + len); + if ( info == NULL ) return -ENOMEM; - ret = copy_from_guest(microcode_buffer.buf, buf, len); + ret = copy_from_guest(info->buffer, buf, len); if ( ret != 0 ) + { + xfree(info); return ret; + } - microcode_buffer.size = len; - wmb(); - - ret = do_microcode_update(); - - xfree(microcode_buffer.buf); - microcode_buffer.buf = NULL; - microcode_buffer.size = 0; + info->buffer_size = len; + info->error = 0; + info->cpu = first_cpu(cpu_online_map); - return ret; + return continue_hypercall_on_cpu(info->cpu, do_microcode_update, info); }