aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/mm/pat.c59
1 files changed, 29 insertions, 30 deletions
diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c
index 076187c76d7a..188e3e07eeeb 100644
--- a/arch/x86/mm/pat.c
+++ b/arch/x86/mm/pat.c
@@ -70,18 +70,22 @@ __setup("debugpat", pat_debug_setup);
70 70
71#ifdef CONFIG_X86_PAT 71#ifdef CONFIG_X86_PAT
72/* 72/*
73 * X86 PAT uses page flags WC and Uncached together to keep track of 73 * X86 PAT uses page flags arch_1 and uncached together to keep track of
74 * memory type of pages that have backing page struct. X86 PAT supports 3 74 * memory type of pages that have backing page struct.
75 * different memory types, _PAGE_CACHE_MODE_WB, _PAGE_CACHE_MODE_WC and 75 *
76 * _PAGE_CACHE_MODE_UC_MINUS and fourth state where page's memory type has not 76 * X86 PAT supports 4 different memory types:
77 * been changed from its default (value of -1 used to denote this). 77 * - _PAGE_CACHE_MODE_WB
78 * Note we do not support _PAGE_CACHE_MODE_UC here. 78 * - _PAGE_CACHE_MODE_WC
79 * - _PAGE_CACHE_MODE_UC_MINUS
80 * - _PAGE_CACHE_MODE_WT
81 *
82 * _PAGE_CACHE_MODE_WB is the default type.
79 */ 83 */
80 84
81#define _PGMT_DEFAULT 0 85#define _PGMT_WB 0
82#define _PGMT_WC (1UL << PG_arch_1) 86#define _PGMT_WC (1UL << PG_arch_1)
83#define _PGMT_UC_MINUS (1UL << PG_uncached) 87#define _PGMT_UC_MINUS (1UL << PG_uncached)
84#define _PGMT_WB (1UL << PG_uncached | 1UL << PG_arch_1) 88#define _PGMT_WT (1UL << PG_uncached | 1UL << PG_arch_1)
85#define _PGMT_MASK (1UL << PG_uncached | 1UL << PG_arch_1) 89#define _PGMT_MASK (1UL << PG_uncached | 1UL << PG_arch_1)
86#define _PGMT_CLEAR_MASK (~_PGMT_MASK) 90#define _PGMT_CLEAR_MASK (~_PGMT_MASK)
87 91
@@ -89,14 +93,14 @@ static inline enum page_cache_mode get_page_memtype(struct page *pg)
89{ 93{
90 unsigned long pg_flags = pg->flags & _PGMT_MASK; 94 unsigned long pg_flags = pg->flags & _PGMT_MASK;
91 95
92 if (pg_flags == _PGMT_DEFAULT) 96 if (pg_flags == _PGMT_WB)
93 return -1; 97 return _PAGE_CACHE_MODE_WB;
94 else if (pg_flags == _PGMT_WC) 98 else if (pg_flags == _PGMT_WC)
95 return _PAGE_CACHE_MODE_WC; 99 return _PAGE_CACHE_MODE_WC;
96 else if (pg_flags == _PGMT_UC_MINUS) 100 else if (pg_flags == _PGMT_UC_MINUS)
97 return _PAGE_CACHE_MODE_UC_MINUS; 101 return _PAGE_CACHE_MODE_UC_MINUS;
98 else 102 else
99 return _PAGE_CACHE_MODE_WB; 103 return _PAGE_CACHE_MODE_WT;
100} 104}
101 105
102static inline void set_page_memtype(struct page *pg, 106static inline void set_page_memtype(struct page *pg,
@@ -113,11 +117,12 @@ static inline void set_page_memtype(struct page *pg,
113 case _PAGE_CACHE_MODE_UC_MINUS: 117 case _PAGE_CACHE_MODE_UC_MINUS:
114 memtype_flags = _PGMT_UC_MINUS; 118 memtype_flags = _PGMT_UC_MINUS;
115 break; 119 break;
116 case _PAGE_CACHE_MODE_WB: 120 case _PAGE_CACHE_MODE_WT:
117 memtype_flags = _PGMT_WB; 121 memtype_flags = _PGMT_WT;
118 break; 122 break;
123 case _PAGE_CACHE_MODE_WB:
119 default: 124 default:
120 memtype_flags = _PGMT_DEFAULT; 125 memtype_flags = _PGMT_WB;
121 break; 126 break;
122 } 127 }
123 128
@@ -401,8 +406,10 @@ static int pat_pagerange_is_ram(resource_size_t start, resource_size_t end)
401 406
402/* 407/*
403 * For RAM pages, we use page flags to mark the pages with appropriate type. 408 * For RAM pages, we use page flags to mark the pages with appropriate type.
404 * The page flags are limited to three types, WB, WC and UC-. WT and WP requests 409 * The page flags are limited to four types, WB (default), WC, WT and UC-.
405 * fail with -EINVAL, and UC gets redirected to UC-. 410 * WP request fails with -EINVAL, and UC gets redirected to UC-. Setting
411 * a new memory type is only allowed for a page mapped with the default WB
412 * type.
406 * 413 *
407 * Here we do two passes: 414 * Here we do two passes:
408 * - Find the memtype of all the pages in the range, look for any conflicts. 415 * - Find the memtype of all the pages in the range, look for any conflicts.
@@ -415,8 +422,7 @@ static int reserve_ram_pages_type(u64 start, u64 end,
415 struct page *page; 422 struct page *page;
416 u64 pfn; 423 u64 pfn;
417 424
418 if ((req_type == _PAGE_CACHE_MODE_WT) || 425 if (req_type == _PAGE_CACHE_MODE_WP) {
419 (req_type == _PAGE_CACHE_MODE_WP)) {
420 if (new_type) 426 if (new_type)
421 *new_type = _PAGE_CACHE_MODE_UC_MINUS; 427 *new_type = _PAGE_CACHE_MODE_UC_MINUS;
422 return -EINVAL; 428 return -EINVAL;
@@ -433,7 +439,7 @@ static int reserve_ram_pages_type(u64 start, u64 end,
433 439
434 page = pfn_to_page(pfn); 440 page = pfn_to_page(pfn);
435 type = get_page_memtype(page); 441 type = get_page_memtype(page);
436 if (type != -1) { 442 if (type != _PAGE_CACHE_MODE_WB) {
437 pr_info("x86/PAT: reserve_ram_pages_type failed [mem %#010Lx-%#010Lx], track 0x%x, req 0x%x\n", 443 pr_info("x86/PAT: reserve_ram_pages_type failed [mem %#010Lx-%#010Lx], track 0x%x, req 0x%x\n",
438 start, end - 1, type, req_type); 444 start, end - 1, type, req_type);
439 if (new_type) 445 if (new_type)
@@ -460,7 +466,7 @@ static int free_ram_pages_type(u64 start, u64 end)
460 466
461 for (pfn = (start >> PAGE_SHIFT); pfn < (end >> PAGE_SHIFT); ++pfn) { 467 for (pfn = (start >> PAGE_SHIFT); pfn < (end >> PAGE_SHIFT); ++pfn) {
462 page = pfn_to_page(pfn); 468 page = pfn_to_page(pfn);
463 set_page_memtype(page, -1); 469 set_page_memtype(page, _PAGE_CACHE_MODE_WB);
464 } 470 }
465 return 0; 471 return 0;
466} 472}
@@ -601,7 +607,7 @@ int free_memtype(u64 start, u64 end)
601 * Only to be called when PAT is enabled 607 * Only to be called when PAT is enabled
602 * 608 *
603 * Returns _PAGE_CACHE_MODE_WB, _PAGE_CACHE_MODE_WC, _PAGE_CACHE_MODE_UC_MINUS 609 * Returns _PAGE_CACHE_MODE_WB, _PAGE_CACHE_MODE_WC, _PAGE_CACHE_MODE_UC_MINUS
604 * or _PAGE_CACHE_MODE_UC 610 * or _PAGE_CACHE_MODE_WT.
605 */ 611 */
606static enum page_cache_mode lookup_memtype(u64 paddr) 612static enum page_cache_mode lookup_memtype(u64 paddr)
607{ 613{
@@ -613,16 +619,9 @@ static enum page_cache_mode lookup_memtype(u64 paddr)
613 619
614 if (pat_pagerange_is_ram(paddr, paddr + PAGE_SIZE)) { 620 if (pat_pagerange_is_ram(paddr, paddr + PAGE_SIZE)) {
615 struct page *page; 621 struct page *page;
616 page = pfn_to_page(paddr >> PAGE_SHIFT);
617 rettype = get_page_memtype(page);
618 /*
619 * -1 from get_page_memtype() implies RAM page is in its
620 * default state and not reserved, and hence of type WB
621 */
622 if (rettype == -1)
623 rettype = _PAGE_CACHE_MODE_WB;
624 622
625 return rettype; 623 page = pfn_to_page(paddr >> PAGE_SHIFT);
624 return get_page_memtype(page);
626 } 625 }
627 626
628 spin_lock(&memtype_lock); 627 spin_lock(&memtype_lock);