179 lines · 2.7 KB · Assembly
RawDownload
/* SPDX-License-Identifier: GPL-2.0-or-later *//* * * Copyright (C) IBM Corporation, 2012 * * Author: Anton Blanchard <anton@au.ibm.com> */ #include <linux/export.h>#include <asm/ppc_asm.h>#include <asm/linkage.h>#include <asm/asm-offsets.h> /** * __arch_clear_user: - Zero a block of memory in user space, with less checking. * @to:   Destination address, in user space. * @n:    Number of bytes to zero. * * Zero a block of memory in user space.  Caller must check * the specified block with access_ok() before calling this function. * * Returns number of bytes that could not be cleared. * On success, this will be zero. */ 	.macro err1100:	EX_TABLE(100b,.Ldo_err1)	.endm 	.macro err2200:	EX_TABLE(200b,.Ldo_err2)	.endm 	.macro err3300:	EX_TABLE(300b,.Ldo_err3)	.endm .Ldo_err1:	mr	r3,r8 .Ldo_err2:	mtctr	r41:err3;	stb	r0,0(r3)	addi	r3,r3,1	addi	r4,r4,-1	bdnz	1b .Ldo_err3:	mr	r3,r4	blr _GLOBAL_TOC(__arch_clear_user)	cmpdi	r4,32	neg	r6,r3	li	r0,0	blt	.Lshort_clear	mr	r8,r3	mtocrf	0x01,r6	clrldi	r6,r6,(64-3) 	/* Get the destination 8 byte aligned */	bf	cr7*4+3,1ferr1;	stb	r0,0(r3)	addi	r3,r3,1 1:	bf	cr7*4+2,2ferr1;	sth	r0,0(r3)	addi	r3,r3,2 2:	bf	cr7*4+1,3ferr1;	stw	r0,0(r3)	addi	r3,r3,4 3:	sub	r4,r4,r6 	cmpdi	r4,32	cmpdi	cr1,r4,512	blt	.Lshort_clear	bgt	cr1,.Llong_clear .Lmedium_clear:	srdi	r6,r4,5	mtctr	r6 	/* Do 32 byte chunks */4:err2;	std	r0,0(r3)err2;	std	r0,8(r3)err2;	std	r0,16(r3)err2;	std	r0,24(r3)	addi	r3,r3,32	addi	r4,r4,-32	bdnz	4b .Lshort_clear:	/* up to 31 bytes to go */	cmpdi	r4,16	blt	6ferr2;	std	r0,0(r3)err2;	std	r0,8(r3)	addi	r3,r3,16	addi	r4,r4,-16 	/* Up to 15 bytes to go */6:	mr	r8,r3	clrldi	r4,r4,(64-4)	mtocrf	0x01,r4	bf	cr7*4+0,7ferr1;	std	r0,0(r3)	addi	r3,r3,8 7:	bf	cr7*4+1,8ferr1;	stw	r0,0(r3)	addi	r3,r3,4 8:	bf	cr7*4+2,9ferr1;	sth	r0,0(r3)	addi	r3,r3,2 9:	bf	cr7*4+3,10ferr1;	stb	r0,0(r3) 10:	li	r3,0	blr .Llong_clear:	LOAD_REG_ADDR(r5, ppc64_caches) 	bf	cr7*4+0,11ferr2;	std	r0,0(r3)	addi	r3,r3,8	addi	r4,r4,-8 	/* Destination is 16 byte aligned, need to get it cache block aligned */11:	lwz	r7,DCACHEL1LOGBLOCKSIZE(r5)	lwz	r9,DCACHEL1BLOCKSIZE(r5) 	/*	 * With worst case alignment the long clear loop takes a minimum	 * of 1 byte less than 2 cachelines.	 */	sldi	r10,r9,2	cmpd	r4,r10	blt	.Lmedium_clear 	neg	r6,r3	addi	r10,r9,-1	and.	r5,r6,r10	beq	13f 	srdi	r6,r5,4	mtctr	r6	mr	r8,r312:err1;	std	r0,0(r3)err1;	std	r0,8(r3)	addi	r3,r3,16	bdnz	12b 	sub	r4,r4,r5 13:	srd	r6,r4,r7	mtctr	r6	mr	r8,r314:err1;	dcbz	0,r3	add	r3,r3,r9	bdnz	14b 	and	r4,r4,r10 	cmpdi	r4,32	blt	.Lshort_clear	b	.Lmedium_clearEXPORT_SYMBOL(__arch_clear_user)