include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[safe/jmp/linux-2.6] / arch / powerpc / mm / mem.c
index 1b119b9..0f594d7 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/string.h>
+#include <linux/gfp.h>
 #include <linux/types.h>
 #include <linux/mm.h>
 #include <linux/stddef.h>
@@ -32,6 +33,7 @@
 #include <linux/pagemap.h>
 #include <linux/suspend.h>
 #include <linux/lmb.h>
+#include <linux/hugetlb.h>
 
 #include <asm/pgalloc.h>
 #include <asm/prom.h>
 #include <asm/btext.h>
 #include <asm/tlb.h>
 #include <asm/sections.h>
+#include <asm/sparsemem.h>
 #include <asm/vdso.h>
+#include <asm/fixmap.h>
+#include <asm/swiotlb.h>
 
 #include "mmu_decl.h"
 
 
 int init_bootmem_done;
 int mem_init_done;
-unsigned long memory_limit;
+phys_addr_t memory_limit;
 
-int page_is_ram(unsigned long pfn)
+#ifdef CONFIG_HIGHMEM
+pte_t *kmap_pte;
+pgprot_t kmap_prot;
+
+EXPORT_SYMBOL(kmap_prot);
+EXPORT_SYMBOL(kmap_pte);
+
+static inline pte_t *virt_to_kpte(unsigned long vaddr)
 {
-       unsigned long paddr = (pfn << PAGE_SHIFT);
+       return pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr),
+                       vaddr), vaddr), vaddr);
+}
+#endif
 
+int page_is_ram(unsigned long pfn)
+{
 #ifndef CONFIG_PPC64   /* XXX for now */
-       return paddr < __pa(high_memory);
+       return pfn < max_pfn;
 #else
+       unsigned long paddr = (pfn << PAGE_SHIFT);
        int i;
        for (i=0; i < lmb.memory.cnt; i++) {
                unsigned long base;
@@ -87,23 +105,14 @@ pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
                return ppc_md.phys_mem_access_prot(file, pfn, size, vma_prot);
 
        if (!page_is_ram(pfn))
-               vma_prot = __pgprot(pgprot_val(vma_prot)
-                                   | _PAGE_GUARDED | _PAGE_NO_CACHE);
+               vma_prot = pgprot_noncached(vma_prot);
+
        return vma_prot;
 }
 EXPORT_SYMBOL(phys_mem_access_prot);
 
 #ifdef CONFIG_MEMORY_HOTPLUG
 
-void online_page(struct page *page)
-{
-       ClearPageReserved(page);
-       init_page_count(page);
-       __free_page(page);
-       totalram_pages++;
-       num_physpages++;
-}
-
 #ifdef CONFIG_NUMA
 int memory_add_physaddr_to_nid(u64 start)
 {
@@ -126,83 +135,41 @@ int arch_add_memory(int nid, u64 start, u64 size)
        /* this should work for most non-highmem platforms */
        zone = pgdata->node_zones;
 
-       return __add_pages(zone, start_pfn, nr_pages);
-}
-
-#ifdef CONFIG_MEMORY_HOTREMOVE
-int remove_memory(u64 start, u64 size)
-{
-       unsigned long start_pfn, end_pfn;
-       int ret;
-
-       start_pfn = start >> PAGE_SHIFT;
-       end_pfn = start_pfn + (size >> PAGE_SHIFT);
-       ret = offline_pages(start_pfn, end_pfn, 120 * HZ);
-       if (ret)
-               goto out;
-       /* Arch-specific calls go here - next patch */
-out:
-       return ret;
+       return __add_pages(nid, zone, start_pfn, nr_pages);
 }
-#endif /* CONFIG_MEMORY_HOTREMOVE */
+#endif /* CONFIG_MEMORY_HOTPLUG */
 
 /*
  * walk_memory_resource() needs to make sure there is no holes in a given
- * memory range. On PPC64, since this range comes from /sysfs, the range
- * is guaranteed to be valid, non-overlapping and can not contain any
- * holes. By the time we get here (memory add or remove), /proc/device-tree
- * is updated and correct. Only reason we need to check against device-tree
- * would be if we allow user-land to specify a memory range through a
- * system call/ioctl etc. instead of doing offline/online through /sysfs.
+ * memory range.  PPC64 does not maintain the memory layout in /proc/iomem.
+ * Instead it maintains it in lmb.memory structures.  Walk through the
+ * memory regions, find holes and callback for contiguous regions.
  */
 int
-walk_memory_resource(unsigned long start_pfn, unsigned long nr_pages, void *arg,
-                       int (*func)(unsigned long, unsigned long, void *))
+walk_system_ram_range(unsigned long start_pfn, unsigned long nr_pages,
+               void *arg, int (*func)(unsigned long, unsigned long, void *))
 {
-       return  (*func)(start_pfn, nr_pages, arg);
-}
-
-#endif /* CONFIG_MEMORY_HOTPLUG */
-
-void show_mem(void)
-{
-       unsigned long total = 0, reserved = 0;
-       unsigned long shared = 0, cached = 0;
-       unsigned long highmem = 0;
-       struct page *page;
-       pg_data_t *pgdat;
-       unsigned long i;
-
-       printk("Mem-info:\n");
-       show_free_areas();
-       printk("Free swap:       %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
-       for_each_online_pgdat(pgdat) {
-               unsigned long flags;
-               pgdat_resize_lock(pgdat, &flags);
-               for (i = 0; i < pgdat->node_spanned_pages; i++) {
-                       if (!pfn_valid(pgdat->node_start_pfn + i))
-                               continue;
-                       page = pgdat_page_nr(pgdat, i);
-                       total++;
-                       if (PageHighMem(page))
-                               highmem++;
-                       if (PageReserved(page))
-                               reserved++;
-                       else if (PageSwapCache(page))
-                               cached++;
-                       else if (page_count(page))
-                               shared += page_count(page) - 1;
-               }
-               pgdat_resize_unlock(pgdat, &flags);
+       struct lmb_property res;
+       unsigned long pfn, len;
+       u64 end;
+       int ret = -1;
+
+       res.base = (u64) start_pfn << PAGE_SHIFT;
+       res.size = (u64) nr_pages << PAGE_SHIFT;
+
+       end = res.base + res.size - 1;
+       while ((res.base < end) && (lmb_find(&res) >= 0)) {
+               pfn = (unsigned long)(res.base >> PAGE_SHIFT);
+               len = (unsigned long)(res.size >> PAGE_SHIFT);
+               ret = (*func)(pfn, len, arg);
+               if (ret)
+                       break;
+               res.base += (res.size + 1);
+               res.size = (end - res.base + 1);
        }
-       printk("%ld pages of RAM\n", total);
-#ifdef CONFIG_HIGHMEM
-       printk("%ld pages of HIGHMEM\n", highmem);
-#endif
-       printk("%ld reserved pages\n", reserved);
-       printk("%ld pages shared\n", shared);
-       printk("%ld pages swap cached\n", cached);
+       return ret;
 }
+EXPORT_SYMBOL_GPL(walk_system_ram_range);
 
 /*
  * Initialize the bootmem system and give it all the memory we
@@ -217,9 +184,11 @@ void __init do_init_bootmem(void)
        unsigned long total_pages;
        int boot_mapsize;
 
-       max_pfn = total_pages = lmb_end_of_DRAM() >> PAGE_SHIFT;
+       max_low_pfn = max_pfn = lmb_end_of_DRAM() >> PAGE_SHIFT;
+       total_pages = (lmb_end_of_DRAM() - memstart_addr) >> PAGE_SHIFT;
 #ifdef CONFIG_HIGHMEM
        total_pages = total_lowmem >> PAGE_SHIFT;
+       max_low_pfn = lowmem_end_addr >> PAGE_SHIFT;
 #endif
 
        /*
@@ -231,7 +200,8 @@ void __init do_init_bootmem(void)
 
        start = lmb_alloc(bootmap_pages << PAGE_SHIFT, PAGE_SIZE);
 
-       boot_mapsize = init_bootmem(start >> PAGE_SHIFT, total_pages);
+       min_low_pfn = MEMORY_START >> PAGE_SHIFT;
+       boot_mapsize = init_bootmem_node(NODE_DATA(0), start >> PAGE_SHIFT, min_low_pfn, max_low_pfn);
 
        /* Add active regions with valid PFNs */
        for (i = 0; i < lmb.memory.cnt; i++) {
@@ -245,18 +215,18 @@ void __init do_init_bootmem(void)
         * present.
         */
 #ifdef CONFIG_HIGHMEM
-       free_bootmem_with_active_regions(0, total_lowmem >> PAGE_SHIFT);
+       free_bootmem_with_active_regions(0, lowmem_end_addr >> PAGE_SHIFT);
 
        /* reserve the sections we're already using */
        for (i = 0; i < lmb.reserved.cnt; i++) {
                unsigned long addr = lmb.reserved.region[i].base +
                                     lmb_size_bytes(&lmb.reserved, i) - 1;
-               if (addr < total_lowmem)
+               if (addr < lowmem_end_addr)
                        reserve_bootmem(lmb.reserved.region[i].base,
                                        lmb_size_bytes(&lmb.reserved, i),
                                        BOOTMEM_DEFAULT);
-               else if (lmb.reserved.region[i].base < total_lowmem) {
-                       unsigned long adjusted_size = total_lowmem -
+               else if (lmb.reserved.region[i].base < lowmem_end_addr) {
+                       unsigned long adjusted_size = lowmem_end_addr -
                                      lmb.reserved.region[i].base;
                        reserve_bootmem(lmb.reserved.region[i].base,
                                        adjusted_size, BOOTMEM_DEFAULT);
@@ -306,27 +276,32 @@ static int __init mark_nonram_nosave(void)
 void __init paging_init(void)
 {
        unsigned long total_ram = lmb_phys_mem_size();
-       unsigned long top_of_ram = lmb_end_of_DRAM();
+       phys_addr_t top_of_ram = lmb_end_of_DRAM();
        unsigned long max_zone_pfns[MAX_NR_ZONES];
 
+#ifdef CONFIG_PPC32
+       unsigned long v = __fix_to_virt(__end_of_fixed_addresses - 1);
+       unsigned long end = __fix_to_virt(FIX_HOLE);
+
+       for (; v < end; v += PAGE_SIZE)
+               map_page(v, 0, 0); /* XXX gross */
+#endif
+
 #ifdef CONFIG_HIGHMEM
        map_page(PKMAP_BASE, 0, 0);     /* XXX gross */
-       pkmap_page_table = pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k
-                       (PKMAP_BASE), PKMAP_BASE), PKMAP_BASE), PKMAP_BASE);
-       map_page(KMAP_FIX_BEGIN, 0, 0); /* XXX gross */
-       kmap_pte = pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k
-                       (KMAP_FIX_BEGIN), KMAP_FIX_BEGIN), KMAP_FIX_BEGIN),
-                        KMAP_FIX_BEGIN);
+       pkmap_page_table = virt_to_kpte(PKMAP_BASE);
+
+       kmap_pte = virt_to_kpte(__fix_to_virt(FIX_KMAP_BEGIN));
        kmap_prot = PAGE_KERNEL;
 #endif /* CONFIG_HIGHMEM */
 
-       printk(KERN_DEBUG "Top of RAM: 0x%lx, Total RAM: 0x%lx\n",
-              top_of_ram, total_ram);
+       printk(KERN_DEBUG "Top of RAM: 0x%llx, Total RAM: 0x%lx\n",
+              (unsigned long long)top_of_ram, total_ram);
        printk(KERN_DEBUG "Memory hole size: %ldMB\n",
-              (top_of_ram - total_ram) >> 20);
+              (long int)((top_of_ram - total_ram) >> 20));
        memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
 #ifdef CONFIG_HIGHMEM
-       max_zone_pfns[ZONE_DMA] = total_lowmem >> PAGE_SHIFT;
+       max_zone_pfns[ZONE_DMA] = lowmem_end_addr >> PAGE_SHIFT;
        max_zone_pfns[ZONE_HIGHMEM] = top_of_ram >> PAGE_SHIFT;
 #else
        max_zone_pfns[ZONE_DMA] = top_of_ram >> PAGE_SHIFT;
@@ -347,6 +322,11 @@ void __init mem_init(void)
        struct page *page;
        unsigned long reservedpages = 0, codesize, initsize, datasize, bsssize;
 
+#ifdef CONFIG_SWIOTLB
+       if (ppc_swiotlb_enable)
+               swiotlb_init(1);
+#endif
+
        num_physpages = lmb.memory.size >> PAGE_SHIFT;
        high_memory = (void *) __va(max_low_pfn * PAGE_SIZE);
 
@@ -381,7 +361,7 @@ void __init mem_init(void)
        {
                unsigned long pfn, highmem_mapnr;
 
-               highmem_mapnr = total_lowmem >> PAGE_SHIFT;
+               highmem_mapnr = lowmem_end_addr >> PAGE_SHIFT;
                for (pfn = highmem_mapnr; pfn < max_mapnr; ++pfn) {
                        struct page *page = pfn_to_page(pfn);
                        if (lmb_is_reserved(pfn << PAGE_SHIFT))
@@ -400,7 +380,7 @@ void __init mem_init(void)
 
        printk(KERN_INFO "Memory: %luk/%luk available (%luk kernel code, "
               "%luk reserved, %luk data, %luk bss, %luk init)\n",
-               (unsigned long)nr_free_pages() << (PAGE_SHIFT-10),
+               nr_free_pages() << (PAGE_SHIFT-10),
                num_physpages << (PAGE_SHIFT-10),
                codesize >> 10,
                reservedpages << (PAGE_SHIFT-10),
@@ -408,6 +388,23 @@ void __init mem_init(void)
                bsssize >> 10,
                initsize >> 10);
 
+#ifdef CONFIG_PPC32
+       pr_info("Kernel virtual memory layout:\n");
+       pr_info("  * 0x%08lx..0x%08lx  : fixmap\n", FIXADDR_START, FIXADDR_TOP);
+#ifdef CONFIG_HIGHMEM
+       pr_info("  * 0x%08lx..0x%08lx  : highmem PTEs\n",
+               PKMAP_BASE, PKMAP_ADDR(LAST_PKMAP));
+#endif /* CONFIG_HIGHMEM */
+#ifdef CONFIG_NOT_COHERENT_CACHE
+       pr_info("  * 0x%08lx..0x%08lx  : consistent mem\n",
+               IOREMAP_TOP, IOREMAP_TOP + CONFIG_CONSISTENT_SIZE);
+#endif /* CONFIG_NOT_COHERENT_CACHE */
+       pr_info("  * 0x%08lx..0x%08lx  : early ioremap\n",
+               ioremap_bot, IOREMAP_TOP);
+       pr_info("  * 0x%08lx..0x%08lx  : vmalloc & ioremap\n",
+               VMALLOC_START, VMALLOC_END);
+#endif /* CONFIG_PPC32 */
+
        mem_init_done = 1;
 }
 
@@ -428,18 +425,26 @@ EXPORT_SYMBOL(flush_dcache_page);
 
 void flush_dcache_icache_page(struct page *page)
 {
+#ifdef CONFIG_HUGETLB_PAGE
+       if (PageCompound(page)) {
+               flush_dcache_icache_hugepage(page);
+               return;
+       }
+#endif
 #ifdef CONFIG_BOOKE
-       void *start = kmap_atomic(page, KM_PPC_SYNC_ICACHE);
-       __flush_dcache_icache(start);
-       kunmap_atomic(start, KM_PPC_SYNC_ICACHE);
+       {
+               void *start = kmap_atomic(page, KM_PPC_SYNC_ICACHE);
+               __flush_dcache_icache(start);
+               kunmap_atomic(start, KM_PPC_SYNC_ICACHE);
+       }
 #elif defined(CONFIG_8xx) || defined(CONFIG_PPC64)
        /* On 8xx there is no need to kmap since highmem is not supported */
        __flush_dcache_icache(page_address(page)); 
 #else
        __flush_dcache_icache_phys(page_to_pfn(page) << PAGE_SHIFT);
 #endif
-
 }
+
 void clear_user_page(void *page, unsigned long vaddr, struct page *pg)
 {
        clear_page(page);
@@ -496,46 +501,13 @@ EXPORT_SYMBOL(flush_icache_user_range);
  * This must always be called with the pte lock held.
  */
 void update_mmu_cache(struct vm_area_struct *vma, unsigned long address,
-                     pte_t pte)
+                     pte_t *ptep)
 {
 #ifdef CONFIG_PPC_STD_MMU
        unsigned long access = 0, trap;
-#endif
-       unsigned long pfn = pte_pfn(pte);
-
-       /* handle i-cache coherency */
-       if (!cpu_has_feature(CPU_FTR_COHERENT_ICACHE) &&
-           !cpu_has_feature(CPU_FTR_NOEXECUTE) &&
-           pfn_valid(pfn)) {
-               struct page *page = pfn_to_page(pfn);
-#ifdef CONFIG_8xx
-               /* On 8xx, cache control instructions (particularly
-                * "dcbst" from flush_dcache_icache) fault as write
-                * operation if there is an unpopulated TLB entry
-                * for the address in question. To workaround that,
-                * we invalidate the TLB here, thus avoiding dcbst
-                * misbehaviour.
-                */
-               _tlbie(address, 0 /* 8xx doesn't care about PID */);
-#endif
-               /* The _PAGE_USER test should really be _PAGE_EXEC, but
-                * older glibc versions execute some code from no-exec
-                * pages, which for now we are supporting.  If exec-only
-                * pages are ever implemented, this will have to change.
-                */
-               if (!PageReserved(page) && (pte_val(pte) & _PAGE_USER)
-                   && !test_bit(PG_arch_1, &page->flags)) {
-                       if (vma->vm_mm == current->active_mm) {
-                               __flush_dcache_icache((void *) address);
-                       } else
-                               flush_dcache_icache_page(page);
-                       set_bit(PG_arch_1, &page->flags);
-               }
-       }
 
-#ifdef CONFIG_PPC_STD_MMU
        /* We only want HPTEs for linux PTEs that have _PAGE_ACCESSED set */
-       if (!pte_young(pte) || address >= TASK_SIZE)
+       if (!pte_young(*ptep) || address >= TASK_SIZE)
                return;
 
        /* We try to figure out if we are coming from an instruction