fedora core 2.6.9-1.11-FC2
[linux-2.6.git] / arch / xen / i386 / kernel / microcode.c
1 /*
2  *      Intel CPU Microcode Update Driver for Linux
3  *
4  *      Copyright (C) 2000-2004 Tigran Aivazian
5  *
6  *      This driver allows to upgrade microcode on Intel processors
7  *      belonging to IA-32 family - PentiumPro, Pentium II, 
8  *      Pentium III, Xeon, Pentium 4, etc.
9  *
10  *      Reference: Section 8.10 of Volume III, Intel Pentium 4 Manual, 
11  *      Order Number 245472 or free download from:
12  *              
13  *      http://developer.intel.com/design/pentium4/manuals/245472.htm
14  *
15  *      For more information, go to http://www.urbanmyth.org/microcode
16  *
17  *      This program is free software; you can redistribute it and/or
18  *      modify it under the terms of the GNU General Public License
19  *      as published by the Free Software Foundation; either version
20  *      2 of the License, or (at your option) any later version.
21  */
22
23 //#define DEBUG /* pr_debug */
24 #include <linux/kernel.h>
25 #include <linux/init.h>
26 #include <linux/sched.h>
27 #include <linux/module.h>
28 #include <linux/slab.h>
29 #include <linux/vmalloc.h>
30 #include <linux/miscdevice.h>
31 #include <linux/spinlock.h>
32 #include <linux/mm.h>
33 #include <linux/syscalls.h>
34
35 #include <asm/msr.h>
36 #include <asm/uaccess.h>
37 #include <asm/processor.h>
38
39 MODULE_DESCRIPTION("Intel CPU (IA-32) Microcode Update Driver");
40 MODULE_AUTHOR("Tigran Aivazian <tigran@veritas.com>");
41 MODULE_LICENSE("GPL");
42
43 #define MICROCODE_VERSION       "1.14-xen"
44
45 #define DEFAULT_UCODE_DATASIZE  (2000)    /* 2000 bytes */
46 #define MC_HEADER_SIZE          (sizeof (microcode_header_t))     /* 48 bytes */
47 #define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE) /* 2048 bytes */
48
49 /* no concurrent ->write()s are allowed on /dev/cpu/microcode */
50 static DECLARE_MUTEX(microcode_sem);
51
52 static void __user *user_buffer;        /* user area microcode data buffer */
53 static unsigned int user_buffer_size;   /* it's size */
54                                 
55 static int microcode_open (struct inode *unused1, struct file *unused2)
56 {
57         return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
58 }
59
60
61 static int do_microcode_update (void)
62 {
63         int err;
64         dom0_op_t op;
65
66         err = sys_mlock((unsigned long)user_buffer, user_buffer_size);
67         if (err != 0)
68                 return err;
69
70         op.cmd = DOM0_MICROCODE;
71         op.u.microcode.data = user_buffer;
72         op.u.microcode.length = user_buffer_size;
73         err = HYPERVISOR_dom0_op(&op);
74
75         (void)sys_munlock((unsigned long)user_buffer, user_buffer_size);
76
77         return err;
78 }
79
80 static ssize_t microcode_write (struct file *file, const char __user *buf, size_t len, loff_t *ppos)
81 {
82         ssize_t ret;
83
84         if (len < DEFAULT_UCODE_TOTALSIZE) {
85                 printk(KERN_ERR "microcode: not enough data\n"); 
86                 return -EINVAL;
87         }
88
89         if ((len >> PAGE_SHIFT) > num_physpages) {
90                 printk(KERN_ERR "microcode: too much data (max %ld pages)\n", num_physpages);
91                 return -EINVAL;
92         }
93
94         down(&microcode_sem);
95
96         user_buffer = (void __user *) buf;
97         user_buffer_size = (int) len;
98
99         ret = do_microcode_update();
100         if (!ret)
101                 ret = (ssize_t)len;
102
103         up(&microcode_sem);
104
105         return ret;
106 }
107
108 static int microcode_ioctl (struct inode *inode, struct file *file, 
109                 unsigned int cmd, unsigned long arg)
110 {
111         switch (cmd) {
112                 /* 
113                  *  XXX: will be removed after microcode_ctl 
114                  *  is updated to ignore failure of this ioctl()
115                  */
116                 case MICROCODE_IOCFREE:
117                         return 0;
118                 default:
119                         return -EINVAL;
120         }
121         return -EINVAL;
122 }
123
124 static struct file_operations microcode_fops = {
125         .owner          = THIS_MODULE,
126         .write          = microcode_write,
127         .ioctl          = microcode_ioctl,
128         .open           = microcode_open,
129 };
130
131 static struct miscdevice microcode_dev = {
132         .minor          = MICROCODE_MINOR,
133         .name           = "microcode",
134         .devfs_name     = "cpu/microcode",
135         .fops           = &microcode_fops,
136 };
137
138 static int __init microcode_init (void)
139 {
140         int error;
141
142         error = misc_register(&microcode_dev);
143         if (error) {
144                 printk(KERN_ERR
145                         "microcode: can't misc_register on minor=%d\n",
146                         MICROCODE_MINOR);
147                 return error;
148         }
149
150         printk(KERN_INFO 
151                 "IA-32 Microcode Update Driver: v" MICROCODE_VERSION " <tigran@veritas.com>\n");
152         return 0;
153 }
154
155 static void __exit microcode_exit (void)
156 {
157         misc_deregister(&microcode_dev);
158         printk(KERN_INFO "IA-32 Microcode Update Driver v" MICROCODE_VERSION " unregistered\n");
159 }
160
161 module_init(microcode_init)
162 module_exit(microcode_exit)
163 MODULE_ALIAS_MISCDEV(MICROCODE_MINOR);