Linux Assembly _ copy_user macro (zz)

Source: Internet
Author: User
Tags prefetch

This document copies the content of the following two documents: (1) "handling Linux kernel missing page exceptions using abnormal tables" http://www-128.ibm.com/#works/cn/linux/kernel/l-page/index.html; (2) "implementation and understanding of user/kernel space data replication" www.linuxforum.net.

The address ing of user processes is sometimes not established (such as a stack), and the page in pg_dir has no corresponding settings. If you access this address in the user mode, a page exception occurs. In the exception handling function, the page will be re-mapped based on the actual situation (such as checking the vm_growsdown flag. When the kernel process accesses these addresses, if you do not need functions such as get_user, the entire kernel will get a bug once a page error occurs.
I used to directly read and write the address space of a user process in kernel mode, and the result is panic. Only get_user can be used.
It is just a piece of assembly, mainly to read and write the target address, but added the corrected code in the Code (. fixup), the purpose is to execute the correction code when an exception occurs, to prevent the kernel from being replaced by a bug.

1. _ copy_user
Macro _ copy_user is defined in include/asm-i386/uaccess. h and is the key to memory replication from user space and kernel space. This macro is extended as follows after compilation: 000 # DEFINE _ copy_user (to, from, size)
001 do {
002 int _ D0, _ D1;
003 _ ASM _ volatile __(
004 "0: rep; movsl/N"
005 "movl % 3, % 0/N"
006 "1: rep; movsb/N"
007 "2:/N"
008 ". Section. fixup,/" ax/"/N"
009 "3: Lea 0 (% 3, % 0 4), % 0/N"
010 "JMP 2B/N"
011 ". Previous/N"
012 ". Section _ ex_table,/" A/"/N"
013 ". Align 4/N"
014 ". Long 0b, 3B/N"
015 ". Long 1B, 2B/N"
016 ". Previous"
017: "= & C" (size), "= & D" (_ D0), "= & S" (_ D1)
018: "R" (size & 3), "0" (size/4), "1" (to), "2" (from)
019: "Memory ");
020} while (0) the main operation of this Code is 004-007. Its main function is to copy the data with the length of size from. Before reading this code, let's take a look at its constraints:
017: "= & C" (size), "= & D" (_ D0), "= & S" (_ D1)
018: "R" (size & 3), "0" (size/4), "1" (to), "2" (from)
019: "Memory ");
017 is the output part. According to the description, we can see that size is saved in ECx, __d0 is saved in Di, and __d1 is saved in SI.
018 is the input part. According to the description, we can see that size/4 (that is, the integer part after size is divided by 4) is saved in ECx, size & 3 (that is, the remainder of size divided by 4) store it in a register, Di, AND Si. Then let's look at the lines-, and we will understand:
Row 004: copy the size/4 4 4 bytes from the from. In order to increase the speed, movsl is used here, so we need to handle the size.
Row 005: copy the remainder of size & 3, that is, size/4, to ECx.
Row 006: Copy data from to based on the number in ECx, where movsb is used.
Row 007: the code is finished.
Now, the replication process is complete. But in fact it is not that simple, because the replication may fail, so the-lines of code are processed in this way. The kernel provides an unexpected table. The structure of each item is (x, y). If an error occurs on address X, it will jump to address y, here, the line 012-015 uses this mechanism to declare two table items during compilation. These lines of code are described as follows:
Row 012: declares that the following content belongs to segment _ ex_table.
Row 013: declares that the content here is 4-byte aligned.
Row 014: Declares the first unexpected table item. If an error occurs at mark 0, the table jumps to mark 3 (. Section. fixup ).
Row 015: Declares the second unexpected table item. That is, if an error occurs at mark 1, the Table jumps to mark 2 (. Section. text ).
The reason for adding B to the flag above is that the previous code is referenced, and F is added if the code to be referenced is to be followed. Here, the size operation convention is: if the replication fails, the size retains the number of data bytes that have not been fully copied.
Since there are only four lines of Data Copying code, the following lines may be 004 and 006. From the exception table above, we can see that the kernel processing policy is:
(1) If an error occurs at 0, the number of bytes that have not been copied is the remainder of the remaining number in ECx multiplied by 4 plus the remainder after dividing the previous size by 4. Lines of code completes this task. "Lea 0 (% 3, %), % 0" means calculating "% ECx = (size % 4) + % ECx * 4 ", and assign the value to the size of the returned C code.
(2) If an error occurs at 1, since the size/4 bytes in ECx have been copied successfully, therefore, you only need to assign the remainder of size/4 stored in any register to size to return.
From the assembly code, we can see that lines of exception handling code are compiled into a segment called fixup. It can be seen that the essence of this Code is to copy data from to, and perform simple Exception Processing on the two places where errors may occur-return the number of uncopied bytes. Note:
(1). Section. fixup, "ax";. Section _ ex_table, "";
Set the two. section and. the code in the middle of previous is compiled into the defined segments, and then jumped back to compile the subsequent code. text Segment, that is, the segment before the custom segment .. Section and. Previous must be used together.
(2) In the example, the _ ex_table exception table is not executed in the user space and is only valid in the kernel.
(3) the purpose of separating the. fixup and. Text segments is to improve the CPU pipeline utilization. Readers familiar with the architecture should know that the current CPU introduces pipeline technology to speed up command execution, that is, while executing the current command, you need to prefetch one or more of the following commands into the pipeline. This technology encounters a problem when facing the Execution Branch of the program: If the prefetch command is not the branch to be executed in the next step of the program, all the commands in the pipeline will be emptied, this will have a certain impact on the system performance. In our program, if. the instruction in the fixup segment is scheduled to be executed normally. in the text segment, when the program executes the preceding commands, these few commands will be prefetch to the pipeline. Normal execution will inevitably lead to the emptying of the pipeline, this will obviously reduce the performance of the entire system. 2. Use _ copy_user/* Hello. C */in the user program */
# Include <stdio. h>
# Include <string. h> # 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) int main (void)
{
Const char * string = "Hello, world! ";
Char Buf [20];
Unsigned long n, m; M = n = strlen (string );
_ Copy_user (BUF, String, N );
Buf [m] = '/0 ';
Printf ("% s/n", Buf );
Exit (0 );
} $ GCC hello. C-O hello $ objdump -- disassemble -- Section =. Text hello
Hello: File Format elf32-i386Disassembly of section. Text:
8048498: 8B 45 C4 mov 0xffffffc4 (% EBP), % eax
804849b: 83 E0 03 and $0x3, % eax
804849e: 8B 55 C4 mov 0xffffffc4 (% EBP), % edX
80484a1: 89 D1 mov % edX, % ECx
80484a3: C1 E9 02 SHR $0x2, % ECx
80484a6: 8d 7d C8 Lea 0xffffffc8 (% EBP), % EDI
80484a9: 8B 75 F4 mov 0xfffffff4 (% EBP), % ESI
80484ac: F3 A5 repz movsl % DS :( % Esi), % es :( % EDI)
80484ae: 89 C1 mov % eax, % ECx
80484b0: F3 A4 repz movsb % DS :( % Esi), % es :( % EDI)
80484b2: 89 C8 mov % ECx, % eax $ objdump -- disassemble -- Section =. fixup hello
Hello: File Format elf32-i386Disassembly of section. fixup: 08048530 <. fixup>:
8048530: 8d 4C 88 00 Lea 0x0 (% eax, % ECx, 4), % ECx
8048534: E9 79 ff jmp 80484b2 <main + 0x42> $ objdump -- full-contents -- Section =__ ex_table hello
Hello: File Format elf32-i386Contents of section _ ex_table:
8048578 ac840408 30850408 b0840408 b2840408 ...... 0 ...........
Because x86 uses a Small End-end addressing method, the above data section is messy. Convert the content in the above _ ex_table into what we usually see:
8048578 80484ac 8048530 80484b0 80484b2 .... 0 ........... (1 ). long 0b, 3B corresponds to 80484ac 8048530, where 80484ac corresponds to the command. in text, the repz movsl % DS :( % Esi), % es :( % EDI), and The 8048530 command is. lea 0x0 (% eax, % ECx, 4), % ECx in fixup.
(2 ). long 1B and 2B correspond to 80484b0 80484b2, where 80484b0 corresponds to the command. in text, the repz movsb % DS :( % Esi), % es :( % EDI), and The 80484b2 command is. moV % ECx, % eax in text.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.