ia64/xen-unstable

changeset 3363:524b831d8294

bitkeeper revision 1.1159.1.523 (41d54b30O4rbtOVTyJB2Od7jzSW30g)

manual merge
author kaf24@scramble.cl.cam.ac.uk
date Fri Dec 31 12:50:56 2004 +0000 (2004-12-31)
parents bdac3ae67e39 fefd1123461f
children 9cee424e24de
files .rootkeys linux-2.6.10-xen-sparse/arch/xen/configs/xen0_defconfig linux-2.6.10-xen-sparse/arch/xen/i386/Kconfig linux-2.6.10-xen-sparse/arch/xen/i386/kernel/Makefile linux-2.6.10-xen-sparse/arch/xen/i386/kernel/microcode.c xen/arch/x86/dom0_ops.c xen/arch/x86/microcode.c xen/include/asm-x86/processor.h xen/include/public/dom0_ops.h
line diff
     1.1 --- a/.rootkeys	Fri Dec 31 00:24:44 2004 +0000
     1.2 +++ b/.rootkeys	Fri Dec 31 12:50:56 2004 +0000
     1.3 @@ -147,6 +147,7 @@ 40f58a0d31M2EkuPbG94ns_nOi0PVA linux-2.6
     1.4  40faa751_zbZlAmLyQgCXdYekVFdWA linux-2.6.10-xen-sparse/arch/xen/i386/kernel/ioport.c
     1.5  41d00d82zN8IfLBRxc7G_i7lbwT3cQ linux-2.6.10-xen-sparse/arch/xen/i386/kernel/irq.c
     1.6  40f56238ue3YRsK52HG7iccNzP1AwQ linux-2.6.10-xen-sparse/arch/xen/i386/kernel/ldt.c
     1.7 +41d54a76YMCA67S8J-TBT3J62Wx6yA linux-2.6.10-xen-sparse/arch/xen/i386/kernel/microcode.c
     1.8  4107adf1cNtsuOxOB4T6paAoY2R2PA linux-2.6.10-xen-sparse/arch/xen/i386/kernel/pci-dma.c
     1.9  40f56238a8iOVDEoostsbun_sy2i4g linux-2.6.10-xen-sparse/arch/xen/i386/kernel/process.c
    1.10  40f56238YQIJoYG2ehDGEcdTgLmGbg linux-2.6.10-xen-sparse/arch/xen/i386/kernel/setup.c
    1.11 @@ -673,6 +674,7 @@ 3ddb79bcBit4xJXbwtX0kb1hh2uO1Q xen/arch/
    1.12  3ddb79bcKIkRR0kqWaJhe5VUDkMdxg xen/arch/x86/io_apic.c
    1.13  3ddb79bdqfIcjkz_h9Hvtp8Tk_19Zw xen/arch/x86/irq.c
    1.14  40ec29ffuOa1ZvmJHzFKyZn4k_RcXg xen/arch/x86/memory.c
    1.15 +41d54a76qfpO0VnbL2tYs0Jgt3W3XA xen/arch/x86/microcode.c
    1.16  3ddb79bdS4UeWWXDH-FaBKqcpMFcnw xen/arch/x86/mpparse.c
    1.17  41aaf566Z4sTDgJ77eEg0TzzQ1ka6Q xen/arch/x86/mtrr/amd.c
    1.18  41aaf566TOpOBXT00wwQGUh20f1rlA xen/arch/x86/mtrr/centaur.c
     2.1 --- a/linux-2.6.10-xen-sparse/arch/xen/configs/xen0_defconfig	Fri Dec 31 00:24:44 2004 +0000
     2.2 +++ b/linux-2.6.10-xen-sparse/arch/xen/configs/xen0_defconfig	Fri Dec 31 12:50:56 2004 +0000
     2.3 @@ -117,6 +117,7 @@ CONFIG_X86_USE_PPRO_CHECKSUM=y
     2.4  # CONFIG_HPET_EMULATE_RTC is not set
     2.5  # CONFIG_SMP is not set
     2.6  CONFIG_PREEMPT=y
     2.7 +CONFIG_MICROCODE=y
     2.8  CONFIG_X86_CPUID=y
     2.9  
    2.10  #
     3.1 --- a/linux-2.6.10-xen-sparse/arch/xen/i386/Kconfig	Fri Dec 31 00:24:44 2004 +0000
     3.2 +++ b/linux-2.6.10-xen-sparse/arch/xen/i386/Kconfig	Fri Dec 31 12:50:56 2004 +0000
     3.3 @@ -437,22 +437,23 @@ config PREEMPT
     3.4  #	   Enabling this feature will cause a message to be printed when the P4
     3.5  #	   enters thermal throttling.
     3.6  
     3.7 -#config MICROCODE
     3.8 -#	 tristate "/dev/cpu/microcode - Intel IA32 CPU microcode support"
     3.9 -#	 ---help---
    3.10 -#	   If you say Y here and also to "/dev file system support" in the
    3.11 -#	   'File systems' section, you will be able to update the microcode on
    3.12 -#	   Intel processors in the IA32 family, e.g. Pentium Pro, Pentium II,
    3.13 -#	   Pentium III, Pentium 4, Xeon etc.  You will obviously need the
    3.14 -#	   actual microcode binary data itself which is not shipped with the
    3.15 -#	   Linux kernel.
    3.16 -#
    3.17 -#	   For latest news and information on obtaining all the required
    3.18 -#	   ingredients for this driver, check:
    3.19 -#	   <http://www.urbanmyth.org/microcode/>.
    3.20 -#
    3.21 -#	   To compile this driver as a module, choose M here: the
    3.22 -#	   module will be called microcode.
    3.23 +config MICROCODE
    3.24 +	 tristate "/dev/cpu/microcode - Intel IA32 CPU microcode support"
    3.25 +	 depends on XEN_PRIVILEGED_GUEST
    3.26 +	 ---help---
    3.27 +	   If you say Y here and also to "/dev file system support" in the
    3.28 +	   'File systems' section, you will be able to update the microcode on
    3.29 +	   Intel processors in the IA32 family, e.g. Pentium Pro, Pentium II,
    3.30 +	   Pentium III, Pentium 4, Xeon etc.  You will obviously need the
    3.31 +	   actual microcode binary data itself which is not shipped with the
    3.32 +	   Linux kernel.
    3.33 +
    3.34 +	   For latest news and information on obtaining all the required
    3.35 +	   ingredients for this driver, check:
    3.36 +	   <http://www.urbanmyth.org/microcode/>.
    3.37 +
    3.38 +	   To compile this driver as a module, choose M here: the
    3.39 +	   module will be called microcode.
    3.40  
    3.41  #config X86_MSR
    3.42  #	 tristate "/dev/cpu/*/msr - Model-specific register support"
     4.1 --- a/linux-2.6.10-xen-sparse/arch/xen/i386/kernel/Makefile	Fri Dec 31 00:24:44 2004 +0000
     4.2 +++ b/linux-2.6.10-xen-sparse/arch/xen/i386/kernel/Makefile	Fri Dec 31 12:50:56 2004 +0000
     4.3 @@ -25,7 +25,7 @@ c-obj-$(CONFIG_ACPI_BOOT)	+= acpi/
     4.4  c-obj-$(CONFIG_MCA)		+= mca.o
     4.5  c-obj-$(CONFIG_X86_MSR)		+= msr.o
     4.6  c-obj-$(CONFIG_X86_CPUID)	+= cpuid.o
     4.7 -c-obj-$(CONFIG_MICROCODE)	+= microcode.o
     4.8 +obj-$(CONFIG_MICROCODE)		+= microcode.o
     4.9  c-obj-$(CONFIG_APM)		+= apm.o
    4.10  obj-$(CONFIG_X86_SMP)		+= smp.o smpboot.o
    4.11  #obj-$(CONFIG_X86_TRAMPOLINE)	+= trampoline.o
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/linux-2.6.10-xen-sparse/arch/xen/i386/kernel/microcode.c	Fri Dec 31 12:50:56 2004 +0000
     5.3 @@ -0,0 +1,163 @@
     5.4 +/*
     5.5 + *	Intel CPU Microcode Update Driver for Linux
     5.6 + *
     5.7 + *	Copyright (C) 2000-2004 Tigran Aivazian
     5.8 + *
     5.9 + *	This driver allows to upgrade microcode on Intel processors
    5.10 + *	belonging to IA-32 family - PentiumPro, Pentium II, 
    5.11 + *	Pentium III, Xeon, Pentium 4, etc.
    5.12 + *
    5.13 + *	Reference: Section 8.10 of Volume III, Intel Pentium 4 Manual, 
    5.14 + *	Order Number 245472 or free download from:
    5.15 + *		
    5.16 + *	http://developer.intel.com/design/pentium4/manuals/245472.htm
    5.17 + *
    5.18 + *	For more information, go to http://www.urbanmyth.org/microcode
    5.19 + *
    5.20 + *	This program is free software; you can redistribute it and/or
    5.21 + *	modify it under the terms of the GNU General Public License
    5.22 + *	as published by the Free Software Foundation; either version
    5.23 + *	2 of the License, or (at your option) any later version.
    5.24 + */
    5.25 +
    5.26 +//#define DEBUG /* pr_debug */
    5.27 +#include <linux/kernel.h>
    5.28 +#include <linux/init.h>
    5.29 +#include <linux/sched.h>
    5.30 +#include <linux/module.h>
    5.31 +#include <linux/slab.h>
    5.32 +#include <linux/vmalloc.h>
    5.33 +#include <linux/miscdevice.h>
    5.34 +#include <linux/spinlock.h>
    5.35 +#include <linux/mm.h>
    5.36 +#include <linux/syscalls.h>
    5.37 +
    5.38 +#include <asm/msr.h>
    5.39 +#include <asm/uaccess.h>
    5.40 +#include <asm/processor.h>
    5.41 +
    5.42 +MODULE_DESCRIPTION("Intel CPU (IA-32) Microcode Update Driver");
    5.43 +MODULE_AUTHOR("Tigran Aivazian <tigran@veritas.com>");
    5.44 +MODULE_LICENSE("GPL");
    5.45 +
    5.46 +#define MICROCODE_VERSION 	"1.14-xen"
    5.47 +
    5.48 +#define DEFAULT_UCODE_DATASIZE 	(2000) 	  /* 2000 bytes */
    5.49 +#define MC_HEADER_SIZE		(sizeof (microcode_header_t))  	  /* 48 bytes */
    5.50 +#define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE) /* 2048 bytes */
    5.51 +
    5.52 +/* no concurrent ->write()s are allowed on /dev/cpu/microcode */
    5.53 +static DECLARE_MUTEX(microcode_sem);
    5.54 +
    5.55 +static void __user *user_buffer;	/* user area microcode data buffer */
    5.56 +static unsigned int user_buffer_size;	/* it's size */
    5.57 +				
    5.58 +static int microcode_open (struct inode *unused1, struct file *unused2)
    5.59 +{
    5.60 +	return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
    5.61 +}
    5.62 +
    5.63 +
    5.64 +static int do_microcode_update (void)
    5.65 +{
    5.66 +	int err;
    5.67 +	dom0_op_t op;
    5.68 +
    5.69 +	err = sys_mlock((unsigned long)user_buffer, user_buffer_size);
    5.70 +	if (err != 0)
    5.71 +		return err;
    5.72 +
    5.73 +	op.cmd = DOM0_MICROCODE;
    5.74 +	op.u.microcode.data = user_buffer;
    5.75 +	op.u.microcode.length = user_buffer_size;
    5.76 +	err = HYPERVISOR_dom0_op(&op);
    5.77 +
    5.78 +	(void)sys_munlock((unsigned long)user_buffer, user_buffer_size);
    5.79 +
    5.80 +	return err;
    5.81 +}
    5.82 +
    5.83 +static ssize_t microcode_write (struct file *file, const char __user *buf, size_t len, loff_t *ppos)
    5.84 +{
    5.85 +	ssize_t ret;
    5.86 +
    5.87 +	if (len < DEFAULT_UCODE_TOTALSIZE) {
    5.88 +		printk(KERN_ERR "microcode: not enough data\n"); 
    5.89 +		return -EINVAL;
    5.90 +	}
    5.91 +
    5.92 +	if ((len >> PAGE_SHIFT) > num_physpages) {
    5.93 +		printk(KERN_ERR "microcode: too much data (max %ld pages)\n", num_physpages);
    5.94 +		return -EINVAL;
    5.95 +	}
    5.96 +
    5.97 +	down(&microcode_sem);
    5.98 +
    5.99 +	user_buffer = (void __user *) buf;
   5.100 +	user_buffer_size = (int) len;
   5.101 +
   5.102 +	ret = do_microcode_update();
   5.103 +	if (!ret)
   5.104 +		ret = (ssize_t)len;
   5.105 +
   5.106 +	up(&microcode_sem);
   5.107 +
   5.108 +	return ret;
   5.109 +}
   5.110 +
   5.111 +static int microcode_ioctl (struct inode *inode, struct file *file, 
   5.112 +		unsigned int cmd, unsigned long arg)
   5.113 +{
   5.114 +	switch (cmd) {
   5.115 +		/* 
   5.116 +		 *  XXX: will be removed after microcode_ctl 
   5.117 +		 *  is updated to ignore failure of this ioctl()
   5.118 +		 */
   5.119 +		case MICROCODE_IOCFREE:
   5.120 +			return 0;
   5.121 +		default:
   5.122 +			return -EINVAL;
   5.123 +	}
   5.124 +	return -EINVAL;
   5.125 +}
   5.126 +
   5.127 +static struct file_operations microcode_fops = {
   5.128 +	.owner		= THIS_MODULE,
   5.129 +	.write		= microcode_write,
   5.130 +	.ioctl		= microcode_ioctl,
   5.131 +	.open		= microcode_open,
   5.132 +};
   5.133 +
   5.134 +static struct miscdevice microcode_dev = {
   5.135 +	.minor		= MICROCODE_MINOR,
   5.136 +	.name		= "microcode",
   5.137 +	.devfs_name	= "cpu/microcode",
   5.138 +	.fops		= &microcode_fops,
   5.139 +};
   5.140 +
   5.141 +static int __init microcode_init (void)
   5.142 +{
   5.143 +	int error;
   5.144 +
   5.145 +	error = misc_register(&microcode_dev);
   5.146 +	if (error) {
   5.147 +		printk(KERN_ERR
   5.148 +			"microcode: can't misc_register on minor=%d\n",
   5.149 +			MICROCODE_MINOR);
   5.150 +		return error;
   5.151 +	}
   5.152 +
   5.153 +	printk(KERN_INFO 
   5.154 +		"IA-32 Microcode Update Driver: v" MICROCODE_VERSION " <tigran@veritas.com>\n");
   5.155 +	return 0;
   5.156 +}
   5.157 +
   5.158 +static void __exit microcode_exit (void)
   5.159 +{
   5.160 +	misc_deregister(&microcode_dev);
   5.161 +	printk(KERN_INFO "IA-32 Microcode Update Driver v" MICROCODE_VERSION " unregistered\n");
   5.162 +}
   5.163 +
   5.164 +module_init(microcode_init)
   5.165 +module_exit(microcode_exit)
   5.166 +MODULE_ALIAS_MISCDEV(MICROCODE_MINOR);
     6.1 --- a/xen/arch/x86/dom0_ops.c	Fri Dec 31 00:24:44 2004 +0000
     6.2 +++ b/xen/arch/x86/dom0_ops.c	Fri Dec 31 12:50:56 2004 +0000
     6.3 @@ -130,6 +130,13 @@ long arch_do_dom0_op(dom0_op_t *op, dom0
     6.4      }
     6.5      break;
     6.6  
     6.7 +    case DOM0_MICROCODE:
     6.8 +    {
     6.9 +        extern int microcode_update(void *buf, unsigned long len);
    6.10 +        ret = microcode_update(op->u.microcode.data, op->u.microcode.length);
    6.11 +    }
    6.12 +    break;
    6.13 +
    6.14      default:
    6.15          ret = -ENOSYS;
    6.16  
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/xen/arch/x86/microcode.c	Fri Dec 31 12:50:56 2004 +0000
     7.3 @@ -0,0 +1,456 @@
     7.4 +/*
     7.5 + *	Intel CPU Microcode Update Driver for Linux
     7.6 + *
     7.7 + *	Copyright (C) 2000-2004 Tigran Aivazian
     7.8 + *
     7.9 + *	This driver allows to upgrade microcode on Intel processors
    7.10 + *	belonging to IA-32 family - PentiumPro, Pentium II, 
    7.11 + *	Pentium III, Xeon, Pentium 4, etc.
    7.12 + *
    7.13 + *	Reference: Section 8.10 of Volume III, Intel Pentium 4 Manual, 
    7.14 + *	Order Number 245472 or free download from:
    7.15 + *		
    7.16 + *	http://developer.intel.com/design/pentium4/manuals/245472.htm
    7.17 + *
    7.18 + *	For more information, go to http://www.urbanmyth.org/microcode
    7.19 + *
    7.20 + *	This program is free software; you can redistribute it and/or
    7.21 + *	modify it under the terms of the GNU General Public License
    7.22 + *	as published by the Free Software Foundation; either version
    7.23 + *	2 of the License, or (at your option) any later version.
    7.24 + *
    7.25 + *	1.0	16 Feb 2000, Tigran Aivazian <tigran@sco.com>
    7.26 + *		Initial release.
    7.27 + *	1.01	18 Feb 2000, Tigran Aivazian <tigran@sco.com>
    7.28 + *		Added read() support + cleanups.
    7.29 + *	1.02	21 Feb 2000, Tigran Aivazian <tigran@sco.com>
    7.30 + *		Added 'device trimming' support. open(O_WRONLY) zeroes
    7.31 + *		and frees the saved copy of applied microcode.
    7.32 + *	1.03	29 Feb 2000, Tigran Aivazian <tigran@sco.com>
    7.33 + *		Made to use devfs (/dev/cpu/microcode) + cleanups.
    7.34 + *	1.04	06 Jun 2000, Simon Trimmer <simon@veritas.com>
    7.35 + *		Added misc device support (now uses both devfs and misc).
    7.36 + *		Added MICROCODE_IOCFREE ioctl to clear memory.
    7.37 + *	1.05	09 Jun 2000, Simon Trimmer <simon@veritas.com>
    7.38 + *		Messages for error cases (non Intel & no suitable microcode).
    7.39 + *	1.06	03 Aug 2000, Tigran Aivazian <tigran@veritas.com>
    7.40 + *		Removed ->release(). Removed exclusive open and status bitmap.
    7.41 + *		Added microcode_rwsem to serialize read()/write()/ioctl().
    7.42 + *		Removed global kernel lock usage.
    7.43 + *	1.07	07 Sep 2000, Tigran Aivazian <tigran@veritas.com>
    7.44 + *		Write 0 to 0x8B msr and then cpuid before reading revision,
    7.45 + *		so that it works even if there were no update done by the
    7.46 + *		BIOS. Otherwise, reading from 0x8B gives junk (which happened
    7.47 + *		to be 0 on my machine which is why it worked even when I
    7.48 + *		disabled update by the BIOS)
    7.49 + *		Thanks to Eric W. Biederman <ebiederman@lnxi.com> for the fix.
    7.50 + *	1.08	11 Dec 2000, Richard Schaal <richard.schaal@intel.com> and
    7.51 + *			     Tigran Aivazian <tigran@veritas.com>
    7.52 + *		Intel Pentium 4 processor support and bugfixes.
    7.53 + *	1.09	30 Oct 2001, Tigran Aivazian <tigran@veritas.com>
    7.54 + *		Bugfix for HT (Hyper-Threading) enabled processors
    7.55 + *		whereby processor resources are shared by all logical processors
    7.56 + *		in a single CPU package.
    7.57 + *	1.10	28 Feb 2002 Asit K Mallick <asit.k.mallick@intel.com> and
    7.58 + *		Tigran Aivazian <tigran@veritas.com>,
    7.59 + *		Serialize updates as required on HT processors due to speculative
    7.60 + *		nature of implementation.
    7.61 + *	1.11	22 Mar 2002 Tigran Aivazian <tigran@veritas.com>
    7.62 + *		Fix the panic when writing zero-length microcode chunk.
    7.63 + *	1.12	29 Sep 2003 Nitin Kamble <nitin.a.kamble@intel.com>, 
    7.64 + *		Jun Nakajima <jun.nakajima@intel.com>
    7.65 + *		Support for the microcode updates in the new format.
    7.66 + *	1.13	10 Oct 2003 Tigran Aivazian <tigran@veritas.com>
    7.67 + *		Removed ->read() method and obsoleted MICROCODE_IOCFREE ioctl
    7.68 + *		because we no longer hold a copy of applied microcode 
    7.69 + *		in kernel memory.
    7.70 + *	1.14	25 Jun 2004 Tigran Aivazian <tigran@veritas.com>
    7.71 + *		Fix sigmatch() macro to handle old CPUs with pf == 0.
    7.72 + *		Thanks to Stuart Swales for pointing out this bug.
    7.73 + */
    7.74 +
    7.75 +#include <xen/config.h>
    7.76 +#include <xen/kernel.h>
    7.77 +#include <xen/init.h>
    7.78 +#include <xen/sched.h>
    7.79 +#include <xen/slab.h>
    7.80 +#include <xen/spinlock.h>
    7.81 +
    7.82 +#include <asm/msr.h>
    7.83 +#include <asm/uaccess.h>
    7.84 +#include <asm/processor.h>
    7.85 +
    7.86 +#define pr_debug(x...) ((void)0)
    7.87 +#define DECLARE_MUTEX(_m) spinlock_t _m = SPIN_LOCK_UNLOCKED
    7.88 +#define down(_m) spin_lock(_m)
    7.89 +#define up(_m) spin_unlock(_m)
    7.90 +#define vmalloc(_s) xmalloc(_s)
    7.91 +#define vfree(_p) xfree(_p)
    7.92 +#define num_online_cpus() smp_num_cpus
    7.93 +static inline int on_each_cpu(
    7.94 +    void (*func) (void *info), void *info, int retry, int wait)
    7.95 +{
    7.96 +    int ret = smp_call_function(func, info, retry, wait);
    7.97 +    func(info);
    7.98 +    return ret;
    7.99 +}
   7.100 +
   7.101 +#if 0
   7.102 +MODULE_DESCRIPTION("Intel CPU (IA-32) Microcode Update Driver");
   7.103 +MODULE_AUTHOR("Tigran Aivazian <tigran@veritas.com>");
   7.104 +MODULE_LICENSE("GPL");
   7.105 +#endif
   7.106 +
   7.107 +#define MICROCODE_VERSION 	"1.14"
   7.108 +
   7.109 +#define DEFAULT_UCODE_DATASIZE 	(2000) 	  /* 2000 bytes */
   7.110 +#define MC_HEADER_SIZE		(sizeof (microcode_header_t))  	  /* 48 bytes */
   7.111 +#define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE) /* 2048 bytes */
   7.112 +#define EXT_HEADER_SIZE		(sizeof (struct extended_sigtable)) /* 20 bytes */
   7.113 +#define EXT_SIGNATURE_SIZE	(sizeof (struct extended_signature)) /* 12 bytes */
   7.114 +#define DWSIZE			(sizeof (u32))
   7.115 +#define get_totalsize(mc) \
   7.116 +	(((microcode_t *)mc)->hdr.totalsize ? \
   7.117 +	 ((microcode_t *)mc)->hdr.totalsize : DEFAULT_UCODE_TOTALSIZE)
   7.118 +#define get_datasize(mc) \
   7.119 +	(((microcode_t *)mc)->hdr.datasize ? \
   7.120 +	 ((microcode_t *)mc)->hdr.datasize : DEFAULT_UCODE_DATASIZE)
   7.121 +
   7.122 +#define sigmatch(s1, s2, p1, p2) \
   7.123 +	(((s1) == (s2)) && (((p1) & (p2)) || (((p1) == 0) && ((p2) == 0))))
   7.124 +
   7.125 +#define exttable_size(et) ((et)->count * EXT_SIGNATURE_SIZE + EXT_HEADER_SIZE)
   7.126 +
   7.127 +/* serialize access to the physical write to MSR 0x79 */
   7.128 +static spinlock_t microcode_update_lock = SPIN_LOCK_UNLOCKED;
   7.129 +
   7.130 +/* no concurrent ->write()s are allowed on /dev/cpu/microcode */
   7.131 +static DECLARE_MUTEX(microcode_sem);
   7.132 +
   7.133 +static void __user *user_buffer;	/* user area microcode data buffer */
   7.134 +static unsigned int user_buffer_size;	/* it's size */
   7.135 +
   7.136 +typedef enum mc_error_code {
   7.137 +	MC_SUCCESS 	= 0,
   7.138 +	MC_NOTFOUND 	= 1,
   7.139 +	MC_MARKED 	= 2,
   7.140 +	MC_ALLOCATED 	= 3,
   7.141 +} mc_error_code_t;
   7.142 +
   7.143 +static struct ucode_cpu_info {
   7.144 +	unsigned int sig;
   7.145 +	unsigned int pf;
   7.146 +	unsigned int rev;
   7.147 +	unsigned int cksum;
   7.148 +	mc_error_code_t err;
   7.149 +	microcode_t *mc;
   7.150 +} ucode_cpu_info[NR_CPUS];
   7.151 +				
   7.152 +static void collect_cpu_info (void *unused)
   7.153 +{
   7.154 +	int cpu_num = smp_processor_id();
   7.155 +	struct cpuinfo_x86 *c = cpu_data + cpu_num;
   7.156 +	struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
   7.157 +	unsigned int val[2];
   7.158 +
   7.159 +	uci->sig = uci->pf = uci->rev = uci->cksum = 0;
   7.160 +	uci->err = MC_NOTFOUND; 
   7.161 +	uci->mc = NULL;
   7.162 +
   7.163 +	if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 ||
   7.164 +	    	cpu_has(c, X86_FEATURE_IA64)) {
   7.165 +		printk(KERN_ERR "microcode: CPU%d not a capable Intel processor\n", cpu_num);
   7.166 +		return;
   7.167 +	} else {
   7.168 +		uci->sig = cpuid_eax(0x00000001);
   7.169 +
   7.170 +		if ((c->x86_model >= 5) || (c->x86 > 6)) {
   7.171 +			/* get processor flags from MSR 0x17 */
   7.172 +			rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
   7.173 +			uci->pf = 1 << ((val[1] >> 18) & 7);
   7.174 +		}
   7.175 +	}
   7.176 +
   7.177 +	wrmsr(MSR_IA32_UCODE_REV, 0, 0);
   7.178 +	__asm__ __volatile__ ("cpuid" : : : "ax", "bx", "cx", "dx");
   7.179 +	/* get the current revision from MSR 0x8B */
   7.180 +	rdmsr(MSR_IA32_UCODE_REV, val[0], uci->rev);
   7.181 +	pr_debug("microcode: collect_cpu_info : sig=0x%x, pf=0x%x, rev=0x%x\n",
   7.182 +			uci->sig, uci->pf, uci->rev);
   7.183 +}
   7.184 +
   7.185 +static inline void mark_microcode_update (int cpu_num, microcode_header_t *mc_header, int sig, int pf, int cksum)
   7.186 +{
   7.187 +	struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
   7.188 +
   7.189 +	pr_debug("Microcode Found.\n");
   7.190 +	pr_debug("   Header Revision 0x%x\n", mc_header->hdrver);
   7.191 +	pr_debug("   Loader Revision 0x%x\n", mc_header->ldrver);
   7.192 +	pr_debug("   Revision 0x%x \n", mc_header->rev);
   7.193 +	pr_debug("   Date %x/%x/%x\n",
   7.194 +		((mc_header->date >> 24 ) & 0xff),
   7.195 +		((mc_header->date >> 16 ) & 0xff),
   7.196 +		(mc_header->date & 0xFFFF));
   7.197 +	pr_debug("   Signature 0x%x\n", sig);
   7.198 +	pr_debug("   Type 0x%x Family 0x%x Model 0x%x Stepping 0x%x\n",
   7.199 +		((sig >> 12) & 0x3),
   7.200 +		((sig >> 8) & 0xf),
   7.201 +		((sig >> 4) & 0xf),
   7.202 +		((sig & 0xf)));
   7.203 +	pr_debug("   Processor Flags 0x%x\n", pf);
   7.204 +	pr_debug("   Checksum 0x%x\n", cksum);
   7.205 +
   7.206 +	if (mc_header->rev < uci->rev) {
   7.207 +		printk(KERN_ERR "microcode: CPU%d not 'upgrading' to earlier revision"
   7.208 +		       " 0x%x (current=0x%x)\n", cpu_num, mc_header->rev, uci->rev);
   7.209 +		goto out;
   7.210 +	} else if (mc_header->rev == uci->rev) {
   7.211 +		/* notify the caller of success on this cpu */
   7.212 +		uci->err = MC_SUCCESS;
   7.213 +		printk(KERN_ERR "microcode: CPU%d already at revision"
   7.214 +			" 0x%x (current=0x%x)\n", cpu_num, mc_header->rev, uci->rev);
   7.215 +		goto out;
   7.216 +	}
   7.217 +
   7.218 +	pr_debug("microcode: CPU%d found a matching microcode update with "
   7.219 +		" revision 0x%x (current=0x%x)\n", cpu_num, mc_header->rev, uci->rev);
   7.220 +	uci->cksum = cksum;
   7.221 +	uci->pf = pf; /* keep the original mc pf for cksum calculation */
   7.222 +	uci->err = MC_MARKED; /* found the match */
   7.223 +out:
   7.224 +	return;
   7.225 +}
   7.226 +
   7.227 +static int find_matching_ucodes (void) 
   7.228 +{
   7.229 +	int cursor = 0;
   7.230 +	int error = 0;
   7.231 +
   7.232 +	while (cursor + MC_HEADER_SIZE < user_buffer_size) {
   7.233 +		microcode_header_t mc_header;
   7.234 +		void *newmc = NULL;
   7.235 +		int i, sum, cpu_num, allocated_flag, total_size, data_size, ext_table_size;
   7.236 +
   7.237 +		if (copy_from_user(&mc_header, user_buffer + cursor, MC_HEADER_SIZE)) {
   7.238 +			printk(KERN_ERR "microcode: error! Can not read user data\n");
   7.239 +			error = -EFAULT;
   7.240 +			goto out;
   7.241 +		}
   7.242 +
   7.243 +		total_size = get_totalsize(&mc_header);
   7.244 +		if ((cursor + total_size > user_buffer_size) || (total_size < DEFAULT_UCODE_TOTALSIZE)) {
   7.245 +			printk(KERN_ERR "microcode: error! Bad data in microcode data file\n");
   7.246 +			error = -EINVAL;
   7.247 +			goto out;
   7.248 +		}
   7.249 +
   7.250 +		data_size = get_datasize(&mc_header);
   7.251 +		if ((data_size + MC_HEADER_SIZE > total_size) || (data_size < DEFAULT_UCODE_DATASIZE)) {
   7.252 +			printk(KERN_ERR "microcode: error! Bad data in microcode data file\n");
   7.253 +			error = -EINVAL;
   7.254 +			goto out;
   7.255 +		}
   7.256 +
   7.257 +		if (mc_header.ldrver != 1 || mc_header.hdrver != 1) {
   7.258 +			printk(KERN_ERR "microcode: error! Unknown microcode update format\n");
   7.259 +			error = -EINVAL;
   7.260 +			goto out;
   7.261 +		}
   7.262 +		
   7.263 +		for (cpu_num = 0; cpu_num < num_online_cpus(); cpu_num++) {
   7.264 +			struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
   7.265 +			if (uci->err != MC_NOTFOUND) /* already found a match or not an online cpu*/
   7.266 +				continue;
   7.267 +
   7.268 +			if (sigmatch(mc_header.sig, uci->sig, mc_header.pf, uci->pf))
   7.269 +				mark_microcode_update(cpu_num, &mc_header, mc_header.sig, mc_header.pf, mc_header.cksum);
   7.270 +		}
   7.271 +
   7.272 +		ext_table_size = total_size - (MC_HEADER_SIZE + data_size);
   7.273 +		if (ext_table_size) {
   7.274 +			struct extended_sigtable ext_header;
   7.275 +			struct extended_signature ext_sig;
   7.276 +			int ext_sigcount;
   7.277 +
   7.278 +			if ((ext_table_size < EXT_HEADER_SIZE) 
   7.279 +					|| ((ext_table_size - EXT_HEADER_SIZE) % EXT_SIGNATURE_SIZE)) {
   7.280 +				printk(KERN_ERR "microcode: error! Bad data in microcode data file\n");
   7.281 +				error = -EINVAL;
   7.282 +				goto out;
   7.283 +			}
   7.284 +			if (copy_from_user(&ext_header, user_buffer + cursor 
   7.285 +					+ MC_HEADER_SIZE + data_size, EXT_HEADER_SIZE)) {
   7.286 +				printk(KERN_ERR "microcode: error! Can not read user data\n");
   7.287 +				error = -EFAULT;
   7.288 +				goto out;
   7.289 +			}
   7.290 +			if (ext_table_size != exttable_size(&ext_header)) {
   7.291 +				printk(KERN_ERR "microcode: error! Bad data in microcode data file\n");
   7.292 +				error = -EFAULT;
   7.293 +				goto out;
   7.294 +			}
   7.295 +
   7.296 +			ext_sigcount = ext_header.count;
   7.297 +			
   7.298 +			for (i = 0; i < ext_sigcount; i++) {
   7.299 +				if (copy_from_user(&ext_sig, user_buffer + cursor + MC_HEADER_SIZE + data_size + EXT_HEADER_SIZE 
   7.300 +						+ EXT_SIGNATURE_SIZE * i, EXT_SIGNATURE_SIZE)) {
   7.301 +					printk(KERN_ERR "microcode: error! Can not read user data\n");
   7.302 +					error = -EFAULT;
   7.303 +					goto out;
   7.304 +				}
   7.305 +				for (cpu_num = 0; cpu_num < num_online_cpus(); cpu_num++) {
   7.306 +					struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
   7.307 +					if (uci->err != MC_NOTFOUND) /* already found a match or not an online cpu*/
   7.308 +						continue;
   7.309 +					if (sigmatch(ext_sig.sig, uci->sig, ext_sig.pf, uci->pf)) {
   7.310 +						mark_microcode_update(cpu_num, &mc_header, ext_sig.sig, ext_sig.pf, ext_sig.cksum);
   7.311 +					}
   7.312 +				}
   7.313 +			}
   7.314 +		}
   7.315 +		/* now check if any cpu has matched */
   7.316 +		for (cpu_num = 0, allocated_flag = 0, sum = 0; cpu_num < num_online_cpus(); cpu_num++) {
   7.317 +			if (ucode_cpu_info[cpu_num].err == MC_MARKED) { 
   7.318 +				struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
   7.319 +				if (!allocated_flag) {
   7.320 +					allocated_flag = 1;
   7.321 +					newmc = vmalloc(total_size);
   7.322 +					if (!newmc) {
   7.323 +						printk(KERN_ERR "microcode: error! Can not allocate memory\n");
   7.324 +						error = -ENOMEM;
   7.325 +						goto out;
   7.326 +					}
   7.327 +					if (copy_from_user(newmc + MC_HEADER_SIZE, 
   7.328 +								user_buffer + cursor + MC_HEADER_SIZE, 
   7.329 +								total_size - MC_HEADER_SIZE)) {
   7.330 +						printk(KERN_ERR "microcode: error! Can not read user data\n");
   7.331 +						vfree(newmc);
   7.332 +						error = -EFAULT;
   7.333 +						goto out;
   7.334 +					}
   7.335 +					memcpy(newmc, &mc_header, MC_HEADER_SIZE);
   7.336 +					/* check extended table checksum */
   7.337 +					if (ext_table_size) {
   7.338 +						int ext_table_sum = 0;
   7.339 +						int * ext_tablep = (((void *) newmc) + MC_HEADER_SIZE + data_size);
   7.340 +						i = ext_table_size / DWSIZE;
   7.341 +						while (i--) ext_table_sum += ext_tablep[i];
   7.342 +						if (ext_table_sum) {
   7.343 +							printk(KERN_WARNING "microcode: aborting, bad extended signature table checksum\n");
   7.344 +							vfree(newmc);
   7.345 +							error = -EINVAL;
   7.346 +							goto out;
   7.347 +						}
   7.348 +					}
   7.349 +
   7.350 +					/* calculate the checksum */
   7.351 +					i = (MC_HEADER_SIZE + data_size) / DWSIZE;
   7.352 +					while (i--) sum += ((int *)newmc)[i];
   7.353 +					sum -= (mc_header.sig + mc_header.pf + mc_header.cksum);
   7.354 +				}
   7.355 +				ucode_cpu_info[cpu_num].mc = newmc;
   7.356 +				ucode_cpu_info[cpu_num].err = MC_ALLOCATED; /* mc updated */
   7.357 +				if (sum + uci->sig + uci->pf + uci->cksum != 0) {
   7.358 +					printk(KERN_ERR "microcode: CPU%d aborting, bad checksum\n", cpu_num);
   7.359 +					error = -EINVAL;
   7.360 +					goto out;
   7.361 +				}
   7.362 +			}
   7.363 +		}
   7.364 +		cursor += total_size; /* goto the next update patch */
   7.365 +	} /* end of while */
   7.366 +out:
   7.367 +	return error;
   7.368 +}
   7.369 +
   7.370 +static void do_update_one (void * unused)
   7.371 +{
   7.372 +	unsigned long flags;
   7.373 +	unsigned int val[2];
   7.374 +	int cpu_num = smp_processor_id();
   7.375 +	struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
   7.376 +
   7.377 +	if (uci->mc == NULL) {
   7.378 +		printk(KERN_INFO "microcode: No suitable data for CPU%d\n", cpu_num);
   7.379 +		return;
   7.380 +	}
   7.381 +
   7.382 +	/* serialize access to the physical write to MSR 0x79 */
   7.383 +	spin_lock_irqsave(&microcode_update_lock, flags);          
   7.384 +
   7.385 +	/* write microcode via MSR 0x79 */
   7.386 +	wrmsr(MSR_IA32_UCODE_WRITE,
   7.387 +		(unsigned long) uci->mc->bits, 
   7.388 +		(unsigned long) uci->mc->bits >> 16 >> 16);
   7.389 +	wrmsr(MSR_IA32_UCODE_REV, 0, 0);
   7.390 +
   7.391 +	__asm__ __volatile__ ("cpuid" : : : "ax", "bx", "cx", "dx");
   7.392 +	/* get the current revision from MSR 0x8B */
   7.393 +	rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
   7.394 +
   7.395 +	/* notify the caller of success on this cpu */
   7.396 +	uci->err = MC_SUCCESS;
   7.397 +	spin_unlock_irqrestore(&microcode_update_lock, flags);
   7.398 +	printk(KERN_INFO "microcode: CPU%d updated from revision "
   7.399 +	       "0x%x to 0x%x, date = %08x \n", 
   7.400 +	       cpu_num, uci->rev, val[1], uci->mc->hdr.date);
   7.401 +	return;
   7.402 +}
   7.403 +
   7.404 +static int do_microcode_update (void)
   7.405 +{
   7.406 +	int i, error;
   7.407 +
   7.408 +	if (on_each_cpu(collect_cpu_info, NULL, 1, 1) != 0) {
   7.409 +		printk(KERN_ERR "microcode: Error! Could not run on all processors\n");
   7.410 +		error = -EIO;
   7.411 +		goto out;
   7.412 +	}
   7.413 +
   7.414 +	if ((error = find_matching_ucodes())) {
   7.415 +		printk(KERN_ERR "microcode: Error in the microcode data\n");
   7.416 +		goto out_free;
   7.417 +	}
   7.418 +
   7.419 +	if (on_each_cpu(do_update_one, NULL, 1, 1) != 0) {
   7.420 +		printk(KERN_ERR "microcode: Error! Could not run on all processors\n");
   7.421 +		error = -EIO;
   7.422 +	}
   7.423 +
   7.424 +out_free:
   7.425 +	for (i = 0; i < num_online_cpus(); i++) {
   7.426 +		if (ucode_cpu_info[i].mc) {
   7.427 +			int j;
   7.428 +			void *tmp = ucode_cpu_info[i].mc;
   7.429 +			vfree(tmp);
   7.430 +			for (j = i; j < num_online_cpus(); j++) {
   7.431 +				if (ucode_cpu_info[j].mc == tmp)
   7.432 +					ucode_cpu_info[j].mc = NULL;
   7.433 +			}
   7.434 +		}
   7.435 +	}
   7.436 +out:
   7.437 +	return error;
   7.438 +}
   7.439 +
   7.440 +int microcode_update(void *buf, unsigned long len)
   7.441 +{
   7.442 +    int ret;
   7.443 +
   7.444 +    if (len < DEFAULT_UCODE_TOTALSIZE) {
   7.445 +        printk(KERN_ERR "microcode: not enough data\n"); 
   7.446 +        return -EINVAL;
   7.447 +    }
   7.448 +
   7.449 +    down(&microcode_sem);
   7.450 +    
   7.451 +    user_buffer = (void __user *) buf;
   7.452 +    user_buffer_size = (int) len;
   7.453 +    
   7.454 +    ret = do_microcode_update();
   7.455 +    
   7.456 +    up(&microcode_sem);
   7.457 +    
   7.458 +    return ret;
   7.459 +}
     8.1 --- a/xen/include/asm-x86/processor.h	Fri Dec 31 00:24:44 2004 +0000
     8.2 +++ b/xen/include/asm-x86/processor.h	Fri Dec 31 12:50:56 2004 +0000
     8.3 @@ -557,21 +557,21 @@ long set_gdt(struct exec_domain *d,
     8.4  long set_debugreg(struct exec_domain *p, int reg, unsigned long value);
     8.5  
     8.6  struct microcode_header {
     8.7 -        unsigned int hdrver;
     8.8 -        unsigned int rev;
     8.9 -        unsigned int date;
    8.10 -        unsigned int sig;
    8.11 -        unsigned int cksum;
    8.12 -        unsigned int ldrver;
    8.13 -        unsigned int pf;
    8.14 -        unsigned int datasize;
    8.15 -        unsigned int totalsize;
    8.16 -        unsigned int reserved[3];
    8.17 +    unsigned int hdrver;
    8.18 +    unsigned int rev;
    8.19 +    unsigned int date;
    8.20 +    unsigned int sig;
    8.21 +    unsigned int cksum;
    8.22 +    unsigned int ldrver;
    8.23 +    unsigned int pf;
    8.24 +    unsigned int datasize;
    8.25 +    unsigned int totalsize;
    8.26 +    unsigned int reserved[3];
    8.27  };
    8.28  
    8.29  struct microcode {
    8.30 -        struct microcode_header hdr;
    8.31 -        unsigned int bits[0];
    8.32 +    struct microcode_header hdr;
    8.33 +    unsigned int bits[0];
    8.34  };
    8.35  
    8.36  typedef struct microcode microcode_t;
    8.37 @@ -579,19 +579,17 @@ typedef struct microcode_header microcod
    8.38  
    8.39  /* microcode format is extended from prescott processors */
    8.40  struct extended_signature {
    8.41 -        unsigned int sig;
    8.42 -        unsigned int pf;
    8.43 -        unsigned int cksum;
    8.44 +    unsigned int sig;
    8.45 +    unsigned int pf;
    8.46 +    unsigned int cksum;
    8.47  };
    8.48  
    8.49  struct extended_sigtable {
    8.50 -        unsigned int count;
    8.51 -        unsigned int cksum;
    8.52 -        unsigned int reserved[3];
    8.53 -        struct extended_signature sigs[0];
    8.54 +    unsigned int count;
    8.55 +    unsigned int cksum;
    8.56 +    unsigned int reserved[3];
    8.57 +    struct extended_signature sigs[0];
    8.58  };
    8.59 -/* '6' because it used to be for P6 only (but now covers Pentium 4 as well) */
    8.60 -#define MICROCODE_IOCFREE	_IO('6',0)
    8.61  
    8.62  /* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */
    8.63  static inline void rep_nop(void)
     9.1 --- a/xen/include/public/dom0_ops.h	Fri Dec 31 00:24:44 2004 +0000
     9.2 +++ b/xen/include/public/dom0_ops.h	Fri Dec 31 12:50:56 2004 +0000
     9.3 @@ -405,6 +405,15 @@ typedef struct {
     9.4      MEMORY_PADDING;
     9.5  } PACKED dom0_perfccontrol_t; /* 16 bytes */
     9.6  
     9.7 +#define DOM0_MICROCODE           35
     9.8 +typedef struct {
     9.9 +    /* IN variables. */
    9.10 +    void   *data;                     /* 0: Pointer to microcode data */
    9.11 +    MEMORY_PADDING;
    9.12 +    u32     length;                   /* 8: Length of microcode data. */
    9.13 +    u32     _pad0;
    9.14 +} PACKED dom0_microcode_t; /* 16 bytes */
    9.15 +
    9.16  typedef struct {
    9.17      u32 cmd;                          /* 0 */
    9.18      u32 interface_version;            /* 4 */ /* DOM0_INTERFACE_VERSION */
    9.19 @@ -439,6 +448,7 @@ typedef struct {
    9.20          dom0_del_memtype_t       del_memtype;
    9.21          dom0_read_memtype_t      read_memtype;
    9.22          dom0_perfccontrol_t      perfccontrol;
    9.23 +        dom0_microcode_t         microcode;
    9.24      } PACKED u;
    9.25  } PACKED dom0_op_t; /* 80 bytes */
    9.26