lkml.org 
[lkml]   [2013]   [Mar]   [3]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[ 011/153] [PARISC] Purge existing TLB entries in set_pte_at and ptep_set_wrprotect
    3.2-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: John David Anglin <dave.anglin@bell.net>

    commit 7139bc1579901b53db7e898789e916ee2fb52d78 upstream.

    This patch goes a long way toward fixing the minifail bug, and
    it  significantly improves the stability of SMP machines such as
    the rp3440.  When write  protecting a page for COW, we need to
    purge the existing translation.  Otherwise, the COW break
    doesn't occur as expected because the TLB may still have a stale entry
    which allows writes.

    [jejb: fix up checkpatch errors]
    Signed-off-by: John David Anglin <dave.anglin@bell.net>
    Signed-off-by: James Bottomley <JBottomley@Parallels.com>
    Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
    ---
    arch/parisc/include/asm/pgtable.h | 13 ++++++++++---
    arch/parisc/kernel/cache.c | 18 ++++++++++++++++++
    2 files changed, 28 insertions(+), 3 deletions(-)

    --- a/arch/parisc/include/asm/pgtable.h
    +++ b/arch/parisc/include/asm/pgtable.h
    @@ -12,11 +12,10 @@

    #include <linux/bitops.h>
    #include <linux/spinlock.h>
    +#include <linux/mm_types.h>
    #include <asm/processor.h>
    #include <asm/cache.h>

    -struct vm_area_struct;
    -
    /*
    * kern_addr_valid(ADDR) tests if ADDR is pointing to valid kernel
    * memory. For the return value to be meaningful, ADDR must be >=
    @@ -40,7 +39,14 @@ struct vm_area_struct;
    do{ \
    *(pteptr) = (pteval); \
    } while(0)
    -#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
    +
    +extern void purge_tlb_entries(struct mm_struct *, unsigned long);
    +
    +#define set_pte_at(mm, addr, ptep, pteval) \
    + do { \
    + set_pte(ptep, pteval); \
    + purge_tlb_entries(mm, addr); \
    + } while (0)

    #endif /* !__ASSEMBLY__ */

    @@ -464,6 +470,7 @@ static inline void ptep_set_wrprotect(st
    old = pte_val(*ptep);
    new = pte_val(pte_wrprotect(__pte (old)));
    } while (cmpxchg((unsigned long *) ptep, old, new) != old);
    + purge_tlb_entries(mm, addr);
    #else
    pte_t old_pte = *ptep;
    set_pte_at(mm, addr, ptep, pte_wrprotect(old_pte));
    --- a/arch/parisc/kernel/cache.c
    +++ b/arch/parisc/kernel/cache.c
    @@ -421,6 +421,24 @@ void kunmap_parisc(void *addr)
    EXPORT_SYMBOL(kunmap_parisc);
    #endif

    +void purge_tlb_entries(struct mm_struct *mm, unsigned long addr)
    +{
    + unsigned long flags;
    +
    + /* Note: purge_tlb_entries can be called at startup with
    + no context. */
    +
    + /* Disable preemption while we play with %sr1. */
    + preempt_disable();
    + mtsp(mm->context, 1);
    + purge_tlb_start(flags);
    + pdtlb(addr);
    + pitlb(addr);
    + purge_tlb_end(flags);
    + preempt_enable();
    +}
    +EXPORT_SYMBOL(purge_tlb_entries);
    +
    void __flush_tlb_range(unsigned long sid, unsigned long start,
    unsigned long end)
    {

    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

    \
     
     \ /
      Last update: 2013-03-04 06:01    [W:4.667 / U:0.120 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site