lkml.org 
[lkml]   [2020]   [Nov]   [23]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.9 42/47] xtensa: disable preemption around cache alias management calls
    Date
    From: Max Filippov <jcmvbkbc@gmail.com>

    commit 3a860d165eb5f4d7cf0bf81ef6a5b5c5e1754422 upstream.

    Although cache alias management calls set up and tear down TLB entries
    and fast_second_level_miss is able to restore TLB entry should it be
    evicted they absolutely cannot preempt each other because they use the
    same TLBTEMP area for different purposes.
    Disable preemption around all cache alias management calls to enforce
    that.

    Cc: stable@vger.kernel.org
    Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    arch/xtensa/mm/cache.c | 14 ++++++++++++++
    1 file changed, 14 insertions(+)

    --- a/arch/xtensa/mm/cache.c
    +++ b/arch/xtensa/mm/cache.c
    @@ -74,8 +74,10 @@ static inline void kmap_invalidate_coher
    kvaddr = TLBTEMP_BASE_1 +
    (page_to_phys(page) & DCACHE_ALIAS_MASK);

    + preempt_disable();
    __invalidate_dcache_page_alias(kvaddr,
    page_to_phys(page));
    + preempt_enable();
    }
    }
    }
    @@ -160,6 +162,7 @@ void flush_dcache_page(struct page *page
    if (!alias && !mapping)
    return;

    + preempt_disable();
    virt = TLBTEMP_BASE_1 + (phys & DCACHE_ALIAS_MASK);
    __flush_invalidate_dcache_page_alias(virt, phys);

    @@ -170,6 +173,7 @@ void flush_dcache_page(struct page *page

    if (mapping)
    __invalidate_icache_page_alias(virt, phys);
    + preempt_enable();
    }

    /* There shouldn't be an entry in the cache for this page anymore. */
    @@ -203,8 +207,10 @@ void local_flush_cache_page(struct vm_ar
    unsigned long phys = page_to_phys(pfn_to_page(pfn));
    unsigned long virt = TLBTEMP_BASE_1 + (address & DCACHE_ALIAS_MASK);

    + preempt_disable();
    __flush_invalidate_dcache_page_alias(virt, phys);
    __invalidate_icache_page_alias(virt, phys);
    + preempt_enable();
    }
    EXPORT_SYMBOL(local_flush_cache_page);

    @@ -231,11 +237,13 @@ update_mmu_cache(struct vm_area_struct *
    unsigned long phys = page_to_phys(page);
    unsigned long tmp;

    + preempt_disable();
    tmp = TLBTEMP_BASE_1 + (phys & DCACHE_ALIAS_MASK);
    __flush_invalidate_dcache_page_alias(tmp, phys);
    tmp = TLBTEMP_BASE_1 + (addr & DCACHE_ALIAS_MASK);
    __flush_invalidate_dcache_page_alias(tmp, phys);
    __invalidate_icache_page_alias(tmp, phys);
    + preempt_enable();

    clear_bit(PG_arch_1, &page->flags);
    }
    @@ -269,7 +277,9 @@ void copy_to_user_page(struct vm_area_st

    if (alias) {
    unsigned long t = TLBTEMP_BASE_1 + (vaddr & DCACHE_ALIAS_MASK);
    + preempt_disable();
    __flush_invalidate_dcache_page_alias(t, phys);
    + preempt_enable();
    }

    /* Copy data */
    @@ -284,9 +294,11 @@ void copy_to_user_page(struct vm_area_st
    if (alias) {
    unsigned long t = TLBTEMP_BASE_1 + (vaddr & DCACHE_ALIAS_MASK);

    + preempt_disable();
    __flush_invalidate_dcache_range((unsigned long) dst, len);
    if ((vma->vm_flags & VM_EXEC) != 0)
    __invalidate_icache_page_alias(t, phys);
    + preempt_enable();

    } else if ((vma->vm_flags & VM_EXEC) != 0) {
    __flush_dcache_range((unsigned long)dst,len);
    @@ -308,7 +320,9 @@ extern void copy_from_user_page(struct v

    if (alias) {
    unsigned long t = TLBTEMP_BASE_1 + (vaddr & DCACHE_ALIAS_MASK);
    + preempt_disable();
    __flush_invalidate_dcache_page_alias(t, phys);
    + preempt_enable();
    }

    memcpy(dst, src, len);

    \
     
     \ /
      Last update: 2020-11-23 14:40    [W:4.203 / U:0.356 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site