[ARM] 2947/1: copy template with new memcpy/memmove
authorNicolas Pitre <nico@cam.org>
Tue, 1 Nov 2005 19:52:23 +0000 (19:52 +0000)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Tue, 1 Nov 2005 19:52:23 +0000 (19:52 +0000)
commit7549423000fc38d39a8b81c601dea0332c113a42
tree6b76fe2867b9634a1d1dbaf682c69ccad4e9f71b
parenta0c6fdb987860e6c7f9b8e57439ca2703f462578
[ARM] 2947/1: copy template with new memcpy/memmove

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: Nicolas Pitre <nico@cam.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
arch/arm/lib/Makefile
arch/arm/lib/copy_template.S [new file with mode: 0644]
arch/arm/lib/memcpy.S
arch/arm/lib/memmove.S [new file with mode: 0644]