X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=arch%2Fpowerpc%2Fmm%2Ftlb_64.c;h=859d29a0cac5c58c53752efd0df59477c14ea2ef;hb=ac67c6247361b3b8644b34e5301a46d5069c1373;hp=09ab81a10f4f05100030d88a03760b9ed5b9b9bf;hpb=c1d962035d49565d8c7a2d97519012ccb861778a;p=powerpc.git diff --git a/arch/powerpc/mm/tlb_64.c b/arch/powerpc/mm/tlb_64.c index 09ab81a10f..859d29a0ca 100644 --- a/arch/powerpc/mm/tlb_64.c +++ b/arch/powerpc/mm/tlb_64.c @@ -21,6 +21,7 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ + #include #include #include @@ -30,7 +31,7 @@ #include #include #include -#include +#include DEFINE_PER_CPU(struct ppc64_tlb_batch, ppc64_tlb_batch); @@ -94,7 +95,7 @@ static void pte_free_submit(struct pte_freelist_batch *batch) void pgtable_free_tlb(struct mmu_gather *tlb, pgtable_free_t pgf) { - /* This is safe as we are holding page_table_lock */ + /* This is safe since tlb_gather_mmu has disabled preemption */ cpumask_t local_cpumask = cpumask_of_cpu(smp_processor_id()); struct pte_freelist_batch **batchp = &__get_cpu_var(pte_freelist_cur); @@ -126,28 +127,46 @@ void pgtable_free_tlb(struct mmu_gather *tlb, pgtable_free_t pgf) * (if we remove it we should clear the _PTE_HPTEFLAGS bits). */ void hpte_update(struct mm_struct *mm, unsigned long addr, - unsigned long pte, int wrprot) + pte_t *ptep, unsigned long pte, int huge) { struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch); unsigned long vsid; + unsigned int psize = mmu_virtual_psize; int i; i = batch->index; + /* We mask the address for the base page size. Huge pages will + * have applied their own masking already + */ + addr &= PAGE_MASK; + + /* Get page size (maybe move back to caller) */ + if (huge) { +#ifdef CONFIG_HUGETLB_PAGE + psize = mmu_huge_psize; +#else + BUG(); +#endif + } + /* * This can happen when we are in the middle of a TLB batch and * we encounter memory pressure (eg copy_page_range when it tries * to allocate a new pte). If we have to reclaim memory and end * up scanning and resetting referenced bits then our batch context * will change mid stream. + * + * We also need to ensure only one page size is present in a given + * batch */ - if (i != 0 && (mm != batch->mm || batch->large != pte_huge(pte))) { + if (i != 0 && (mm != batch->mm || batch->psize != psize)) { flush_tlb_pending(); i = 0; } if (i == 0) { batch->mm = mm; - batch->large = pte_huge(pte); + batch->psize = psize; } if (addr < KERNELBASE) { vsid = get_vsid(mm->context.id, addr); @@ -155,7 +174,7 @@ void hpte_update(struct mm_struct *mm, unsigned long addr, } else vsid = get_kernel_vsid(addr); batch->vaddr[i] = (vsid << 28 ) | (addr & 0x0fffffff); - batch->pte[i] = __pte(pte); + batch->pte[i] = __real_pte(__pte(pte), ptep); batch->index = ++i; if (i >= PPC64_TLB_BATCH_NR) flush_tlb_pending(); @@ -177,7 +196,8 @@ void __flush_tlb_pending(struct ppc64_tlb_batch *batch) local = 1; if (i == 1) - flush_hash_page(batch->vaddr[0], batch->pte[0], local); + flush_hash_page(batch->vaddr[0], batch->pte[0], + batch->psize, local); else flush_hash_range(i, local); batch->index = 0; @@ -186,7 +206,7 @@ void __flush_tlb_pending(struct ppc64_tlb_batch *batch) void pte_free_finish(void) { - /* This is safe as we are holding page_table_lock */ + /* This is safe since tlb_gather_mmu has disabled preemption */ struct pte_freelist_batch **batchp = &__get_cpu_var(pte_freelist_cur); if (*batchp == NULL)