summaryrefslogtreecommitdiff
path: root/arch/sparc/mm/tlb.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-05-06 09:08:03 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2014-05-06 09:08:03 -0700
commit9bd29c56ade57106501d21fd4b0936644a426cb6 (patch)
tree39cf0349a7877fdbf91dd3609b2d1b7b6028a751 /arch/sparc/mm/tlb.c
parent30321c7b658a5661eea715b33e82a5fd3e33e180 (diff)
parentfe866433f843b080246ce729b5e6b27b5f5d9a58 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc
Pull sparc fixes from David Miller: "I've been auditing the THP support on sparc64 and found several bugs, hopefully most of which are fixed completely here. Also an RT kernel locking fix from Kirill Tkhai" * git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc: sparc64: Give more detailed information in {pgd,pmd}_ERROR() and kill pte_ERROR(). sparc64: Add basic validations to {pud,pmd}_bad(). sparc64: Use 'ILOG2_4MB' instead of constant '22'. sparc64: Fix range check in kern_addr_valid(). sparc64: Fix top-level fault handling bugs. sparc64: Handle 32-bit tasks properly in compute_effective_address(). sparc64: Don't use _PAGE_PRESENT in pte_modify() mask. sparc64: Fix hex values in comment above pte_modify(). sparc64: Fix bugs in get_user_pages_fast() wrt. THP. sparc64: Fix huge PMD invalidation. sparc64: Fix executable bit testing in set_pmd_at() paths. sparc64: Normalize NMI watchdog logging and behavior. sparc64: Make itc_sync_lock raw sparc64: Fix argument sign extension for compat_sys_futex().
Diffstat (limited to 'arch/sparc/mm/tlb.c')
-rw-r--r--arch/sparc/mm/tlb.c26
1 files changed, 20 insertions, 6 deletions
diff --git a/arch/sparc/mm/tlb.c b/arch/sparc/mm/tlb.c
index b12cb5e72812..b89aba217e3b 100644
--- a/arch/sparc/mm/tlb.c
+++ b/arch/sparc/mm/tlb.c
@@ -134,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;
@@ -142,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;
}
@@ -177,19 +180,30 @@ void set_pmd_at(struct mm_struct *mm, unsigned long addr,
}
if (!pmd_none(orig)) {
- pte_t orig_pte = __pte(pmd_val(orig));
- bool exec = pte_exec(orig_pte);
-
addr &= HPAGE_MASK;
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);
tlb_batch_add_one(mm, addr + REAL_HPAGE_SIZE, exec);
} else {
- tlb_batch_pmd_scan(mm, addr, orig, exec);
+ 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)
{