Merge with /pub/scm/linux/kernel/git/torvalds/linux-2.6.git
[powerpc.git] / arch / sparc64 / mm / init.c
index 5f67b53..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
@@ -205,8 +208,8 @@ inline void flush_dcache_page_impl(struct page *page)
 }
 
 #define PG_dcache_dirty                PG_arch_1
-#define PG_dcache_cpu_shift    24
-#define PG_dcache_cpu_mask     (256 - 1)
+#define PG_dcache_cpu_shift    24UL
+#define PG_dcache_cpu_mask     (256UL - 1UL)
 
 #if NR_CPUS > 256
 #error D-cache dirty tracking and thread_info->cpu need fixing for > 256 cpus
@@ -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)
@@ -901,8 +926,7 @@ static unsigned long __init bootmem_init(unsigned long *pages_avail,
                    min_low_pfn, bootmap_pfn, max_low_pfn);
 #endif
        bootmap_size = init_bootmem_node(NODE_DATA(0), bootmap_pfn,
-                                        (phys_base >> PAGE_SHIFT),
-                                        end_pfn);
+                                        min_low_pfn, end_pfn);
 
        /* Now register the available physical memory with the
         * allocator.
@@ -1311,25 +1335,24 @@ void __init paging_init(void)
        pages_avail = 0;
        last_valid_pfn = end_pfn = bootmem_init(&pages_avail, phys_base);
 
-       max_mapnr = last_valid_pfn - (phys_base >> PAGE_SHIFT);
+       max_mapnr = last_valid_pfn;
 
        kernel_physical_mapping_init();
 
        {
                unsigned long zones_size[MAX_NR_ZONES];
                unsigned long zholes_size[MAX_NR_ZONES];
-               unsigned long npages;
                int znum;
 
                for (znum = 0; znum < MAX_NR_ZONES; znum++)
                        zones_size[znum] = zholes_size[znum] = 0;
 
-               npages = end_pfn - (phys_base >> PAGE_SHIFT);
-               zones_size[ZONE_DMA] = npages;
-               zholes_size[ZONE_DMA] = npages - pages_avail;
+               zones_size[ZONE_DMA] = end_pfn;
+               zholes_size[ZONE_DMA] = end_pfn - pages_avail;
 
                free_area_init_node(0, &contig_page_data, zones_size,
-                                   phys_base >> PAGE_SHIFT, zholes_size);
+                                   __pa(PAGE_OFFSET) >> PAGE_SHIFT,
+                                   zholes_size);
        }
 
        device_scan();
@@ -1455,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++;
@@ -1471,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++;
@@ -1799,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 */