]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - arch/x86/mm/pageattr.c
x86, generic: CPA add statistics about state of direct mapping v4
[linux-2.6-omap-h63xx.git] / arch / x86 / mm / pageattr.c
index f7823a17286838d016985c3c3bb9885c08982c95..668205bca15eb46ae3a6871294b08e7943364190 100644 (file)
@@ -34,6 +34,19 @@ struct cpa_data {
        unsigned        force_split : 1;
 };
 
+static unsigned long direct_pages_count[PG_LEVEL_NUM];
+
+void __meminit update_page_count(int level, unsigned long pages)
+{
+#ifdef CONFIG_PROC_FS
+       unsigned long flags;
+       /* Protect against CPA */
+       spin_lock_irqsave(&pgd_lock, flags);
+       direct_pages_count[level] += pages;
+       spin_unlock_irqrestore(&pgd_lock, flags);
+#endif
+}
+
 #ifdef CONFIG_X86_64
 
 static inline unsigned long highmap_start_pfn(void)
@@ -483,9 +496,7 @@ static int split_large_page(pte_t *kpte, unsigned long address)
                goto out_unlock;
 
        pbase = (pte_t *)page_address(base);
-#ifdef CONFIG_X86_32
-       paravirt_alloc_pt(&init_mm, page_to_pfn(base));
-#endif
+       paravirt_alloc_pte(&init_mm, page_to_pfn(base));
        ref_prot = pte_pgprot(pte_clrhuge(*kpte));
 
 #ifdef CONFIG_X86_64
@@ -502,6 +513,12 @@ static int split_large_page(pte_t *kpte, unsigned long address)
        for (i = 0; i < PTRS_PER_PTE; i++, pfn += pfninc)
                set_pte(&pbase[i], pfn_pte(pfn, ref_prot));
 
+       if (address >= (unsigned long)__va(0) &&
+               address < (unsigned long)__va(max_pfn_mapped << PAGE_SHIFT)) {
+               direct_pages_count[level]--;
+               direct_pages_count[level - 1] += PTRS_PER_PTE;
+       }
+
        /*
         * Install the new, split up pagetable. Important details here:
         *
@@ -779,14 +796,20 @@ static inline int change_page_attr_clear(unsigned long addr, int numpages,
 
 int _set_memory_uc(unsigned long addr, int numpages)
 {
+       /*
+        * for now UC MINUS. see comments in ioremap_nocache()
+        */
        return change_page_attr_set(addr, numpages,
-                                   __pgprot(_PAGE_CACHE_UC));
+                                   __pgprot(_PAGE_CACHE_UC_MINUS));
 }
 
 int set_memory_uc(unsigned long addr, int numpages)
 {
+       /*
+        * for now UC MINUS. see comments in ioremap_nocache()
+        */
        if (reserve_memtype(addr, addr + numpages * PAGE_SIZE,
-                           _PAGE_CACHE_UC, NULL))
+                           _PAGE_CACHE_UC_MINUS, NULL))
                return -EINVAL;
 
        return _set_memory_uc(addr, numpages);
@@ -993,7 +1016,7 @@ static const struct file_operations dpa_fops = {
        .release        = single_release,
 };
 
-int __init debug_pagealloc_proc_init(void)
+static int __init debug_pagealloc_proc_init(void)
 {
        struct dentry *de;
 
@@ -1025,6 +1048,22 @@ bool kernel_page_present(struct page *page)
 
 #endif /* CONFIG_DEBUG_PAGEALLOC */
 
+#ifdef CONFIG_PROC_FS
+int arch_report_meminfo(char *page)
+{
+       int n;
+       n = sprintf(page, "DirectMap4k:  %8lu\n"
+                         "DirectMap2M:  %8lu\n",
+                       direct_pages_count[PG_LEVEL_4K],
+                       direct_pages_count[PG_LEVEL_2M]);
+#ifdef CONFIG_X86_64
+       n += sprintf(page + n, "DirectMap1G:  %8lu\n",
+                       direct_pages_count[PG_LEVEL_1G]);
+#endif
+       return n;
+}
+#endif
+
 /*
  * The testcases use internal knowledge of the implementation that shouldn't
  * be exposed to the rest of the kernel. Include these directly here.