e820内存数据处理

e820参数的存储

在setup.S中,

 311 meme820:                                                                        
 312         xorl    %ebx, %ebx                      # continuation counter          
 313         movw    $E820MAP, %di                   # point into the whitelist      
 314                                                 # so we can have the bios       
 315                                                 # directly write into it.       
 316                                                                                 
 317 jmpe820:                                                                        
 318         movl    $0x0000e820, %eax               # e820, upper word zeroed       
 319         movl    $SMAP, %edx                     # ascii 'SMAP'                  
 320         movl    $20, %ecx                       # size of the e820rec           
 321         pushw   %ds                             # data record.                  
 322         popw    %es                                                             
 323         int     $0x15                           # make the call                 
 324         jc      bail820                         # fall to e801 if it fails      
 325                                                                                 
 326         cmpl    $SMAP, %eax                     # check the return is `SMAP'    
 327         jne     bail820                         # fall to e801 if it fails      
 328                                                                                 
 329 #       cmpl    $1, 16(%di)                     # is this usable memory?        
 330 #       jne     again820                                                        
 331                                                                                 
 332         # If this is usable memory, we save it by simply advancing %di by       
 333         # sizeof(e820rec).                                                      
 334         #                                                                       
 335 good820:                                                                        
 336         movb    (E820NR), %al                   # up to 32 entries              
 337         cmpb    $E820MAX, %al                                                   
 338         jnl     bail820                                                         
 339                                                                                                                                                                                                              
 340         incb    (E820NR)                                                        
 341         movw    %di, %ax                                                        
 342         addw    $20, %ax                                                        
 343         movw    %ax, %di                                                        
 344 again820:                                                                       
 345         cmpl    $0, %ebx                        # check to see if               
 346         jne     jmpe820                         # %ebx is set to EOF            
 347 bail820:   

在文件include/asm-i386/e820.h 中

 15 #define E820MAP 0x2d0           /* our map */                                                                                                                                                                 
 16 #define E820MAX 32              /* number of entries in E820MAP */              
 17 #define E820NR  0x1e8           /* # entries in E820MAP */ 

流程:
1)setup.S代码被搬移到0x90000处。此时CS=DS=0x9000,处于实模式
2) $E820MAP, %di ,将0x9000:0x2d0(物理地址0x902d0),赋值给di
3)调用BIOS查询820内存中断,然后将查询的值放到di寄存器指向的地址,也就是把返回的查询值放入到物理地址0x902d0中。
4)同时中断返回的长度值放在al中,通过 movb (E820NR), %al语句,将长度值返回到物理地址0x901e8中。
*(0x901e8)=6,代表6条e820内存信息。下图中是,e820信息返回在0x902d0处的信息。
e820数据格式
e820map的结构体如下:

 28 struct e820map {                                                                
 29     int nr_map;                                                                 
 30     struct e820entry {                                                          
 31         unsigned long long addr;        /* start of memory segment */           
 32         unsigned long long size;        /* size of memory segment */                                                                                                                                          
 33         unsigned long type;             /* type of memory segment */            
 34     } map[E820MAX];                                                             
 35 };

可以看出,addr代表着红色的框,size代表着黄色的框,type代表着蓝色的框。

将0x90000处的信息赋值给boot_params变量

在kernel/head.S中

219 /*                                                                              
220  * Copy bootup parameters out of the way.                                       
221  * Note: %esi still has the pointer to the real-mode data.                      
222  */                                                                             
223         movl $boot_params,%edi                                                  
224         movl $(PARAM_SIZE/4),%ecx                                               
225         cld                                                                     
226         rep 
227         movsl 

因为esi=0x90000处,把boot_params的地址传递给edi,然后通过movsl,完成把0x90000处的内容搬移到变量boot_params指向的地址。

通过E20_MAP或者E820_MAP_NR信息访问e820的内存

 34 #define PARAM   (boot_params)                                                   
 35 #define SCREEN_INFO (*(struct screen_info *) (PARAM+0))                         
 36 #define EXT_MEM_K (*(unsigned short *) (PARAM+2))                               
 37 #define ALT_MEM_K (*(unsigned long *) (PARAM+0x1e0))                            
 38 #define E820_MAP_NR (*(char*) (PARAM+E820NR))                                   
 39 #define E820_MAP    ((struct e820entry *) (PARAM+E820MAP))  

sanitize_e820_map内存规整函数

内存规整
说明:这个横线从左到右,代表着这个内存。在同一个内存地址被几种类型的内存包含着。
地址从低到高也就是,横线从左到右,找出对应纵线在纵向的同一水平位置,第一个出现的,然后往下顺。
这样完成内存规整。
调试的E820是规整的,不包含重复的。

流程

setup_arch---->machine_specific_memory_setup()---->sanitize_e820_map------->copy_e820_map–>add_memory_region
说明:

  1. sanitize_e820_map是把E820_MAP中的数据规整下,然后通过add_memory_region把E820_MAP数据保存到e820。
  2. parse_cmdline_early(cmdline_p),也就是通过启动内核参数传递内存相关参数,修改变量e820。

猜你喜欢

转载自blog.csdn.net/chengbeng1745/article/details/84965260