• Nicolas Pitre's avatar
    [ARM] 2947/1: copy template with new memcpy/memmove · 75494230
    Nicolas Pitre authored
    Patch from Nicolas Pitre
    
    This patch provides a new implementation for optimized memory copy
    functions on ARM.  It is made of two levels: a template that consists of
    the core copy code and separate files that define macros to be used with
    the core code depending on the type of copy needed. This allows for best
    performances while sharing the same core for implementing memcpy(),
    copy_from_user() and copy_to_user() for instance.
    
    Two reasons for this work:
    
    1) the current copy_to_user/copy_from_user implementation assumes no
       task switch will ever occur in the middle of each copied page making
       it completely unsafe with CONFIG_PREEMPT=y.
    
    2) current copy implementations are measurably suboptimal and optimizing
       different implementations separately is a pain and more opportunities
       for bugs.
    
    The reason for (1) is the fact that copy inside user pages are performed
    with the ldm instruction which has no mean for testing user protections
    and could possibly race with process preemption bypassing the COW mechanism
    for example.  This is a longstanding issue that we said ought to be fixed
    for about two years now.  The solution is to substitute those ldm insns
    with a series of ldrt or strt insns to enforce user memory protection.
    At least on StrongARM and XScale cores the ldm is not faster than the
    equivalent ldr/str insns with a warm i-cache so there is no measurable
    performance degradation with that change. The fact that the copy code is
    a template makes it pretty easy to reuse the same core code as for memcpy
    and benefit from the same performance optimizations.
    
    Now (2) is best demonstrated with actual throughput measurements.
    First, here is a summary of memcopy tests performed on a StrongARM core:
    
    	PTR alignment	buffer size	kernel version	this version
    	------------------------------------------------------------
    	  aligned	     32		 59.73		107.43
    	unaligned	     32		 61.31		 74.72
    	  aligned	    100		132.47		136.15
    	unaligned	    100	    	103.84		123.76
    	  aligned	   4096		130.67		130.80
    	unaligned	   4096	    	130.68		130.64
    	  aligned	1048576		 68.03		68.18
    	unaligned	1048576		 68.03		68.18
    
    The buffer size is in bytes and the measured speed in MB/s.  The copy
    was performed repeatedly with given buffer and throughput averaged over
    3 seconds.
    
    Here we can see that the current kernel version has a higher entry cost
    that shows up with small buffers.  As buffer size grows both implementation
    converge to the same throughput.
    
    Now here's the exact same test performed on an XScale core (PXA255):
    
    	PTR alignment	buffer size	kernel version	this version
    	------------------------------------------------------------
    	  aligned	     32		 46.99		 77.58
    	unaligned	     32		 53.61		 59.59
    	  aligned	    100		107.19		136.59
    	unaligned	    100		 83.61		 97.58
    	  aligned	   4096		129.13		129.98
    	unaligned	   4096		128.36		128.53
    	  aligned	1048576		 53.76		 59.41
    	unaligned	1048576		 33.67		 56.96
    
    Again we can see the entry setup cost being higher for the current kernel
    before getting to the main copy loop.  Then throughput results converge
    as long as the buffer remains in the cache. Then the 1MB case shows more
    differences probably due to better pld placement and/or less instruction
    interlocks in this proposed implementation.
    
    Disclaimer: The PXA system was running with slower clocks than the
    StrongARM system so trying to infer any conclusion by comparing those
    separate sets of results side by side would be completely inappropriate.
    
    So...  What this patch does is to replace both memcpy and memmove with
    an implementation based on the provided copy code template.  The memmove
    code is kept separate since it is used only if the memory areas involved
    do overlap in which case the code is a transposition of the template but
    with the copy occurring in the opposite direction (trying to fit that
    mode into the template turned it into a mess not worth it for memmove
    alone).  And obviously both memcpy and memmove were tested with all kinds
    of pointer alignments and buffer sizes to exercise all code paths for
    correctness.
    
    The next patch will provide the now trivial replacement implementation
    copy_to_user and copy_from_user.
    Signed-off-by: default avatarNicolas Pitre <nico@cam.org>
    Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
    75494230
copy_template.S 5.73 KB