ia64/xen-unstable
annotate xen/arch/x86/microcode.c @ 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>
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 | 3eb7a0cfffc2 |
children | f163138e3340 |
rev | line source |
---|---|
kaf24@3362 | 1 /* |
keir@18497 | 2 * Intel CPU Microcode Update Driver for Linux |
keir@18489 | 3 * |
keir@18497 | 4 * Copyright (C) 2000-2006 Tigran Aivazian <tigran@aivazian.fsnet.co.uk> |
keir@18497 | 5 * 2006 Shaohua Li <shaohua.li@intel.com> * |
keir@18497 | 6 * This driver allows to upgrade microcode on Intel processors |
keir@18497 | 7 * belonging to IA-32 family - PentiumPro, Pentium II, |
keir@18497 | 8 * Pentium III, Xeon, Pentium 4, etc. |
keir@18497 | 9 * |
keir@18497 | 10 * Reference: Section 8.11 of Volume 3a, IA-32 Intel? Architecture |
keir@18497 | 11 * Software Developer's Manual |
keir@18497 | 12 * Order Number 253668 or free download from: |
keir@18497 | 13 * |
keir@18497 | 14 * http://developer.intel.com/design/pentium4/manuals/253668.htm |
keir@18497 | 15 * |
keir@18497 | 16 * For more information, go to http://www.urbanmyth.org/microcode |
keir@18497 | 17 * |
keir@18497 | 18 * This program is free software; you can redistribute it and/or |
keir@18497 | 19 * modify it under the terms of the GNU General Public License |
keir@18497 | 20 * as published by the Free Software Foundation; either version |
keir@18497 | 21 * 2 of the License, or (at your option) any later version. |
kaf24@3362 | 22 */ |
kaf24@3362 | 23 |
kaf24@3362 | 24 #include <xen/config.h> |
cl349@5285 | 25 #include <xen/lib.h> |
kaf24@3362 | 26 #include <xen/kernel.h> |
kaf24@3362 | 27 #include <xen/init.h> |
kaf24@3362 | 28 #include <xen/sched.h> |
cl349@5287 | 29 #include <xen/smp.h> |
kaf24@3362 | 30 #include <xen/spinlock.h> |
keir@18489 | 31 #include <xen/guest_access.h> |
kaf24@3362 | 32 |
cl349@5291 | 33 #include <asm/current.h> |
kaf24@3362 | 34 #include <asm/msr.h> |
kaf24@3362 | 35 #include <asm/uaccess.h> |
kaf24@3362 | 36 #include <asm/processor.h> |
keir@18489 | 37 #include <asm/microcode.h> |
kaf24@3362 | 38 |
keir@18489 | 39 const struct microcode_ops *microcode_ops; |
kaf24@3362 | 40 |
keir@18489 | 41 static DEFINE_SPINLOCK(microcode_mutex); |
kaf24@3362 | 42 |
keir@18489 | 43 struct ucode_cpu_info ucode_cpu_info[NR_CPUS]; |
keir@18489 | 44 |
keir@18505 | 45 struct microcode_info { |
keir@18505 | 46 unsigned int cpu; |
keir@18505 | 47 uint32_t buffer_size; |
keir@18505 | 48 int error; |
keir@18505 | 49 char buffer[1]; |
keir@18489 | 50 }; |
keir@18489 | 51 |
keir@18489 | 52 static void microcode_fini_cpu(int cpu) |
kaf24@3362 | 53 { |
keir@18497 | 54 struct ucode_cpu_info *uci = ucode_cpu_info + cpu; |
kaf24@3362 | 55 |
keir@18497 | 56 spin_lock(µcode_mutex); |
keir@18499 | 57 xfree(uci->mc.valid_mc); |
keir@18499 | 58 uci->mc.valid_mc = NULL; |
keir@18497 | 59 uci->valid = 0; |
keir@18497 | 60 spin_unlock(µcode_mutex); |
keir@18489 | 61 } |
kaf24@3362 | 62 |
keir@18489 | 63 static int collect_cpu_info(int cpu) |
keir@18489 | 64 { |
keir@18497 | 65 int err = 0; |
keir@18497 | 66 struct ucode_cpu_info *uci = ucode_cpu_info + cpu; |
keir@18489 | 67 |
keir@18497 | 68 memset(uci, 0, sizeof(*uci)); |
keir@18497 | 69 err = microcode_ops->collect_cpu_info(cpu, &uci->cpu_sig); |
keir@18497 | 70 if ( !err ) |
keir@18497 | 71 uci->valid = 1; |
keir@18489 | 72 |
keir@18497 | 73 return err; |
keir@18489 | 74 } |
keir@18489 | 75 |
keir@18489 | 76 static int microcode_resume_cpu(int cpu) |
keir@18489 | 77 { |
keir@18497 | 78 int err = 0; |
keir@18497 | 79 struct ucode_cpu_info *uci = ucode_cpu_info + cpu; |
keir@18497 | 80 struct cpu_signature nsig; |
keir@18489 | 81 |
keir@18497 | 82 gdprintk(XENLOG_INFO, "microcode: CPU%d resumed\n", cpu); |
kaf24@3362 | 83 |
keir@18497 | 84 if ( !uci->mc.valid_mc ) |
keir@18497 | 85 return -EIO; |
keir@18489 | 86 |
keir@18497 | 87 /* |
keir@18497 | 88 * Let's verify that the 'cached' ucode does belong |
keir@18497 | 89 * to this cpu (a bit of paranoia): |
keir@18497 | 90 */ |
keir@18497 | 91 err = microcode_ops->collect_cpu_info(cpu, &nsig); |
keir@18497 | 92 if ( err ) |
keir@18497 | 93 { |
keir@18497 | 94 microcode_fini_cpu(cpu); |
keir@18497 | 95 return err; |
keir@18497 | 96 } |
keir@18489 | 97 |
keir@18497 | 98 if ( memcmp(&nsig, &uci->cpu_sig, sizeof(nsig)) ) |
keir@18497 | 99 { |
keir@18497 | 100 microcode_fini_cpu(cpu); |
keir@18497 | 101 /* Should we look for a new ucode here? */ |
keir@18497 | 102 return -EIO; |
keir@18497 | 103 } |
keir@18497 | 104 |
keir@18497 | 105 err = microcode_ops->apply_microcode(cpu); |
keir@18497 | 106 |
keir@18497 | 107 return err; |
kaf24@3362 | 108 } |
kaf24@3362 | 109 |
keir@18505 | 110 static int microcode_update_cpu(const void *buf, size_t size) |
kaf24@3362 | 111 { |
keir@18505 | 112 int err; |
keir@18505 | 113 unsigned int cpu = smp_processor_id(); |
keir@18497 | 114 struct ucode_cpu_info *uci = ucode_cpu_info + cpu; |
keir@18489 | 115 |
keir@18497 | 116 spin_lock(µcode_mutex); |
keir@18489 | 117 |
keir@18497 | 118 /* |
keir@18497 | 119 * Check if the system resume is in progress (uci->valid != NULL), |
keir@18497 | 120 * otherwise just request a firmware: |
keir@18497 | 121 */ |
keir@18497 | 122 if ( uci->valid ) |
keir@18497 | 123 { |
keir@18497 | 124 err = microcode_resume_cpu(cpu); |
keir@18497 | 125 } |
keir@18497 | 126 else |
keir@18497 | 127 { |
keir@18497 | 128 err = collect_cpu_info(cpu); |
keir@18497 | 129 if ( !err && uci->valid ) |
keir@18497 | 130 err = microcode_ops->cpu_request_microcode(cpu, buf, size); |
keir@18497 | 131 } |
keir@18497 | 132 |
keir@18497 | 133 spin_unlock(µcode_mutex); |
keir@18497 | 134 |
keir@18497 | 135 return err; |
kaf24@3362 | 136 } |
kaf24@3362 | 137 |
keir@18505 | 138 static long do_microcode_update(void *_info) |
kaf24@3362 | 139 { |
keir@18505 | 140 struct microcode_info *info = _info; |
keir@18505 | 141 int error; |
kaf24@3362 | 142 |
keir@18505 | 143 BUG_ON(info->cpu != smp_processor_id()); |
kaf24@3362 | 144 |
keir@18505 | 145 error = microcode_update_cpu(info->buffer, info->buffer_size); |
keir@18505 | 146 if ( error ) |
keir@18505 | 147 info->error = error; |
kaf24@3362 | 148 |
keir@18505 | 149 info->cpu = next_cpu(info->cpu, cpu_online_map); |
keir@18505 | 150 if ( info->cpu >= NR_CPUS ) |
keir@18505 | 151 return info->error; |
keir@18505 | 152 |
keir@18505 | 153 return continue_hypercall_on_cpu(info->cpu, do_microcode_update, info); |
kaf24@3362 | 154 } |
kaf24@3362 | 155 |
keir@18417 | 156 int microcode_update(XEN_GUEST_HANDLE(const_void) buf, unsigned long len) |
kaf24@3362 | 157 { |
keir@18497 | 158 int ret; |
keir@18505 | 159 struct microcode_info *info; |
keir@18489 | 160 |
keir@18505 | 161 if ( len != (uint32_t)len ) |
keir@18497 | 162 return -E2BIG; |
kfraser@10545 | 163 |
keir@18499 | 164 if ( microcode_ops == NULL ) |
keir@18497 | 165 return -EINVAL; |
kfraser@10545 | 166 |
keir@18505 | 167 info = xmalloc_bytes(sizeof(*info) + len); |
keir@18505 | 168 if ( info == NULL ) |
keir@18497 | 169 return -ENOMEM; |
keir@18497 | 170 |
keir@18505 | 171 ret = copy_from_guest(info->buffer, buf, len); |
keir@18497 | 172 if ( ret != 0 ) |
keir@18505 | 173 { |
keir@18505 | 174 xfree(info); |
keir@18497 | 175 return ret; |
keir@18505 | 176 } |
keir@18497 | 177 |
keir@18505 | 178 info->buffer_size = len; |
keir@18505 | 179 info->error = 0; |
keir@18505 | 180 info->cpu = first_cpu(cpu_online_map); |
keir@18497 | 181 |
keir@18505 | 182 return continue_hypercall_on_cpu(info->cpu, do_microcode_update, info); |
kaf24@3362 | 183 } |