aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>2004-11-29 15:46:14 +0000
committerkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>2004-11-29 15:46:14 +0000
commitb77c39cbdcf15abcf8cfded7dac921fa31078bc6 (patch)
treed605d2ae6c0e9420b85b05a3ed58128cf7400229
parent2b9c469bec58196f555c5686a5ba114b8d6c4844 (diff)
parent3ef3ee4b43019cead82889ec22b683dce3f45ecd (diff)
downloadxen-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--.rootkeys2
-rw-r--r--linux-2.6.9-xen-sparse/arch/xen/configs/xen0_defconfig1
-rw-r--r--linux-2.6.9-xen-sparse/arch/xen/i386/Kconfig5
-rw-r--r--linux-2.6.9-xen-sparse/arch/xen/i386/kernel/cpu/Makefile2
-rw-r--r--linux-2.6.9-xen-sparse/arch/xen/i386/kernel/cpu/mtrr/Makefile16
-rw-r--r--linux-2.6.9-xen-sparse/arch/xen/i386/kernel/cpu/mtrr/main.c165
-rw-r--r--linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/mach-xen/setup_arch_post.h3
-rw-r--r--xen/arch/x86/dom0_ops.c37
-rw-r--r--xen/include/public/dom0_ops.h53
9 files changed, 282 insertions, 2 deletions
diff --git a/.rootkeys b/.rootkeys
index e92266e5c1..8bda240f8f 100644
--- a/.rootkeys
+++ b/.rootkeys
@@ -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, &ltype);
+ 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 */