diff options
author | kaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk> | 2004-11-29 15:46:14 +0000 |
---|---|---|
committer | kaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk> | 2004-11-29 15:46:14 +0000 |
commit | b77c39cbdcf15abcf8cfded7dac921fa31078bc6 (patch) | |
tree | d605d2ae6c0e9420b85b05a3ed58128cf7400229 | |
parent | 2b9c469bec58196f555c5686a5ba114b8d6c4844 (diff) | |
parent | 3ef3ee4b43019cead82889ec22b683dce3f45ecd (diff) | |
download | xen-b77c39cbdcf15abcf8cfded7dac921fa31078bc6.tar.gz xen-b77c39cbdcf15abcf8cfded7dac921fa31078bc6.tar.bz2 xen-b77c39cbdcf15abcf8cfded7dac921fa31078bc6.zip |
bitkeeper revision 1.1159.187.35 (41ab44466PjrfuHbuNH4oKGm-TGC5w)
Merge scramble.cl.cam.ac.uk:/auto/groups/xeno/BK/xen-2.0-testing.bk
into scramble.cl.cam.ac.uk:/local/scratch/kaf24/xen-2.0-testing.bk
-rw-r--r-- | .rootkeys | 2 | ||||
-rw-r--r-- | linux-2.6.9-xen-sparse/arch/xen/configs/xen0_defconfig | 1 | ||||
-rw-r--r-- | linux-2.6.9-xen-sparse/arch/xen/i386/Kconfig | 5 | ||||
-rw-r--r-- | linux-2.6.9-xen-sparse/arch/xen/i386/kernel/cpu/Makefile | 2 | ||||
-rw-r--r-- | linux-2.6.9-xen-sparse/arch/xen/i386/kernel/cpu/mtrr/Makefile | 16 | ||||
-rw-r--r-- | linux-2.6.9-xen-sparse/arch/xen/i386/kernel/cpu/mtrr/main.c | 165 | ||||
-rw-r--r-- | linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/mach-xen/setup_arch_post.h | 3 | ||||
-rw-r--r-- | xen/arch/x86/dom0_ops.c | 37 | ||||
-rw-r--r-- | xen/include/public/dom0_ops.h | 53 |
9 files changed, 282 insertions, 2 deletions
@@ -138,6 +138,8 @@ 40f56238eczveJ86k_4hNxCLRQIF-g linux-2.6.9-xen-sparse/arch/xen/i386/kernel/Makefile 40f56238rXVTJQKbBuXXLH52qEArcg linux-2.6.9-xen-sparse/arch/xen/i386/kernel/cpu/Makefile 40f562385s4lr6Zg92gExe7UQ4A76Q linux-2.6.9-xen-sparse/arch/xen/i386/kernel/cpu/common.c +41ab440bnpxZdWShZrGgM9pPaz5rmA linux-2.6.9-xen-sparse/arch/xen/i386/kernel/cpu/mtrr/Makefile +41ab440bBKWz-aEOEojU4PAMXe3Ppg linux-2.6.9-xen-sparse/arch/xen/i386/kernel/cpu/mtrr/main.c 40f56238XDtHSijkAFlbv1PT8Bhw_Q linux-2.6.9-xen-sparse/arch/xen/i386/kernel/entry.S 40f56238bnvciAuyzAiMkdzGErYt1A linux-2.6.9-xen-sparse/arch/xen/i386/kernel/head.S 40f58a0d31M2EkuPbG94ns_nOi0PVA linux-2.6.9-xen-sparse/arch/xen/i386/kernel/i386_ksyms.c diff --git a/linux-2.6.9-xen-sparse/arch/xen/configs/xen0_defconfig b/linux-2.6.9-xen-sparse/arch/xen/configs/xen0_defconfig index 80bd0dbc2a..7d7cd9b99b 100644 --- a/linux-2.6.9-xen-sparse/arch/xen/configs/xen0_defconfig +++ b/linux-2.6.9-xen-sparse/arch/xen/configs/xen0_defconfig @@ -110,6 +110,7 @@ CONFIG_X86_CPUID=y # CONFIG_EDD is not set CONFIG_NOHIGHMEM=y # CONFIG_HIGHMEM4G is not set +CONFIG_MTRR=y CONFIG_HAVE_DEC_LOCK=y # CONFIG_REGPARM is not set diff --git a/linux-2.6.9-xen-sparse/arch/xen/i386/Kconfig b/linux-2.6.9-xen-sparse/arch/xen/i386/Kconfig index 6e22f7ca21..02b89bcb9f 100644 --- a/linux-2.6.9-xen-sparse/arch/xen/i386/Kconfig +++ b/linux-2.6.9-xen-sparse/arch/xen/i386/Kconfig @@ -564,6 +564,11 @@ config HAVE_ARCH_BOOTMEM_NODE # low memory. Setting this option will put user-space page table # entries in high memory. +config MTRR + bool + depends on XEN_PRIVILEGED_GUEST + default y + #config MTRR # bool "MTRR (Memory Type Range Register) support" # ---help--- diff --git a/linux-2.6.9-xen-sparse/arch/xen/i386/kernel/cpu/Makefile b/linux-2.6.9-xen-sparse/arch/xen/i386/kernel/cpu/Makefile index 478e023a6d..2f65f0a835 100644 --- a/linux-2.6.9-xen-sparse/arch/xen/i386/kernel/cpu/Makefile +++ b/linux-2.6.9-xen-sparse/arch/xen/i386/kernel/cpu/Makefile @@ -18,7 +18,7 @@ c-obj-y += umc.o #obj-$(CONFIG_X86_MCE) += ../../../../i386/kernel/cpu/mcheck/ -#obj-$(CONFIG_MTRR) += ../../../../i386/kernel/cpu/mtrr/ +obj-$(CONFIG_MTRR) += mtrr/ #obj-$(CONFIG_CPU_FREQ) += ../../../../i386/kernel/cpu/cpufreq/ c-link := diff --git a/linux-2.6.9-xen-sparse/arch/xen/i386/kernel/cpu/mtrr/Makefile b/linux-2.6.9-xen-sparse/arch/xen/i386/kernel/cpu/mtrr/Makefile new file mode 100644 index 0000000000..e25eb7264e --- /dev/null +++ b/linux-2.6.9-xen-sparse/arch/xen/i386/kernel/cpu/mtrr/Makefile @@ -0,0 +1,16 @@ +obj-y := main.o +c-obj-y := if.o + +c-link := + +$(patsubst %.o,$(obj)/%.c,$(c-obj-y) $(c-link)): $(obj)/mtrr.h + @ln -fsn $(srctree)/arch/i386/kernel/cpu/mtrr/$(notdir $@) $@ + +$(patsubst %.o,$(obj)/%.c,$(obj-y)): $(obj)/mtrr.h + +$(obj)/mtrr.h: + @ln -fsn $(srctree)/arch/i386/kernel/cpu/mtrr/mtrr.h $@ + +obj-y += $(c-obj-y) + +clean-files += $(patsubst %.o,%.c,$(c-obj-y) $(c-obj-) $(c-link)) diff --git a/linux-2.6.9-xen-sparse/arch/xen/i386/kernel/cpu/mtrr/main.c b/linux-2.6.9-xen-sparse/arch/xen/i386/kernel/cpu/mtrr/main.c new file mode 100644 index 0000000000..c06cf9396c --- /dev/null +++ b/linux-2.6.9-xen-sparse/arch/xen/i386/kernel/cpu/mtrr/main.c @@ -0,0 +1,165 @@ +#include <linux/init.h> +#include <linux/proc_fs.h> +#include <linux/ctype.h> +#include <linux/module.h> +#include <linux/seq_file.h> +#include <asm/uaccess.h> + +#include <asm/mtrr.h> +#include "mtrr.h" + +void generic_get_mtrr(unsigned int reg, unsigned long *base, + unsigned int *size, mtrr_type * type) +{ + dom0_op_t op; + + op.cmd = DOM0_READ_MEMTYPE; + op.u.read_memtype.reg = reg; + (void)HYPERVISOR_dom0_op(&op); + + *size = op.u.read_memtype.nr_pfns; + *base = op.u.read_memtype.pfn; + *type = op.u.read_memtype.type; +} + +struct mtrr_ops generic_mtrr_ops = { + .use_intel_if = 1, + .get = generic_get_mtrr, +}; + +struct mtrr_ops *mtrr_if = &generic_mtrr_ops; +unsigned int num_var_ranges; +unsigned int *usage_table; + +void __init set_num_var_ranges(void) +{ + dom0_op_t op; + + for (num_var_ranges = 0; ; num_var_ranges++) { + op.cmd = DOM0_READ_MEMTYPE; + op.u.read_memtype.reg = num_var_ranges; + if (HYPERVISOR_dom0_op(&op) != 0) + break; + } +} + +static void __init init_table(void) +{ + int i, max; + + max = num_var_ranges; + if ((usage_table = kmalloc(max * sizeof *usage_table, GFP_KERNEL)) + == NULL) { + printk(KERN_ERR "mtrr: could not allocate\n"); + return; + } + for (i = 0; i < max; i++) + usage_table[i] = 0; +} + +int mtrr_add_page(unsigned long base, unsigned long size, + unsigned int type, char increment) +{ + int error; + dom0_op_t op; + + op.cmd = DOM0_ADD_MEMTYPE; + op.u.add_memtype.pfn = base; + op.u.add_memtype.nr_pfns = size; + op.u.add_memtype.type = type; + if ((error = HYPERVISOR_dom0_op(&op))) + return error; + + if (increment) + ++usage_table[op.u.add_memtype.reg]; + + return op.u.add_memtype.reg; +} + +int +mtrr_add(unsigned long base, unsigned long size, unsigned int type, + char increment) +{ + if ((base & (PAGE_SIZE - 1)) || (size & (PAGE_SIZE - 1))) { + printk(KERN_WARNING "mtrr: size and base must be multiples of 4 kiB\n"); + printk(KERN_DEBUG "mtrr: size: 0x%lx base: 0x%lx\n", size, base); + return -EINVAL; + } + return mtrr_add_page(base >> PAGE_SHIFT, size >> PAGE_SHIFT, type, + increment); +} + +int mtrr_del_page(int reg, unsigned long base, unsigned long size) +{ + int i, max; + mtrr_type ltype; + unsigned long lbase; + unsigned int lsize; + int error = -EINVAL; + dom0_op_t op; + + max = num_var_ranges; + if (reg < 0) { + /* Search for existing MTRR */ + for (i = 0; i < max; ++i) { + mtrr_if->get(i, &lbase, &lsize, <ype); + if (lbase == base && lsize == size) { + reg = i; + break; + } + } + if (reg < 0) { + printk(KERN_DEBUG "mtrr: no MTRR for %lx000,%lx000 found\n", base, + size); + goto out; + } + } + if (usage_table[reg] < 1) { + printk(KERN_WARNING "mtrr: reg: %d has count=0\n", reg); + goto out; + } + if (--usage_table[reg] < 1) { + op.cmd = DOM0_DEL_MEMTYPE; + op.u.del_memtype.handle = 0; + op.u.add_memtype.reg = reg; + (void)HYPERVISOR_dom0_op(&op); + } + error = reg; + out: + return error; +} + +int +mtrr_del(int reg, unsigned long base, unsigned long size) +{ + if ((base & (PAGE_SIZE - 1)) || (size & (PAGE_SIZE - 1))) { + printk(KERN_INFO "mtrr: size and base must be multiples of 4 kiB\n"); + printk(KERN_DEBUG "mtrr: size: 0x%lx base: 0x%lx\n", size, base); + return -EINVAL; + } + return mtrr_del_page(reg, base >> PAGE_SHIFT, size >> PAGE_SHIFT); +} + +EXPORT_SYMBOL(mtrr_add); +EXPORT_SYMBOL(mtrr_del); + +static int __init mtrr_init(void) +{ + struct cpuinfo_x86 *c = &boot_cpu_data; + + if (!(xen_start_info.flags & SIF_PRIVILEGED)) + return -ENODEV; + + if ((!cpu_has(c, X86_FEATURE_MTRR)) && + (!cpu_has(c, X86_FEATURE_K6_MTRR)) && + (!cpu_has(c, X86_FEATURE_CYRIX_ARR)) && + (!cpu_has(c, X86_FEATURE_CENTAUR_MCR))) + return -ENODEV; + + set_num_var_ranges(); + init_table(); + + return 0; +} + +subsys_initcall(mtrr_init); diff --git a/linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/mach-xen/setup_arch_post.h b/linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/mach-xen/setup_arch_post.h index 8f6c7b2daa..3791c91ae0 100644 --- a/linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/mach-xen/setup_arch_post.h +++ b/linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/mach-xen/setup_arch_post.h @@ -28,8 +28,9 @@ void __init machine_specific_modify_cpu_capabilities(struct cpuinfo_x86 *c) clear_bit(X86_FEATURE_DE, c->x86_capability); clear_bit(X86_FEATURE_PSE, c->x86_capability); clear_bit(X86_FEATURE_PGE, c->x86_capability); - clear_bit(X86_FEATURE_MTRR, c->x86_capability); clear_bit(X86_FEATURE_FXSR, c->x86_capability); + if (!(xen_start_info.flags & SIF_PRIVILEGED)) + clear_bit(X86_FEATURE_MTRR, c->x86_capability); } extern void hypervisor_callback(void); diff --git a/xen/arch/x86/dom0_ops.c b/xen/arch/x86/dom0_ops.c index 057a8b3e77..b632e539c7 100644 --- a/xen/arch/x86/dom0_ops.c +++ b/xen/arch/x86/dom0_ops.c @@ -21,6 +21,9 @@ #include <asm/shadow.h> #include <public/sched_ctl.h> +#include <asm/mtrr.h> +#include "mtrr/mtrr.h" + #define TRC_DOM0OP_ENTER_BASE 0x00020000 #define TRC_DOM0OP_LEAVE_BASE 0x00030000 @@ -93,6 +96,40 @@ long arch_do_dom0_op(dom0_op_t *op, dom0_op_t *u_dom0_op) } break; + case DOM0_ADD_MEMTYPE: + { + ret = mtrr_add_page( + op->u.add_memtype.pfn, + op->u.add_memtype.nr_pfns, + op->u.add_memtype.type, + 1); + } + break; + + case DOM0_DEL_MEMTYPE: + { + ret = mtrr_del_page(op->u.del_memtype.reg, 0, 0); + } + break; + + case DOM0_READ_MEMTYPE: + { + unsigned long pfn; + unsigned int nr_pfns; + mtrr_type type; + + ret = -EINVAL; + if ( op->u.read_memtype.reg < num_var_ranges ) + { + mtrr_if->get(op->u.read_memtype.reg, &pfn, &nr_pfns, &type); + (void)__put_user(pfn, &u_dom0_op->u.read_memtype.pfn); + (void)__put_user(nr_pfns, &u_dom0_op->u.read_memtype.nr_pfns); + (void)__put_user(type, &u_dom0_op->u.read_memtype.type); + ret = 0; + } + } + break; + default: ret = -ENOSYS; diff --git a/xen/include/public/dom0_ops.h b/xen/include/public/dom0_ops.h index 9339bcc318..f8c7bab6d3 100644 --- a/xen/include/public/dom0_ops.h +++ b/xen/include/public/dom0_ops.h @@ -336,6 +336,56 @@ typedef struct { u32 type; /* 8: vm_assist cmd */ } PACKED dom0_setdomainvmassist_t; /* 12 bytes */ +/* + * Request memory range (@pfn, @pfn+@nr_pfns-1) to have type @type. + * On x86, @type is an architecture-defined MTRR memory type. + * On success, returns the MTRR that was used (@reg) and a handle that can + * be passed to DOM0_DEL_MEMTYPE to accurately tear down the new setting. + * (x86-specific). + */ +#define DOM0_ADD_MEMTYPE 31 +typedef struct { + /* IN variables. */ + memory_t pfn; /* 0 */ + MEMORY_PADDING; + memory_t nr_pfns; /* 8 */ + MEMORY_PADDING; + u32 type; /* 16 */ + u32 __pad0; + /* OUT variables. */ + u32 handle; /* 24 */ + u32 reg; /* 28 */ +} PACKED dom0_add_memtype_t; /* 32 bytes */ + +/* + * Tear down an existing memory-range type. If @handle is remembered then it + * should be passed in to accurately tear down the correct setting (in case + * of overlapping memory regions with differing types). If it is not known + * then @handle should be set to zero. In all cases @reg must be set. + * (x86-specific). + */ +#define DOM0_DEL_MEMTYPE 32 +typedef struct { + /* IN variables. */ + u32 handle; /* 0 */ + u32 reg; /* 4 */ +} PACKED dom0_del_memtype_t; /* 8 bytes */ + +/* Read current type of an MTRR (x86-specific). */ +#define DOM0_READ_MEMTYPE 33 +typedef struct { + /* IN variables. */ + u32 reg; /* 0 */ + u32 __pad0; + /* OUT variables. */ + memory_t pfn; /* 8 */ + MEMORY_PADDING; + memory_t nr_pfns; /* 16 */ + MEMORY_PADDING; + u32 type; /* 24 */ + u32 __pad1; +} PACKED dom0_read_memtype_t; /* 32 bytes */ + typedef struct { u32 cmd; /* 0 */ u32 interface_version; /* 4 */ /* DOM0_INTERFACE_VERSION */ @@ -366,6 +416,9 @@ typedef struct { dom0_setdomainmaxmem_t setdomainmaxmem; dom0_getpageframeinfo2_t getpageframeinfo2; dom0_setdomainvmassist_t setdomainvmassist; + dom0_add_memtype_t add_memtype; + dom0_del_memtype_t del_memtype; + dom0_read_memtype_t read_memtype; } PACKED u; } PACKED dom0_op_t; /* 80 bytes */ |