Merge master.kernel.org:/pub/scm/linux/kernel/git/wim/linux-2.6-watchdog
[pandora-kernel.git] / arch / sparc64 / mm / init.c
index c2b5561..cb75a27 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/initrd.h>
 #include <linux/swap.h>
 #include <linux/pagemap.h>
+#include <linux/poison.h>
 #include <linux/fs.h>
 #include <linux/seq_file.h>
 #include <linux/kprobes.h>
@@ -42,6 +43,7 @@
 #include <asm/sections.h>
 #include <asm/tsb.h>
 #include <asm/hypervisor.h>
+#include <asm/prom.h>
 
 extern void device_scan(void);
 
@@ -101,8 +103,6 @@ static void __init read_obp_memory(const char *property,
                prom_halt();
        }
 
-       *num_ents = ents;
-
        /* Sanitize what we got from the firmware, by page aligning
         * everything.
         */
@@ -124,6 +124,25 @@ static void __init read_obp_memory(const char *property,
                regs[i].phys_addr = base;
                regs[i].reg_size = size;
        }
+
+       for (i = 0; i < ents; i++) {
+               if (regs[i].reg_size == 0UL) {
+                       int j;
+
+                       for (j = i; j < ents - 1; j++) {
+                               regs[j].phys_addr =
+                                       regs[j+1].phys_addr;
+                               regs[j].reg_size =
+                                       regs[j+1].reg_size;
+                       }
+
+                       ents--;
+                       i--;
+               }
+       }
+
+       *num_ents = ents;
+
        sort(regs, ents, sizeof(struct linux_prom64_registers),
             cmp_p64, NULL);
 }
@@ -283,6 +302,7 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t p
        struct mm_struct *mm;
        struct tsb *tsb;
        unsigned long tag, flags;
+       unsigned long tsb_index, tsb_hash_shift;
 
        if (tlb_type != hypervisor) {
                unsigned long pfn = pte_pfn(pte);
@@ -312,10 +332,26 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t p
 
        mm = vma->vm_mm;
 
+       tsb_index = MM_TSB_BASE;
+       tsb_hash_shift = PAGE_SHIFT;
+
        spin_lock_irqsave(&mm->context.lock, flags);
 
-       tsb = &mm->context.tsb[(address >> PAGE_SHIFT) &
-                              (mm->context.tsb_nentries - 1UL)];
+#ifdef CONFIG_HUGETLB_PAGE
+       if (mm->context.tsb_block[MM_TSB_HUGE].tsb != NULL) {
+               if ((tlb_type == hypervisor &&
+                    (pte_val(pte) & _PAGE_SZALL_4V) == _PAGE_SZHUGE_4V) ||
+                   (tlb_type != hypervisor &&
+                    (pte_val(pte) & _PAGE_SZALL_4U) == _PAGE_SZHUGE_4U)) {
+                       tsb_index = MM_TSB_HUGE;
+                       tsb_hash_shift = HPAGE_SHIFT;
+               }
+       }
+#endif
+
+       tsb = mm->context.tsb_block[tsb_index].tsb;
+       tsb += ((address >> tsb_hash_shift) &
+               (mm->context.tsb_block[tsb_index].tsb_nentries - 1UL));
        tag = (address >> 22UL);
        tsb_insert(tsb, tag, pte_val(pte));
 
@@ -1322,6 +1358,8 @@ void __init paging_init(void)
 
        kernel_physical_mapping_init();
 
+       prom_build_devicetree();
+
        {
                unsigned long zones_size[MAX_NR_ZONES];
                unsigned long zholes_size[MAX_NR_ZONES];
@@ -1359,7 +1397,7 @@ static void __init taint_real_pages(void)
                while (old_start < old_end) {
                        int n;
 
-                       for (n = 0; pavail_rescan_ents; n++) {
+                       for (n = 0; n < pavail_rescan_ents; n++) {
                                unsigned long new_start, new_end;
 
                                new_start = pavail_rescan[n].phys_addr;
@@ -1381,6 +1419,32 @@ static void __init taint_real_pages(void)
        }
 }
 
+int __init page_in_phys_avail(unsigned long paddr)
+{
+       int i;
+
+       paddr &= PAGE_MASK;
+
+       for (i = 0; i < pavail_rescan_ents; i++) {
+               unsigned long start, end;
+
+               start = pavail_rescan[i].phys_addr;
+               end = start + pavail_rescan[i].reg_size;
+
+               if (paddr >= start && paddr < end)
+                       return 1;
+       }
+       if (paddr >= kern_base && paddr < (kern_base + kern_size))
+               return 1;
+#ifdef CONFIG_BLK_DEV_INITRD
+       if (paddr >= __pa(initrd_start) &&
+           paddr < __pa(PAGE_ALIGN(initrd_end)))
+               return 1;
+#endif
+
+       return 0;
+}
+
 void __init mem_init(void)
 {
        unsigned long codepages, datapages, initpages;
@@ -1457,11 +1521,11 @@ void free_initmem(void)
                page = (addr +
                        ((unsigned long) __va(kern_base)) -
                        ((unsigned long) KERNBASE));
-               memset((void *)addr, 0xcc, PAGE_SIZE);
+               memset((void *)addr, POISON_FREE_INITMEM, PAGE_SIZE);
                p = virt_to_page(page);
 
                ClearPageReserved(p);
-               set_page_count(p, 1);
+               init_page_count(p);
                __free_page(p);
                num_physpages++;
                totalram_pages++;
@@ -1477,7 +1541,7 @@ void free_initrd_mem(unsigned long start, unsigned long end)
                struct page *p = virt_to_page(start);
 
                ClearPageReserved(p);
-               set_page_count(p, 1);
+               init_page_count(p);
                __free_page(p);
                num_physpages++;
                totalram_pages++;
@@ -1505,6 +1569,7 @@ pgprot_t PAGE_EXEC __read_mostly;
 unsigned long pg_iobits __read_mostly;
 
 unsigned long _PAGE_IE __read_mostly;
+EXPORT_SYMBOL(_PAGE_IE);
 
 unsigned long _PAGE_E __read_mostly;
 EXPORT_SYMBOL(_PAGE_E);
@@ -1811,8 +1876,8 @@ void __flush_tlb_all(void)
 void online_page(struct page *page)
 {
        ClearPageReserved(page);
-       set_page_count(page, 0);
-       free_cold_page(page);
+       init_page_count(page);
+       __free_page(page);
        totalram_pages++;
        num_physpages++;
 }