aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/mm/pageattr.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/mm/pageattr.c')
-rw-r--r--arch/x86/mm/pageattr.c62
1 files changed, 58 insertions, 4 deletions
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
index 60bcb5b6a37e..fb6f2ab40dda 100644
--- a/arch/x86/mm/pageattr.c
+++ b/arch/x86/mm/pageattr.c
@@ -34,6 +34,41 @@ struct cpa_data {
34 unsigned force_split : 1; 34 unsigned force_split : 1;
35}; 35};
36 36
37#ifdef CONFIG_PROC_FS
38static unsigned long direct_pages_count[PG_LEVEL_NUM];
39
40void update_page_count(int level, unsigned long pages)
41{
42 unsigned long flags;
43
44 /* Protect against CPA */
45 spin_lock_irqsave(&pgd_lock, flags);
46 direct_pages_count[level] += pages;
47 spin_unlock_irqrestore(&pgd_lock, flags);
48}
49
50static void split_page_count(int level)
51{
52 direct_pages_count[level]--;
53 direct_pages_count[level - 1] += PTRS_PER_PTE;
54}
55
56int arch_report_meminfo(char *page)
57{
58 int n = sprintf(page, "DirectMap4k: %8lu\n"
59 "DirectMap2M: %8lu\n",
60 direct_pages_count[PG_LEVEL_4K],
61 direct_pages_count[PG_LEVEL_2M]);
62#ifdef CONFIG_X86_64
63 n += sprintf(page + n, "DirectMap1G: %8lu\n",
64 direct_pages_count[PG_LEVEL_1G]);
65#endif
66 return n;
67}
68#else
69static inline void split_page_count(int level) { }
70#endif
71
37#ifdef CONFIG_X86_64 72#ifdef CONFIG_X86_64
38 73
39static inline unsigned long highmap_start_pfn(void) 74static inline unsigned long highmap_start_pfn(void)
@@ -500,6 +535,16 @@ static int split_large_page(pte_t *kpte, unsigned long address)
500 for (i = 0; i < PTRS_PER_PTE; i++, pfn += pfninc) 535 for (i = 0; i < PTRS_PER_PTE; i++, pfn += pfninc)
501 set_pte(&pbase[i], pfn_pte(pfn, ref_prot)); 536 set_pte(&pbase[i], pfn_pte(pfn, ref_prot));
502 537
538 if (address >= (unsigned long)__va(0) &&
539 address < (unsigned long)__va(max_low_pfn_mapped << PAGE_SHIFT))
540 split_page_count(level);
541
542#ifdef CONFIG_X86_64
543 if (address >= (unsigned long)__va(1UL<<32) &&
544 address < (unsigned long)__va(max_pfn_mapped << PAGE_SHIFT))
545 split_page_count(level);
546#endif
547
503 /* 548 /*
504 * Install the new, split up pagetable. Important details here: 549 * Install the new, split up pagetable. Important details here:
505 * 550 *
@@ -613,15 +658,24 @@ static int cpa_process_alias(struct cpa_data *cpa)
613 struct cpa_data alias_cpa; 658 struct cpa_data alias_cpa;
614 int ret = 0; 659 int ret = 0;
615 660
616 if (cpa->pfn > max_pfn_mapped) 661 if (cpa->pfn >= max_pfn_mapped)
617 return 0; 662 return 0;
618 663
664#ifdef CONFIG_X86_64
665 if (cpa->pfn >= max_low_pfn_mapped && cpa->pfn < (1UL<<(32-PAGE_SHIFT)))
666 return 0;
667#endif
619 /* 668 /*
620 * No need to redo, when the primary call touched the direct 669 * No need to redo, when the primary call touched the direct
621 * mapping already: 670 * mapping already:
622 */ 671 */
623 if (!within(cpa->vaddr, PAGE_OFFSET, 672 if (!(within(cpa->vaddr, PAGE_OFFSET,
624 PAGE_OFFSET + (max_pfn_mapped << PAGE_SHIFT))) { 673 PAGE_OFFSET + (max_low_pfn_mapped << PAGE_SHIFT))
674#ifdef CONFIG_X86_64
675 || within(cpa->vaddr, PAGE_OFFSET + (1UL<<32),
676 PAGE_OFFSET + (max_pfn_mapped << PAGE_SHIFT))
677#endif
678 )) {
625 679
626 alias_cpa = *cpa; 680 alias_cpa = *cpa;
627 alias_cpa.vaddr = (unsigned long) __va(cpa->pfn << PAGE_SHIFT); 681 alias_cpa.vaddr = (unsigned long) __va(cpa->pfn << PAGE_SHIFT);
@@ -805,7 +859,7 @@ int _set_memory_wc(unsigned long addr, int numpages)
805 859
806int set_memory_wc(unsigned long addr, int numpages) 860int set_memory_wc(unsigned long addr, int numpages)
807{ 861{
808 if (!pat_wc_enabled) 862 if (!pat_enabled)
809 return set_memory_uc(addr, numpages); 863 return set_memory_uc(addr, numpages);
810 864
811 if (reserve_memtype(addr, addr + numpages * PAGE_SIZE, 865 if (reserve_memtype(addr, addr + numpages * PAGE_SIZE,