ia64/xen-unstable

changeset 18505:879330497672

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 <keir.fraser@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Tue Sep 16 13:40:59 2008 +0100 (2008-09-16)
parents 88445b184dc6
children f163138e3340
files xen/arch/x86/microcode.c
line diff
     1.1 --- a/xen/arch/x86/microcode.c	Tue Sep 16 13:18:32 2008 +0100
     1.2 +++ b/xen/arch/x86/microcode.c	Tue Sep 16 13:40:59 2008 +0100
     1.3 @@ -42,14 +42,13 @@ static DEFINE_SPINLOCK(microcode_mutex);
     1.4  
     1.5  struct ucode_cpu_info ucode_cpu_info[NR_CPUS];
     1.6  
     1.7 -struct microcode_buffer {
     1.8 -    void *buf;
     1.9 -    size_t size;
    1.10 +struct microcode_info {
    1.11 +    unsigned int cpu;
    1.12 +    uint32_t buffer_size;
    1.13 +    int error;
    1.14 +    char buffer[1];
    1.15  };
    1.16  
    1.17 -static struct microcode_buffer microcode_buffer;
    1.18 -static bool_t microcode_error;
    1.19 -
    1.20  static void microcode_fini_cpu(int cpu)
    1.21  {
    1.22      struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
    1.23 @@ -108,14 +107,12 @@ static int microcode_resume_cpu(int cpu)
    1.24      return err;
    1.25  }
    1.26  
    1.27 -static int microcode_update_cpu(int cpu, const void *buf, size_t size)
    1.28 +static int microcode_update_cpu(const void *buf, size_t size)
    1.29  {
    1.30 -    int err = 0;
    1.31 +    int err;
    1.32 +    unsigned int cpu = smp_processor_id();
    1.33      struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
    1.34  
    1.35 -    /* We should bind the task to the CPU */
    1.36 -    BUG_ON(raw_smp_processor_id() != cpu);
    1.37 -
    1.38      spin_lock(&microcode_mutex);
    1.39  
    1.40      /*
    1.41 @@ -138,59 +135,49 @@ static int microcode_update_cpu(int cpu,
    1.42      return err;
    1.43  }
    1.44  
    1.45 -static void do_microcode_update_one(void *info)
    1.46 +static long do_microcode_update(void *_info)
    1.47  {
    1.48 -    int error = microcode_update_cpu(
    1.49 -        smp_processor_id(), microcode_buffer.buf, microcode_buffer.size);
    1.50 -    if ( error )
    1.51 -        microcode_error = error;
    1.52 -}
    1.53 +    struct microcode_info *info = _info;
    1.54 +    int error;
    1.55  
    1.56 -static int do_microcode_update(void)
    1.57 -{
    1.58 -    microcode_error = 0;
    1.59 +    BUG_ON(info->cpu != smp_processor_id());
    1.60  
    1.61 -    if ( on_each_cpu(do_microcode_update_one, NULL, 1, 1) != 0 )
    1.62 -    {
    1.63 -        printk(KERN_ERR "microcode: Error! Could not run on all processors\n");
    1.64 -        return -EIO;
    1.65 -    }
    1.66 +    error = microcode_update_cpu(info->buffer, info->buffer_size);
    1.67 +    if ( error )
    1.68 +        info->error = error;
    1.69  
    1.70 -    return microcode_error;
    1.71 +    info->cpu = next_cpu(info->cpu, cpu_online_map);
    1.72 +    if ( info->cpu >= NR_CPUS )
    1.73 +        return info->error;
    1.74 +
    1.75 +    return continue_hypercall_on_cpu(info->cpu, do_microcode_update, info);
    1.76  }
    1.77  
    1.78  int microcode_update(XEN_GUEST_HANDLE(const_void) buf, unsigned long len)
    1.79  {
    1.80      int ret;
    1.81 -
    1.82 -    /* XXX FIXME: No allocations in interrupt context. */
    1.83 -    return -EINVAL;
    1.84 +    struct microcode_info *info;
    1.85  
    1.86 -    if ( len != (typeof(microcode_buffer.size))len )
    1.87 -    {
    1.88 -        printk(KERN_ERR "microcode: too much data\n");
    1.89 +    if ( len != (uint32_t)len )
    1.90          return -E2BIG;
    1.91 -    }
    1.92  
    1.93      if ( microcode_ops == NULL )
    1.94          return -EINVAL;
    1.95  
    1.96 -    microcode_buffer.buf = xmalloc_array(uint8_t, len);
    1.97 -    if ( microcode_buffer.buf == NULL )
    1.98 +    info = xmalloc_bytes(sizeof(*info) + len);
    1.99 +    if ( info == NULL )
   1.100          return -ENOMEM;
   1.101  
   1.102 -    ret = copy_from_guest(microcode_buffer.buf, buf, len);
   1.103 +    ret = copy_from_guest(info->buffer, buf, len);
   1.104      if ( ret != 0 )
   1.105 +    {
   1.106 +        xfree(info);
   1.107          return ret;
   1.108 -
   1.109 -    microcode_buffer.size = len;
   1.110 -    wmb();
   1.111 +    }
   1.112  
   1.113 -    ret = do_microcode_update();
   1.114 +    info->buffer_size = len;
   1.115 +    info->error = 0;
   1.116 +    info->cpu = first_cpu(cpu_online_map);
   1.117  
   1.118 -    xfree(microcode_buffer.buf);
   1.119 -    microcode_buffer.buf = NULL;
   1.120 -    microcode_buffer.size = 0;
   1.121 -
   1.122 -    return ret;
   1.123 +    return continue_hypercall_on_cpu(info->cpu, do_microcode_update, info);
   1.124  }