diff options
-rw-r--r-- | arch/x86/mm/init_32.c | 5 | ||||
-rw-r--r-- | arch/x86/mm/init_64.c | 7 | ||||
-rw-r--r-- | arch/x86/mm/pageattr.c | 35 | ||||
-rw-r--r-- | fs/proc/proc_misc.c | 7 | ||||
-rw-r--r-- | include/asm-x86/pgtable.h | 3 |
5 files changed, 57 insertions, 0 deletions
diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c index ec30d10154b6..0269ac230bfa 100644 --- a/arch/x86/mm/init_32.c +++ b/arch/x86/mm/init_32.c | |||
@@ -162,6 +162,7 @@ static void __init kernel_physical_mapping_init(pgd_t *pgd_base) | |||
162 | pgd_t *pgd; | 162 | pgd_t *pgd; |
163 | pmd_t *pmd; | 163 | pmd_t *pmd; |
164 | pte_t *pte; | 164 | pte_t *pte; |
165 | unsigned pages_2m = 0, pages_4k = 0; | ||
165 | 166 | ||
166 | pgd_idx = pgd_index(PAGE_OFFSET); | 167 | pgd_idx = pgd_index(PAGE_OFFSET); |
167 | pgd = pgd_base + pgd_idx; | 168 | pgd = pgd_base + pgd_idx; |
@@ -197,6 +198,7 @@ static void __init kernel_physical_mapping_init(pgd_t *pgd_base) | |||
197 | is_kernel_text(addr2)) | 198 | is_kernel_text(addr2)) |
198 | prot = PAGE_KERNEL_LARGE_EXEC; | 199 | prot = PAGE_KERNEL_LARGE_EXEC; |
199 | 200 | ||
201 | pages_2m++; | ||
200 | set_pmd(pmd, pfn_pmd(pfn, prot)); | 202 | set_pmd(pmd, pfn_pmd(pfn, prot)); |
201 | 203 | ||
202 | pfn += PTRS_PER_PTE; | 204 | pfn += PTRS_PER_PTE; |
@@ -213,11 +215,14 @@ static void __init kernel_physical_mapping_init(pgd_t *pgd_base) | |||
213 | if (is_kernel_text(addr)) | 215 | if (is_kernel_text(addr)) |
214 | prot = PAGE_KERNEL_EXEC; | 216 | prot = PAGE_KERNEL_EXEC; |
215 | 217 | ||
218 | pages_4k++; | ||
216 | set_pte(pte, pfn_pte(pfn, prot)); | 219 | set_pte(pte, pfn_pte(pfn, prot)); |
217 | } | 220 | } |
218 | max_pfn_mapped = pfn; | 221 | max_pfn_mapped = pfn; |
219 | } | 222 | } |
220 | } | 223 | } |
224 | update_page_count(PG_LEVEL_2M, pages_2m); | ||
225 | update_page_count(PG_LEVEL_4K, pages_4k); | ||
221 | } | 226 | } |
222 | 227 | ||
223 | static inline int page_kills_ppro(unsigned long pagenr) | 228 | static inline int page_kills_ppro(unsigned long pagenr) |
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index 819dad973b13..5e4383859053 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c | |||
@@ -312,6 +312,8 @@ __meminit void early_iounmap(void *addr, unsigned long size) | |||
312 | static unsigned long __meminit | 312 | static unsigned long __meminit |
313 | phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end) | 313 | phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end) |
314 | { | 314 | { |
315 | unsigned long pages = 0; | ||
316 | |||
315 | int i = pmd_index(address); | 317 | int i = pmd_index(address); |
316 | 318 | ||
317 | for (; i < PTRS_PER_PMD; i++, address += PMD_SIZE) { | 319 | for (; i < PTRS_PER_PMD; i++, address += PMD_SIZE) { |
@@ -328,9 +330,11 @@ phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end) | |||
328 | if (pmd_val(*pmd)) | 330 | if (pmd_val(*pmd)) |
329 | continue; | 331 | continue; |
330 | 332 | ||
333 | pages++; | ||
331 | set_pte((pte_t *)pmd, | 334 | set_pte((pte_t *)pmd, |
332 | pfn_pte(address >> PAGE_SHIFT, PAGE_KERNEL_LARGE)); | 335 | pfn_pte(address >> PAGE_SHIFT, PAGE_KERNEL_LARGE)); |
333 | } | 336 | } |
337 | update_page_count(PG_LEVEL_2M, pages); | ||
334 | return address; | 338 | return address; |
335 | } | 339 | } |
336 | 340 | ||
@@ -350,6 +354,7 @@ phys_pmd_update(pud_t *pud, unsigned long address, unsigned long end) | |||
350 | static unsigned long __meminit | 354 | static unsigned long __meminit |
351 | phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end) | 355 | phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end) |
352 | { | 356 | { |
357 | unsigned long pages = 0; | ||
353 | unsigned long last_map_addr = end; | 358 | unsigned long last_map_addr = end; |
354 | int i = pud_index(addr); | 359 | int i = pud_index(addr); |
355 | 360 | ||
@@ -374,6 +379,7 @@ phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end) | |||
374 | } | 379 | } |
375 | 380 | ||
376 | if (direct_gbpages) { | 381 | if (direct_gbpages) { |
382 | pages++; | ||
377 | set_pte((pte_t *)pud, | 383 | set_pte((pte_t *)pud, |
378 | pfn_pte(addr >> PAGE_SHIFT, PAGE_KERNEL_LARGE)); | 384 | pfn_pte(addr >> PAGE_SHIFT, PAGE_KERNEL_LARGE)); |
379 | last_map_addr = (addr & PUD_MASK) + PUD_SIZE; | 385 | last_map_addr = (addr & PUD_MASK) + PUD_SIZE; |
@@ -390,6 +396,7 @@ phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end) | |||
390 | unmap_low_page(pmd); | 396 | unmap_low_page(pmd); |
391 | } | 397 | } |
392 | __flush_tlb_all(); | 398 | __flush_tlb_all(); |
399 | update_page_count(PG_LEVEL_1G, pages); | ||
393 | 400 | ||
394 | return last_map_addr >> PAGE_SHIFT; | 401 | return last_map_addr >> PAGE_SHIFT; |
395 | } | 402 | } |
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index 60bcb5b6a37e..668205bca15e 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c | |||
@@ -34,6 +34,19 @@ struct cpa_data { | |||
34 | unsigned force_split : 1; | 34 | unsigned force_split : 1; |
35 | }; | 35 | }; |
36 | 36 | ||
37 | static unsigned long direct_pages_count[PG_LEVEL_NUM]; | ||
38 | |||
39 | void __meminit update_page_count(int level, unsigned long pages) | ||
40 | { | ||
41 | #ifdef CONFIG_PROC_FS | ||
42 | unsigned long flags; | ||
43 | /* Protect against CPA */ | ||
44 | spin_lock_irqsave(&pgd_lock, flags); | ||
45 | direct_pages_count[level] += pages; | ||
46 | spin_unlock_irqrestore(&pgd_lock, flags); | ||
47 | #endif | ||
48 | } | ||
49 | |||
37 | #ifdef CONFIG_X86_64 | 50 | #ifdef CONFIG_X86_64 |
38 | 51 | ||
39 | static inline unsigned long highmap_start_pfn(void) | 52 | static inline unsigned long highmap_start_pfn(void) |
@@ -500,6 +513,12 @@ static int split_large_page(pte_t *kpte, unsigned long address) | |||
500 | for (i = 0; i < PTRS_PER_PTE; i++, pfn += pfninc) | 513 | for (i = 0; i < PTRS_PER_PTE; i++, pfn += pfninc) |
501 | set_pte(&pbase[i], pfn_pte(pfn, ref_prot)); | 514 | set_pte(&pbase[i], pfn_pte(pfn, ref_prot)); |
502 | 515 | ||
516 | if (address >= (unsigned long)__va(0) && | ||
517 | address < (unsigned long)__va(max_pfn_mapped << PAGE_SHIFT)) { | ||
518 | direct_pages_count[level]--; | ||
519 | direct_pages_count[level - 1] += PTRS_PER_PTE; | ||
520 | } | ||
521 | |||
503 | /* | 522 | /* |
504 | * Install the new, split up pagetable. Important details here: | 523 | * Install the new, split up pagetable. Important details here: |
505 | * | 524 | * |
@@ -1029,6 +1048,22 @@ bool kernel_page_present(struct page *page) | |||
1029 | 1048 | ||
1030 | #endif /* CONFIG_DEBUG_PAGEALLOC */ | 1049 | #endif /* CONFIG_DEBUG_PAGEALLOC */ |
1031 | 1050 | ||
1051 | #ifdef CONFIG_PROC_FS | ||
1052 | int arch_report_meminfo(char *page) | ||
1053 | { | ||
1054 | int n; | ||
1055 | n = sprintf(page, "DirectMap4k: %8lu\n" | ||
1056 | "DirectMap2M: %8lu\n", | ||
1057 | direct_pages_count[PG_LEVEL_4K], | ||
1058 | direct_pages_count[PG_LEVEL_2M]); | ||
1059 | #ifdef CONFIG_X86_64 | ||
1060 | n += sprintf(page + n, "DirectMap1G: %8lu\n", | ||
1061 | direct_pages_count[PG_LEVEL_1G]); | ||
1062 | #endif | ||
1063 | return n; | ||
1064 | } | ||
1065 | #endif | ||
1066 | |||
1032 | /* | 1067 | /* |
1033 | * The testcases use internal knowledge of the implementation that shouldn't | 1068 | * The testcases use internal knowledge of the implementation that shouldn't |
1034 | * be exposed to the rest of the kernel. Include these directly here. | 1069 | * be exposed to the rest of the kernel. Include these directly here. |
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c index 7e277f2ad466..15f7bd41029b 100644 --- a/fs/proc/proc_misc.c +++ b/fs/proc/proc_misc.c | |||
@@ -123,6 +123,11 @@ static int uptime_read_proc(char *page, char **start, off_t off, | |||
123 | return proc_calc_metrics(page, start, off, count, eof, len); | 123 | return proc_calc_metrics(page, start, off, count, eof, len); |
124 | } | 124 | } |
125 | 125 | ||
126 | int __attribute__((weak)) arch_report_meminfo(char *page) | ||
127 | { | ||
128 | return 0; | ||
129 | } | ||
130 | |||
126 | static int meminfo_read_proc(char *page, char **start, off_t off, | 131 | static int meminfo_read_proc(char *page, char **start, off_t off, |
127 | int count, int *eof, void *data) | 132 | int count, int *eof, void *data) |
128 | { | 133 | { |
@@ -221,6 +226,8 @@ static int meminfo_read_proc(char *page, char **start, off_t off, | |||
221 | 226 | ||
222 | len += hugetlb_report_meminfo(page + len); | 227 | len += hugetlb_report_meminfo(page + len); |
223 | 228 | ||
229 | len += arch_report_meminfo(page + len); | ||
230 | |||
224 | return proc_calc_metrics(page, start, off, count, eof, len); | 231 | return proc_calc_metrics(page, start, off, count, eof, len); |
225 | #undef K | 232 | #undef K |
226 | } | 233 | } |
diff --git a/include/asm-x86/pgtable.h b/include/asm-x86/pgtable.h index 97c271b2910b..111564fa5e70 100644 --- a/include/asm-x86/pgtable.h +++ b/include/asm-x86/pgtable.h | |||
@@ -369,8 +369,11 @@ enum { | |||
369 | PG_LEVEL_4K, | 369 | PG_LEVEL_4K, |
370 | PG_LEVEL_2M, | 370 | PG_LEVEL_2M, |
371 | PG_LEVEL_1G, | 371 | PG_LEVEL_1G, |
372 | PG_LEVEL_NUM | ||
372 | }; | 373 | }; |
373 | 374 | ||
375 | void update_page_count(int level, unsigned long pages); | ||
376 | |||
374 | /* | 377 | /* |
375 | * Helper function that returns the kernel pagetable entry controlling | 378 | * Helper function that returns the kernel pagetable entry controlling |
376 | * the virtual address 'address'. NULL means no pagetable entry present. | 379 | * the virtual address 'address'. NULL means no pagetable entry present. |