Linux核心代碼之初始化核心臨時頁表

來源:互聯網
上載者:User

      漫長而黑暗的史前時代終於到了setup。在setup彙編函數中,linux通過設定cr0寄存器的PE位(從實模式切換到保護模式)完成了史前文明到現代文明的轉變。在setup時期,linux已經瞭解到世上可用的記憶體資源遠遠不止1MB。此時linux的慾望開始膨脹,最為滿足它慾望的第一步,它開始搶佔記憶體資源的前8MB。

  初始化臨時核心頁表是在startup_32組合語言函數中完成的。在ULK所述中,假設核心能容納於RAM的前8MB空間,然後對RAM的前8MB進行恒等映射(例如使用者地址0x00003000映射物理地址0x00003000,0xc0003000映射到物理地址0x00003000),來初始化臨時頁全域目錄swapper_pg_dir和相應的頁表。映射8MB只需要填充swapper_pg_dir中第0項,1項,768項和769項。前兩項是給使用者線性地址映射,後兩項給核心線性地址映射。用頁全域目錄裡的兩項就能對8MB映射的理由是2×1024(頁表有1024項)×4K(一頁的大小)=8M。實際上初始化核心頁表來對RAM的前8MB映射不是個硬性的規定。這取決於你的核心的配置(我認為大多數情況下是對8MB映射)。在startup_32中可以看到,對多少記憶體進行映射是通過pg0動態判斷的。

  linux/arch/i386/kernel/head.S

  page_pde_offset = (__PAGE_OFFSET >> 20);

  /*__PAGE_OFFSET是0xc0000000,核心線性空間的起始地址。

  page_pde_offset=0xc00(十進位為3072)*/

  movl $(pg0 - __PAGE_OFFSET), %edi

  /*pg0的線性地址可以在/boot/System.map檔案中找到。我的Ubuntu8.04機器上是0xc04f4000。

  減去0xc0000000就是pg0的物理地址(004f4000),放入edi中。*/

  movl $(swapper_pg_dir - __PAGE_OFFSET), %edx

  /*swapper_pg_dir的線性地址也可以在/boot/System.map檔案中找到。我機器上是0xc047d000。

  減去0xc0000000就是swapper_pg_dir的物理地址(0047d000),放入edx中。*/

  movl $0x007, %eax /* 0x007 = PRESENT+RW+USER */

  /*頁目錄項和頁表項的低12位是標誌位,把標誌位0x007放入eax中。*/

  10:

  leal 0x007(%edi),%ecx /* Create PDE entry */

  /*第一迴圈時把edi指向的pg0的物理地址加上0x007放入ecx中。

  第二次迴圈時把edi指向的物理地址0x4f5000加上0x007放入ecx中。*/

  movl %ecx,(%edx) /* Store identity PDE entry */

  /*第一次迴圈時把ecx中的內容放入swapper_pg_dir的第0項裡。

  第二次迴圈時把ecx中的內容放入swapper_pg_dir的第1項裡。*/

  movl %ecx,page_pde_offset(%edx) /* Store kernel PDE entry */

  /*第一次迴圈時把ecx中的內容放入swapper_pg_dir的第768項裡。因為前面算出page_pde_offset的值為3072,而swapper_pg_dir中每項是4個位元組,所以3072/4=768。

  第二次迴圈時把ecx中的內容放入swapper_pg_dir的第769項裡。*/

  addl $4,%edx

  /*第一次迴圈時,此時edx指向swapper_pg_dir的第1項。

  第二次迴圈時,此時edx指向swapper_pg_dir的第2項。*/

  movl $1024, %ecx

  /*為初始化1024個頁表項設定計數*/

  11:

  stosl

  /*把eax中的內容放入edi指向的物理地址中,然後edi+4。*/

  addl $0x1000,%eax

  loop 11b

  /*跳到上面的11處迴圈。

  第一次執行1024次後,從pg0物理地址(0x4f4000)開始存放的是0x007,0x1007,0x2007,...,0x3ff007,也就是當前能夠映射到物理地址從0x000到0x3fffff處。此時edi中的值為0x4f5000。

  第二次執行1024次後,從物理地址(0x4f5000)開始存放的是0x400007,0x401007,0x402007,...,7ff007,也就是當前能夠映射到物理地址0x000到7fffff處,正好8MB。此時edi中的值為0x4f6000。*/

  leal (INIT_MAP_BEYOND_END+0x007)(%edi),%ebp

  /*INIT_MAP_BEYOND_END的值為128k,在此檔案中的一個宏定義。把edi指向的物理地址加上128k加上0x007放入edp中。*/

  cmpl %ebp,%eax

  /*在第一次迴圈中ebp中的值為0x515007,eax中的值為0x400007小於0x515007。當前所映射到的最大物理地址為0x3fffff沒有包含0x515007,所以沒有映射完。

  在第二次迴圈中ebp中的值為0x516007,eax中的值為0x800007大於0x516007。當前所映射到的最大物理地址為0x7fffff包含了0x516007,所以8MB物理地址映射完畢。*/

  jb 10b

  /*第一次迴圈做完時跳到上面的10處繼續迴圈

  第二次迴圈做完時跳出迴圈。*/

  movl %edi,(init_pg_tables_end - __PAGE_OFFSET)

  /*最後把0x4f6000放入init_pg_tables_end 所表示的物理地址中。也在/boot/System.map中。*/

  此時的linux胃口越來越大,8MB的資源已不能滿足它的胃口了。它的黑手開始慢慢伸向896MB以下的記憶體了。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

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.