At the heart of the code for copying data between kernel and user-space on x86, there is the macro `__copy_user`, which expands to some assembly as follows :

{{{
 #define __copy_user(to,from,size)     
do {         
 int __d0, __d1;       
 __asm__ __volatile__(      
  "0: rep; movsl\n"     
  " movl %3,%0\n"     
  "1: rep; movsb\n"     
  "2:\n"       
  ".section .fixup,\"ax\"\n"    
  "3: lea 0(%3,%0,4),%0\n"    
  " jmp 2b\n"     
  ".previous\n"      
  ".section __ex_table,\"a\"\n"    
  " .align 4\n"     
  " .long 0b,3b\n"     
  " .long 1b,2b\n"     
  ".previous"      
  : "=&c"(size), "=&D" (__d0), "=&S" (__d1)  
  : "r"(size & 3), "0"(size / 4), "1"(to), "2"(from) 
  : "memory");      
} while (0)
}}}

This is perhaps an intimidating few lines, so we here we go into more detail into the code. Don't forget to read the inline assembly links on this site.

== Naive copy ==

{{{
  "0: rep; movsl\n"
  " movl %3,%0\n"
  "1: rep; movsb\n"
  "2:\n"
}}}

The first three lines naively copy 'size' bytes from 'from' to 'to'. I write "naively" because it might happen that the copy fails; then a memory exception would occur. A memory fault could occur for several reasons, each having their own way to handle the fault. The extra code used in '`__copy_user`' is one way to handle simple errors.

== Fixup ==

{{{
  ".section .fixup,\"ax\"\n"
  "3: lea 0(%3,%0,4),%0\n"    
  " jmp 2b\n"
}}}

The kernel contains a table (in section '`__ex_table`') containing entries (X, Y) saying that if an error occurs at address X, then jump to address Y. The entries declared in the '`__copy_user`' code thus say that if a memory error occurs when executing the code at the label '0:', the handler should return to (and then execute) the code at the label '3:', calculating the actual number of non-copied bytes. Likewise, an error at '1:' makes the handler return to '2:', just skipping any more copying.

Note that `lea 0(%3,%0,4),%0` is equivalent to the calculation `%ecx = (size % 4) + %ecx * 4`.

Labels like '0:', '1:', ... are "local labels", which can be used several times for different locations in the same code. They are then referenced by '0b', '1f', ... meaning "label 0 searching backwards" and "label 1 searching forwards" respectively.

== Sections ==

{{{
  ".previous\n"
}}}

The assembler directive `.previous` just tells the assembler to put the following code/data in the section used before the current section, probably the `.text` section.

The exception table data is put into the `__ex_table` section used by all exception table code in the kernel.

== Exception table ==

{{{
  ".section __ex_table,\"a\"\n"    
  " .align 4\n"     
  " .long 0b,3b\n"     
  " .long 1b,2b\n"     
  ".previous"      
}}}

The actual exception table itself in X,Y form, as described above.

''Originally by Per Persson, modified by John Levon. ''
----
CategoryDocs