Linux physical memory Detection

Source: Internet
Author: User

After linux is loaded into memory by bootloader, the linux kernel code initially executed by the cpu is/header. start_of_setup function in the S file. After some preparation, this function will jump to the main file in the boot directory. c main function execution. In this main function, we can see the Code related to memory management for the first time. This Code calls the detect_memeory () function to detect the physical memory of the system.
 
Execute the following assembly code in header. S:
 
 
Start_of_setup:
.....
# Jump to C code (shocould not return)
Calll main
.....
Jump to the main. c file under the boot directory.
 
Void main (void)
{
......
/* Detect memory layout */
Detect_memory ();/* Memory detection function */
......
}
 
 
Int detect_memory (void)
{
Int err =-1;
 
If (detect_memory_e820 ()> 0)
Err = 0;
 
If (! Detect_memory_e801 ())
Err = 0;
 
If (! Detect_memory_88 ())
Err = 0;
 
Return err;
}
The preceding Code indicates that the Linux kernel will respectively call detect_memory_e820 (), detcct_memory_e801 (), and detect_memory_88 () to obtain the physical memory layout of the system, these three functions call bios interrupt in the form of integrated assembly to obtain memory information. The interrupt call form is int 0x15, at the same time, set the AX register to 0xe820h, 0xe801h, and 0x88 h before the call. If you are interested in the 0x15 interrupt, you can query the relevant manual. The code for detect_memory_e820 () is analyzed below. Other codes are basically the same.
 
# Define SMAP 0x534d4150/* ASCII "SMAP "*/
/* Due to historical reasons, some I/o devices also occupy part of the memory
Physical address space, so the physical memory that the system can use is empty
The memory is not consecutive, and the system memory is divided into many segments.
Properties are also different. Int 0x15 each time the physical memory is queried
Returns the information of a memory segment.
We must query the physical memory in iterative mode.
The detect_memory_e820 () function places int 0x15 in a do-while loop,
Each time a memory segment is obtained, it is placed in struct e820entry, and
The structure of struct e820entry is exactly the structure of e820 returned results! And Image
Other results obtained at startup will eventually be placed in
In boot_params, e820 is put into boot_params.e820_map.
*/
Static int detect_memory_e820 (void)
{
Int count = 0;/* used to record the number of detected physical memory */
Struct biosregs ireg, oreg;
Struct e820entry * desc = boot_params.e820_map;
Static struct e820entry buf;/* static so it is zeroed */
 
Initregs (& ireg);/* initialize related registers in ireg */
Ireg. ax = 0xe820;
Ireg. cx = sizeof buf;/* e820entry Data Structure size */
Ireg. edx = SMAP;/* ID */
Ireg. di = (size_t) & buf;/* store where int15 returned values */
 
/*
* Note: at least one BIOS is known which assumes that
* Buffer pointed to by one e820 call is the same one
* The previous call, and only changes modified fields. Therefore,
* We use a temporary buffer and copy the results entry by entry.
*
* This routine deliberately does not try to account
* ACPI 3 + extended attributes. This is because there are
* BIOSes in the field which report zero for the valid bit
* All ranges, and we don't currently make any use of
* Other attribute bits. Revisit this if we see the extended
* Attribute bits deployed in a meaningful way in the future.
*/
 
Do {
/* The input parameters for executing this inline assembly statement include:
Eax register = 0xe820
Dx register = 'smap'
Edi register = desc
Ebx register = next
Ecx register = size

Parameters returned to the C language code include:
Id = eax register
Rr = edx register
Ext = ebx register
Size = ecx register
The memory address pointed to by desc is set when the call is interrupted at 0x15.
*/
Intcall (0x15, & ireg, & oreg );
/* Select the next one */
Ireg. ebx = oreg. ebx;/* for next iteration ...*/
 
/* BIOSes which terminate the chain with CF = 1 as opposed
To % ebx = 0 don't always report the SMAP signature on
The final, failing, probe .*/
If (oreg. eflags & X86_EFLAGS_CF)
Break;
 
/* Some BIOSes stop returning SMAP in the middle
The search loop. We don't know exactly how the BIOS
Screwed up the map at that point, we might have
Partial map, the full map, or complete garbage, so
Just return failure .*/
If (oreg. eax! = SMAP ){
Count = 0;
Break;
}
 
* Desc ++ = buf;/* assign the buf value to desc */
Count ++;/* Add one probe count */
}
While (ireg. ebx & count <ARRAY_SIZE (boot_params.e820_map ));
/* Keep the number of memory blocks in the variable */
Return boot_params.e820_entries = count;
}
The returned value structure for storing the interrupt is as follows:
 
Struct e820entry {
_ U64 addr;/* start of memory segment */
_ U64 size;/* size of memory segment */
_ U32 type;/* type of memory segment */
} _ Attribute _ (packed ));
After the start_kernel function is jumped in during kernel initialization, execute the following initialization:
Start_kernel ()-> setup_arch ()-> setup_memory_map ()
 
 
/* Call x86_init.resources.memory_setup () to optimize the e820 memory graph,
Save the values in e820 to e820_saved and print the memory graph.
*/
Void _ init setup_memory_map (void)
{
Char * who;
/* Call the memory_setup function in the x86 system */
Who = x86_init.resources.memory_setup ();
/* Save to e820_saved */
Memcpy (& e820_saved, & e820, sizeof (struct e820map ));
Printk (KERN_INFO "BIOS-provided physical RAM map: \ n ");
/* Print the output */
E820_print_map (who );
}
The memory_setup function under x86 is defined in x86_init.c.
 
 
Struct x86_init_ops x86_init _ initdata = {
 
. Resources = {
......
. Memory_setup = default_machine_specific_memory_setup,
},
......
};
 
Char * _ init default_machine_specific_memory_setup (void)
{
Char * who = "BIOS-e820 ";
U32 new_nr;
/*
* Try to copy the BIOS-supplied E820-map.
*
* Otherwise fake a memory map; one section from 0 k-> 640 k,
* The next section from 1 mb-> appropriate_mem_k
*/
New_nr = boot_params.e820_entries;
/* Remove overlaps */
Sanitize_e820_map (boot_params.e820_map,
ARRAY_SIZE (boot_params.e820_map ),
& New_nr );
/* The number of memories obtained after the overlapping parts are removed */
Boot_params.e820_entries = new_nr;
/* Assign the value to the global variable e820. If the value is smaller than 0, error handling is performed */
If (append_e820_map (boot_params.e820_map, boot_params.e820_entries)
<0 ){
......
}
 
/* In case someone cares ...*/
Return who;
}
Append_e820_map call _ append_e820_map implementation
 
 
 
Static int _ init _ append_e820_map (struct e820entry * biosmap, int nr_map)
{
While (nr_map) {/* loop nr_map call, add memory block to e820 */
U64 start = biosmap-> addr;
U64 size = biosmap-> size;
U64 end = start + size;
U32 type = biosmap-> type;
/* Overflow in 64 bits? Ignore the memory map .*/
If (start> end)
Return-1;
/* Add a function */
E820_add_region (start, size, type );
Biosmap ++;
Nr_map --;
}
Return 0;
}
 
 
Void _ init e820_add_region (u64 start, u64 size, int type)
{
_ E820_add_region (& e820, start, size, type );
}
The e820 is in the e820map structure.
 
 
Struct e820map {
_ U32 nr_map;
Struct e820entry map [E820_X_MAX];
};
The E820_X_MAX size is 128.
 
 
Tatic void _ init _ e820_add_region (struct e820map * e820x, u64 start, u64 size,
Int type)
{
Int x = e820x-> nr_map;
 
If (x> = ARRAY_SIZE (e820x-> map )){
Printk (KERN_ERR "Ooops! Too your entries in the memory map! \ N ");
Return;
}
By now, the physical memory has been read from the BIOS and stored in the global variable e820, which is the basis for establishing a memory management framework in the Linux kernel. We will see later that it will be used to create initialization nodes and management zones.

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.