]> err.no Git - linux-2.6/blobdiff - arch/x86/mm/pageattr.c
x86: fix /proc/meminfo DirectMap
[linux-2.6] / arch / x86 / mm / pageattr.c
index afd40054d157e353d43c78013504f5481df24a9c..f5f5154ea11e4b788d98a9a12e4d23ddd28e4525 100644 (file)
@@ -55,13 +55,19 @@ static void split_page_count(int level)
 
 int arch_report_meminfo(char *page)
 {
-       int n = sprintf(page, "DirectMap4k:  %8lu\n"
-                       "DirectMap2M:  %8lu\n",
-                       direct_pages_count[PG_LEVEL_4K],
-                       direct_pages_count[PG_LEVEL_2M]);
+       int n = sprintf(page, "DirectMap4k:  %8lu kB\n",
+                       direct_pages_count[PG_LEVEL_4K] << 2);
+#if defined(CONFIG_X86_64) || defined(CONFIG_X86_PAE)
+       n += sprintf(page + n, "DirectMap2M:  %8lu kB\n",
+                       direct_pages_count[PG_LEVEL_2M] << 11);
+#else
+       n += sprintf(page + n, "DirectMap4M:  %8lu kB\n",
+                       direct_pages_count[PG_LEVEL_2M] << 12);
+#endif
 #ifdef CONFIG_X86_64
-       n += sprintf(page + n, "DirectMap1G:  %8lu\n",
-                    direct_pages_count[PG_LEVEL_1G]);
+       if (direct_gbpages)
+               n += sprintf(page + n, "DirectMap1G:  %8lu kB\n",
+                       direct_pages_count[PG_LEVEL_1G] << 20);
 #endif
        return n;
 }
@@ -141,7 +147,7 @@ static void cpa_flush_all(unsigned long cache)
 {
        BUG_ON(irqs_disabled());
 
-       on_each_cpu(__cpa_flush_all, (void *) cache, 1, 1);
+       on_each_cpu(__cpa_flush_all, (void *) cache, 1);
 }
 
 static void __cpa_flush_range(void *arg)
@@ -162,7 +168,7 @@ static void cpa_flush_range(unsigned long start, int numpages, int cache)
        BUG_ON(irqs_disabled());
        WARN_ON(PAGE_ALIGN(start) != start);
 
-       on_each_cpu(__cpa_flush_range, NULL, 1, 1);
+       on_each_cpu(__cpa_flush_range, NULL, 1);
 
        if (!cache)
                return;
@@ -262,6 +268,7 @@ pte_t *lookup_address(unsigned long address, unsigned int *level)
 
        return pte_offset_kernel(pmd, address);
 }
+EXPORT_SYMBOL_GPL(lookup_address);
 
 /*
  * Set the new pmd in all the pgds we know about:
@@ -536,8 +543,14 @@ static int split_large_page(pte_t *kpte, unsigned long address)
                set_pte(&pbase[i], pfn_pte(pfn, ref_prot));
 
        if (address >= (unsigned long)__va(0) &&
+               address < (unsigned long)__va(max_low_pfn_mapped << PAGE_SHIFT))
+               split_page_count(level);
+
+#ifdef CONFIG_X86_64
+       if (address >= (unsigned long)__va(1UL<<32) &&
                address < (unsigned long)__va(max_pfn_mapped << PAGE_SHIFT))
                split_page_count(level);
+#endif
 
        /*
         * Install the new, split up pagetable. Important details here:
@@ -585,10 +598,9 @@ repeat:
        if (!pte_val(old_pte)) {
                if (!primary)
                        return 0;
-               printk(KERN_WARNING "CPA: called for zero pte. "
+               WARN(1, KERN_WARNING "CPA: called for zero pte. "
                       "vaddr = %lx cpa->vaddr = %lx\n", address,
                       cpa->vaddr);
-               WARN_ON(1);
                return -EINVAL;
        }
 
@@ -652,15 +664,24 @@ static int cpa_process_alias(struct cpa_data *cpa)
        struct cpa_data alias_cpa;
        int ret = 0;
 
-       if (cpa->pfn > max_pfn_mapped)
+       if (cpa->pfn >= max_pfn_mapped)
                return 0;
 
+#ifdef CONFIG_X86_64
+       if (cpa->pfn >= max_low_pfn_mapped && cpa->pfn < (1UL<<(32-PAGE_SHIFT)))
+               return 0;
+#endif
        /*
         * No need to redo, when the primary call touched the direct
         * mapping already:
         */
-       if (!within(cpa->vaddr, PAGE_OFFSET,
-                   PAGE_OFFSET + (max_pfn_mapped << PAGE_SHIFT))) {
+       if (!(within(cpa->vaddr, PAGE_OFFSET,
+                   PAGE_OFFSET + (max_low_pfn_mapped << PAGE_SHIFT))
+#ifdef CONFIG_X86_64
+               || within(cpa->vaddr, PAGE_OFFSET + (1UL<<32),
+                   PAGE_OFFSET + (max_pfn_mapped << PAGE_SHIFT))
+#endif
+       )) {
 
                alias_cpa = *cpa;
                alias_cpa.vaddr = (unsigned long) __va(cpa->pfn << PAGE_SHIFT);