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
nexedi
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