ia64/xen-unstable
changeset 10545:bad506bc0c85
[XEN] Upgrade microcode driver to 1.14a.
Based on a patch from Jan Beulich.
Signed-off-by: Keir Fraser <keir@xensource.com>
Based on a patch from Jan Beulich.
Signed-off-by: Keir Fraser <keir@xensource.com>
author | kfraser@dhcp93.uk.xensource.com |
---|---|
date | Tue Jun 27 15:22:55 2006 +0100 (2006-06-27) |
parents | 1a52829fd60e |
children | ab0cae84cfec |
files | xen/arch/x86/microcode.c |
line diff
1.1 --- a/xen/arch/x86/microcode.c Tue Jun 27 14:38:58 2006 +0100 1.2 +++ b/xen/arch/x86/microcode.c Tue Jun 27 15:22:55 2006 +0100 1.3 @@ -83,9 +83,9 @@ 1.4 #include <asm/processor.h> 1.5 1.6 #define pr_debug(x...) ((void)0) 1.7 -#define DECLARE_MUTEX(_m) DEFINE_SPINLOCK(_m) 1.8 -#define down(_m) spin_lock(_m) 1.9 -#define up(_m) spin_unlock(_m) 1.10 +#define DEFINE_MUTEX(_m) DEFINE_SPINLOCK(_m) 1.11 +#define mutex_lock(_m) spin_lock(_m) 1.12 +#define mutex_unlock(_m) spin_unlock(_m) 1.13 #define vmalloc(_s) xmalloc_bytes(_s) 1.14 #define vfree(_p) xfree(_p) 1.15 1.16 @@ -95,7 +95,10 @@ MODULE_AUTHOR("Tigran Aivazian <tigran@v 1.17 MODULE_LICENSE("GPL"); 1.18 #endif 1.19 1.20 -#define MICROCODE_VERSION "1.14" 1.21 +static int verbose; 1.22 +boolean_param("microcode.verbose", verbose); 1.23 + 1.24 +#define MICROCODE_VERSION "1.14a" 1.25 1.26 #define DEFAULT_UCODE_DATASIZE (2000) /* 2000 bytes */ 1.27 #define MC_HEADER_SIZE (sizeof (microcode_header_t)) /* 48 bytes */ 1.28 @@ -119,21 +122,22 @@ MODULE_LICENSE("GPL"); 1.29 static DEFINE_SPINLOCK(microcode_update_lock); 1.30 1.31 /* no concurrent ->write()s are allowed on /dev/cpu/microcode */ 1.32 -static DECLARE_MUTEX(microcode_sem); 1.33 +static DEFINE_MUTEX(microcode_mutex); 1.34 1.35 static void __user *user_buffer; /* user area microcode data buffer */ 1.36 static unsigned int user_buffer_size; /* it's size */ 1.37 1.38 typedef enum mc_error_code { 1.39 MC_SUCCESS = 0, 1.40 - MC_NOTFOUND = 1, 1.41 - MC_MARKED = 2, 1.42 - MC_ALLOCATED = 3, 1.43 + MC_IGNORED = 1, 1.44 + MC_NOTFOUND = 2, 1.45 + MC_MARKED = 3, 1.46 + MC_ALLOCATED = 4, 1.47 } mc_error_code_t; 1.48 1.49 static struct ucode_cpu_info { 1.50 unsigned int sig; 1.51 - unsigned int pf; 1.52 + unsigned int pf, orig_pf; 1.53 unsigned int rev; 1.54 unsigned int cksum; 1.55 mc_error_code_t err; 1.56 @@ -163,6 +167,7 @@ static void collect_cpu_info (void *unus 1.57 rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]); 1.58 uci->pf = 1 << ((val[1] >> 18) & 7); 1.59 } 1.60 + uci->orig_pf = uci->pf; 1.61 } 1.62 1.63 wrmsr(MSR_IA32_UCODE_REV, 0, 0); 1.64 @@ -196,23 +201,34 @@ static inline void mark_microcode_update 1.65 pr_debug(" Checksum 0x%x\n", cksum); 1.66 1.67 if (mc_header->rev < uci->rev) { 1.68 - printk(KERN_ERR "microcode: CPU%d not 'upgrading' to earlier revision" 1.69 - " 0x%x (current=0x%x)\n", cpu_num, mc_header->rev, uci->rev); 1.70 - goto out; 1.71 + if (uci->err == MC_NOTFOUND) { 1.72 + uci->err = MC_IGNORED; 1.73 + uci->cksum = mc_header->rev; 1.74 + } else if (uci->err == MC_IGNORED && uci->cksum < mc_header->rev) 1.75 + uci->cksum = mc_header->rev; 1.76 } else if (mc_header->rev == uci->rev) { 1.77 - /* notify the caller of success on this cpu */ 1.78 - uci->err = MC_SUCCESS; 1.79 - printk(KERN_ERR "microcode: CPU%d already at revision" 1.80 - " 0x%x (current=0x%x)\n", cpu_num, mc_header->rev, uci->rev); 1.81 - goto out; 1.82 + if (uci->err < MC_MARKED) { 1.83 + /* notify the caller of success on this cpu */ 1.84 + uci->err = MC_SUCCESS; 1.85 + } 1.86 + } else if (uci->err != MC_ALLOCATED || mc_header->rev > uci->mc->hdr.rev) { 1.87 + pr_debug("microcode: CPU%d found a matching microcode update with " 1.88 + " revision 0x%x (current=0x%x)\n", cpu_num, mc_header->rev, uci->rev); 1.89 + uci->cksum = cksum; 1.90 + uci->pf = pf; /* keep the original mc pf for cksum calculation */ 1.91 + uci->err = MC_MARKED; /* found the match */ 1.92 + for_each_online_cpu(cpu_num) { 1.93 + if (ucode_cpu_info + cpu_num != uci 1.94 + && ucode_cpu_info[cpu_num].mc == uci->mc) { 1.95 + uci->mc = NULL; 1.96 + break; 1.97 + } 1.98 + } 1.99 + if (uci->mc != NULL) { 1.100 + vfree(uci->mc); 1.101 + uci->mc = NULL; 1.102 + } 1.103 } 1.104 - 1.105 - pr_debug("microcode: CPU%d found a matching microcode update with " 1.106 - " revision 0x%x (current=0x%x)\n", cpu_num, mc_header->rev, uci->rev); 1.107 - uci->cksum = cksum; 1.108 - uci->pf = pf; /* keep the original mc pf for cksum calculation */ 1.109 - uci->err = MC_MARKED; /* found the match */ 1.110 -out: 1.111 return; 1.112 } 1.113 1.114 @@ -251,13 +267,11 @@ static int find_matching_ucodes (void) 1.115 error = -EINVAL; 1.116 goto out; 1.117 } 1.118 - 1.119 - for (cpu_num = 0; cpu_num < num_online_cpus(); cpu_num++) { 1.120 + 1.121 + for_each_online_cpu(cpu_num) { 1.122 struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; 1.123 - if (uci->err != MC_NOTFOUND) /* already found a match or not an online cpu*/ 1.124 - continue; 1.125 1.126 - if (sigmatch(mc_header.sig, uci->sig, mc_header.pf, uci->pf)) 1.127 + if (sigmatch(mc_header.sig, uci->sig, mc_header.pf, uci->orig_pf)) 1.128 mark_microcode_update(cpu_num, &mc_header, mc_header.sig, mc_header.pf, mc_header.cksum); 1.129 } 1.130 1.131 @@ -294,18 +308,19 @@ static int find_matching_ucodes (void) 1.132 error = -EFAULT; 1.133 goto out; 1.134 } 1.135 - for (cpu_num = 0; cpu_num < num_online_cpus(); cpu_num++) { 1.136 + for_each_online_cpu(cpu_num) { 1.137 struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; 1.138 - if (uci->err != MC_NOTFOUND) /* already found a match or not an online cpu*/ 1.139 - continue; 1.140 - if (sigmatch(ext_sig.sig, uci->sig, ext_sig.pf, uci->pf)) { 1.141 + 1.142 + if (sigmatch(ext_sig.sig, uci->sig, ext_sig.pf, uci->orig_pf)) { 1.143 mark_microcode_update(cpu_num, &mc_header, ext_sig.sig, ext_sig.pf, ext_sig.cksum); 1.144 } 1.145 } 1.146 } 1.147 } 1.148 /* now check if any cpu has matched */ 1.149 - for (cpu_num = 0, allocated_flag = 0, sum = 0; cpu_num < num_online_cpus(); cpu_num++) { 1.150 + allocated_flag = 0; 1.151 + sum = 0; 1.152 + for_each_online_cpu(cpu_num) { 1.153 if (ucode_cpu_info[cpu_num].err == MC_MARKED) { 1.154 struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; 1.155 if (!allocated_flag) { 1.156 @@ -367,7 +382,13 @@ static void do_update_one (void * unused 1.157 struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; 1.158 1.159 if (uci->mc == NULL) { 1.160 - printk(KERN_INFO "microcode: No new microcode data for CPU%d\n", cpu_num); 1.161 + if (verbose) { 1.162 + if (uci->err == MC_SUCCESS) 1.163 + printk(KERN_INFO "microcode: CPU%d already at revision 0x%x\n", 1.164 + cpu_num, uci->rev); 1.165 + else 1.166 + printk(KERN_INFO "microcode: No new microcode data for CPU%d\n", cpu_num); 1.167 + } 1.168 return; 1.169 } 1.170 1.171 @@ -416,16 +437,19 @@ static int do_microcode_update (void) 1.172 } 1.173 1.174 out_free: 1.175 - for (i = 0; i < num_online_cpus(); i++) { 1.176 + for_each_online_cpu(i) { 1.177 if (ucode_cpu_info[i].mc) { 1.178 int j; 1.179 void *tmp = ucode_cpu_info[i].mc; 1.180 vfree(tmp); 1.181 - for (j = i; j < num_online_cpus(); j++) { 1.182 + for_each_online_cpu(j) { 1.183 if (ucode_cpu_info[j].mc == tmp) 1.184 ucode_cpu_info[j].mc = NULL; 1.185 } 1.186 } 1.187 + if (ucode_cpu_info[i].err == MC_IGNORED && verbose) 1.188 + printk(KERN_WARNING "microcode: CPU%d not 'upgrading' to earlier revision" 1.189 + " 0x%x (current=0x%x)\n", i, ucode_cpu_info[i].cksum, ucode_cpu_info[i].rev); 1.190 } 1.191 out: 1.192 return error; 1.193 @@ -433,21 +457,21 @@ out: 1.194 1.195 int microcode_update(void *buf, unsigned long len) 1.196 { 1.197 - int ret; 1.198 + int ret; 1.199 1.200 - if (len < DEFAULT_UCODE_TOTALSIZE) { 1.201 - printk(KERN_ERR "microcode: not enough data\n"); 1.202 - return -EINVAL; 1.203 - } 1.204 + if (len < DEFAULT_UCODE_TOTALSIZE) { 1.205 + printk(KERN_ERR "microcode: not enough data\n"); 1.206 + return -EINVAL; 1.207 + } 1.208 + 1.209 + mutex_lock(µcode_mutex); 1.210 1.211 - down(µcode_sem); 1.212 - 1.213 - user_buffer = (void __user *) buf; 1.214 - user_buffer_size = (int) len; 1.215 - 1.216 - ret = do_microcode_update(); 1.217 - 1.218 - up(µcode_sem); 1.219 - 1.220 - return ret; 1.221 + user_buffer = (void __user *) buf; 1.222 + user_buffer_size = (int) len; 1.223 + 1.224 + ret = do_microcode_update(); 1.225 + 1.226 + mutex_unlock(µcode_mutex); 1.227 + 1.228 + return ret; 1.229 }