linux-mips.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Chris Packham <Chris.Packham@alliedtelesis.co.nz>
To: Paul Burton <paul.burton@mips.com>,
	"linux-mips@vger.kernel.org" <linux-mips@vger.kernel.org>
Cc: Paul Burton <pburton@wavecomp.com>
Subject: Re: [PATCH] MIPS: mm: Implement flush_cache_v(un)map using __flush_kernel_vmap_range
Date: Wed, 29 May 2019 23:17:50 +0000	[thread overview]
Message-ID: <27d08fadfad14988a1f289fd2a0219f0@svr-chch-ex1.atlnz.lc> (raw)
In-Reply-To: 20190529224659.27614-1-paul.burton@mips.com

Hi Paul,

On 30/05/19 10:47 AM, Paul Burton wrote:
> Our flush_cache_vmap() & flush_cache_vunmap() implementations for R4k
> style systems simply call r4k_blast_dcache() to wipe out the whole L1
> dcache if it suffers from aliases. This is unsafe on SMP for 2 reasons:
> 
> 1) r4k_blast_dcache() relies upon preemption being disabled so that it
>     can use current_cpu_data/smp_processor_id() to discover the
>     properties of the current CPU's dcache & ensure the whole flush
>     operation happens on one CPU. This may not be the case when
>     flush_cache_vmap() or flush_cache_vunmap() are called.
> 
> 2) It only flushes caches on one CPU, which means the caches for other
>     CPUs may still contain stale data.
> 
> We already have an implementation of flush_kernel_vmap_range() which
> does exactly what we need - it invalidates dcache entries on all CPUs
> safely, and is better optimized to avoid wiping out the entire cache for
> small flushes.
> 
> Reimplement flush_cache_vmap() & flush_cache_vunmap() using
> __flush_kernel_vmap_range() which does what we need already.
> 
> For tx39 __flush_kernel_vmap_range() will simply BUG(), but so far as I
> can see tx39 systems don't suffer from dcache aliasing so this should be
> fine since it should never be called.
> 
> Signed-off-by: Paul Burton <paul.burton@mips.com>
> Reported-by: Chris Packham <chris.packham@alliedtelesis.co.nz>
> ---
> Chris, would you mind giving this a try?

This doesn't quite seem to work. It avoids the BUG() but I get other bad 
behavior. I can't discount it being something odd about my half finished 
port but I can replicate the badness without this patch.

One is a kernel panic in response to activity on the console (output 
below). The other seems to be a result of receiving garbage on the 
console. I wonder if the range needs to be rounded up to a cacheline 
boundary?

Run /sbin/init as init process
overlayfs: upper fs does not support xattr, falling back to index=off 
and metacopy=off.
overlayfs: upper fs does not support xattr, falling back to index=off 
and metacopy=off.
overlayfs: upper fs does not support xattr, falling back to index=off 
and metacopy=off.
random: crng init done
CPU 0 Unable to handle kernel paging request at virtual address 
00000000, epc == 80652e00, ra == 80652dc4
Oops[#1]:
CPU: 0 PID: 7 Comm: kworker/u4:0 Not tainted 5.1.0-at1 #15
Workqueue: events_unbound flush_to_ldisc
$ 0   : 00000000 00000001 00000000 00000000
$ 4   : 8f82aa00 fffffff8 fffffffd 00000001
$ 8   : 8da08818 00000000 00000001 00000018
$12   : fefefeff 7f7f7f7f 00000001 00000001
$16   : c00e1268 c00e126c 00000002 8f84bd18
$20   : 8da08819 83fa6e00 00000001 c00e1270
$24   : 0000c3b6 80336694
$28   : 8f84a000 8f84bcf0 0000000d 80652dc4
Hi    : d49c5168
Lo    : 7f29931c
epc   : 80652e00 __mutex_lock.isra.1+0xa8/0x464
ra    : 80652dc4 __mutex_lock.isra.1+0x6c/0x464
Status: 10008f03        KERNEL EXL IE
Cause : 0080000c (ExcCode 03)
BadVA : 00000000
PrId  : 0002a080 (Broadcom BMIPS4350)
Modules linked in:
Process kworker/u4:0 (pid: 7, threadinfo=f89f9771, task=a0a456a2, 
tls=00000000)
Stack : 00000002 8064f534 8f82aa80 8f82aa80 6b2dc12d 8006b2c8 8090fc78 
83fa6e6c
         83fa6e6c 8064f4a4 c00e1270 00000000 83fa6e6c 8064f534 c00df000 
83fa6e00
         c00e1268 00000000 8da08819 83fa6e00 00000001 c00df018 0000000d 
80334b50
         83fa6e6c 80654aa0 fffb8a00 80790000 83fa6e00 0000000a c00df000 
803358a0
         8f84bd70 00000000 00000000 8da08818 00000000 00000000 8da08818 
80336520
         ...
Call Trace:
[<80652e00>] __mutex_lock.isra.1+0xa8/0x464
[<80334b50>] commit_echoes+0x28/0xc4
[<803358a0>] n_tty_receive_char_special+0xa20/0xc04
[<80336520>] n_tty_receive_buf_common+0xa9c/0xc10
[<803366ac>] n_tty_receive_buf2+0x18/0x24
[<8033a6b8>] tty_port_default_receive_buf+0x50/0xa4
[<80339fc4>] flush_to_ldisc+0xb8/0x12c
[<80052098>] process_one_work+0x224/0x424
[<80052400>] worker_thread+0x168/0x5a0
[<8005882c>] kthread+0x13c/0x144
[<80015e6c>] ret_from_kernel_thread+0x14/0x1c
Code: afa2002c  ae13000c  afb70028 <ac530000> 8e020008  105300b6 
00000000  8f820000  afa20030



> ---
>   arch/mips/include/asm/cacheflush.h | 28 ++++++++++++----------------
>   arch/mips/mm/c-r4k.c               | 15 ---------------
>   arch/mips/mm/c-tx39.c              | 16 ----------------
>   arch/mips/mm/cache.c               |  3 ---
>   4 files changed, 12 insertions(+), 50 deletions(-)
> 
> diff --git a/arch/mips/include/asm/cacheflush.h b/arch/mips/include/asm/cacheflush.h
> index d687b40b9fbb..6285c830c9f2 100644
> --- a/arch/mips/include/asm/cacheflush.h
> +++ b/arch/mips/include/asm/cacheflush.h
> @@ -85,22 +85,6 @@ extern void (*__flush_icache_user_range)(unsigned long start,
>   extern void (*__local_flush_icache_user_range)(unsigned long start,
>   					       unsigned long end);
>   
> -extern void (*__flush_cache_vmap)(void);
> -
> -static inline void flush_cache_vmap(unsigned long start, unsigned long end)
> -{
> -	if (cpu_has_dc_aliases)
> -		__flush_cache_vmap();
> -}
> -
> -extern void (*__flush_cache_vunmap)(void);
> -
> -static inline void flush_cache_vunmap(unsigned long start, unsigned long end)
> -{
> -	if (cpu_has_dc_aliases)
> -		__flush_cache_vunmap();
> -}
> -
>   extern void copy_to_user_page(struct vm_area_struct *vma,
>   	struct page *page, unsigned long vaddr, void *dst, const void *src,
>   	unsigned long len);
> @@ -150,4 +134,16 @@ static inline void invalidate_kernel_vmap_range(void *vaddr, int size)
>   		__flush_kernel_vmap_range((unsigned long) vaddr, size);
>   }
>   
> +static inline void flush_cache_vmap(unsigned long start, unsigned long end)
> +{
> +	if (cpu_has_dc_aliases)
> +		__flush_kernel_vmap_range(start, end - start);
> +}
> +
> +static inline void flush_cache_vunmap(unsigned long start, unsigned long end)
> +{
> +	if (cpu_has_dc_aliases)
> +		__flush_kernel_vmap_range(start, end - start);
> +}
> +
>   #endif /* _ASM_CACHEFLUSH_H */
> diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
> index 5166e38cd1c6..2b2953d3949d 100644
> --- a/arch/mips/mm/c-r4k.c
> +++ b/arch/mips/mm/c-r4k.c
> @@ -559,16 +559,6 @@ static inline int has_valid_asid(const struct mm_struct *mm, unsigned int type)
>   	return 0;
>   }
>   
> -static void r4k__flush_cache_vmap(void)
> -{
> -	r4k_blast_dcache();
> -}
> -
> -static void r4k__flush_cache_vunmap(void)
> -{
> -	r4k_blast_dcache();
> -}
> -
>   /*
>    * Note: flush_tlb_range() assumes flush_cache_range() sufficiently flushes
>    * whole caches when vma is executable.
> @@ -1854,9 +1844,6 @@ void r4k_cache_init(void)
>   	else
>   		shm_align_mask = PAGE_SIZE-1;
>   
> -	__flush_cache_vmap	= r4k__flush_cache_vmap;
> -	__flush_cache_vunmap	= r4k__flush_cache_vunmap;
> -
>   	flush_cache_all		= cache_noop;
>   	__flush_cache_all	= r4k___flush_cache_all;
>   	flush_cache_mm		= r4k_flush_cache_mm;
> @@ -1931,8 +1918,6 @@ void r4k_cache_init(void)
>   	case CPU_LOONGSON3:
>   		/* Loongson-3 maintains cache coherency by hardware */
>   		__flush_cache_all	= cache_noop;
> -		__flush_cache_vmap	= cache_noop;
> -		__flush_cache_vunmap	= cache_noop;
>   		__flush_kernel_vmap_range = (void *)cache_noop;
>   		flush_cache_mm		= (void *)cache_noop;
>   		flush_cache_page	= (void *)cache_noop;
> diff --git a/arch/mips/mm/c-tx39.c b/arch/mips/mm/c-tx39.c
> index b7c8a9d79c35..6bf13a7db485 100644
> --- a/arch/mips/mm/c-tx39.c
> +++ b/arch/mips/mm/c-tx39.c
> @@ -121,16 +121,6 @@ static inline void tx39_blast_icache(void)
>   	local_irq_restore(flags);
>   }
>   
> -static void tx39__flush_cache_vmap(void)
> -{
> -	tx39_blast_dcache();
> -}
> -
> -static void tx39__flush_cache_vunmap(void)
> -{
> -	tx39_blast_dcache();
> -}
> -
>   static inline void tx39_flush_cache_all(void)
>   {
>   	if (!cpu_has_dc_aliases)
> @@ -339,8 +329,6 @@ void tx39_cache_init(void)
>   	switch (current_cpu_type()) {
>   	case CPU_TX3912:
>   		/* TX39/H core (writethru direct-map cache) */
> -		__flush_cache_vmap	= tx39__flush_cache_vmap;
> -		__flush_cache_vunmap	= tx39__flush_cache_vunmap;
>   		flush_cache_all = tx39h_flush_icache_all;
>   		__flush_cache_all	= tx39h_flush_icache_all;
>   		flush_cache_mm		= (void *) tx39h_flush_icache_all;
> @@ -363,10 +351,6 @@ void tx39_cache_init(void)
>   	default:
>   		/* TX39/H2,H3 core (writeback 2way-set-associative cache) */
>   		/* board-dependent init code may set WBON */
> -
> -		__flush_cache_vmap	= tx39__flush_cache_vmap;
> -		__flush_cache_vunmap	= tx39__flush_cache_vunmap;
> -
>   		flush_cache_all = tx39_flush_cache_all;
>   		__flush_cache_all = tx39___flush_cache_all;
>   		flush_cache_mm = tx39_flush_cache_mm;
> diff --git a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c
> index 3da216988672..c6c0ef539d3a 100644
> --- a/arch/mips/mm/cache.c
> +++ b/arch/mips/mm/cache.c
> @@ -40,9 +40,6 @@ EXPORT_SYMBOL_GPL(__flush_icache_user_range);
>   void (*__local_flush_icache_user_range)(unsigned long start, unsigned long end);
>   EXPORT_SYMBOL_GPL(__local_flush_icache_user_range);
>   
> -void (*__flush_cache_vmap)(void);
> -void (*__flush_cache_vunmap)(void);
> -
>   void (*__flush_kernel_vmap_range)(unsigned long vaddr, int size);
>   EXPORT_SYMBOL_GPL(__flush_kernel_vmap_range);
>   
> 


      reply	other threads:[~2019-05-29 23:18 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-05-28 22:12 [PATCH] MIPS: mm: Use SMP safe operations for flush_cache_vmap Chris Packham
2019-05-29 22:47 ` [PATCH] MIPS: mm: Implement flush_cache_v(un)map using __flush_kernel_vmap_range Paul Burton
2019-05-29 23:17   ` Chris Packham [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=27d08fadfad14988a1f289fd2a0219f0@svr-chch-ex1.atlnz.lc \
    --to=chris.packham@alliedtelesis.co.nz \
    --cc=linux-mips@vger.kernel.org \
    --cc=paul.burton@mips.com \
    --cc=pburton@wavecomp.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).