Commit 6823c0fe authored by Dave Jones's avatar Dave Jones

[PATCH] Correct indentation on x86-64 MTRR driver.

Somewhere along the line, indentation on this file went mental.
parent feed5186
/* x86-64 MTRR (Memory Type Range Register) driver.
Based largely upon arch/i386/kernel/mtrr.c
Copyright (C) 1997-2000 Richard Gooch
Copyright (C) 1997-2000 Richard Gooch
Copyright (C) 2002 Dave Jones.
This library is free software; you can redistribute it and/or
......@@ -20,7 +20,7 @@
(For earlier history, see arch/i386/kernel/mtrr.c)
v2.00 September 2001 Dave Jones <davej@suse.de>
Initial rewrite for x86-64.
Initial rewrite for x86-64.
Removal of non-Intel style MTRR code.
v2.01 June 2002 Dave Jones <davej@suse.de>
Removal of redundant abstraction layer.
......@@ -84,7 +84,7 @@
typedef u8 mtrr_type;
#define LINE_SIZE 80
#define LINE_SIZE 80
#ifdef CONFIG_SMP
#define set_mtrr(reg,base,size,type) set_mtrr_smp (reg, base, size, type)
......@@ -124,42 +124,42 @@ static void set_mtrr_prepare (struct set_mtrr_context *ctxt)
local_irq_save(ctxt->flags);
local_irq_disable();
/* Save value of CR4 and clear Page Global Enable (bit 7) */
/* Save value of CR4 and clear Page Global Enable (bit 7) */
if (cpu_has_pge) {
ctxt->cr4val = read_cr4();
write_cr4(ctxt->cr4val & ~(1UL << 7));
}
}
/* Disable and flush caches. Note that wbinvd flushes the TLBs as
a side-effect */
/* Disable and flush caches. Note that wbinvd flushes the TLBs as
a side-effect */
cr0 = read_cr0() | 0x40000000;
wbinvd();
wbinvd();
write_cr0(cr0);
wbinvd();
wbinvd();
/* Disable MTRRs, and set the default type to uncached */
/* Disable MTRRs, and set the default type to uncached */
rdmsr(MSR_MTRRdefType, ctxt->deftype_lo, ctxt->deftype_hi);
wrmsr(MSR_MTRRdefType, ctxt->deftype_lo & 0xf300UL, ctxt->deftype_hi);
}
/* Restore the processor after a set_mtrr_prepare */
/* Restore the processor after a set_mtrr_prepare */
static void set_mtrr_done (struct set_mtrr_context *ctxt)
{
/* Flush caches and TLBs */
wbinvd();
/* Flush caches and TLBs */
wbinvd();
/* Restore MTRRdefType */
/* Restore MTRRdefType */
wrmsr(MSR_MTRRdefType, ctxt->deftype_lo, ctxt->deftype_hi);
/* Enable caches */
/* Enable caches */
write_cr0(read_cr0() & 0xbfffffff);
/* Restore value of CR4 */
/* Restore value of CR4 */
if (cpu_has_pge)
write_cr4 (ctxt->cr4val);
/* Re-enable interrupts locally (if enabled previously) */
/* Re-enable interrupts locally (if enabled previously) */
local_irq_restore(ctxt->flags);
}
......@@ -193,21 +193,21 @@ static void get_mtrr (unsigned int reg, u64 *base, u32 *size, mtrr_type * type)
rdmsr (MSR_MTRRphysMask(reg), mask_lo, mask_hi);
if ((mask_lo & 0x800) == 0) {
/* Invalid (i.e. free) range */
*base = 0;
*size = 0;
*type = 0;
return;
}
/* Invalid (i.e. free) range */
*base = 0;
*size = 0;
*type = 0;
return;
}
rdmsr (MSR_MTRRphysBase(reg), base_lo, base_hi);
/* Work out the shifted address mask. */
/* Work out the shifted address mask. */
newsize = (u64) mask_hi << 32 | (mask_lo & ~0x800);
newsize = ~newsize+1;
*size = (u32) newsize >> PAGE_SHIFT;
*base = base_hi << (32 - PAGE_SHIFT) | base_lo >> PAGE_SHIFT;
*type = base_lo & 0xff;
*base = base_hi << (32 - PAGE_SHIFT) | base_lo >> PAGE_SHIFT;
*type = base_lo & 0xff;
}
......@@ -224,7 +224,7 @@ static void get_mtrr (unsigned int reg, u64 *base, u32 *size, mtrr_type * type)
static void set_mtrr_up (unsigned int reg, u64 base,
u32 size, mtrr_type type, int do_safe)
{
struct set_mtrr_context ctxt;
struct set_mtrr_context ctxt;
u64 base64;
u64 size64;
......@@ -232,8 +232,8 @@ static void set_mtrr_up (unsigned int reg, u64 base,
set_mtrr_prepare (&ctxt);
if (size == 0) {
/* The invalid bit is kept in the mask, so we simply clear the
relevant mask register to disable a range. */
/* The invalid bit is kept in the mask, so we simply clear the
relevant mask register to disable a range. */
wrmsr (MSR_MTRRphysMask(reg), 0, 0);
} else {
base64 = (base << PAGE_SHIFT) & size_and_mask;
......@@ -242,7 +242,7 @@ static void set_mtrr_up (unsigned int reg, u64 base,
size64 = ~((size << PAGE_SHIFT) - 1);
size64 = size64 & size_and_mask;
wrmsr (MSR_MTRRphysMask(reg), (u32) (size64 | 0x800), (u32) (size64 >> 32));
}
}
if (do_safe)
set_mtrr_done (&ctxt);
}
......@@ -259,7 +259,7 @@ struct mtrr_var_range {
/* Get the MSR pair relating to a var range */
static void __init get_mtrr_var_range (unsigned int index,
struct mtrr_var_range *vr)
struct mtrr_var_range *vr)
{
rdmsr (MSR_MTRRphysBase(index), vr->base_lo, vr->base_hi);
rdmsr (MSR_MTRRphysMask(index), vr->mask_lo, vr->mask_hi);
......@@ -272,35 +272,35 @@ static int __init set_mtrr_var_range_testing (unsigned int index,
struct mtrr_var_range *vr)
{
u32 lo, hi;
int changed = FALSE;
int changed = FALSE;
rdmsr (MSR_MTRRphysBase(index), lo, hi);
if ((vr->base_lo & 0xfffff0ff) != (lo & 0xfffff0ff) ||
(vr->base_hi & 0x000fffff) != (hi & 0x000fffff)) {
wrmsr (MSR_MTRRphysBase(index), vr->base_lo, vr->base_hi);
changed = TRUE;
}
changed = TRUE;
}
rdmsr (MSR_MTRRphysMask(index), lo, hi);
if ((vr->mask_lo & 0xfffff800) != (lo & 0xfffff800) ||
(vr->mask_hi & 0x000fffff) != (hi & 0x000fffff)) {
wrmsr (MSR_MTRRphysMask(index), vr->mask_lo, vr->mask_hi);
changed = TRUE;
}
return changed;
changed = TRUE;
}
return changed;
}
static void __init get_fixed_ranges (mtrr_type * frs)
{
u32 *p = (u32 *) frs;
int i;
int i;
rdmsr (MSR_MTRRfix64K_00000, p[0], p[1]);
for (i = 0; i < 2; i++)
for (i = 0; i < 2; i++)
rdmsr (MSR_MTRRfix16K_80000 + i, p[2 + i * 2], p[3 + i * 2]);
for (i = 0; i < 8; i++)
for (i = 0; i < 8; i++)
rdmsr (MSR_MTRRfix4K_C0000 + i, p[6 + i * 2], p[7 + i * 2]);
}
......@@ -308,8 +308,8 @@ static void __init get_fixed_ranges (mtrr_type * frs)
static int __init set_fixed_ranges_testing (mtrr_type * frs)
{
u32 *p = (u32 *) frs;
int changed = FALSE;
int i;
int changed = FALSE;
int i;
u32 lo, hi;
printk (KERN_INFO "mtrr: rdmsr 64K_00000\n");
......@@ -317,8 +317,8 @@ static int __init set_fixed_ranges_testing (mtrr_type * frs)
if (p[0] != lo || p[1] != hi) {
printk (KERN_INFO "mtrr: Writing %x:%x to 64K MSR. lohi were %x:%x\n", p[0], p[1], lo, hi);
wrmsr (MSR_MTRRfix64K_00000, p[0], p[1]);
changed = TRUE;
}
changed = TRUE;
}
printk (KERN_INFO "mtrr: rdmsr 16K_80000\n");
for (i = 0; i < 2; i++) {
......@@ -326,9 +326,9 @@ static int __init set_fixed_ranges_testing (mtrr_type * frs)
if (p[2 + i * 2] != lo || p[3 + i * 2] != hi) {
printk (KERN_INFO "mtrr: Writing %x:%x to 16K MSR%d. lohi were %x:%x\n", p[2 + i * 2], p[3 + i * 2], i, lo, hi );
wrmsr (MSR_MTRRfix16K_80000 + i, p[2 + i * 2], p[3 + i * 2]);
changed = TRUE;
changed = TRUE;
}
}
}
printk (KERN_INFO "mtrr: rdmsr 4K_C0000\n");
for (i = 0; i < 8; i++) {
......@@ -337,18 +337,18 @@ static int __init set_fixed_ranges_testing (mtrr_type * frs)
if (p[6 + i * 2] != lo || p[7 + i * 2] != hi) {
printk (KERN_INFO "mtrr: Writing %x:%x to 4K MSR%d. lohi were %x:%x\n", p[6 + i * 2], p[7 + i * 2], i, lo, hi);
wrmsr (MSR_MTRRfix4K_C0000 + i, p[6 + i * 2], p[7 + i * 2]);
changed = TRUE;
changed = TRUE;
}
}
}
return changed;
return changed;
}
struct mtrr_state {
unsigned int num_var_ranges;
struct mtrr_var_range *var_ranges;
mtrr_type fixed_ranges[NUM_FIXED_RANGES];
mtrr_type def_type;
unsigned int num_var_ranges;
struct mtrr_var_range *var_ranges;
mtrr_type fixed_ranges[NUM_FIXED_RANGES];
mtrr_type def_type;
unsigned char enabled;
};
......@@ -356,23 +356,23 @@ struct mtrr_state {
/* Grab all of the MTRR state for this CPU into *state */
static void __init get_mtrr_state (struct mtrr_state *state)
{
unsigned int nvrs, i;
struct mtrr_var_range *vrs;
unsigned int nvrs, i;
struct mtrr_var_range *vrs;
u32 lo, dummy;
nvrs = state->num_var_ranges = get_num_var_ranges();
vrs = state->var_ranges
= kmalloc (nvrs * sizeof (struct mtrr_var_range), GFP_KERNEL);
if (vrs == NULL)
nvrs = state->num_var_ranges = 0;
vrs = state->var_ranges
= kmalloc (nvrs * sizeof (struct mtrr_var_range), GFP_KERNEL);
if (vrs == NULL)
nvrs = state->num_var_ranges = 0;
for (i = 0; i < nvrs; i++)
get_mtrr_var_range (i, &vrs[i]);
get_fixed_ranges (state->fixed_ranges);
for (i = 0; i < nvrs; i++)
get_mtrr_var_range (i, &vrs[i]);
get_fixed_ranges (state->fixed_ranges);
rdmsr (MSR_MTRRdefType, lo, dummy);
state->def_type = (lo & 0xff);
state->enabled = (lo & 0xc00) >> 10;
state->def_type = (lo & 0xff);
state->enabled = (lo & 0xc00) >> 10;
}
......@@ -392,26 +392,26 @@ static void __init finalize_mtrr_state (struct mtrr_state *state)
* [RETURNS] 0 if no changes made, else a mask indication what was changed.
*/
static u64 __init set_mtrr_state (struct mtrr_state *state,
struct set_mtrr_context *ctxt)
struct set_mtrr_context *ctxt)
{
unsigned int i;
unsigned int i;
u64 change_mask = 0;
for (i = 0; i < state->num_var_ranges; i++)
for (i = 0; i < state->num_var_ranges; i++)
if (set_mtrr_var_range_testing (i, &state->var_ranges[i]))
change_mask |= MTRR_CHANGE_MASK_VARIABLE;
change_mask |= MTRR_CHANGE_MASK_VARIABLE;
if (set_fixed_ranges_testing (state->fixed_ranges))
change_mask |= MTRR_CHANGE_MASK_FIXED;
/* Set_mtrr_restore restores the old value of MTRRdefType,
so to set it we fiddle with the saved value */
change_mask |= MTRR_CHANGE_MASK_FIXED;
/* Set_mtrr_restore restores the old value of MTRRdefType,
so to set it we fiddle with the saved value */
if ((ctxt->deftype_lo & 0xff) != state->def_type
|| ((ctxt->deftype_lo & 0xc00) >> 10) != state->enabled) {
ctxt->deftype_lo |= (state->def_type | state->enabled << 10);
change_mask |= MTRR_CHANGE_MASK_DEFTYPE;
}
ctxt->deftype_lo |= (state->def_type | state->enabled << 10);
change_mask |= MTRR_CHANGE_MASK_DEFTYPE;
}
return change_mask;
return change_mask;
}
......@@ -422,8 +422,8 @@ static volatile int wait_barrier_cache_enable = FALSE;
struct set_mtrr_data {
u64 smp_base;
u32 smp_size;
unsigned int smp_reg;
mtrr_type smp_type;
unsigned int smp_reg;
mtrr_type smp_type;
};
/*
......@@ -431,67 +431,67 @@ struct set_mtrr_data {
*/
static void ipi_handler (void *info)
{
struct set_mtrr_data *data = info;
struct set_mtrr_context ctxt;
struct set_mtrr_data *data = info;
struct set_mtrr_context ctxt;
set_mtrr_prepare (&ctxt);
/* Notify master that I've flushed and disabled my cache */
atomic_dec (&undone_count);
/* Notify master that I've flushed and disabled my cache */
atomic_dec (&undone_count);
while (wait_barrier_execute)
barrier ();
/* The master has cleared me to execute */
/* The master has cleared me to execute */
set_mtrr_up (data->smp_reg, data->smp_base, data->smp_size,
data->smp_type, FALSE);
data->smp_type, FALSE);
/* Notify master CPU that I've executed the function */
atomic_dec (&undone_count);
/* Notify master CPU that I've executed the function */
atomic_dec (&undone_count);
/* Wait for master to clear me to enable cache and return */
/* Wait for master to clear me to enable cache and return */
while (wait_barrier_cache_enable)
barrier ();
set_mtrr_done (&ctxt);
set_mtrr_done (&ctxt);
}
static void set_mtrr_smp (unsigned int reg, u64 base, u32 size, mtrr_type type)
{
struct set_mtrr_data data;
struct set_mtrr_context ctxt;
data.smp_reg = reg;
data.smp_base = base;
data.smp_size = size;
data.smp_type = type;
wait_barrier_execute = TRUE;
wait_barrier_cache_enable = TRUE;
struct set_mtrr_data data;
struct set_mtrr_context ctxt;
data.smp_reg = reg;
data.smp_base = base;
data.smp_size = size;
data.smp_type = type;
wait_barrier_execute = TRUE;
wait_barrier_cache_enable = TRUE;
atomic_set (&undone_count, num_online_cpus() - 1);
/* Start the ball rolling on other CPUs */
if (smp_call_function (ipi_handler, &data, 1, 0) != 0)
panic ("mtrr: timed out waiting for other CPUs\n");
/* Start the ball rolling on other CPUs */
if (smp_call_function (ipi_handler, &data, 1, 0) != 0)
panic ("mtrr: timed out waiting for other CPUs\n");
/* Flush and disable the local CPU's cache */
/* Flush and disable the local CPU's cache */
set_mtrr_prepare (&ctxt);
/* Wait for all other CPUs to flush and disable their caches */
/* Wait for all other CPUs to flush and disable their caches */
while (atomic_read (&undone_count) > 0)
barrier ();
/* Set up for completion wait and then release other CPUs to change MTRRs */
atomic_set (&undone_count, num_online_cpus() - 1);
wait_barrier_execute = FALSE;
wait_barrier_execute = FALSE;
set_mtrr_up (reg, base, size, type, FALSE);
/* Now wait for other CPUs to complete the function */
/* Now wait for other CPUs to complete the function */
while (atomic_read (&undone_count) > 0)
barrier ();
/* Now all CPUs should have finished the function. Release the barrier to
allow them to re-enable their caches and return from their interrupt,
then enable the local cache and return */
wait_barrier_cache_enable = FALSE;
set_mtrr_done (&ctxt);
/* Now all CPUs should have finished the function. Release the barrier to
allow them to re-enable their caches and return from their interrupt,
then enable the local cache and return */
wait_barrier_cache_enable = FALSE;
set_mtrr_done (&ctxt);
}
......@@ -500,44 +500,44 @@ static void __init mtrr_state_warn (u32 mask)
{
if (!mask)
return;
if (mask & MTRR_CHANGE_MASK_FIXED)
printk ("mtrr: your CPUs had inconsistent fixed MTRR settings\n");
if (mask & MTRR_CHANGE_MASK_VARIABLE)
printk ("mtrr: your CPUs had inconsistent variable MTRR settings\n");
if (mask & MTRR_CHANGE_MASK_DEFTYPE)
printk ("mtrr: your CPUs had inconsistent MTRRdefType settings\n");
printk ("mtrr: probably your BIOS does not setup all CPUs\n");
if (mask & MTRR_CHANGE_MASK_FIXED)
printk ("mtrr: your CPUs had inconsistent fixed MTRR settings\n");
if (mask & MTRR_CHANGE_MASK_VARIABLE)
printk ("mtrr: your CPUs had inconsistent variable MTRR settings\n");
if (mask & MTRR_CHANGE_MASK_DEFTYPE)
printk ("mtrr: your CPUs had inconsistent MTRRdefType settings\n");
printk ("mtrr: probably your BIOS does not setup all CPUs\n");
}
#endif /* CONFIG_SMP */
#endif /* CONFIG_SMP */
static inline char * attrib_to_str (int x)
{
return (x <= 6) ? mtrr_strings[x] : "?";
return (x <= 6) ? mtrr_strings[x] : "?";
}
static void __init init_table (void)
{
int i, max;
int i, max;
max = get_num_var_ranges ();
max = get_num_var_ranges ();
if ((usage_table = kmalloc (max * sizeof *usage_table, GFP_KERNEL))==NULL) {
printk ("mtrr: could not allocate\n");
return;
}
printk ("mtrr: could not allocate\n");
return;
}
for (i = 0; i < max; i++)
usage_table[i] = 1;
#ifdef USERSPACE_INTERFACE
if ((ascii_buffer = kmalloc (max * LINE_SIZE, GFP_KERNEL)) == NULL) {
printk ("mtrr: could not allocate\n");
return;
}
ascii_buf_bytes = 0;
compute_ascii ();
printk ("mtrr: could not allocate\n");
return;
}
ascii_buf_bytes = 0;
compute_ascii ();
#endif
}
......@@ -548,18 +548,18 @@ static void __init init_table (void)
*/
static int get_free_region(void)
{
int i, max;
mtrr_type ltype;
int i, max;
mtrr_type ltype;
u64 lbase;
u32 lsize;
max = get_num_var_ranges ();
max = get_num_var_ranges ();
for (i = 0; i < max; ++i) {
get_mtrr (i, &lbase, &lsize, &ltype);
if (lsize == 0)
return i;
}
return -ENOSPC;
}
return -ENOSPC;
}
......@@ -597,16 +597,16 @@ static int get_free_region(void)
int mtrr_add_page (u64 base, u32 size, unsigned int type, char increment)
{
int i, max;
mtrr_type ltype;
int i, max;
mtrr_type ltype;
u64 lbase, last;
u32 lsize;
if (base + size < 0x100) {
printk (KERN_WARNING
"mtrr: cannot set region below 1 MiB (0x%Lx000,0x%x000)\n",
base, size);
return -EINVAL;
base, size);
return -EINVAL;
}
#if defined(__x86_64__) && defined(CONFIG_AGP)
......@@ -621,7 +621,7 @@ int mtrr_add_page (u64 base, u32 size, unsigned int type, char increment)
#endif
/* Check upper bits of base and last are equal and lower bits are 0
for base and 1 for last */
for base and 1 for last */
last = base + size - 1;
for (lbase = base; !(lbase & 1) && (last & 1);
lbase = lbase >> 1, last = last >> 1) ;
......@@ -630,35 +630,36 @@ int mtrr_add_page (u64 base, u32 size, unsigned int type, char increment)
printk (KERN_WARNING
"mtrr: base(0x%Lx000) is not aligned on a size(0x%x000) boundary\n",
base, size);
return -EINVAL;
}
return -EINVAL;
}
if (type >= MTRR_NUM_TYPES) {
printk ("mtrr: type: %u illegal\n", type);
return -EINVAL;
}
printk ("mtrr: type: %u illegal\n", type);
return -EINVAL;
}
/* If the type is WC, check that this processor supports it */
/* If the type is WC, check that this processor supports it */
if ((type == MTRR_TYPE_WRCOMB) && !have_wrcomb()) {
printk (KERN_WARNING
"mtrr: your processor doesn't support write-combining\n");
return -ENOSYS;
}
return -ENOSYS;
}
if (base & (size_or_mask>>PAGE_SHIFT)) {
printk (KERN_WARNING "mtrr: base(%lx) exceeds the MTRR width(%lx)\n",
base, (size_or_mask>>PAGE_SHIFT));
(unsigned long) base,
(unsigned long) (size_or_mask>>PAGE_SHIFT));
return -EINVAL;
}
if (size & (size_or_mask>>PAGE_SHIFT)) {
printk (KERN_WARNING "mtrr: size exceeds the MTRR width\n");
return -EINVAL;
}
return -EINVAL;
}
increment = increment ? 1 : 0;
max = get_num_var_ranges ();
/* Search for existing MTRR */
increment = increment ? 1 : 0;
max = get_num_var_ranges ();
/* Search for existing MTRR */
down (&mtrr_lock);
for (i = 0; i < max; ++i) {
get_mtrr (i, &lbase, &lsize, &ltype);
......@@ -667,15 +668,15 @@ int mtrr_add_page (u64 base, u32 size, unsigned int type, char increment)
if ((base < lbase) && (base + size <= lbase))
continue;
/* At this point we know there is some kind of overlap/enclosure */
/* At this point we know there is some kind of overlap/enclosure */
if ((base < lbase) || (base + size > lbase + lsize)) {
up (&mtrr_lock);
printk (KERN_WARNING
"mtrr: 0x%Lx000,0x%x000 overlaps existing"
" 0x%Lx000,0x%x000\n", base, size, lbase, lsize);
return -EINVAL;
}
/* New region is enclosed by an existing region */
return -EINVAL;
}
/* New region is enclosed by an existing region */
if (ltype != type) {
if (type == MTRR_TYPE_UNCACHABLE)
continue;
......@@ -685,26 +686,26 @@ int mtrr_add_page (u64 base, u32 size, unsigned int type, char increment)
base, size,
attrib_to_str (ltype),
attrib_to_str (type));
return -EINVAL;
}
return -EINVAL;
}
if (increment)
++usage_table[i];
compute_ascii ();
compute_ascii ();
up (&mtrr_lock);
return i;
}
/* Search for an empty MTRR */
return i;
}
/* Search for an empty MTRR */
i = get_free_region();
if (i < 0) {
up (&mtrr_lock);
printk ("mtrr: no more MTRRs available\n");
return i;
}
set_mtrr (i, base, size, type);
usage_table[i] = 1;
compute_ascii ();
printk ("mtrr: no more MTRRs available\n");
return i;
}
set_mtrr (i, base, size, type);
usage_table[i] = 1;
compute_ascii ();
up (&mtrr_lock);
return i;
return i;
}
......@@ -744,10 +745,10 @@ int mtrr_add_page (u64 base, u32 size, unsigned int type, char increment)
int mtrr_add (u64 base, u32 size, unsigned int type, char increment)
{
if ((base & (PAGE_SIZE - 1)) || (size & (PAGE_SIZE - 1))) {
printk ("mtrr: size and base must be multiples of 4 kiB\n");
printk ("mtrr: size and base must be multiples of 4 kiB\n");
printk ("mtrr: size: 0x%x base: 0x%Lx\n", size, base);
return -EINVAL;
}
return -EINVAL;
}
return mtrr_add_page (base >> PAGE_SHIFT, size >> PAGE_SHIFT, type,
increment);
}
......@@ -767,56 +768,56 @@ int mtrr_add (u64 base, u32 size, unsigned int type, char increment)
* On success the register is returned, on failure a negative error
* code.
*/
int mtrr_del_page (int reg, u64 base, u32 size)
{
int i, max;
mtrr_type ltype;
int i, max;
mtrr_type ltype;
u64 lbase;
u32 lsize;
max = get_num_var_ranges ();
max = get_num_var_ranges ();
down (&mtrr_lock);
if (reg < 0) {
/* Search for existing MTRR */
/* Search for existing MTRR */
for (i = 0; i < max; ++i) {
get_mtrr (i, &lbase, &lsize, &ltype);
if (lbase == base && lsize == size) {
reg = i;
break;
}
}
reg = i;
break;
}
}
if (reg < 0) {
up (&mtrr_lock);
printk ("mtrr: no MTRR for %Lx000,%x000 found\n", base, size);
return -EINVAL;
return -EINVAL;
}
}
}
if (reg >= max) {
up (&mtrr_lock);
printk ("mtrr: register: %d too big\n", reg);
return -EINVAL;
}
printk ("mtrr: register: %d too big\n", reg);
return -EINVAL;
}
get_mtrr (reg, &lbase, &lsize, &ltype);
if (lsize < 1) {
up (&mtrr_lock);
printk ("mtrr: MTRR %d not used\n", reg);
return -EINVAL;
}
printk ("mtrr: MTRR %d not used\n", reg);
return -EINVAL;
}
if (usage_table[reg] < 1) {
up (&mtrr_lock);
printk ("mtrr: reg: %d has count=0\n", reg);
return -EINVAL;
}
printk ("mtrr: reg: %d has count=0\n", reg);
return -EINVAL;
}
if (--usage_table[reg] < 1)
set_mtrr (reg, 0, 0, 0);
compute_ascii ();
compute_ascii ();
up (&mtrr_lock);
return reg;
return reg;
}
......@@ -834,14 +835,14 @@ int mtrr_del_page (int reg, u64 base, u32 size)
* On success the register is returned, on failure a negative error
* code.
*/
int mtrr_del (int reg, u64 base, u32 size)
{
if ((base & (PAGE_SIZE - 1)) || (size & (PAGE_SIZE - 1))) {
printk ("mtrr: size and base must be multiples of 4 kiB\n");
printk ("mtrr: size and base must be multiples of 4 kiB\n");
printk ("mtrr: size: 0x%x base: 0x%Lx\n", size, base);
return -EINVAL;
}
return -EINVAL;
}
return mtrr_del_page (reg, base >> PAGE_SHIFT, size >> PAGE_SHIFT);
}
......@@ -851,64 +852,64 @@ int mtrr_del (int reg, u64 base, u32 size)
static int mtrr_file_add (u64 base, u32 size, unsigned int type,
struct file *file, int page)
{
int reg, max;
unsigned int *fcount = file->private_data;
int reg, max;
unsigned int *fcount = file->private_data;
max = get_num_var_ranges ();
max = get_num_var_ranges ();
if (fcount == NULL) {
if ((fcount =
kmalloc (max * sizeof *fcount, GFP_KERNEL)) == NULL) {
printk ("mtrr: could not allocate\n");
return -ENOMEM;
printk ("mtrr: could not allocate\n");
return -ENOMEM;
}
memset (fcount, 0, max * sizeof *fcount);
file->private_data = fcount;
}
memset (fcount, 0, max * sizeof *fcount);
file->private_data = fcount;
}
if (!page) {
if (!page) {
if ((base & (PAGE_SIZE - 1)) || (size & (PAGE_SIZE - 1))) {
printk
("mtrr: size and base must be multiples of 4 kiB\n");
printk ("mtrr: size: 0x%x base: 0x%Lx\n", size, base);
return -EINVAL;
return -EINVAL;
}
base >>= PAGE_SHIFT;
size >>= PAGE_SHIFT;
}
base >>= PAGE_SHIFT;
size >>= PAGE_SHIFT;
}
reg = mtrr_add_page (base, size, type, 1);
reg = mtrr_add_page (base, size, type, 1);
if (reg >= 0)
++fcount[reg];
return reg;
return reg;
}
static int mtrr_file_del (u64 base, u32 size,
struct file *file, int page)
struct file *file, int page)
{
int reg;
unsigned int *fcount = file->private_data;
int reg;
unsigned int *fcount = file->private_data;
if (!page) {
if (!page) {
if ((base & (PAGE_SIZE - 1)) || (size & (PAGE_SIZE - 1))) {
printk
("mtrr: size and base must be multiples of 4 kiB\n");
printk ("mtrr: size: 0x%x base: 0x%Lx\n", size, base);
return -EINVAL;
return -EINVAL;
}
base >>= PAGE_SHIFT;
size >>= PAGE_SHIFT;
}
base >>= PAGE_SHIFT;
size >>= PAGE_SHIFT;
}
reg = mtrr_del_page (-1, base, size);
reg = mtrr_del_page (-1, base, size);
if (reg < 0)
return reg;
if (fcount == NULL)
return reg;
if (fcount[reg] < 1)
return -EINVAL;
--fcount[reg];
return reg;
--fcount[reg];
return reg;
}
......@@ -924,8 +925,8 @@ static ssize_t mtrr_read (struct file *file, char *buf, size_t len,
if (copy_to_user (buf, ascii_buffer + *ppos, len))
return -EFAULT;
*ppos += len;
return len;
*ppos += len;
return len;
}
......@@ -939,240 +940,240 @@ static ssize_t mtrr_write (struct file *file, const char *buf,
int i, err, reg;
u64 base;
u32 size;
char *ptr;
char line[LINE_SIZE];
char *ptr;
char line[LINE_SIZE];
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
/* Can't seek (pwrite) on this device */
/* Can't seek (pwrite) on this device */
if (ppos != &file->f_pos)
return -ESPIPE;
memset (line, 0, LINE_SIZE);
memset (line, 0, LINE_SIZE);
if (len > LINE_SIZE)
len = LINE_SIZE;
if (copy_from_user (line, buf, len - 1))
return -EFAULT;
ptr = line + strlen (line) - 1;
ptr = line + strlen (line) - 1;
if (*ptr == '\n')
*ptr = '\0';
if (!strncmp (line, "disable=", 8)) {
reg = simple_strtoul (line + 8, &ptr, 0);
err = mtrr_del_page (reg, 0, 0);
reg = simple_strtoul (line + 8, &ptr, 0);
err = mtrr_del_page (reg, 0, 0);
if (err < 0)
return err;
return len;
}
return len;
}
if (strncmp (line, "base=", 5)) {
printk ("mtrr: no \"base=\" in line: \"%s\"\n", line);
return -EINVAL;
}
printk ("mtrr: no \"base=\" in line: \"%s\"\n", line);
return -EINVAL;
}
base = simple_strtoull (line + 5, &ptr, 0);
base = simple_strtoull (line + 5, &ptr, 0);
for (; isspace (*ptr); ++ptr) ;
if (strncmp (ptr, "size=", 5)) {
printk ("mtrr: no \"size=\" in line: \"%s\"\n", line);
return -EINVAL;
}
printk ("mtrr: no \"size=\" in line: \"%s\"\n", line);
return -EINVAL;
}
size = simple_strtoull (ptr + 5, &ptr, 0);
size = simple_strtoull (ptr + 5, &ptr, 0);
if ((base & 0xfff) || (size & 0xfff)) {
printk ("mtrr: size and base must be multiples of 4 kiB\n");
printk ("mtrr: size and base must be multiples of 4 kiB\n");
printk ("mtrr: size: 0x%x base: 0x%Lx\n", size, base);
return -EINVAL;
}
return -EINVAL;
}
for (; isspace (*ptr); ++ptr) ;
if (strncmp (ptr, "type=", 5)) {
printk ("mtrr: no \"type=\" in line: \"%s\"\n", line);
return -EINVAL;
}
ptr += 5;
printk ("mtrr: no \"type=\" in line: \"%s\"\n", line);
return -EINVAL;
}
ptr += 5;
for (; isspace (*ptr); ++ptr) ;
for (i = 0; i < MTRR_NUM_TYPES; ++i) {
if (strcmp (ptr, mtrr_strings[i]))
continue;
base >>= PAGE_SHIFT;
size >>= PAGE_SHIFT;
base >>= PAGE_SHIFT;
size >>= PAGE_SHIFT;
err = mtrr_add_page ((u64) base, size, i, 1);
if (err < 0)
return err;
return len;
}
printk ("mtrr: illegal type: \"%s\"\n", ptr);
return -EINVAL;
return len;
}
printk ("mtrr: illegal type: \"%s\"\n", ptr);
return -EINVAL;
}
static int mtrr_ioctl (struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
unsigned int cmd, unsigned long arg)
{
int err;
mtrr_type type;
struct mtrr_sentry sentry;
struct mtrr_gentry gentry;
int err;
mtrr_type type;
struct mtrr_sentry sentry;
struct mtrr_gentry gentry;
switch (cmd) {
default:
return -ENOIOCTLCMD;
default:
return -ENOIOCTLCMD;
case MTRRIOC_ADD_ENTRY:
case MTRRIOC_ADD_ENTRY:
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
if (copy_from_user (&sentry, (void *) arg, sizeof sentry))
return -EFAULT;
return -EFAULT;
err = mtrr_file_add (sentry.base, sentry.size, sentry.type,
file, 0);
if (err < 0)
return err;
break;
break;
case MTRRIOC_SET_ENTRY:
case MTRRIOC_SET_ENTRY:
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
if (copy_from_user (&sentry, (void *) arg, sizeof sentry))
return -EFAULT;
err = mtrr_add (sentry.base, sentry.size, sentry.type, 0);
return -EFAULT;
err = mtrr_add (sentry.base, sentry.size, sentry.type, 0);
if (err < 0)
return err;
break;
break;
case MTRRIOC_DEL_ENTRY:
case MTRRIOC_DEL_ENTRY:
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
if (copy_from_user (&sentry, (void *) arg, sizeof sentry))
return -EFAULT;
err = mtrr_file_del (sentry.base, sentry.size, file, 0);
return -EFAULT;
err = mtrr_file_del (sentry.base, sentry.size, file, 0);
if (err < 0)
return err;
break;
break;
case MTRRIOC_KILL_ENTRY:
case MTRRIOC_KILL_ENTRY:
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
if (copy_from_user (&sentry, (void *) arg, sizeof sentry))
return -EFAULT;
err = mtrr_del (-1, sentry.base, sentry.size);
return -EFAULT;
err = mtrr_del (-1, sentry.base, sentry.size);
if (err < 0)
return err;
break;
break;
case MTRRIOC_GET_ENTRY:
case MTRRIOC_GET_ENTRY:
if (copy_from_user (&gentry, (void *) arg, sizeof gentry))
return -EFAULT;
return -EFAULT;
if (gentry.regnum >= get_num_var_ranges ())
return -EINVAL;
get_mtrr (gentry.regnum, (u64*) &gentry.base, &gentry.size, &type);
/* Hide entries that go above 4GB */
/* Hide entries that go above 4GB */
if (gentry.base + gentry.size > 0x100000
|| gentry.size == 0x100000)
gentry.base = gentry.size = gentry.type = 0;
else {
gentry.base <<= PAGE_SHIFT;
gentry.size <<= PAGE_SHIFT;
gentry.type = type;
}
gentry.base = gentry.size = gentry.type = 0;
else {
gentry.base <<= PAGE_SHIFT;
gentry.size <<= PAGE_SHIFT;
gentry.type = type;
}
if (copy_to_user ((void *) arg, &gentry, sizeof gentry))
return -EFAULT;
break;
return -EFAULT;
break;
case MTRRIOC_ADD_PAGE_ENTRY:
case MTRRIOC_ADD_PAGE_ENTRY:
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
if (copy_from_user (&sentry, (void *) arg, sizeof sentry))
return -EFAULT;
return -EFAULT;
err = mtrr_file_add (sentry.base, sentry.size, sentry.type, file, 1);
if (err < 0)
return err;
break;
break;
case MTRRIOC_SET_PAGE_ENTRY:
case MTRRIOC_SET_PAGE_ENTRY:
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
if (copy_from_user (&sentry, (void *) arg, sizeof sentry))
return -EFAULT;
err = mtrr_add_page (sentry.base, sentry.size, sentry.type, 0);
return -EFAULT;
err = mtrr_add_page (sentry.base, sentry.size, sentry.type, 0);
if (err < 0)
return err;
break;
break;
case MTRRIOC_DEL_PAGE_ENTRY:
case MTRRIOC_DEL_PAGE_ENTRY:
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
if (copy_from_user (&sentry, (void *) arg, sizeof sentry))
return -EFAULT;
err = mtrr_file_del (sentry.base, sentry.size, file, 1);
return -EFAULT;
err = mtrr_file_del (sentry.base, sentry.size, file, 1);
if (err < 0)
return err;
break;
break;
case MTRRIOC_KILL_PAGE_ENTRY:
case MTRRIOC_KILL_PAGE_ENTRY:
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
if (copy_from_user (&sentry, (void *) arg, sizeof sentry))
return -EFAULT;
err = mtrr_del_page (-1, sentry.base, sentry.size);
return -EFAULT;
err = mtrr_del_page (-1, sentry.base, sentry.size);
if (err < 0)
return err;
break;
break;
case MTRRIOC_GET_PAGE_ENTRY:
case MTRRIOC_GET_PAGE_ENTRY:
if (copy_from_user (&gentry, (void *) arg, sizeof gentry))
return -EFAULT;
return -EFAULT;
if (gentry.regnum >= get_num_var_ranges ())
return -EINVAL;
get_mtrr (gentry.regnum, (u64*) &gentry.base, &gentry.size, &type);
gentry.type = type;
gentry.type = type;
if (copy_to_user ((void *) arg, &gentry, sizeof gentry))
return -EFAULT;
break;
}
return 0;
return -EFAULT;
break;
}
return 0;
}
static int mtrr_close (struct inode *ino, struct file *file)
{
int i, max;
unsigned int *fcount = file->private_data;
int i, max;
unsigned int *fcount = file->private_data;
if (fcount == NULL)
return 0;
lock_kernel ();
max = get_num_var_ranges ();
max = get_num_var_ranges ();
for (i = 0; i < max; ++i) {
while (fcount[i] > 0) {
if (mtrr_del (i, 0, 0) < 0)
printk ("mtrr: reg %d not used\n", i);
--fcount[i];
--fcount[i];
}
}
}
unlock_kernel ();
kfree (fcount);
file->private_data = NULL;
return 0;
kfree (fcount);
file->private_data = NULL;
return 0;
}
static struct file_operations mtrr_fops = {
.owner = THIS_MODULE,
.read = mtrr_read,
.write = mtrr_write,
.read = mtrr_read,
.write = mtrr_write,
.ioctl = mtrr_ioctl,
.release = mtrr_close,
};
......@@ -1185,38 +1186,38 @@ static devfs_handle_t devfs_handle;
static void compute_ascii (void)
{
char factor;
int i, max;
mtrr_type type;
char factor;
int i, max;
mtrr_type type;
u64 base;
u32 size;
ascii_buf_bytes = 0;
max = get_num_var_ranges ();
ascii_buf_bytes = 0;
max = get_num_var_ranges ();
for (i = 0; i < max; i++) {
get_mtrr (i, &base, &size, &type);
if (size == 0)
usage_table[i] = 0;
else {
if (size < (0x100000 >> PAGE_SHIFT)) {
/* less than 1MB */
factor = 'K';
size <<= PAGE_SHIFT - 10;
/* less than 1MB */
factor = 'K';
size <<= PAGE_SHIFT - 10;
} else {
factor = 'M';
size >>= 20 - PAGE_SHIFT;
}
factor = 'M';
size >>= 20 - PAGE_SHIFT;
}
sprintf (ascii_buffer + ascii_buf_bytes,
"reg%02i: base=0x%05Lx000 (%4iMB), size=%4i%cB: %s, count=%d\n",
i, base, (u32) base >> (20 - PAGE_SHIFT), size, factor,
attrib_to_str (type), usage_table[i]);
attrib_to_str (type), usage_table[i]);
ascii_buf_bytes += strlen (ascii_buffer + ascii_buf_bytes);
}
}
}
devfs_set_file_size (devfs_handle, ascii_buf_bytes);
devfs_set_file_size (devfs_handle, ascii_buf_bytes);
#ifdef CONFIG_PROC_FS
if (proc_root_mtrr)
proc_root_mtrr->size = ascii_buf_bytes;
if (proc_root_mtrr)
proc_root_mtrr->size = ascii_buf_bytes;
#endif
}
......@@ -1225,7 +1226,7 @@ static void compute_ascii (void)
EXPORT_SYMBOL (mtrr_add);
EXPORT_SYMBOL (mtrr_del);
static void __init mtrr_setup (void)
{
printk ("mtrr: v%s)\n", MTRR_VERSION);
......@@ -1234,7 +1235,7 @@ static void __init mtrr_setup (void)
/* Query the width (in bits) of the physical
addressable memory on the Hammer family. */
if ((cpuid_eax (0x80000000) >= 0x80000008)) {
u32 phys_addr;
u32 phys_addr;
phys_addr = cpuid_eax (0x80000008) & 0xff;
size_or_mask = ~((1L << phys_addr) - 1);
/*
......@@ -1263,30 +1264,30 @@ void __init mtrr_init_secondary_cpu (void)
{
u64 mask;
int count;
struct set_mtrr_context ctxt;
struct set_mtrr_context ctxt;
/* Note that this is not ideal, since the cache is only flushed/disabled
for this CPU while the MTRRs are changed, but changing this requires
more invasive changes to the way the kernel boots */
/* Note that this is not ideal, since the cache is only flushed/disabled
for this CPU while the MTRRs are changed, but changing this requires
more invasive changes to the way the kernel boots */
set_mtrr_prepare (&ctxt);
mask = set_mtrr_state (&smp_mtrr_state, &ctxt);
set_mtrr_done (&ctxt);
mask = set_mtrr_state (&smp_mtrr_state, &ctxt);
set_mtrr_done (&ctxt);
/* Use the atomic bitops to update the global mask */
/* Use the atomic bitops to update the global mask */
for (count = 0; count < sizeof mask * 8; ++count) {
if (mask & 0x01)
set_bit (count, &smp_changes_mask);
mask >>= 1;
}
mask >>= 1;
}
}
#endif /* CONFIG_SMP */
#endif /* CONFIG_SMP */
int __init mtrr_init (void)
{
#ifdef CONFIG_SMP
/* mtrr_setup() should already have been called from mtrr_init_boot_cpu() */
/* mtrr_setup() should already have been called from mtrr_init_boot_cpu() */
finalize_mtrr_state (&smp_mtrr_state);
mtrr_state_warn (smp_changes_mask);
......@@ -1295,17 +1296,17 @@ int __init mtrr_init (void)
#endif
#ifdef CONFIG_PROC_FS
proc_root_mtrr = create_proc_entry ("mtrr", S_IWUSR | S_IRUGO, &proc_root);
if (proc_root_mtrr) {
proc_root_mtrr->owner = THIS_MODULE;
proc_root_mtrr->proc_fops = &mtrr_fops;
}
proc_root_mtrr = create_proc_entry ("mtrr", S_IWUSR | S_IRUGO, &proc_root);
if (proc_root_mtrr) {
proc_root_mtrr->owner = THIS_MODULE;
proc_root_mtrr->proc_fops = &mtrr_fops;
}
#endif
#ifdef CONFIG_DEVFS_FS
devfs_handle = devfs_register (NULL, "cpu/mtrr", DEVFS_FL_DEFAULT, 0, 0,
S_IFREG | S_IRUGO | S_IWUSR,
&mtrr_fops, NULL);
devfs_handle = devfs_register (NULL, "cpu/mtrr", DEVFS_FL_DEFAULT, 0, 0,
S_IFREG | S_IRUGO | S_IWUSR,
&mtrr_fops, NULL);
#endif
init_table ();
return 0;
init_table ();
return 0;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment