diff options
Diffstat (limited to 'arch/sparc/mm/tlb.c')
| -rw-r--r-- | arch/sparc/mm/tlb.c | 48 | 
1 files changed, 32 insertions, 16 deletions
diff --git a/arch/sparc/mm/tlb.c b/arch/sparc/mm/tlb.c index 7a91f288c70..b89aba217e3 100644 --- a/arch/sparc/mm/tlb.c +++ b/arch/sparc/mm/tlb.c @@ -4,7 +4,6 @@   */  #include <linux/kernel.h> -#include <linux/init.h>  #include <linux/percpu.h>  #include <linux/mm.h>  #include <linux/swap.h> @@ -135,7 +134,7 @@ no_cache_flush:  #ifdef CONFIG_TRANSPARENT_HUGEPAGE  static void tlb_batch_pmd_scan(struct mm_struct *mm, unsigned long vaddr, -			       pmd_t pmd, bool exec) +			       pmd_t pmd)  {  	unsigned long end;  	pte_t *pte; @@ -143,8 +142,11 @@ static void tlb_batch_pmd_scan(struct mm_struct *mm, unsigned long vaddr,  	pte = pte_offset_map(&pmd, vaddr);  	end = vaddr + HPAGE_SIZE;  	while (vaddr < end) { -		if (pte_val(*pte) & _PAGE_VALID) +		if (pte_val(*pte) & _PAGE_VALID) { +			bool exec = pte_exec(*pte); +  			tlb_batch_add_one(mm, vaddr, exec); +		}  		pte++;  		vaddr += PAGE_SIZE;  	} @@ -161,8 +163,8 @@ void set_pmd_at(struct mm_struct *mm, unsigned long addr,  	if (mm == &init_mm)  		return; -	if ((pmd_val(pmd) ^ pmd_val(orig)) & PMD_ISHUGE) { -		if (pmd_val(pmd) & PMD_ISHUGE) +	if ((pmd_val(pmd) ^ pmd_val(orig)) & _PAGE_PMD_HUGE) { +		if (pmd_val(pmd) & _PAGE_PMD_HUGE)  			mm->context.huge_pte_count++;  		else  			mm->context.huge_pte_count--; @@ -178,16 +180,30 @@ void set_pmd_at(struct mm_struct *mm, unsigned long addr,  	}  	if (!pmd_none(orig)) { -		bool exec = ((pmd_val(orig) & PMD_HUGE_EXEC) != 0); -  		addr &= HPAGE_MASK; -		if (pmd_val(orig) & PMD_ISHUGE) +		if (pmd_trans_huge(orig)) { +			pte_t orig_pte = __pte(pmd_val(orig)); +			bool exec = pte_exec(orig_pte); +  			tlb_batch_add_one(mm, addr, exec); -		else -			tlb_batch_pmd_scan(mm, addr, orig, exec); +			tlb_batch_add_one(mm, addr + REAL_HPAGE_SIZE, exec); +		} else { +			tlb_batch_pmd_scan(mm, addr, orig); +		}  	}  } +void pmdp_invalidate(struct vm_area_struct *vma, unsigned long address, +		     pmd_t *pmdp) +{ +	pmd_t entry = *pmdp; + +	pmd_val(entry) &= ~_PAGE_VALID; + +	set_pmd_at(vma->vm_mm, address, pmdp, entry); +	flush_tlb_range(vma, address, address + HPAGE_PMD_SIZE); +} +  void pgtable_trans_huge_deposit(struct mm_struct *mm, pmd_t *pmdp,  				pgtable_t pgtable)  { @@ -196,11 +212,11 @@ void pgtable_trans_huge_deposit(struct mm_struct *mm, pmd_t *pmdp,  	assert_spin_locked(&mm->page_table_lock);  	/* FIFO */ -	if (!mm->pmd_huge_pte) +	if (!pmd_huge_pte(mm, pmdp))  		INIT_LIST_HEAD(lh);  	else -		list_add(lh, (struct list_head *) mm->pmd_huge_pte); -	mm->pmd_huge_pte = pgtable; +		list_add(lh, (struct list_head *) pmd_huge_pte(mm, pmdp)); +	pmd_huge_pte(mm, pmdp) = pgtable;  }  pgtable_t pgtable_trans_huge_withdraw(struct mm_struct *mm, pmd_t *pmdp) @@ -211,12 +227,12 @@ pgtable_t pgtable_trans_huge_withdraw(struct mm_struct *mm, pmd_t *pmdp)  	assert_spin_locked(&mm->page_table_lock);  	/* FIFO */ -	pgtable = mm->pmd_huge_pte; +	pgtable = pmd_huge_pte(mm, pmdp);  	lh = (struct list_head *) pgtable;  	if (list_empty(lh)) -		mm->pmd_huge_pte = NULL; +		pmd_huge_pte(mm, pmdp) = NULL;  	else { -		mm->pmd_huge_pte = (pgtable_t) lh->next; +		pmd_huge_pte(mm, pmdp) = (pgtable_t) lh->next;  		list_del(lh);  	}  	pte_val(pgtable[0]) = 0;  | 
