diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2008-07-15 01:44:51 -0400 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2008-07-15 01:44:51 -0400 |
commit | 43d2548bb2ef7e6d753f91468a746784041e522d (patch) | |
tree | 77d13fcd48fd998393abb825ec36e2b732684a73 /arch/x86/mm/pageattr.c | |
parent | 585583d95c5660973bc0cf64add517b040acd8a4 (diff) | |
parent | 85082fd7cbe3173198aac0eb5e85ab1edcc6352c (diff) |
Merge commit '85082fd7cbe3173198aac0eb5e85ab1edcc6352c' into test-build
Manual fixup of:
arch/powerpc/Kconfig
Diffstat (limited to 'arch/x86/mm/pageattr.c')
-rw-r--r-- | arch/x86/mm/pageattr.c | 63 |
1 files changed, 59 insertions, 4 deletions
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index 60bcb5b6a37e..47f4e2e4a096 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 | ||
38 | static unsigned long direct_pages_count[PG_LEVEL_NUM]; | ||
39 | |||
40 | void 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 | |||
50 | static void split_page_count(int level) | ||
51 | { | ||
52 | direct_pages_count[level]--; | ||
53 | direct_pages_count[level - 1] += PTRS_PER_PTE; | ||
54 | } | ||
55 | |||
56 | int 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 | ||
69 | static inline void split_page_count(int level) { } | ||
70 | #endif | ||
71 | |||
37 | #ifdef CONFIG_X86_64 | 72 | #ifdef CONFIG_X86_64 |
38 | 73 | ||
39 | static inline unsigned long highmap_start_pfn(void) | 74 | static inline unsigned long highmap_start_pfn(void) |
@@ -227,6 +262,7 @@ pte_t *lookup_address(unsigned long address, unsigned int *level) | |||
227 | 262 | ||
228 | return pte_offset_kernel(pmd, address); | 263 | return pte_offset_kernel(pmd, address); |
229 | } | 264 | } |
265 | EXPORT_SYMBOL_GPL(lookup_address); | ||
230 | 266 | ||
231 | /* | 267 | /* |
232 | * Set the new pmd in all the pgds we know about: | 268 | * Set the new pmd in all the pgds we know about: |
@@ -500,6 +536,16 @@ static int split_large_page(pte_t *kpte, unsigned long address) | |||
500 | for (i = 0; i < PTRS_PER_PTE; i++, pfn += pfninc) | 536 | for (i = 0; i < PTRS_PER_PTE; i++, pfn += pfninc) |
501 | set_pte(&pbase[i], pfn_pte(pfn, ref_prot)); | 537 | set_pte(&pbase[i], pfn_pte(pfn, ref_prot)); |
502 | 538 | ||
539 | if (address >= (unsigned long)__va(0) && | ||
540 | address < (unsigned long)__va(max_low_pfn_mapped << PAGE_SHIFT)) | ||
541 | split_page_count(level); | ||
542 | |||
543 | #ifdef CONFIG_X86_64 | ||
544 | if (address >= (unsigned long)__va(1UL<<32) && | ||
545 | address < (unsigned long)__va(max_pfn_mapped << PAGE_SHIFT)) | ||
546 | split_page_count(level); | ||
547 | #endif | ||
548 | |||
503 | /* | 549 | /* |
504 | * Install the new, split up pagetable. Important details here: | 550 | * Install the new, split up pagetable. Important details here: |
505 | * | 551 | * |
@@ -613,15 +659,24 @@ static int cpa_process_alias(struct cpa_data *cpa) | |||
613 | struct cpa_data alias_cpa; | 659 | struct cpa_data alias_cpa; |
614 | int ret = 0; | 660 | int ret = 0; |
615 | 661 | ||
616 | if (cpa->pfn > max_pfn_mapped) | 662 | if (cpa->pfn >= max_pfn_mapped) |
617 | return 0; | 663 | return 0; |
618 | 664 | ||
665 | #ifdef CONFIG_X86_64 | ||
666 | if (cpa->pfn >= max_low_pfn_mapped && cpa->pfn < (1UL<<(32-PAGE_SHIFT))) | ||
667 | return 0; | ||
668 | #endif | ||
619 | /* | 669 | /* |
620 | * No need to redo, when the primary call touched the direct | 670 | * No need to redo, when the primary call touched the direct |
621 | * mapping already: | 671 | * mapping already: |
622 | */ | 672 | */ |
623 | if (!within(cpa->vaddr, PAGE_OFFSET, | 673 | if (!(within(cpa->vaddr, PAGE_OFFSET, |
624 | PAGE_OFFSET + (max_pfn_mapped << PAGE_SHIFT))) { | 674 | PAGE_OFFSET + (max_low_pfn_mapped << PAGE_SHIFT)) |
675 | #ifdef CONFIG_X86_64 | ||
676 | || within(cpa->vaddr, PAGE_OFFSET + (1UL<<32), | ||
677 | PAGE_OFFSET + (max_pfn_mapped << PAGE_SHIFT)) | ||
678 | #endif | ||
679 | )) { | ||
625 | 680 | ||
626 | alias_cpa = *cpa; | 681 | alias_cpa = *cpa; |
627 | alias_cpa.vaddr = (unsigned long) __va(cpa->pfn << PAGE_SHIFT); | 682 | alias_cpa.vaddr = (unsigned long) __va(cpa->pfn << PAGE_SHIFT); |
@@ -805,7 +860,7 @@ int _set_memory_wc(unsigned long addr, int numpages) | |||
805 | 860 | ||
806 | int set_memory_wc(unsigned long addr, int numpages) | 861 | int set_memory_wc(unsigned long addr, int numpages) |
807 | { | 862 | { |
808 | if (!pat_wc_enabled) | 863 | if (!pat_enabled) |
809 | return set_memory_uc(addr, numpages); | 864 | return set_memory_uc(addr, numpages); |
810 | 865 | ||
811 | if (reserve_memtype(addr, addr + numpages * PAGE_SIZE, | 866 | if (reserve_memtype(addr, addr + numpages * PAGE_SIZE, |