2 * CPU Microcode Update Driver for Linux on Xen
4 * Copyright (C) 2000-2006 Tigran Aivazian <tigran@aivazian.fsnet.co.uk>
5 * 2006 Shaohua Li <shaohua.li@intel.com>
7 * This driver allows to upgrade microcode on Intel processors
8 * belonging to IA-32 family - PentiumPro, Pentium II,
9 * Pentium III, Xeon, Pentium 4, etc.
11 * Reference: Section 8.11 of Volume 3a, IA-32 Intel? Architecture
12 * Software Developer's Manual
13 * Order Number 253668 or free download from:
15 * http://developer.intel.com/Assets/PDF/manual/253668.pdf
17 * For more information, go to http://www.urbanmyth.org/microcode
19 * This program is free software; you can redistribute it and/or
20 * modify it under the terms of the GNU General Public License
21 * as published by the Free Software Foundation; either version
22 * 2 of the License, or (at your option) any later version.
25 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
27 #include <linux/platform_device.h>
28 #include <linux/miscdevice.h>
29 #include <linux/capability.h>
30 #include <linux/kernel.h>
31 #include <linux/module.h>
32 #include <linux/mutex.h>
33 #include <linux/cpu.h>
36 #include <linux/firmware.h>
37 #include <linux/uaccess.h>
38 #include <linux/vmalloc.h>
40 #include <asm/microcode.h>
41 #include <asm/processor.h>
42 #include <asm/cpu_device_id.h>
46 MODULE_DESCRIPTION("Microcode Update Driver");
47 MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>");
48 MODULE_LICENSE("GPL");
51 module_param(verbose, int, 0644);
53 #define MICROCODE_VERSION "2.00-xen"
58 * All non cpu-hotplug-callback call sites use:
60 * - microcode_mutex to synchronize with each other;
61 * - get/put_online_cpus() to synchronize with
62 * the cpu-hotplug-callback call sites.
64 * We guarantee that only a single cpu is being
65 * updated at any particular moment of time.
67 static DEFINE_MUTEX(microcode_mutex);
69 #ifdef CONFIG_MICROCODE_OLD_INTERFACE
70 static int do_microcode_update(const void __user *ubuf, size_t len)
79 if (copy_from_user(kbuf, ubuf, len) == 0) {
80 struct xen_platform_op op;
82 op.cmd = XENPF_microcode_update;
83 set_xen_guest_handle(op.u.microcode.data, kbuf);
84 op.u.microcode.length = len;
85 err = HYPERVISOR_platform_op(&op);
94 static int microcode_open(struct inode *inode, struct file *file)
96 return capable(CAP_SYS_RAWIO) ? nonseekable_open(inode, file) : -EPERM;
99 static ssize_t microcode_write(struct file *file, const char __user *buf,
100 size_t len, loff_t *ppos)
102 ssize_t ret = -EINVAL;
104 if ((len >> PAGE_SHIFT) > totalram_pages) {
105 pr_err("too much data (max %ld pages)\n", totalram_pages);
109 mutex_lock(µcode_mutex);
111 if (do_microcode_update(buf, len) == 0)
114 mutex_unlock(µcode_mutex);
119 static const struct file_operations microcode_fops = {
120 .owner = THIS_MODULE,
121 .write = microcode_write,
122 .open = microcode_open,
126 static struct miscdevice microcode_dev = {
127 .minor = MICROCODE_MINOR,
129 .nodename = "cpu/microcode",
130 .fops = µcode_fops,
133 static int __init microcode_dev_init(void)
137 if (!is_initial_xendomain())
140 error = misc_register(µcode_dev);
142 pr_err("can't misc_register on minor=%d\n", MICROCODE_MINOR);
149 static void __exit microcode_dev_exit(void)
151 misc_deregister(µcode_dev);
154 MODULE_ALIAS_MISCDEV(MICROCODE_MINOR);
155 MODULE_ALIAS("devname:cpu/microcode");
157 #define microcode_dev_init() 0
158 #define microcode_dev_exit() do { } while (0)
161 /* fake device for request_firmware */
162 static struct platform_device *microcode_pdev;
164 static int request_microcode(const char *name)
166 const struct firmware *firmware;
168 struct xen_platform_op op;
170 error = request_firmware(&firmware, name, µcode_pdev->dev);
172 pr_debug("microcode: data file %s load failed\n", name);
176 op.cmd = XENPF_microcode_update;
177 set_xen_guest_handle(op.u.microcode.data, firmware->data);
178 op.u.microcode.length = firmware->size;
179 error = HYPERVISOR_platform_op(&op);
181 release_firmware(firmware);
184 pr_debug("ucode load failed\n");
189 static const char amd_uc_name[] = "amd-ucode/microcode_amd.bin";
190 static const char amd_uc_fmt[] = "amd-ucode/microcode_amd_fam%x.bin";
191 static const char intel_uc_fmt[] = "intel-ucode/%02x-%02x-%02x";
193 static int ucode_cpu_callback(struct notifier_block *nfb,
194 unsigned long action, void *hcpu)
196 unsigned int cpu = (unsigned long)hcpu;
197 struct xen_platform_op op;
199 const char *uc_name = buf;
203 op.cmd = XENPF_get_cpu_version;
204 op.u.pcpu_version.xen_cpuid = cpu;
205 if (HYPERVISOR_platform_op(&op))
207 if (op.u.pcpu_version.family == boot_cpu_data.x86
208 && op.u.pcpu_version.model == boot_cpu_data.x86_model
209 && op.u.pcpu_version.stepping == boot_cpu_data.x86_mask)
211 if (strncmp(op.u.pcpu_version.vendor_id,
212 "GenuineIntel", 12) == 0)
213 snprintf(buf, sizeof(buf), intel_uc_fmt,
214 op.u.pcpu_version.family,
215 op.u.pcpu_version.model,
216 op.u.pcpu_version.stepping);
217 else if (strncmp(op.u.pcpu_version.vendor_id,
218 "AuthenicAMD", 12) == 0) {
219 if (op.u.pcpu_version.family >= 0x15)
220 snprintf(buf, sizeof(buf), amd_uc_fmt,
221 op.u.pcpu_version.family);
223 uc_name = amd_uc_name;
226 request_microcode(uc_name);
233 static struct notifier_block ucode_cpu_notifier = {
234 .notifier_call = ucode_cpu_callback
238 /* Autoload on Intel and AMD systems */
239 static const struct x86_cpu_id microcode_id[] = {
240 { X86_VENDOR_INTEL, X86_FAMILY_ANY, X86_MODEL_ANY, },
241 { X86_VENDOR_AMD, X86_FAMILY_ANY, X86_MODEL_ANY, },
244 MODULE_DEVICE_TABLE(x86cpu, microcode_id);
247 static int __init microcode_init(void)
249 const struct cpuinfo_x86 *c = &boot_cpu_data;
251 const char *fw_name = buf;
254 if (c->x86_vendor == X86_VENDOR_INTEL)
255 snprintf(buf, sizeof(buf), intel_uc_fmt,
256 c->x86, c->x86_model, c->x86_mask);
257 else if (c->x86_vendor == X86_VENDOR_AMD) {
259 snprintf(buf, sizeof(buf), amd_uc_fmt, c->x86);
261 fw_name = amd_uc_name;
263 pr_err("no support for this CPU vendor\n");
267 microcode_pdev = platform_device_register_simple("microcode", -1,
269 if (IS_ERR(microcode_pdev))
270 return PTR_ERR(microcode_pdev);
272 request_microcode(fw_name);
274 error = microcode_dev_init();
276 platform_device_unregister(microcode_pdev);
280 pr_info("Microcode Update Driver: v" MICROCODE_VERSION
281 " <tigran@aivazian.fsnet.co.uk>, Peter Oruba\n");
283 error = register_pcpu_notifier(&ucode_cpu_notifier);
285 pr_warn("pCPU notifier registration failed (%d)\n", error);
289 module_init(microcode_init);
291 static void __exit microcode_exit(void)
293 unregister_pcpu_notifier(&ucode_cpu_notifier);
294 microcode_dev_exit();
295 platform_device_unregister(microcode_pdev);
297 pr_info("Microcode Update Driver: v" MICROCODE_VERSION " removed.\n");
299 module_exit(microcode_exit);