Merge with /pub/scm/linux/kernel/git/torvalds/linux-2.6.git
[powerpc.git] / arch / sparc64 / mm / init.c
index b40f647..1539a83 100644 (file)
@@ -165,6 +165,8 @@ static void zero_ctor(void *addr, kmem_cache_t *cache, unsigned long flags)
        clear_page(addr);
 }
 
+extern void tsb_cache_init(void);
+
 void pgtable_cache_init(void)
 {
        pgtable_cache = kmem_cache_create("pgtable_cache",
@@ -174,9 +176,10 @@ void pgtable_cache_init(void)
                                          zero_ctor,
                                          NULL);
        if (!pgtable_cache) {
-               prom_printf("pgtable_cache_init(): Could not create!\n");
+               prom_printf("Could not create pgtable_cache\n");
                prom_halt();
        }
+       tsb_cache_init();
 }
 
 #ifdef CONFIG_DEBUG_DCFLUSH
@@ -279,7 +282,8 @@ 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;
+       unsigned long tag, flags;
+       unsigned long tsb_index, tsb_hash_shift;
 
        if (tlb_type != hypervisor) {
                unsigned long pfn = pte_pfn(pte);
@@ -308,10 +312,31 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t p
        }
 
        mm = vma->vm_mm;
-       tsb = &mm->context.tsb[(address >> PAGE_SHIFT) &
-                              (mm->context.tsb_nentries - 1UL)];
+
+       tsb_index = MM_TSB_BASE;
+       tsb_hash_shift = PAGE_SHIFT;
+
+       spin_lock_irqsave(&mm->context.lock, flags);
+
+#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));
+
+       spin_unlock_irqrestore(&mm->context.lock, flags);
 }
 
 void flush_dcache_page(struct page *page)
@@ -1453,7 +1478,7 @@ void free_initmem(void)
                p = virt_to_page(page);
 
                ClearPageReserved(p);
-               set_page_count(p, 1);
+               init_page_count(p);
                __free_page(p);
                num_physpages++;
                totalram_pages++;
@@ -1469,7 +1494,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++;
@@ -1797,3 +1822,21 @@ void __flush_tlb_all(void)
        __asm__ __volatile__("wrpr      %0, 0, %%pstate"
                             : : "r" (pstate));
 }
+
+#ifdef CONFIG_MEMORY_HOTPLUG
+
+void online_page(struct page *page)
+{
+       ClearPageReserved(page);
+       init_page_count(page);
+       __free_page(page);
+       totalram_pages++;
+       num_physpages++;
+}
+
+int remove_memory(u64 start, u64 size)
+{
+       return -EINVAL;
+}
+
+#endif /* CONFIG_MEMORY_HOTPLUG */