Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
6823c0fe
Commit
6823c0fe
authored
Oct 17, 2002
by
Dave Jones
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[PATCH] Correct indentation on x86-64 MTRR driver.
Somewhere along the line, indentation on this file went mental.
parent
feed5186
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
360 additions
and
359 deletions
+360
-359
arch/x86_64/kernel/mtrr.c
arch/x86_64/kernel/mtrr.c
+360
-359
No files found.
arch/x86_64/kernel/mtrr.c
View file @
6823c0fe
/* 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
;
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment