⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 clear_user.s

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 S
字号:
/* * This routine clears to zero a linear memory buffer in user space. * * Inputs: *	in0:	address of buffer *	in1:	length of buffer in bytes * Outputs: *	r8:	number of bytes that didn't get cleared due to a fault *  * Copyright (C) 1998, 1999 Hewlett-Packard Co * Copyright (C) 1999 Stephane Eranian <eranian@hpl.hp.com> */#include <asm/asmmacro.h>//// arguments//#define buf		r32#define len		r33//// local registers//#define cnt		r16#define buf2		r17#define saved_lc	r18#define saved_pfs	r19#define tmp		r20#define len2		r21#define len3		r22//// Theory of operations://	- we check whether or not the buffer is small, i.e., less than 17//	  in which case we do the byte by byte loop.////	- Otherwise we go progressively from 1 byte store to 8byte store in//	  the head part, the body is a 16byte store loop and we finish we the//	  tail for the last 15 bytes.//	  The good point about this breakdown is that the long buffer handling//	  contains only 2 branches.////	The reason for not using shifting & masking for both the head and the//	tail is to stay semantically correct. This routine is not supposed//	to write bytes outside of the buffer. While most of the time this would//	be ok, we can't tolerate a mistake. A classical example is the case//	of multithreaded code were to the extra bytes touched is actually owned//	by another thread which runs concurrently to ours. Another, less likely,//	example is with device drivers where reading an I/O mapped location may//	have side effects (same thing for writing).//// The label comes first because our store instruction contains a comma// and confuse the preprocessor otherwise//#define EX(y,x...)				\	.section __ex_table,"a";		\	data4 @gprel(99f);			\	data4 y-99f;				\	.previous;				\99:	x	.text	.psr abi64	.psr lsb	.lsbGLOBAL_ENTRY(__do_clear_user)	UNW(.prologue)	UNW(.save ar.pfs, saved_pfs) 	alloc	saved_pfs=ar.pfs,2,0,0,0	cmp.eq p6,p0=r0,len		// check for zero length	UNW(.save ar.lc, saved_lc)	mov saved_lc=ar.lc		// preserve ar.lc (slow)	.body	;;				// avoid WAW on CFM	adds tmp=-1,len			// br.ctop is repeat/until	mov ret0=len			// return value is length at this point(p6)	br.ret.spnt.few rp	;;	cmp.lt p6,p0=16,len		// if len > 16 then long memset	mov ar.lc=tmp			// initialize lc for small count (p6)	br.cond.dptk.few long_do_clear	;;				// WAR on ar.lc	//	// worst case 16 cyles, avg 8 cycles	//	// We could have played with the predicates to use the extra	// M slot for 2 stores/iteration but the cost the initialization	// the various counters compared to how long the loop is supposed	// to last on average does not make this solution viable.	//1:		EX( .Lexit1, st1 [buf]=r0,1 )	adds len=-1,len			// countdown length using len	br.cloop.dptk.few 1b	;;				// avoid RAW on ar.lc	//	// .Lexit4: comes from byte by byte loop	//	    len contains bytes left.Lexit1:				mov ret0=len			// faster than using ar.lc	mov ar.lc=saved_lc	br.ret.sptk.few rp		// end of short clear_user	//	// At this point we know we have more than 16 bytes to copy	// so we focus on alignment (no branches required)	//	// The use of len/len2 for countdown of the number of bytes left	// instead of ret0 is due to the fact that the exception code 	// changes the values of r8.	//long_do_clear:	tbit.nz p6,p0=buf,0		// odd alignment (for long_do_clear)	;;	EX( .Lexit3, (p6) st1 [buf]=r0,1 )	// 1-byte aligned(p6)	adds len=-1,len;;		// sync because buf is modified	tbit.nz p6,p0=buf,1	;;	EX( .Lexit3, (p6) st2 [buf]=r0,2 )	// 2-byte aligned(p6)	adds len=-2,len;;	tbit.nz p6,p0=buf,2	;;	EX( .Lexit3, (p6) st4 [buf]=r0,4 )	// 4-byte aligned(p6)	adds len=-4,len;;	tbit.nz p6,p0=buf,3	;;	EX( .Lexit3, (p6) st8 [buf]=r0,8 )	// 8-byte aligned(p6)	adds len=-8,len;;	shr.u cnt=len,4		// number of 128-bit (2x64bit) words	;;		cmp.eq p6,p0=r0,cnt	adds tmp=-1,cnt(p6)	br.cond.dpnt.few .dotail 	// we have less than 16 bytes left	;;	adds buf2=8,buf			// setup second base pointer	mov ar.lc=tmp	;;	//	// 16bytes/iteration core loop	//	// The second store can never generate a fault because 	// we come into the loop only when we are 16-byte aligned.	// This means that if we cross a page then it will always be	// in the first store and never in the second.	//	// 	// We need to keep track of the remaining length. A possible (optimistic)	// way would be to ue ar.lc and derive how many byte were left by	// doing : left= 16*ar.lc + 16.  this would avoid the addition at	// every iteration. 	// However we need to keep the synchronization point. A template	// M;;MB does not exist and thus we can keep the addition at no	// extra cycle cost (use a nop slot anyway). It also simplifies the	// (unlikely)  error recovery code	//2:						EX(.Lexit3, st8 [buf]=r0,16 )	;;				// needed to get len correct when error	st8 [buf2]=r0,16	adds len=-16,len			br.cloop.dptk.few 2b	;;	mov ar.lc=saved_lc	// 	// tail correction based on len only	//	// We alternate the use of len3,len2 to allow parallelism and correct	// error handling. We also reuse p6/p7 to return correct value.	// The addition of len2/len3 does not cost anything more compared to	// the regular memset as we had empty slots.	//.dotail:					mov len2=len			// for parallelization of error handling	mov len3=len	tbit.nz p6,p0=len,3		;;	EX( .Lexit2, (p6) st8 [buf]=r0,8 )	// at least 8 bytes(p6)	adds len3=-8,len2	tbit.nz p7,p6=len,2		;;	EX( .Lexit2, (p7) st4 [buf]=r0,4 )	// at least 4 bytes(p7)	adds len2=-4,len3	tbit.nz p6,p7=len,1	;;	EX( .Lexit2, (p6) st2 [buf]=r0,2 )	// at least 2 bytes(p6)	adds len3=-2,len2	tbit.nz p7,p6=len,0	;;	EX( .Lexit2, (p7) st1 [buf]=r0 )	// only 1 byte left	mov ret0=r0				// success	br.ret.dptk.few rp			// end of most likely path	//	// Outlined error handling code	//	//	// .Lexit3: comes from core loop, need restore pr/lc	//	    len contains bytes left	//	//	// .Lexit2:	// 	if p6 -> coming from st8 or st2 : len2 contains what's left	// 	if p7 -> coming from st4 or st1 : len3 contains what's left	// We must restore lc/pr even though might not have been used..Lexit2:	.pred.rel "mutex", p6, p7(p6)	mov len=len2(p7)	mov len=len3	;;	//	// .Lexit4: comes from head, need not restore pr/lc	//	    len contains bytes left	//.Lexit3:	mov ret0=len	mov ar.lc=saved_lc	br.ret.dptk.few rpEND(__do_clear_user)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -