aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorShaohua Li <shaohua.li@intel.com>2006-09-27 04:50:51 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-09-27 11:26:18 -0400
commit9a3110bf4bb0466b43b898533bfd4952001bc38f (patch)
treea2a9c94564562fda7fb8ca2bbec9611e094ed1f6 /arch
parent36b756f2b5762e6d5acba0c18e75cb5c11f11c1b (diff)
[PATCH] x86 microcode: microcode driver cleanup.
Clean up microcode update driver and make it more readable. [akpm@osdl.org: cleanups] Signed-off-by: Shaohua Li <shaohua.li@intel.com> Acked-by: Tigran Aivazian <tigran@veritas.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/i386/Kconfig5
-rw-r--r--arch/i386/kernel/microcode.c508
-rw-r--r--arch/x86_64/Kconfig5
3 files changed, 260 insertions, 258 deletions
diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig
index 3fd9f1e8b093..0cbeb26ac3fb 100644
--- a/arch/i386/Kconfig
+++ b/arch/i386/Kconfig
@@ -416,6 +416,11 @@ config MICROCODE
416 To compile this driver as a module, choose M here: the 416 To compile this driver as a module, choose M here: the
417 module will be called microcode. 417 module will be called microcode.
418 418
419config MICROCODE_OLD_INTERFACE
420 bool
421 depends on MICROCODE
422 default y
423
419config X86_MSR 424config X86_MSR
420 tristate "/dev/cpu/*/msr - Model-specific register support" 425 tristate "/dev/cpu/*/msr - Model-specific register support"
421 help 426 help
diff --git a/arch/i386/kernel/microcode.c b/arch/i386/kernel/microcode.c
index 40b44cc0d14b..00bdc3dd693e 100644
--- a/arch/i386/kernel/microcode.c
+++ b/arch/i386/kernel/microcode.c
@@ -2,6 +2,7 @@
2 * Intel CPU Microcode Update Driver for Linux 2 * Intel CPU Microcode Update Driver for Linux
3 * 3 *
4 * Copyright (C) 2000-2004 Tigran Aivazian 4 * Copyright (C) 2000-2004 Tigran Aivazian
5 * 2006 Shaohua Li <shaohua.li@intel.com>
5 * 6 *
6 * This driver allows to upgrade microcode on Intel processors 7 * This driver allows to upgrade microcode on Intel processors
7 * belonging to IA-32 family - PentiumPro, Pentium II, 8 * belonging to IA-32 family - PentiumPro, Pentium II,
@@ -91,9 +92,6 @@ MODULE_DESCRIPTION("Intel CPU (IA-32) Microcode Update Driver");
91MODULE_AUTHOR("Tigran Aivazian <tigran@veritas.com>"); 92MODULE_AUTHOR("Tigran Aivazian <tigran@veritas.com>");
92MODULE_LICENSE("GPL"); 93MODULE_LICENSE("GPL");
93 94
94static int verbose;
95module_param(verbose, int, 0644);
96
97#define MICROCODE_VERSION "1.14a" 95#define MICROCODE_VERSION "1.14a"
98 96
99#define DEFAULT_UCODE_DATASIZE (2000) /* 2000 bytes */ 97#define DEFAULT_UCODE_DATASIZE (2000) /* 2000 bytes */
@@ -120,55 +118,40 @@ static DEFINE_SPINLOCK(microcode_update_lock);
120/* no concurrent ->write()s are allowed on /dev/cpu/microcode */ 118/* no concurrent ->write()s are allowed on /dev/cpu/microcode */
121static DEFINE_MUTEX(microcode_mutex); 119static DEFINE_MUTEX(microcode_mutex);
122 120
123static void __user *user_buffer; /* user area microcode data buffer */
124static unsigned int user_buffer_size; /* it's size */
125
126typedef enum mc_error_code {
127 MC_SUCCESS = 0,
128 MC_IGNORED = 1,
129 MC_NOTFOUND = 2,
130 MC_MARKED = 3,
131 MC_ALLOCATED = 4,
132} mc_error_code_t;
133
134static struct ucode_cpu_info { 121static struct ucode_cpu_info {
122 int valid;
135 unsigned int sig; 123 unsigned int sig;
136 unsigned int pf, orig_pf; 124 unsigned int pf;
137 unsigned int rev; 125 unsigned int rev;
138 unsigned int cksum;
139 mc_error_code_t err;
140 microcode_t *mc; 126 microcode_t *mc;
141} ucode_cpu_info[NR_CPUS]; 127} ucode_cpu_info[NR_CPUS];
142
143static int microcode_open (struct inode *unused1, struct file *unused2)
144{
145 return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
146}
147 128
148static void collect_cpu_info (void *unused) 129static void collect_cpu_info(int cpu_num)
149{ 130{
150 int cpu_num = smp_processor_id();
151 struct cpuinfo_x86 *c = cpu_data + cpu_num; 131 struct cpuinfo_x86 *c = cpu_data + cpu_num;
152 struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; 132 struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
153 unsigned int val[2]; 133 unsigned int val[2];
154 134
155 uci->sig = uci->pf = uci->rev = uci->cksum = 0; 135 /* We should bind the task to the CPU */
156 uci->err = MC_NOTFOUND; 136 BUG_ON(raw_smp_processor_id() != cpu_num);
137 uci->pf = uci->rev = 0;
157 uci->mc = NULL; 138 uci->mc = NULL;
139 uci->valid = 1;
158 140
159 if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 || 141 if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 ||
160 cpu_has(c, X86_FEATURE_IA64)) { 142 cpu_has(c, X86_FEATURE_IA64)) {
161 printk(KERN_ERR "microcode: CPU%d not a capable Intel processor\n", cpu_num); 143 printk(KERN_ERR "microcode: CPU%d not a capable Intel "
144 "processor\n", cpu_num);
145 uci->valid = 0;
162 return; 146 return;
163 } else { 147 }
164 uci->sig = cpuid_eax(0x00000001);
165 148
166 if ((c->x86_model >= 5) || (c->x86 > 6)) { 149 uci->sig = cpuid_eax(0x00000001);
167 /* get processor flags from MSR 0x17 */ 150
168 rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]); 151 if ((c->x86_model >= 5) || (c->x86 > 6)) {
169 uci->pf = 1 << ((val[1] >> 18) & 7); 152 /* get processor flags from MSR 0x17 */
170 } 153 rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
171 uci->orig_pf = uci->pf; 154 uci->pf = 1 << ((val[1] >> 18) & 7);
172 } 155 }
173 156
174 wrmsr(MSR_IA32_UCODE_REV, 0, 0); 157 wrmsr(MSR_IA32_UCODE_REV, 0, 0);
@@ -180,218 +163,160 @@ static void collect_cpu_info (void *unused)
180 uci->sig, uci->pf, uci->rev); 163 uci->sig, uci->pf, uci->rev);
181} 164}
182 165
183static inline void mark_microcode_update (int cpu_num, microcode_header_t *mc_header, int sig, int pf, int cksum) 166static inline int microcode_update_match(int cpu_num,
167 microcode_header_t *mc_header, int sig, int pf)
184{ 168{
185 struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; 169 struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
186 170
187 pr_debug("Microcode Found.\n"); 171 if (!sigmatch(sig, uci->sig, pf, uci->pf)
188 pr_debug(" Header Revision 0x%x\n", mc_header->hdrver); 172 || mc_header->rev <= uci->rev)
189 pr_debug(" Loader Revision 0x%x\n", mc_header->ldrver); 173 return 0;
190 pr_debug(" Revision 0x%x \n", mc_header->rev); 174 return 1;
191 pr_debug(" Date %x/%x/%x\n",
192 ((mc_header->date >> 24 ) & 0xff),
193 ((mc_header->date >> 16 ) & 0xff),
194 (mc_header->date & 0xFFFF));
195 pr_debug(" Signature 0x%x\n", sig);
196 pr_debug(" Type 0x%x Family 0x%x Model 0x%x Stepping 0x%x\n",
197 ((sig >> 12) & 0x3),
198 ((sig >> 8) & 0xf),
199 ((sig >> 4) & 0xf),
200 ((sig & 0xf)));
201 pr_debug(" Processor Flags 0x%x\n", pf);
202 pr_debug(" Checksum 0x%x\n", cksum);
203
204 if (mc_header->rev < uci->rev) {
205 if (uci->err == MC_NOTFOUND) {
206 uci->err = MC_IGNORED;
207 uci->cksum = mc_header->rev;
208 } else if (uci->err == MC_IGNORED && uci->cksum < mc_header->rev)
209 uci->cksum = mc_header->rev;
210 } else if (mc_header->rev == uci->rev) {
211 if (uci->err < MC_MARKED) {
212 /* notify the caller of success on this cpu */
213 uci->err = MC_SUCCESS;
214 }
215 } else if (uci->err != MC_ALLOCATED || mc_header->rev > uci->mc->hdr.rev) {
216 pr_debug("microcode: CPU%d found a matching microcode update with "
217 " revision 0x%x (current=0x%x)\n", cpu_num, mc_header->rev, uci->rev);
218 uci->cksum = cksum;
219 uci->pf = pf; /* keep the original mc pf for cksum calculation */
220 uci->err = MC_MARKED; /* found the match */
221 for_each_online_cpu(cpu_num) {
222 if (ucode_cpu_info + cpu_num != uci
223 && ucode_cpu_info[cpu_num].mc == uci->mc) {
224 uci->mc = NULL;
225 break;
226 }
227 }
228 if (uci->mc != NULL) {
229 vfree(uci->mc);
230 uci->mc = NULL;
231 }
232 }
233 return;
234} 175}
235 176
236static int find_matching_ucodes (void) 177static int microcode_sanity_check(void *mc)
237{ 178{
238 int cursor = 0; 179 microcode_header_t *mc_header = mc;
239 int error = 0; 180 struct extended_sigtable *ext_header = NULL;
240 181 struct extended_signature *ext_sig;
241 while (cursor + MC_HEADER_SIZE < user_buffer_size) { 182 unsigned long total_size, data_size, ext_table_size;
242 microcode_header_t mc_header; 183 int sum, orig_sum, ext_sigcount = 0, i;
243 void *newmc = NULL; 184
244 int i, sum, cpu_num, allocated_flag, total_size, data_size, ext_table_size; 185 total_size = get_totalsize(mc_header);
186 data_size = get_datasize(mc_header);
187 if ((data_size + MC_HEADER_SIZE > total_size)
188 || (data_size < DEFAULT_UCODE_DATASIZE)) {
189 printk(KERN_ERR "microcode: error! "
190 "Bad data size in microcode data file\n");
191 return -EINVAL;
192 }
245 193
246 if (copy_from_user(&mc_header, user_buffer + cursor, MC_HEADER_SIZE)) { 194 if (mc_header->ldrver != 1 || mc_header->hdrver != 1) {
247 printk(KERN_ERR "microcode: error! Can not read user data\n"); 195 printk(KERN_ERR "microcode: error! "
248 error = -EFAULT; 196 "Unknown microcode update format\n");
249 goto out; 197 return -EINVAL;
198 }
199 ext_table_size = total_size - (MC_HEADER_SIZE + data_size);
200 if (ext_table_size) {
201 if ((ext_table_size < EXT_HEADER_SIZE)
202 || ((ext_table_size - EXT_HEADER_SIZE) % EXT_SIGNATURE_SIZE)) {
203 printk(KERN_ERR "microcode: error! "
204 "Small exttable size in microcode data file\n");
205 return -EINVAL;
250 } 206 }
251 207 ext_header = mc + MC_HEADER_SIZE + data_size;
252 total_size = get_totalsize(&mc_header); 208 if (ext_table_size != exttable_size(ext_header)) {
253 if ((cursor + total_size > user_buffer_size) || (total_size < DEFAULT_UCODE_TOTALSIZE)) { 209 printk(KERN_ERR "microcode: error! "
254 printk(KERN_ERR "microcode: error! Bad data in microcode data file\n"); 210 "Bad exttable size in microcode data file\n");
255 error = -EINVAL; 211 return -EFAULT;
256 goto out;
257 } 212 }
213 ext_sigcount = ext_header->count;
214 }
258 215
259 data_size = get_datasize(&mc_header); 216 /* check extended table checksum */
260 if ((data_size + MC_HEADER_SIZE > total_size) || (data_size < DEFAULT_UCODE_DATASIZE)) { 217 if (ext_table_size) {
261 printk(KERN_ERR "microcode: error! Bad data in microcode data file\n"); 218 int ext_table_sum = 0;
262 error = -EINVAL; 219 int * ext_tablep = (int *)ext_header;
263 goto out; 220
221 i = ext_table_size / DWSIZE;
222 while (i--)
223 ext_table_sum += ext_tablep[i];
224 if (ext_table_sum) {
225 printk(KERN_WARNING "microcode: aborting, "
226 "bad extended signature table checksum\n");
227 return -EINVAL;
264 } 228 }
229 }
265 230
266 if (mc_header.ldrver != 1 || mc_header.hdrver != 1) { 231 /* calculate the checksum */
267 printk(KERN_ERR "microcode: error! Unknown microcode update format\n"); 232 orig_sum = 0;
268 error = -EINVAL; 233 i = (MC_HEADER_SIZE + data_size) / DWSIZE;
269 goto out; 234 while (i--)
235 orig_sum += ((int *)mc)[i];
236 if (orig_sum) {
237 printk(KERN_ERR "microcode: aborting, bad checksum\n");
238 return -EINVAL;
239 }
240 if (!ext_table_size)
241 return 0;
242 /* check extended signature checksum */
243 for (i = 0; i < ext_sigcount; i++) {
244 ext_sig = (struct extended_signature *)((void *)ext_header
245 + EXT_HEADER_SIZE + EXT_SIGNATURE_SIZE * i);
246 sum = orig_sum
247 - (mc_header->sig + mc_header->pf + mc_header->cksum)
248 + (ext_sig->sig + ext_sig->pf + ext_sig->cksum);
249 if (sum) {
250 printk(KERN_ERR "microcode: aborting, bad checksum\n");
251 return -EINVAL;
270 } 252 }
253 }
254 return 0;
255}
271 256
272 for_each_online_cpu(cpu_num) { 257/*
273 struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; 258 * return 0 - no update found
274 259 * return 1 - found update
275 if (sigmatch(mc_header.sig, uci->sig, mc_header.pf, uci->orig_pf)) 260 * return < 0 - error
276 mark_microcode_update(cpu_num, &mc_header, mc_header.sig, mc_header.pf, mc_header.cksum); 261 */
277 } 262static int get_maching_microcode(void *mc, int cpu)
263{
264 struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
265 microcode_header_t *mc_header = mc;
266 struct extended_sigtable *ext_header;
267 unsigned long total_size = get_totalsize(mc_header);
268 int ext_sigcount, i;
269 struct extended_signature *ext_sig;
270 void *new_mc;
271
272 if (microcode_update_match(cpu, mc_header,
273 mc_header->sig, mc_header->pf))
274 goto find;
275
276 if (total_size <= get_datasize(mc_header) + MC_HEADER_SIZE)
277 return 0;
278
279 ext_header = (struct extended_sigtable *)(mc +
280 get_datasize(mc_header) + MC_HEADER_SIZE);
281 ext_sigcount = ext_header->count;
282 ext_sig = (struct extended_signature *)((void *)ext_header
283 + EXT_HEADER_SIZE);
284 for (i = 0; i < ext_sigcount; i++) {
285 if (microcode_update_match(cpu, mc_header,
286 ext_sig->sig, ext_sig->pf))
287 goto find;
288 ext_sig++;
289 }
290 return 0;
291find:
292 pr_debug("microcode: CPU %d found a matching microcode update with"
293 " version 0x%x (current=0x%x)\n", cpu, mc_header->rev,uci->rev);
294 new_mc = vmalloc(total_size);
295 if (!new_mc) {
296 printk(KERN_ERR "microcode: error! Can not allocate memory\n");
297 return -ENOMEM;
298 }
278 299
279 ext_table_size = total_size - (MC_HEADER_SIZE + data_size); 300 /* free previous update file */
280 if (ext_table_size) { 301 vfree(uci->mc);
281 struct extended_sigtable ext_header;
282 struct extended_signature ext_sig;
283 int ext_sigcount;
284 302
285 if ((ext_table_size < EXT_HEADER_SIZE) 303 memcpy(new_mc, mc, total_size);
286 || ((ext_table_size - EXT_HEADER_SIZE) % EXT_SIGNATURE_SIZE)) { 304 uci->mc = new_mc;
287 printk(KERN_ERR "microcode: error! Bad data in microcode data file\n"); 305 return 1;
288 error = -EINVAL;
289 goto out;
290 }
291 if (copy_from_user(&ext_header, user_buffer + cursor
292 + MC_HEADER_SIZE + data_size, EXT_HEADER_SIZE)) {
293 printk(KERN_ERR "microcode: error! Can not read user data\n");
294 error = -EFAULT;
295 goto out;
296 }
297 if (ext_table_size != exttable_size(&ext_header)) {
298 printk(KERN_ERR "microcode: error! Bad data in microcode data file\n");
299 error = -EFAULT;
300 goto out;
301 }
302
303 ext_sigcount = ext_header.count;
304
305 for (i = 0; i < ext_sigcount; i++) {
306 if (copy_from_user(&ext_sig, user_buffer + cursor + MC_HEADER_SIZE + data_size + EXT_HEADER_SIZE
307 + EXT_SIGNATURE_SIZE * i, EXT_SIGNATURE_SIZE)) {
308 printk(KERN_ERR "microcode: error! Can not read user data\n");
309 error = -EFAULT;
310 goto out;
311 }
312 for_each_online_cpu(cpu_num) {
313 struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
314
315 if (sigmatch(ext_sig.sig, uci->sig, ext_sig.pf, uci->orig_pf)) {
316 mark_microcode_update(cpu_num, &mc_header, ext_sig.sig, ext_sig.pf, ext_sig.cksum);
317 }
318 }
319 }
320 }
321 /* now check if any cpu has matched */
322 allocated_flag = 0;
323 sum = 0;
324 for_each_online_cpu(cpu_num) {
325 if (ucode_cpu_info[cpu_num].err == MC_MARKED) {
326 struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
327 if (!allocated_flag) {
328 allocated_flag = 1;
329 newmc = vmalloc(total_size);
330 if (!newmc) {
331 printk(KERN_ERR "microcode: error! Can not allocate memory\n");
332 error = -ENOMEM;
333 goto out;
334 }
335 if (copy_from_user(newmc + MC_HEADER_SIZE,
336 user_buffer + cursor + MC_HEADER_SIZE,
337 total_size - MC_HEADER_SIZE)) {
338 printk(KERN_ERR "microcode: error! Can not read user data\n");
339 vfree(newmc);
340 error = -EFAULT;
341 goto out;
342 }
343 memcpy(newmc, &mc_header, MC_HEADER_SIZE);
344 /* check extended table checksum */
345 if (ext_table_size) {
346 int ext_table_sum = 0;
347 int * ext_tablep = (((void *) newmc) + MC_HEADER_SIZE + data_size);
348 i = ext_table_size / DWSIZE;
349 while (i--) ext_table_sum += ext_tablep[i];
350 if (ext_table_sum) {
351 printk(KERN_WARNING "microcode: aborting, bad extended signature table checksum\n");
352 vfree(newmc);
353 error = -EINVAL;
354 goto out;
355 }
356 }
357
358 /* calculate the checksum */
359 i = (MC_HEADER_SIZE + data_size) / DWSIZE;
360 while (i--) sum += ((int *)newmc)[i];
361 sum -= (mc_header.sig + mc_header.pf + mc_header.cksum);
362 }
363 ucode_cpu_info[cpu_num].mc = newmc;
364 ucode_cpu_info[cpu_num].err = MC_ALLOCATED; /* mc updated */
365 if (sum + uci->sig + uci->pf + uci->cksum != 0) {
366 printk(KERN_ERR "microcode: CPU%d aborting, bad checksum\n", cpu_num);
367 error = -EINVAL;
368 goto out;
369 }
370 }
371 }
372 cursor += total_size; /* goto the next update patch */
373 } /* end of while */
374out:
375 return error;
376} 306}
377 307
378static void do_update_one (void * unused) 308static void apply_microcode(int cpu)
379{ 309{
380 unsigned long flags; 310 unsigned long flags;
381 unsigned int val[2]; 311 unsigned int val[2];
382 int cpu_num = smp_processor_id(); 312 int cpu_num = raw_smp_processor_id();
383 struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; 313 struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
384 314
385 if (uci->mc == NULL) { 315 /* We should bind the task to the CPU */
386 if (verbose) { 316 BUG_ON(cpu_num != cpu);
387 if (uci->err == MC_SUCCESS) 317
388 printk(KERN_INFO "microcode: CPU%d already at revision 0x%x\n", 318 if (uci->mc == NULL)
389 cpu_num, uci->rev);
390 else
391 printk(KERN_INFO "microcode: No new microcode data for CPU%d\n", cpu_num);
392 }
393 return; 319 return;
394 }
395 320
396 /* serialize access to the physical write to MSR 0x79 */ 321 /* serialize access to the physical write to MSR 0x79 */
397 spin_lock_irqsave(&microcode_update_lock, flags); 322 spin_lock_irqsave(&microcode_update_lock, flags);
@@ -408,54 +333,98 @@ static void do_update_one (void * unused)
408 /* get the current revision from MSR 0x8B */ 333 /* get the current revision from MSR 0x8B */
409 rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]); 334 rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
410 335
411 /* notify the caller of success on this cpu */
412 uci->err = MC_SUCCESS;
413 spin_unlock_irqrestore(&microcode_update_lock, flags); 336 spin_unlock_irqrestore(&microcode_update_lock, flags);
414 printk(KERN_INFO "microcode: CPU%d updated from revision " 337 if (val[1] != uci->mc->hdr.rev) {
338 printk(KERN_ERR "microcode: CPU%d updated from revision "
339 "0x%x to 0x%x failed\n", cpu_num, uci->rev, val[1]);
340 return;
341 }
342 pr_debug("microcode: CPU%d updated from revision "
415 "0x%x to 0x%x, date = %08x \n", 343 "0x%x to 0x%x, date = %08x \n",
416 cpu_num, uci->rev, val[1], uci->mc->hdr.date); 344 cpu_num, uci->rev, val[1], uci->mc->hdr.date);
417 return; 345 uci->rev = val[1];
418} 346}
419 347
420static int do_microcode_update (void) 348#ifdef CONFIG_MICROCODE_OLD_INTERFACE
421{ 349static void __user *user_buffer; /* user area microcode data buffer */
422 int i, error; 350static unsigned int user_buffer_size; /* it's size */
423 351
424 if (on_each_cpu(collect_cpu_info, NULL, 1, 1) != 0) { 352static long get_next_ucode(void **mc, long offset)
425 printk(KERN_ERR "microcode: Error! Could not run on all processors\n"); 353{
426 error = -EIO; 354 microcode_header_t mc_header;
427 goto out; 355 unsigned long total_size;
356
357 /* No more data */
358 if (offset >= user_buffer_size)
359 return 0;
360 if (copy_from_user(&mc_header, user_buffer + offset, MC_HEADER_SIZE)) {
361 printk(KERN_ERR "microcode: error! Can not read user data\n");
362 return -EFAULT;
428 } 363 }
429 364 total_size = get_totalsize(&mc_header);
430 if ((error = find_matching_ucodes())) { 365 if ((offset + total_size > user_buffer_size)
431 printk(KERN_ERR "microcode: Error in the microcode data\n"); 366 || (total_size < DEFAULT_UCODE_TOTALSIZE)) {
432 goto out_free; 367 printk(KERN_ERR "microcode: error! Bad total size in microcode "
368 "data file\n");
369 return -EINVAL;
433 } 370 }
434 371 *mc = vmalloc(total_size);
435 if (on_each_cpu(do_update_one, NULL, 1, 1) != 0) { 372 if (!*mc)
436 printk(KERN_ERR "microcode: Error! Could not run on all processors\n"); 373 return -ENOMEM;
437 error = -EIO; 374 if (copy_from_user(*mc, user_buffer + offset, total_size)) {
375 printk(KERN_ERR "microcode: error! Can not read user data\n");
376 vfree(*mc);
377 return -EFAULT;
438 } 378 }
379 return offset + total_size;
380}
439 381
440out_free: 382static int do_microcode_update (void)
441 for_each_online_cpu(i) { 383{
442 if (ucode_cpu_info[i].mc) { 384 long cursor = 0;
443 int j; 385 int error = 0;
444 void *tmp = ucode_cpu_info[i].mc; 386 void * new_mc;
445 vfree(tmp); 387 int cpu;
446 for_each_online_cpu(j) { 388 cpumask_t old;
447 if (ucode_cpu_info[j].mc == tmp) 389
448 ucode_cpu_info[j].mc = NULL; 390 old = current->cpus_allowed;
449 } 391
392 while ((cursor = get_next_ucode(&new_mc, cursor)) > 0) {
393 error = microcode_sanity_check(new_mc);
394 if (error)
395 goto out;
396 /*
397 * It's possible the data file has multiple matching ucode,
398 * lets keep searching till the latest version
399 */
400 for_each_online_cpu(cpu) {
401 struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
402
403 if (!uci->valid)
404 continue;
405 set_cpus_allowed(current, cpumask_of_cpu(cpu));
406 error = get_maching_microcode(new_mc, cpu);
407 if (error < 0)
408 goto out;
409 if (error == 1)
410 apply_microcode(cpu);
450 } 411 }
451 if (ucode_cpu_info[i].err == MC_IGNORED && verbose) 412 vfree(new_mc);
452 printk(KERN_WARNING "microcode: CPU%d not 'upgrading' to earlier revision"
453 " 0x%x (current=0x%x)\n", i, ucode_cpu_info[i].cksum, ucode_cpu_info[i].rev);
454 } 413 }
455out: 414out:
415 if (cursor > 0)
416 vfree(new_mc);
417 if (cursor < 0)
418 error = cursor;
419 set_cpus_allowed(current, old);
456 return error; 420 return error;
457} 421}
458 422
423static int microcode_open (struct inode *unused1, struct file *unused2)
424{
425 return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
426}
427
459static ssize_t microcode_write (struct file *file, const char __user *buf, size_t len, loff_t *ppos) 428static ssize_t microcode_write (struct file *file, const char __user *buf, size_t len, loff_t *ppos)
460{ 429{
461 ssize_t ret; 430 ssize_t ret;
@@ -470,6 +439,7 @@ static ssize_t microcode_write (struct file *file, const char __user *buf, size_
470 return -EINVAL; 439 return -EINVAL;
471 } 440 }
472 441
442 lock_cpu_hotplug();
473 mutex_lock(&microcode_mutex); 443 mutex_lock(&microcode_mutex);
474 444
475 user_buffer = (void __user *) buf; 445 user_buffer = (void __user *) buf;
@@ -480,6 +450,7 @@ static ssize_t microcode_write (struct file *file, const char __user *buf, size_
480 ret = (ssize_t)len; 450 ret = (ssize_t)len;
481 451
482 mutex_unlock(&microcode_mutex); 452 mutex_unlock(&microcode_mutex);
453 unlock_cpu_hotplug();
483 454
484 return ret; 455 return ret;
485} 456}
@@ -496,7 +467,7 @@ static struct miscdevice microcode_dev = {
496 .fops = &microcode_fops, 467 .fops = &microcode_fops,
497}; 468};
498 469
499static int __init microcode_init (void) 470static int __init microcode_dev_init (void)
500{ 471{
501 int error; 472 int error;
502 473
@@ -508,6 +479,28 @@ static int __init microcode_init (void)
508 return error; 479 return error;
509 } 480 }
510 481
482 return 0;
483}
484
485static void __exit microcode_dev_exit (void)
486{
487 misc_deregister(&microcode_dev);
488}
489
490MODULE_ALIAS_MISCDEV(MICROCODE_MINOR);
491#else
492#define microcode_dev_init() 0
493#define microcode_dev_exit() do { } while(0)
494#endif
495
496static int __init microcode_init (void)
497{
498 int error;
499
500 error = microcode_dev_init();
501 if (error)
502 return error;
503
511 printk(KERN_INFO 504 printk(KERN_INFO
512 "IA-32 Microcode Update Driver: v" MICROCODE_VERSION " <tigran@veritas.com>\n"); 505 "IA-32 Microcode Update Driver: v" MICROCODE_VERSION " <tigran@veritas.com>\n");
513 return 0; 506 return 0;
@@ -515,9 +508,8 @@ static int __init microcode_init (void)
515 508
516static void __exit microcode_exit (void) 509static void __exit microcode_exit (void)
517{ 510{
518 misc_deregister(&microcode_dev); 511 microcode_dev_exit();
519} 512}
520 513
521module_init(microcode_init) 514module_init(microcode_init)
522module_exit(microcode_exit) 515module_exit(microcode_exit)
523MODULE_ALIAS_MISCDEV(MICROCODE_MINOR);
diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig
index 326aff7a87ea..ab4cbcb9e3b3 100644
--- a/arch/x86_64/Kconfig
+++ b/arch/x86_64/Kconfig
@@ -186,6 +186,11 @@ config MICROCODE
186 If you use modprobe or kmod you may also want to add the line 186 If you use modprobe or kmod you may also want to add the line
187 'alias char-major-10-184 microcode' to your /etc/modules.conf file. 187 'alias char-major-10-184 microcode' to your /etc/modules.conf file.
188 188
189config MICROCODE_OLD_INTERFACE
190 bool
191 depends on MICROCODE
192 default y
193
189config X86_MSR 194config X86_MSR
190 tristate "/dev/cpu/*/msr - Model-specific register support" 195 tristate "/dev/cpu/*/msr - Model-specific register support"
191 help 196 help