blob: 852018b109c5f0429e75f4d879467912b07b5d20 [file] [log] [blame]
#include <linux/init.h>
#include <linux/mm.h>
#include <asm/pat.h>
#include "mtrr.h"
#include <xen/xen.h>
#include <xen/interface/platform.h>
#include <asm/xen/hypervisor.h>
#include <asm/xen/hypercall.h>
static void xen_set_mtrr(unsigned int reg, unsigned long base,
unsigned long size, mtrr_type type)
{
struct xen_platform_op op;
int error;
/* mtrr_ops->set() is called once per CPU,
* but Xen's ops apply to all CPUs.
*/
if (smp_processor_id())
return;
if (size == 0) {
op.cmd = XENPF_del_memtype;
op.u.del_memtype.handle = 0;
op.u.del_memtype.reg = reg;
} else {
op.cmd = XENPF_add_memtype;
op.u.add_memtype.mfn = base;
op.u.add_memtype.nr_mfns = size;
op.u.add_memtype.type = type;
}
error = HYPERVISOR_dom0_op(&op);
BUG_ON(error != 0);
}
static void xen_get_mtrr(unsigned int reg, unsigned long *base,
unsigned long *size, mtrr_type *type)
{
struct xen_platform_op op;
op.cmd = XENPF_read_memtype;
op.u.read_memtype.reg = reg;
if (HYPERVISOR_dom0_op(&op) != 0) {
*base = 0;
*size = 0;
*type = 0;
return;
}
*size = op.u.read_memtype.nr_mfns;
*base = op.u.read_memtype.mfn;
*type = op.u.read_memtype.type;
}
static int __init xen_num_var_ranges(void)
{
int ranges;
struct xen_platform_op op;
op.cmd = XENPF_read_memtype;
for (ranges = 0; ; ranges++) {
op.u.read_memtype.reg = ranges;
if (HYPERVISOR_dom0_op(&op) != 0)
break;
}
return ranges;
}
/*
* DOM0 TODO: Need to fill in the remaining mtrr methods to have full
* working userland mtrr support.
*/
static struct mtrr_ops xen_mtrr_ops = {
.vendor = X86_VENDOR_UNKNOWN,
.get_free_region = generic_get_free_region,
.set = xen_set_mtrr,
.get = xen_get_mtrr,
.have_wrcomb = positive_have_wrcomb,
.validate_add_page = generic_validate_add_page,
.use_intel_if = 0,
.num_var_ranges = xen_num_var_ranges,
};
void __init xen_init_mtrr(void)
{
/*
* Check that we're running under Xen, and privileged enough
* to play with MTRRs.
*/
if (!xen_initial_domain())
return;
/*
* Check that the CPU has an MTRR implementation we can
* support.
*/
if (cpu_has_mtrr ||
cpu_has_k6_mtrr ||
cpu_has_cyrix_arr ||
cpu_has_centaur_mcr) {
mtrr_if = &xen_mtrr_ops;
pat_init();
}
}