aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/mm/pgtable_64.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/mm/pgtable_64.c')
-rw-r--r--arch/powerpc/mm/pgtable_64.c104
1 files changed, 36 insertions, 68 deletions
diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c
index c8d709ab489d..4fe5f64cc179 100644
--- a/arch/powerpc/mm/pgtable_64.c
+++ b/arch/powerpc/mm/pgtable_64.c
@@ -33,9 +33,9 @@
33#include <linux/swap.h> 33#include <linux/swap.h>
34#include <linux/stddef.h> 34#include <linux/stddef.h>
35#include <linux/vmalloc.h> 35#include <linux/vmalloc.h>
36#include <linux/bootmem.h>
37#include <linux/memblock.h> 36#include <linux/memblock.h>
38#include <linux/slab.h> 37#include <linux/slab.h>
38#include <linux/hugetlb.h>
39 39
40#include <asm/pgalloc.h> 40#include <asm/pgalloc.h>
41#include <asm/page.h> 41#include <asm/page.h>
@@ -51,6 +51,7 @@
51#include <asm/cputable.h> 51#include <asm/cputable.h>
52#include <asm/sections.h> 52#include <asm/sections.h>
53#include <asm/firmware.h> 53#include <asm/firmware.h>
54#include <asm/dma.h>
54 55
55#include "mmu_decl.h" 56#include "mmu_decl.h"
56 57
@@ -75,11 +76,7 @@ static __ref void *early_alloc_pgtable(unsigned long size)
75{ 76{
76 void *pt; 77 void *pt;
77 78
78 if (init_bootmem_done) 79 pt = __va(memblock_alloc_base(size, size, __pa(MAX_DMA_ADDRESS)));
79 pt = __alloc_bootmem(size, size, __pa(MAX_DMA_ADDRESS));
80 else
81 pt = __va(memblock_alloc_base(size, size,
82 __pa(MAX_DMA_ADDRESS)));
83 memset(pt, 0, size); 80 memset(pt, 0, size);
84 81
85 return pt; 82 return pt;
@@ -113,10 +110,6 @@ int map_kernel_page(unsigned long ea, unsigned long pa, int flags)
113 __pgprot(flags))); 110 __pgprot(flags)));
114 } else { 111 } else {
115#ifdef CONFIG_PPC_MMU_NOHASH 112#ifdef CONFIG_PPC_MMU_NOHASH
116 /* Warning ! This will blow up if bootmem is not initialized
117 * which our ppc64 code is keen to do that, we'll need to
118 * fix it and/or be more careful
119 */
120 pgdp = pgd_offset_k(ea); 113 pgdp = pgd_offset_k(ea);
121#ifdef PUD_TABLE_SIZE 114#ifdef PUD_TABLE_SIZE
122 if (pgd_none(*pgdp)) { 115 if (pgd_none(*pgdp)) {
@@ -352,16 +345,31 @@ EXPORT_SYMBOL(iounmap);
352EXPORT_SYMBOL(__iounmap); 345EXPORT_SYMBOL(__iounmap);
353EXPORT_SYMBOL(__iounmap_at); 346EXPORT_SYMBOL(__iounmap_at);
354 347
348#ifndef __PAGETABLE_PUD_FOLDED
349/* 4 level page table */
350struct page *pgd_page(pgd_t pgd)
351{
352 if (pgd_huge(pgd))
353 return pte_page(pgd_pte(pgd));
354 return virt_to_page(pgd_page_vaddr(pgd));
355}
356#endif
357
358struct page *pud_page(pud_t pud)
359{
360 if (pud_huge(pud))
361 return pte_page(pud_pte(pud));
362 return virt_to_page(pud_page_vaddr(pud));
363}
364
355/* 365/*
356 * For hugepage we have pfn in the pmd, we use PTE_RPN_SHIFT bits for flags 366 * For hugepage we have pfn in the pmd, we use PTE_RPN_SHIFT bits for flags
357 * For PTE page, we have a PTE_FRAG_SIZE (4K) aligned virtual address. 367 * For PTE page, we have a PTE_FRAG_SIZE (4K) aligned virtual address.
358 */ 368 */
359struct page *pmd_page(pmd_t pmd) 369struct page *pmd_page(pmd_t pmd)
360{ 370{
361#ifdef CONFIG_TRANSPARENT_HUGEPAGE 371 if (pmd_trans_huge(pmd) || pmd_huge(pmd))
362 if (pmd_trans_huge(pmd))
363 return pfn_to_page(pmd_pfn(pmd)); 372 return pfn_to_page(pmd_pfn(pmd));
364#endif
365 return virt_to_page(pmd_page_vaddr(pmd)); 373 return virt_to_page(pmd_page_vaddr(pmd));
366} 374}
367 375
@@ -731,29 +739,15 @@ void pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,
731void hpte_do_hugepage_flush(struct mm_struct *mm, unsigned long addr, 739void hpte_do_hugepage_flush(struct mm_struct *mm, unsigned long addr,
732 pmd_t *pmdp, unsigned long old_pmd) 740 pmd_t *pmdp, unsigned long old_pmd)
733{ 741{
734 int ssize, i; 742 int ssize;
735 unsigned long s_addr; 743 unsigned int psize;
736 int max_hpte_count; 744 unsigned long vsid;
737 unsigned int psize, valid; 745 unsigned long flags = 0;
738 unsigned char *hpte_slot_array; 746 const struct cpumask *tmp;
739 unsigned long hidx, vpn, vsid, hash, shift, slot;
740
741 /*
742 * Flush all the hptes mapping this hugepage
743 */
744 s_addr = addr & HPAGE_PMD_MASK;
745 hpte_slot_array = get_hpte_slot_array(pmdp);
746 /*
747 * IF we try to do a HUGE PTE update after a withdraw is done.
748 * we will find the below NULL. This happens when we do
749 * split_huge_page_pmd
750 */
751 if (!hpte_slot_array)
752 return;
753 747
754 /* get the base page size,vsid and segment size */ 748 /* get the base page size,vsid and segment size */
755#ifdef CONFIG_DEBUG_VM 749#ifdef CONFIG_DEBUG_VM
756 psize = get_slice_psize(mm, s_addr); 750 psize = get_slice_psize(mm, addr);
757 BUG_ON(psize == MMU_PAGE_16M); 751 BUG_ON(psize == MMU_PAGE_16M);
758#endif 752#endif
759 if (old_pmd & _PAGE_COMBO) 753 if (old_pmd & _PAGE_COMBO)
@@ -761,46 +755,20 @@ void hpte_do_hugepage_flush(struct mm_struct *mm, unsigned long addr,
761 else 755 else
762 psize = MMU_PAGE_64K; 756 psize = MMU_PAGE_64K;
763 757
764 if (!is_kernel_addr(s_addr)) { 758 if (!is_kernel_addr(addr)) {
765 ssize = user_segment_size(s_addr); 759 ssize = user_segment_size(addr);
766 vsid = get_vsid(mm->context.id, s_addr, ssize); 760 vsid = get_vsid(mm->context.id, addr, ssize);
767 WARN_ON(vsid == 0); 761 WARN_ON(vsid == 0);
768 } else { 762 } else {
769 vsid = get_kernel_vsid(s_addr, mmu_kernel_ssize); 763 vsid = get_kernel_vsid(addr, mmu_kernel_ssize);
770 ssize = mmu_kernel_ssize; 764 ssize = mmu_kernel_ssize;
771 } 765 }
772 766
773 if (ppc_md.hugepage_invalidate) 767 tmp = cpumask_of(smp_processor_id());
774 return ppc_md.hugepage_invalidate(vsid, s_addr, 768 if (cpumask_equal(mm_cpumask(mm), tmp))
775 hpte_slot_array, 769 flags |= HPTE_LOCAL_UPDATE;
776 psize, ssize); 770
777 /* 771 return flush_hash_hugepage(vsid, addr, pmdp, psize, ssize, flags);
778 * No bluk hpte removal support, invalidate each entry
779 */
780 shift = mmu_psize_defs[psize].shift;
781 max_hpte_count = HPAGE_PMD_SIZE >> shift;
782 for (i = 0; i < max_hpte_count; i++) {
783 /*
784 * 8 bits per each hpte entries
785 * 000| [ secondary group (one bit) | hidx (3 bits) | valid bit]
786 */
787 valid = hpte_valid(hpte_slot_array, i);
788 if (!valid)
789 continue;
790 hidx = hpte_hash_index(hpte_slot_array, i);
791
792 /* get the vpn */
793 addr = s_addr + (i * (1ul << shift));
794 vpn = hpt_vpn(addr, vsid, ssize);
795 hash = hpt_hash(vpn, shift, ssize);
796 if (hidx & _PTEIDX_SECONDARY)
797 hash = ~hash;
798
799 slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
800 slot += hidx & _PTEIDX_GROUP_IX;
801 ppc_md.hpte_invalidate(slot, vpn, psize,
802 MMU_PAGE_16M, ssize, 0);
803 }
804} 772}
805 773
806static pmd_t pmd_set_protbits(pmd_t pmd, pgprot_t pgprot) 774static pmd_t pmd_set_protbits(pmd_t pmd, pgprot_t pgprot)