diff options
author | Toshi Kani <toshi.kani@hp.com> | 2015-05-26 04:28:06 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2015-05-27 08:40:56 -0400 |
commit | 9b3aca620883fc06636737c82a4d024b22182281 (patch) | |
tree | 4fd88b4f24b6db7b083e02db06b08b878e2f470c | |
parent | 7f0431e3dc8953f41e9433581c1fdd7ee45860b0 (diff) |
x86/mm/mtrr: Fix MTRR state checks in mtrr_type_lookup()
'mtrr_state.enabled' contains the FE (fixed MTRRs enabled)
and E (MTRRs enabled) flags in MSR_MTRRdefType. Intel SDM,
section 11.11.2.1, defines these flags as follows:
- All MTRRs are disabled when the E flag is clear.
The FE flag has no affect when the E flag is clear.
- The default type is enabled when the E flag is set.
- MTRR variable ranges are enabled when the E flag is set.
- MTRR fixed ranges are enabled when both E and FE flags
are set.
MTRR state checks in __mtrr_type_lookup() do not match with SDM.
Hence, this patch makes the following changes:
- The current code detects MTRRs disabled when both E and
FE flags are clear in mtrr_state.enabled. Fix to detect
MTRRs disabled when the E flag is clear.
- The current code does not check if the FE bit is set in
mtrr_state.enabled when looking at the fixed entries.
Fix to check the FE flag.
- The current code returns the default type when the E flag
is clear in mtrr_state.enabled. However, the default type
is UC when the E flag is clear. Remove the code as this
case is handled as MTRR disabled with the 1st change.
In addition, this patch defines the E and FE flags in
mtrr_state.enabled as follows.
- FE flag: MTRR_STATE_MTRR_FIXED_ENABLED
- E flag: MTRR_STATE_MTRR_ENABLED
print_mtrr_state() and x86_get_mtrr_mem_range() are also updated
accordingly.
Signed-off-by: Toshi Kani <toshi.kani@hp.com>
Signed-off-by: Borislav Petkov <bp@suse.de>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: Elliott@hp.com
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Luis R. Rodriguez <mcgrof@suse.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: dave.hansen@intel.com
Cc: linux-mm <linux-mm@kvack.org>
Cc: pebolle@tiscali.nl
Link: http://lkml.kernel.org/r/1431714237-880-4-git-send-email-toshi.kani@hp.com
Link: http://lkml.kernel.org/r/1432628901-18044-4-git-send-email-bp@alien8.de
Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r-- | arch/x86/include/asm/mtrr.h | 4 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/mtrr/cleanup.c | 3 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/mtrr/generic.c | 15 |
3 files changed, 14 insertions, 8 deletions
diff --git a/arch/x86/include/asm/mtrr.h b/arch/x86/include/asm/mtrr.h index f768f6298419..ef927948657c 100644 --- a/arch/x86/include/asm/mtrr.h +++ b/arch/x86/include/asm/mtrr.h | |||
@@ -127,4 +127,8 @@ struct mtrr_gentry32 { | |||
127 | _IOW(MTRR_IOCTL_BASE, 9, struct mtrr_sentry32) | 127 | _IOW(MTRR_IOCTL_BASE, 9, struct mtrr_sentry32) |
128 | #endif /* CONFIG_COMPAT */ | 128 | #endif /* CONFIG_COMPAT */ |
129 | 129 | ||
130 | /* Bit fields for enabled in struct mtrr_state_type */ | ||
131 | #define MTRR_STATE_MTRR_FIXED_ENABLED 0x01 | ||
132 | #define MTRR_STATE_MTRR_ENABLED 0x02 | ||
133 | |||
130 | #endif /* _ASM_X86_MTRR_H */ | 134 | #endif /* _ASM_X86_MTRR_H */ |
diff --git a/arch/x86/kernel/cpu/mtrr/cleanup.c b/arch/x86/kernel/cpu/mtrr/cleanup.c index 5f90b85ff22e..70d7c93f4550 100644 --- a/arch/x86/kernel/cpu/mtrr/cleanup.c +++ b/arch/x86/kernel/cpu/mtrr/cleanup.c | |||
@@ -98,7 +98,8 @@ x86_get_mtrr_mem_range(struct range *range, int nr_range, | |||
98 | continue; | 98 | continue; |
99 | base = range_state[i].base_pfn; | 99 | base = range_state[i].base_pfn; |
100 | if (base < (1<<(20-PAGE_SHIFT)) && mtrr_state.have_fixed && | 100 | if (base < (1<<(20-PAGE_SHIFT)) && mtrr_state.have_fixed && |
101 | (mtrr_state.enabled & 1)) { | 101 | (mtrr_state.enabled & MTRR_STATE_MTRR_ENABLED) && |
102 | (mtrr_state.enabled & MTRR_STATE_MTRR_FIXED_ENABLED)) { | ||
102 | /* Var MTRR contains UC entry below 1M? Skip it: */ | 103 | /* Var MTRR contains UC entry below 1M? Skip it: */ |
103 | printk(BIOS_BUG_MSG, i); | 104 | printk(BIOS_BUG_MSG, i); |
104 | if (base + size <= (1<<(20-PAGE_SHIFT))) | 105 | if (base + size <= (1<<(20-PAGE_SHIFT))) |
diff --git a/arch/x86/kernel/cpu/mtrr/generic.c b/arch/x86/kernel/cpu/mtrr/generic.c index e202d26f64a2..b0599dbb899a 100644 --- a/arch/x86/kernel/cpu/mtrr/generic.c +++ b/arch/x86/kernel/cpu/mtrr/generic.c | |||
@@ -119,14 +119,16 @@ static u8 __mtrr_type_lookup(u64 start, u64 end, u64 *partial_end, int *repeat) | |||
119 | if (!mtrr_state_set) | 119 | if (!mtrr_state_set) |
120 | return 0xFF; | 120 | return 0xFF; |
121 | 121 | ||
122 | if (!mtrr_state.enabled) | 122 | if (!(mtrr_state.enabled & MTRR_STATE_MTRR_ENABLED)) |
123 | return 0xFF; | 123 | return 0xFF; |
124 | 124 | ||
125 | /* Make end inclusive end, instead of exclusive */ | 125 | /* Make end inclusive end, instead of exclusive */ |
126 | end--; | 126 | end--; |
127 | 127 | ||
128 | /* Look in fixed ranges. Just return the type as per start */ | 128 | /* Look in fixed ranges. Just return the type as per start */ |
129 | if (mtrr_state.have_fixed && (start < 0x100000)) { | 129 | if ((start < 0x100000) && |
130 | (mtrr_state.have_fixed) && | ||
131 | (mtrr_state.enabled & MTRR_STATE_MTRR_FIXED_ENABLED)) { | ||
130 | int idx; | 132 | int idx; |
131 | 133 | ||
132 | if (start < 0x80000) { | 134 | if (start < 0x80000) { |
@@ -149,9 +151,6 @@ static u8 __mtrr_type_lookup(u64 start, u64 end, u64 *partial_end, int *repeat) | |||
149 | * Look of multiple ranges matching this address and pick type | 151 | * Look of multiple ranges matching this address and pick type |
150 | * as per MTRR precedence | 152 | * as per MTRR precedence |
151 | */ | 153 | */ |
152 | if (!(mtrr_state.enabled & 2)) | ||
153 | return mtrr_state.def_type; | ||
154 | |||
155 | prev_match = 0xFF; | 154 | prev_match = 0xFF; |
156 | for (i = 0; i < num_var_ranges; ++i) { | 155 | for (i = 0; i < num_var_ranges; ++i) { |
157 | unsigned short start_state, end_state, inclusive; | 156 | unsigned short start_state, end_state, inclusive; |
@@ -355,7 +354,9 @@ static void __init print_mtrr_state(void) | |||
355 | mtrr_attrib_to_str(mtrr_state.def_type)); | 354 | mtrr_attrib_to_str(mtrr_state.def_type)); |
356 | if (mtrr_state.have_fixed) { | 355 | if (mtrr_state.have_fixed) { |
357 | pr_debug("MTRR fixed ranges %sabled:\n", | 356 | pr_debug("MTRR fixed ranges %sabled:\n", |
358 | mtrr_state.enabled & 1 ? "en" : "dis"); | 357 | ((mtrr_state.enabled & MTRR_STATE_MTRR_ENABLED) && |
358 | (mtrr_state.enabled & MTRR_STATE_MTRR_FIXED_ENABLED)) ? | ||
359 | "en" : "dis"); | ||
359 | print_fixed(0x00000, 0x10000, mtrr_state.fixed_ranges + 0); | 360 | print_fixed(0x00000, 0x10000, mtrr_state.fixed_ranges + 0); |
360 | for (i = 0; i < 2; ++i) | 361 | for (i = 0; i < 2; ++i) |
361 | print_fixed(0x80000 + i * 0x20000, 0x04000, | 362 | print_fixed(0x80000 + i * 0x20000, 0x04000, |
@@ -368,7 +369,7 @@ static void __init print_mtrr_state(void) | |||
368 | print_fixed_last(); | 369 | print_fixed_last(); |
369 | } | 370 | } |
370 | pr_debug("MTRR variable ranges %sabled:\n", | 371 | pr_debug("MTRR variable ranges %sabled:\n", |
371 | mtrr_state.enabled & 2 ? "en" : "dis"); | 372 | mtrr_state.enabled & MTRR_STATE_MTRR_ENABLED ? "en" : "dis"); |
372 | high_width = (__ffs64(size_or_mask) - (32 - PAGE_SHIFT) + 3) / 4; | 373 | high_width = (__ffs64(size_or_mask) - (32 - PAGE_SHIFT) + 3) / 4; |
373 | 374 | ||
374 | for (i = 0; i < num_var_ranges; ++i) { | 375 | for (i = 0; i < num_var_ranges; ++i) { |