xref: /openbmc/linux/arch/ia64/lib/flush.S (revision ab03e604)
1457c8996SThomas Gleixner/* SPDX-License-Identifier: GPL-2.0-only */
21da177e4SLinus Torvalds/*
31da177e4SLinus Torvalds * Cache flushing routines.
41da177e4SLinus Torvalds *
52074615aSDavid Mosberger-Tang * Copyright (C) 1999-2001, 2005 Hewlett-Packard Co
62074615aSDavid Mosberger-Tang *	David Mosberger-Tang <davidm@hpl.hp.com>
708357f82SZoltan Menyhart *
808357f82SZoltan Menyhart * 05/28/05 Zoltan Menyhart	Dynamic stride size
91da177e4SLinus Torvalds */
1008357f82SZoltan Menyhart
11*ab03e604SMasahiro Yamada#include <linux/export.h>
121da177e4SLinus Torvalds#include <asm/asmmacro.h>
131da177e4SLinus Torvalds
141da177e4SLinus Torvalds	/*
151da177e4SLinus Torvalds	 * flush_icache_range(start,end)
1608357f82SZoltan Menyhart	 *
1708357f82SZoltan Menyhart	 *	Make i-cache(s) coherent with d-caches.
1808357f82SZoltan Menyhart	 *
1908357f82SZoltan Menyhart	 *	Must deal with range from start to end-1 but nothing else (need to
201da177e4SLinus Torvalds	 *	be careful not to touch addresses that may be unmapped).
2108357f82SZoltan Menyhart	 *
2208357f82SZoltan Menyhart	 *	Note: "in0" and "in1" are preserved for debugging purposes.
231da177e4SLinus Torvalds	 */
241f7ad57bSPrasanna S Panchamukhi	.section .kprobes.text,"ax"
251da177e4SLinus TorvaldsGLOBAL_ENTRY(flush_icache_range)
2608357f82SZoltan Menyhart
271da177e4SLinus Torvalds	.prologue
281da177e4SLinus Torvalds	alloc	r2=ar.pfs,2,0,0,0
2908357f82SZoltan Menyhart	movl	r3=ia64_i_cache_stride_shift
3008357f82SZoltan Menyhart 	mov	r21=1
311da177e4SLinus Torvalds	;;
3208357f82SZoltan Menyhart	ld8	r20=[r3]		// r20: stride shift
3308357f82SZoltan Menyhart	sub	r22=in1,r0,1		// last byte address
3408357f82SZoltan Menyhart	;;
3508357f82SZoltan Menyhart	shr.u	r23=in0,r20		// start / (stride size)
3608357f82SZoltan Menyhart	shr.u	r22=r22,r20		// (last byte address) / (stride size)
3708357f82SZoltan Menyhart	shl	r21=r21,r20		// r21: stride size of the i-cache(s)
3808357f82SZoltan Menyhart	;;
3908357f82SZoltan Menyhart	sub	r8=r22,r23		// number of strides - 1
4008357f82SZoltan Menyhart	shl	r24=r23,r20		// r24: addresses for "fc.i" =
4108357f82SZoltan Menyhart					//	"start" rounded down to stride boundary
421da177e4SLinus Torvalds	.save	ar.lc,r3
431da177e4SLinus Torvalds	mov	r3=ar.lc		// save ar.lc
441da177e4SLinus Torvalds	;;
451da177e4SLinus Torvalds
461da177e4SLinus Torvalds	.body
471da177e4SLinus Torvalds	mov	ar.lc=r8
481da177e4SLinus Torvalds	;;
4908357f82SZoltan Menyhart	/*
5008357f82SZoltan Menyhart	 * 32 byte aligned loop, even number of (actually 2) bundles
5108357f82SZoltan Menyhart	 */
5208357f82SZoltan Menyhart.Loop:	fc.i	r24			// issuable on M0 only
5308357f82SZoltan Menyhart	add	r24=r21,r24		// we flush "stride size" bytes per iteration
5408357f82SZoltan Menyhart	nop.i	0
551da177e4SLinus Torvalds	br.cloop.sptk.few .Loop
561da177e4SLinus Torvalds	;;
571da177e4SLinus Torvalds	sync.i
581da177e4SLinus Torvalds	;;
591da177e4SLinus Torvalds	srlz.i
601da177e4SLinus Torvalds	;;
611da177e4SLinus Torvalds	mov	ar.lc=r3		// restore ar.lc
621da177e4SLinus Torvalds	br.ret.sptk.many rp
631da177e4SLinus TorvaldsEND(flush_icache_range)
64e007c533SAl ViroEXPORT_SYMBOL_GPL(flush_icache_range)
6562fdd767SFenghua Yu
6662fdd767SFenghua Yu	/*
6762fdd767SFenghua Yu	 * clflush_cache_range(start,size)
6862fdd767SFenghua Yu	 *
6962fdd767SFenghua Yu	 *	Flush cache lines from start to start+size-1.
7062fdd767SFenghua Yu	 *
7162fdd767SFenghua Yu	 *	Must deal with range from start to start+size-1 but nothing else
7262fdd767SFenghua Yu	 *	(need to be careful not to touch addresses that may be
7362fdd767SFenghua Yu	 *	unmapped).
7462fdd767SFenghua Yu	 *
7562fdd767SFenghua Yu	 *	Note: "in0" and "in1" are preserved for debugging purposes.
7662fdd767SFenghua Yu	 */
7762fdd767SFenghua Yu	.section .kprobes.text,"ax"
7862fdd767SFenghua YuGLOBAL_ENTRY(clflush_cache_range)
7962fdd767SFenghua Yu
8062fdd767SFenghua Yu	.prologue
8162fdd767SFenghua Yu	alloc	r2=ar.pfs,2,0,0,0
8262fdd767SFenghua Yu	movl	r3=ia64_cache_stride_shift
8362fdd767SFenghua Yu	mov	r21=1
8462fdd767SFenghua Yu	add     r22=in1,in0
8562fdd767SFenghua Yu	;;
8662fdd767SFenghua Yu	ld8	r20=[r3]		// r20: stride shift
8762fdd767SFenghua Yu	sub	r22=r22,r0,1		// last byte address
8862fdd767SFenghua Yu	;;
8962fdd767SFenghua Yu	shr.u	r23=in0,r20		// start / (stride size)
9062fdd767SFenghua Yu	shr.u	r22=r22,r20		// (last byte address) / (stride size)
9162fdd767SFenghua Yu	shl	r21=r21,r20		// r21: stride size of the i-cache(s)
9262fdd767SFenghua Yu	;;
9362fdd767SFenghua Yu	sub	r8=r22,r23		// number of strides - 1
9462fdd767SFenghua Yu	shl	r24=r23,r20		// r24: addresses for "fc" =
9562fdd767SFenghua Yu					//	"start" rounded down to stride
9662fdd767SFenghua Yu					//	boundary
9762fdd767SFenghua Yu	.save	ar.lc,r3
9862fdd767SFenghua Yu	mov	r3=ar.lc		// save ar.lc
9962fdd767SFenghua Yu	;;
10062fdd767SFenghua Yu
10162fdd767SFenghua Yu	.body
10262fdd767SFenghua Yu	mov	ar.lc=r8
10362fdd767SFenghua Yu	;;
10462fdd767SFenghua Yu	/*
10562fdd767SFenghua Yu	 * 32 byte aligned loop, even number of (actually 2) bundles
10662fdd767SFenghua Yu	 */
10762fdd767SFenghua Yu.Loop_fc:
10862fdd767SFenghua Yu	fc	r24		// issuable on M0 only
10962fdd767SFenghua Yu	add	r24=r21,r24	// we flush "stride size" bytes per iteration
11062fdd767SFenghua Yu	nop.i	0
11162fdd767SFenghua Yu	br.cloop.sptk.few .Loop_fc
11262fdd767SFenghua Yu	;;
11362fdd767SFenghua Yu	sync.i
11462fdd767SFenghua Yu	;;
11562fdd767SFenghua Yu	srlz.i
11662fdd767SFenghua Yu	;;
11762fdd767SFenghua Yu	mov	ar.lc=r3		// restore ar.lc
11862fdd767SFenghua Yu	br.ret.sptk.many rp
11962fdd767SFenghua YuEND(clflush_cache_range)
120