From: BitKeeper B. <ri...@su...> - 2005-01-03 04:31:52
|
ChangeSet 1.1550.1.76, 2004/12/31 12:47:51+00:00, ka...@sc... Add microcode driver to Xen. linux-2.6.10-xen-sparse/arch/xen/configs/xen0_defconfig | 1 linux-2.6.10-xen-sparse/arch/xen/i386/Kconfig | 33 - linux-2.6.10-xen-sparse/arch/xen/i386/kernel/Makefile | 2 linux-2.6.10-xen-sparse/arch/xen/i386/kernel/microcode.c | 163 +++++ xen/arch/x86/dom0_ops.c | 7 xen/arch/x86/microcode.c | 456 +++++++++++++++ xen/include/asm-x86/processor.h | 30 xen/include/public/dom0_ops.h | 10 8 files changed, 680 insertions(+), 22 deletions(-) diff -Nru a/linux-2.6.10-xen-sparse/arch/xen/configs/xen0_defconfig b/linux-2.6.10-xen-sparse/arch/xen/configs/xen0_defconfig --- a/linux-2.6.10-xen-sparse/arch/xen/configs/xen0_defconfig 2004-12-31 08:00:35 -05:00 +++ b/linux-2.6.10-xen-sparse/arch/xen/configs/xen0_defconfig 2004-12-31 08:00:35 -05:00 @@ -115,6 +115,7 @@ # CONFIG_HPET_EMULATE_RTC is not set # CONFIG_SMP is not set CONFIG_PREEMPT=y +CONFIG_MICROCODE=y CONFIG_X86_CPUID=y # diff -Nru a/linux-2.6.10-xen-sparse/arch/xen/i386/Kconfig b/linux-2.6.10-xen-sparse/arch/xen/i386/Kconfig --- a/linux-2.6.10-xen-sparse/arch/xen/i386/Kconfig 2004-12-31 08:00:35 -05:00 +++ b/linux-2.6.10-xen-sparse/arch/xen/i386/Kconfig 2004-12-31 08:00:35 -05:00 @@ -440,22 +440,23 @@ # Enabling this feature will cause a message to be printed when the P4 # enters thermal throttling. -#config MICROCODE -# tristate "/dev/cpu/microcode - Intel IA32 CPU microcode support" -# ---help--- -# If you say Y here and also to "/dev file system support" in the -# 'File systems' section, you will be able to update the microcode on -# Intel processors in the IA32 family, e.g. Pentium Pro, Pentium II, -# Pentium III, Pentium 4, Xeon etc. You will obviously need the -# actual microcode binary data itself which is not shipped with the -# Linux kernel. -# -# For latest news and information on obtaining all the required -# ingredients for this driver, check: -# <http://www.urbanmyth.org/microcode/>. -# -# To compile this driver as a module, choose M here: the -# module will be called microcode. +config MICROCODE + tristate "/dev/cpu/microcode - Intel IA32 CPU microcode support" + depends on XEN_PRIVILEGED_GUEST + ---help--- + If you say Y here and also to "/dev file system support" in the + 'File systems' section, you will be able to update the microcode on + Intel processors in the IA32 family, e.g. Pentium Pro, Pentium II, + Pentium III, Pentium 4, Xeon etc. You will obviously need the + actual microcode binary data itself which is not shipped with the + Linux kernel. + + For latest news and information on obtaining all the required + ingredients for this driver, check: + <http://www.urbanmyth.org/microcode/>. + + To compile this driver as a module, choose M here: the + module will be called microcode. #config X86_MSR # tristate "/dev/cpu/*/msr - Model-specific register support" diff -Nru a/linux-2.6.10-xen-sparse/arch/xen/i386/kernel/Makefile b/linux-2.6.10-xen-sparse/arch/xen/i386/kernel/Makefile --- a/linux-2.6.10-xen-sparse/arch/xen/i386/kernel/Makefile 2004-12-31 08:00:35 -05:00 +++ b/linux-2.6.10-xen-sparse/arch/xen/i386/kernel/Makefile 2004-12-31 08:00:35 -05:00 @@ -25,7 +25,7 @@ c-obj-$(CONFIG_MCA) += mca.o c-obj-$(CONFIG_X86_MSR) += msr.o c-obj-$(CONFIG_X86_CPUID) += cpuid.o -c-obj-$(CONFIG_MICROCODE) += microcode.o +obj-$(CONFIG_MICROCODE) += microcode.o c-obj-$(CONFIG_APM) += apm.o c-obj-$(CONFIG_X86_SMP) += smp.o smpboot.o c-obj-$(CONFIG_X86_TRAMPOLINE) += trampoline.o diff -Nru a/linux-2.6.10-xen-sparse/arch/xen/i386/kernel/microcode.c b/linux-2.6.10-xen-sparse/arch/xen/i386/kernel/microcode.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/linux-2.6.10-xen-sparse/arch/xen/i386/kernel/microcode.c 2004-12-31 08:00:35 -05:00 @@ -0,0 +1,163 @@ +/* + * Intel CPU Microcode Update Driver for Linux + * + * Copyright (C) 2000-2004 Tigran Aivazian + * + * This driver allows to upgrade microcode on Intel processors + * belonging to IA-32 family - PentiumPro, Pentium II, + * Pentium III, Xeon, Pentium 4, etc. + * + * Reference: Section 8.10 of Volume III, Intel Pentium 4 Manual, + * Order Number 245472 or free download from: + * + * http://developer.intel.com/design/pentium4/manuals/245472.htm + * + * For more information, go to http://www.urbanmyth.org/microcode + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +//#define DEBUG /* pr_debug */ +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/sched.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/vmalloc.h> +#include <linux/miscdevice.h> +#include <linux/spinlock.h> +#include <linux/mm.h> +#include <linux/syscalls.h> + +#include <asm/msr.h> +#include <asm/uaccess.h> +#include <asm/processor.h> + +MODULE_DESCRIPTION("Intel CPU (IA-32) Microcode Update Driver"); +MODULE_AUTHOR("Tigran Aivazian <ti...@ve...>"); +MODULE_LICENSE("GPL"); + +#define MICROCODE_VERSION "1.14-xen" + +#define DEFAULT_UCODE_DATASIZE (2000) /* 2000 bytes */ +#define MC_HEADER_SIZE (sizeof (microcode_header_t)) /* 48 bytes */ +#define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE) /* 2048 bytes */ + +/* no concurrent ->write()s are allowed on /dev/cpu/microcode */ +static DECLARE_MUTEX(microcode_sem); + +static void __user *user_buffer; /* user area microcode data buffer */ +static unsigned int user_buffer_size; /* it's size */ + +static int microcode_open (struct inode *unused1, struct file *unused2) +{ + return capable(CAP_SYS_RAWIO) ? 0 : -EPERM; +} + + +static int do_microcode_update (void) +{ + int err; + dom0_op_t op; + + err = sys_mlock((unsigned long)user_buffer, user_buffer_size); + if (err != 0) + return err; + + op.cmd = DOM0_MICROCODE; + op.u.microcode.data = user_buffer; + op.u.microcode.length = user_buffer_size; + err = HYPERVISOR_dom0_op(&op); + + (void)sys_munlock((unsigned long)user_buffer, user_buffer_size); + + return err; +} + +static ssize_t microcode_write (struct file *file, const char __user *buf, size_t len, loff_t *ppos) +{ + ssize_t ret; + + if (len < DEFAULT_UCODE_TOTALSIZE) { + printk(KERN_ERR "microcode: not enough data\n"); + return -EINVAL; + } + + if ((len >> PAGE_SHIFT) > num_physpages) { + printk(KERN_ERR "microcode: too much data (max %ld pages)\n", num_physpages); + return -EINVAL; + } + + down(µcode_sem); + + user_buffer = (void __user *) buf; + user_buffer_size = (int) len; + + ret = do_microcode_update(); + if (!ret) + ret = (ssize_t)len; + + up(µcode_sem); + + return ret; +} + +static int microcode_ioctl (struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + switch (cmd) { + /* + * XXX: will be removed after microcode_ctl + * is updated to ignore failure of this ioctl() + */ + case MICROCODE_IOCFREE: + return 0; + default: + return -EINVAL; + } + return -EINVAL; +} + +static struct file_operations microcode_fops = { + .owner = THIS_MODULE, + .write = microcode_write, + .ioctl = microcode_ioctl, + .open = microcode_open, +}; + +static struct miscdevice microcode_dev = { + .minor = MICROCODE_MINOR, + .name = "microcode", + .devfs_name = "cpu/microcode", + .fops = µcode_fops, +}; + +static int __init microcode_init (void) +{ + int error; + + error = misc_register(µcode_dev); + if (error) { + printk(KERN_ERR + "microcode: can't misc_register on minor=%d\n", + MICROCODE_MINOR); + return error; + } + + printk(KERN_INFO + "IA-32 Microcode Update Driver: v" MICROCODE_VERSION " <ti...@ve...>\n"); + return 0; +} + +static void __exit microcode_exit (void) +{ + misc_deregister(µcode_dev); + printk(KERN_INFO "IA-32 Microcode Update Driver v" MICROCODE_VERSION " unregistered\n"); +} + +module_init(microcode_init) +module_exit(microcode_exit) +MODULE_ALIAS_MISCDEV(MICROCODE_MINOR); diff -Nru a/xen/arch/x86/dom0_ops.c b/xen/arch/x86/dom0_ops.c --- a/xen/arch/x86/dom0_ops.c 2004-12-31 08:00:35 -05:00 +++ b/xen/arch/x86/dom0_ops.c 2004-12-31 08:00:35 -05:00 @@ -130,6 +130,13 @@ } break; + case DOM0_MICROCODE: + { + extern int microcode_update(void *buf, unsigned long len); + ret = microcode_update(op->u.microcode.data, op->u.microcode.length); + } + break; + default: ret = -ENOSYS; |