xref: /kernel/linux/linux-5.10/arch/ia64/lib/flush.S (revision 8c2ecf20)
18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Cache flushing routines.
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (C) 1999-2001, 2005 Hewlett-Packard Co
68c2ecf20Sopenharmony_ci *	David Mosberger-Tang <davidm@hpl.hp.com>
78c2ecf20Sopenharmony_ci *
88c2ecf20Sopenharmony_ci * 05/28/05 Zoltan Menyhart	Dynamic stride size
98c2ecf20Sopenharmony_ci */
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#include <asm/asmmacro.h>
128c2ecf20Sopenharmony_ci#include <asm/export.h>
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ci	/*
168c2ecf20Sopenharmony_ci	 * flush_icache_range(start,end)
178c2ecf20Sopenharmony_ci	 *
188c2ecf20Sopenharmony_ci	 *	Make i-cache(s) coherent with d-caches.
198c2ecf20Sopenharmony_ci	 *
208c2ecf20Sopenharmony_ci	 *	Must deal with range from start to end-1 but nothing else (need to
218c2ecf20Sopenharmony_ci	 *	be careful not to touch addresses that may be unmapped).
228c2ecf20Sopenharmony_ci	 *
238c2ecf20Sopenharmony_ci	 *	Note: "in0" and "in1" are preserved for debugging purposes.
248c2ecf20Sopenharmony_ci	 */
258c2ecf20Sopenharmony_ci	.section .kprobes.text,"ax"
268c2ecf20Sopenharmony_ciGLOBAL_ENTRY(flush_icache_range)
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci	.prologue
298c2ecf20Sopenharmony_ci	alloc	r2=ar.pfs,2,0,0,0
308c2ecf20Sopenharmony_ci	movl	r3=ia64_i_cache_stride_shift
318c2ecf20Sopenharmony_ci 	mov	r21=1
328c2ecf20Sopenharmony_ci	;;
338c2ecf20Sopenharmony_ci	ld8	r20=[r3]		// r20: stride shift
348c2ecf20Sopenharmony_ci	sub	r22=in1,r0,1		// last byte address
358c2ecf20Sopenharmony_ci	;;
368c2ecf20Sopenharmony_ci	shr.u	r23=in0,r20		// start / (stride size)
378c2ecf20Sopenharmony_ci	shr.u	r22=r22,r20		// (last byte address) / (stride size)
388c2ecf20Sopenharmony_ci	shl	r21=r21,r20		// r21: stride size of the i-cache(s)
398c2ecf20Sopenharmony_ci	;;
408c2ecf20Sopenharmony_ci	sub	r8=r22,r23		// number of strides - 1
418c2ecf20Sopenharmony_ci	shl	r24=r23,r20		// r24: addresses for "fc.i" =
428c2ecf20Sopenharmony_ci					//	"start" rounded down to stride boundary
438c2ecf20Sopenharmony_ci	.save	ar.lc,r3
448c2ecf20Sopenharmony_ci	mov	r3=ar.lc		// save ar.lc
458c2ecf20Sopenharmony_ci	;;
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci	.body
488c2ecf20Sopenharmony_ci	mov	ar.lc=r8
498c2ecf20Sopenharmony_ci	;;
508c2ecf20Sopenharmony_ci	/*
518c2ecf20Sopenharmony_ci	 * 32 byte aligned loop, even number of (actually 2) bundles
528c2ecf20Sopenharmony_ci	 */
538c2ecf20Sopenharmony_ci.Loop:	fc.i	r24			// issuable on M0 only
548c2ecf20Sopenharmony_ci	add	r24=r21,r24		// we flush "stride size" bytes per iteration
558c2ecf20Sopenharmony_ci	nop.i	0
568c2ecf20Sopenharmony_ci	br.cloop.sptk.few .Loop
578c2ecf20Sopenharmony_ci	;;
588c2ecf20Sopenharmony_ci	sync.i
598c2ecf20Sopenharmony_ci	;;
608c2ecf20Sopenharmony_ci	srlz.i
618c2ecf20Sopenharmony_ci	;;
628c2ecf20Sopenharmony_ci	mov	ar.lc=r3		// restore ar.lc
638c2ecf20Sopenharmony_ci	br.ret.sptk.many rp
648c2ecf20Sopenharmony_ciEND(flush_icache_range)
658c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(flush_icache_range)
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci	/*
688c2ecf20Sopenharmony_ci	 * clflush_cache_range(start,size)
698c2ecf20Sopenharmony_ci	 *
708c2ecf20Sopenharmony_ci	 *	Flush cache lines from start to start+size-1.
718c2ecf20Sopenharmony_ci	 *
728c2ecf20Sopenharmony_ci	 *	Must deal with range from start to start+size-1 but nothing else
738c2ecf20Sopenharmony_ci	 *	(need to be careful not to touch addresses that may be
748c2ecf20Sopenharmony_ci	 *	unmapped).
758c2ecf20Sopenharmony_ci	 *
768c2ecf20Sopenharmony_ci	 *	Note: "in0" and "in1" are preserved for debugging purposes.
778c2ecf20Sopenharmony_ci	 */
788c2ecf20Sopenharmony_ci	.section .kprobes.text,"ax"
798c2ecf20Sopenharmony_ciGLOBAL_ENTRY(clflush_cache_range)
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci	.prologue
828c2ecf20Sopenharmony_ci	alloc	r2=ar.pfs,2,0,0,0
838c2ecf20Sopenharmony_ci	movl	r3=ia64_cache_stride_shift
848c2ecf20Sopenharmony_ci	mov	r21=1
858c2ecf20Sopenharmony_ci	add     r22=in1,in0
868c2ecf20Sopenharmony_ci	;;
878c2ecf20Sopenharmony_ci	ld8	r20=[r3]		// r20: stride shift
888c2ecf20Sopenharmony_ci	sub	r22=r22,r0,1		// last byte address
898c2ecf20Sopenharmony_ci	;;
908c2ecf20Sopenharmony_ci	shr.u	r23=in0,r20		// start / (stride size)
918c2ecf20Sopenharmony_ci	shr.u	r22=r22,r20		// (last byte address) / (stride size)
928c2ecf20Sopenharmony_ci	shl	r21=r21,r20		// r21: stride size of the i-cache(s)
938c2ecf20Sopenharmony_ci	;;
948c2ecf20Sopenharmony_ci	sub	r8=r22,r23		// number of strides - 1
958c2ecf20Sopenharmony_ci	shl	r24=r23,r20		// r24: addresses for "fc" =
968c2ecf20Sopenharmony_ci					//	"start" rounded down to stride
978c2ecf20Sopenharmony_ci					//	boundary
988c2ecf20Sopenharmony_ci	.save	ar.lc,r3
998c2ecf20Sopenharmony_ci	mov	r3=ar.lc		// save ar.lc
1008c2ecf20Sopenharmony_ci	;;
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_ci	.body
1038c2ecf20Sopenharmony_ci	mov	ar.lc=r8
1048c2ecf20Sopenharmony_ci	;;
1058c2ecf20Sopenharmony_ci	/*
1068c2ecf20Sopenharmony_ci	 * 32 byte aligned loop, even number of (actually 2) bundles
1078c2ecf20Sopenharmony_ci	 */
1088c2ecf20Sopenharmony_ci.Loop_fc:
1098c2ecf20Sopenharmony_ci	fc	r24		// issuable on M0 only
1108c2ecf20Sopenharmony_ci	add	r24=r21,r24	// we flush "stride size" bytes per iteration
1118c2ecf20Sopenharmony_ci	nop.i	0
1128c2ecf20Sopenharmony_ci	br.cloop.sptk.few .Loop_fc
1138c2ecf20Sopenharmony_ci	;;
1148c2ecf20Sopenharmony_ci	sync.i
1158c2ecf20Sopenharmony_ci	;;
1168c2ecf20Sopenharmony_ci	srlz.i
1178c2ecf20Sopenharmony_ci	;;
1188c2ecf20Sopenharmony_ci	mov	ar.lc=r3		// restore ar.lc
1198c2ecf20Sopenharmony_ci	br.ret.sptk.many rp
1208c2ecf20Sopenharmony_ciEND(clflush_cache_range)
121