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