aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/mm/pat.c
diff options
context:
space:
mode:
authorVenki Pallipadi <venkatesh.pallipadi@intel.com>2008-05-29 15:01:44 -0400
committerIngo Molnar <mingo@elte.hu>2008-06-12 04:03:55 -0400
commitc26421d01986e1521043c8feb47256833df3bf31 (patch)
treea125634e3f93fb2f3f89f23808e4bd0cf41dc743 /arch/x86/mm/pat.c
parent46dd98a5c0b907f94742579ab605be1933a37abd (diff)
x86: fix Xorg crash with xf86MapVidMem error
Clarify the usage of mtrr_lookup() in PAT code, and to make PAT code resilient to mtrr lookup problems. Specifically, pat_x_mtrr_type() is restructured to highlight, under what conditions we look for mtrr hint. pat_x_mtrr_type() uses a default type when there are any errors in mtrr lookup (still maintaining the pat consistency). And, reserve_memtype() highlights its usage ot mtrr_lookup for request type of '-1' and also defaults in a sane way on any mtrr lookup failure. pat.c looks at mtrr type of a range to get a hint on what mapping type to request when user/API: (1) hasn't specified any type (/dev/mem mapping) and we do not want to take performance hit by always mapping UC_MINUS. This will be the case for /dev/mem mappings used to map BIOS area or ACPI region which are WB'able. In this case, as long as MTRR is not WB, PAT will request UC_MINUS for such mappings. (2) user/API requests WB mapping while in reality MTRR may have UC or WC. In this case, PAT can map as WB (without checking MTRR) and still effective type will be UC or WC. But, a subsequent request to map same region as UC or WC may fail, as the region will get trackked as WB in PAT list. Looking at MTRR hint helps us to track based on effective type rather than what user requested. Again, here mtrr_lookup is only used as hint and we fallback to WB mapping (as requested by user) as default. In both cases, after using the mtrr hint, we still go through the memtype list to make sure there are no inconsistencies among multiple users. Signed-off-by: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com> Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com> Tested-by: Rufus & Azrael <rufus-azrael@numericable.fr> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/mm/pat.c')
-rw-r--r--arch/x86/mm/pat.c49
1 files changed, 24 insertions, 25 deletions
diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c
index e83b770676d5..320d644a8107 100644
--- a/arch/x86/mm/pat.c
+++ b/arch/x86/mm/pat.c
@@ -164,32 +164,33 @@ static int pat_x_mtrr_type(u64 start, u64 end, unsigned long prot,
164 unsigned long pat_type; 164 unsigned long pat_type;
165 u8 mtrr_type; 165 u8 mtrr_type;
166 166
167 mtrr_type = mtrr_type_lookup(start, end);
168 if (mtrr_type == 0xFF) { /* MTRR not enabled */
169 *ret_prot = prot;
170 return 0;
171 }
172 if (mtrr_type == 0xFE) { /* MTRR match error */
173 *ret_prot = _PAGE_CACHE_UC;
174 return -1;
175 }
176 if (mtrr_type != MTRR_TYPE_UNCACHABLE &&
177 mtrr_type != MTRR_TYPE_WRBACK &&
178 mtrr_type != MTRR_TYPE_WRCOMB) { /* MTRR type unhandled */
179 *ret_prot = _PAGE_CACHE_UC;
180 return -1;
181 }
182
183 pat_type = prot & _PAGE_CACHE_MASK; 167 pat_type = prot & _PAGE_CACHE_MASK;
184 prot &= (~_PAGE_CACHE_MASK); 168 prot &= (~_PAGE_CACHE_MASK);
185 169
186 /* Currently doing intersection by hand. Optimize it later. */ 170 /*
171 * We return the PAT request directly for types where PAT takes
172 * precedence with respect to MTRR and for UC_MINUS.
173 * Consistency checks with other PAT requests is done later
174 * while going through memtype list.
175 */
187 if (pat_type == _PAGE_CACHE_WC) { 176 if (pat_type == _PAGE_CACHE_WC) {
188 *ret_prot = prot | _PAGE_CACHE_WC; 177 *ret_prot = prot | _PAGE_CACHE_WC;
178 return 0;
189 } else if (pat_type == _PAGE_CACHE_UC_MINUS) { 179 } else if (pat_type == _PAGE_CACHE_UC_MINUS) {
190 *ret_prot = prot | _PAGE_CACHE_UC_MINUS; 180 *ret_prot = prot | _PAGE_CACHE_UC_MINUS;
191 } else if (pat_type == _PAGE_CACHE_UC || 181 return 0;
192 mtrr_type == MTRR_TYPE_UNCACHABLE) { 182 } else if (pat_type == _PAGE_CACHE_UC) {
183 *ret_prot = prot | _PAGE_CACHE_UC;
184 return 0;
185 }
186
187 /*
188 * Look for MTRR hint to get the effective type in case where PAT
189 * request is for WB.
190 */
191 mtrr_type = mtrr_type_lookup(start, end);
192
193 if (mtrr_type == MTRR_TYPE_UNCACHABLE) {
193 *ret_prot = prot | _PAGE_CACHE_UC; 194 *ret_prot = prot | _PAGE_CACHE_UC;
194 } else if (mtrr_type == MTRR_TYPE_WRCOMB) { 195 } else if (mtrr_type == MTRR_TYPE_WRCOMB) {
195 *ret_prot = prot | _PAGE_CACHE_WC; 196 *ret_prot = prot | _PAGE_CACHE_WC;
@@ -246,14 +247,12 @@ int reserve_memtype(u64 start, u64 end, unsigned long req_type,
246 247
247 if (req_type == -1) { 248 if (req_type == -1) {
248 /* 249 /*
249 * Special case where caller wants to inherit from mtrr or 250 * Call mtrr_lookup to get the type hint. This is an
250 * existing pat mapping, defaulting to UC_MINUS in case of 251 * optimization for /dev/mem mmap'ers into WB memory (BIOS
251 * no match. 252 * tools and ACPI tools). Use WB request for WB memory and use
253 * UC_MINUS otherwise.
252 */ 254 */
253 u8 mtrr_type = mtrr_type_lookup(start, end); 255 u8 mtrr_type = mtrr_type_lookup(start, end);
254 if (mtrr_type == 0xFE) { /* MTRR match error */
255 err = -1;
256 }
257 256
258 if (mtrr_type == MTRR_TYPE_WRBACK) { 257 if (mtrr_type == MTRR_TYPE_WRBACK) {
259 req_type = _PAGE_CACHE_WB; 258 req_type = _PAGE_CACHE_WB;