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>
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 -
   1.199 -    if (len < DEFAULT_UCODE_TOTALSIZE) {
   1.200 -        printk(KERN_ERR "microcode: not enough data\n"); 
   1.201 -        return -EINVAL;
   1.202 -    }
   1.203 +	int ret;
   1.204  
   1.205 -    down(&microcode_sem);
   1.206 -    
   1.207 -    user_buffer = (void __user *) buf;
   1.208 -    user_buffer_size = (int) len;
   1.209 -    
   1.210 -    ret = do_microcode_update();
   1.211 -    
   1.212 -    up(&microcode_sem);
   1.213 -    
   1.214 -    return ret;
   1.215 +	if (len < DEFAULT_UCODE_TOTALSIZE) {
   1.216 +		printk(KERN_ERR "microcode: not enough data\n"); 
   1.217 +		return -EINVAL;
   1.218 +	}
   1.219 +
   1.220 +	mutex_lock(&microcode_mutex);
   1.221 +
   1.222 +	user_buffer = (void __user *) buf;
   1.223 +	user_buffer_size = (int) len;
   1.224 +
   1.225 +	ret = do_microcode_update();
   1.226 +
   1.227 +	mutex_unlock(&microcode_mutex);
   1.228 +
   1.229 +	return ret;
   1.230  }