這是MIPS虛擬映射佈局圖,在接下來的實驗中,咱們須要特別注意的地址分別是kuseg和kseg0區,首先列出這兩個區域的意義。緩存
MIPS虛存映射佈局
32位的MIPS CPU最大尋址空間爲4GB(2^32字節),這4GB虛存空間被劃分爲四個部分:app
kuseg (TLB-mapped cacheable user space, 0x00000000 - 0x7fffffff): 這一段是用戶模式下可用的地址,大小爲2G,也就是MIPS約定的用戶內存空間。須要經過MMU進行虛擬地址到物理 地址的轉換。ide
kseg0 (direct-mapped cached kernel space, 0x80000000 - 0x9fffffff): 這一段是內核地址,其內存虛存地址到物理內存地址的映射轉換不經過MMU,使用時只須要將地址的最高位清零 (& 0x7fffffff), 這些地址就被轉換爲物理地址。也就是說,這段邏輯地址被連續地映射到物理內存的低端512M空間。對這段地址 的存取都會經過高速緩存(cached)。一般在沒有MMU的系統中,這段空間用於存放大多數程序和數據。對於有 MMU 的系統,操做系統的內核會存放在這個區域。函數
kuseg中有三個大小爲PDMAP(4MB)的區域,分別從0x7f400000開始是ENVS,PAGES和User VPT。須要注意的是PAGES和User VPT的關係:User VPT中存放了1024個頁表,因爲自映射的關係,這個頁表裏又包括了頁目錄的頁表,每個頁表中又有1024個頁表項。PAGES存放了48個頁表,這48個頁表映射的內容是16*1024個物理頁框的結構體(struct Page)的物理內存。在lab2實驗中,咱們只用了boot_map_segment函數將PAGES的內容進行了映射,並無操做User VPT的空間。佈局
第一幅圖將是咱們理解整個mm/pmap.c的核心,接下來將按照init/init.c中的順序進行逐一解釋每一個函數的細節和總體的啓動佈局。spa
1 //這是init/init.c裏的函數調用順序 2 mips_detect_memory(); 3 mips_vm_init(); 4 page_init();
1 void mips_detect_memory() 2 { 3 //in bytes 4 basemem = 64 * 1024 * 1024;//物理內存的大小爲64MB-->26位 5 npage = 16 * 1024;//物理頁框的個數 6 maxpa = basemem;//最大的物理地址 7 extmem = 0;//延申的空間 8 printf("Physical memory: %dK available, ", (int)(maxpa / 1024)); 9 printf("base = %dK, extended = %dK\n", (int)(basemem / 1024), 10 (int)(extmem / 1024)); 11 }
2.初始化一些內存相關的參數,意義寫在註釋裏,不贅述。操作系統
1 void mips_vm_init() 2 { 3 extern char end[]; 4 extern int mCONTEXT; 5 extern struct Env *envs; 6 7 Pde *pgdir; 8 u_int n; 9 10 /* Step 1 */ 11 pgdir = alloc(BY2PG, BY2PG, 1); 12 printf("to memory %x for struct page directory.\n", freemem); 13 mCONTEXT = (int)pgdir;//mCONTEXT是虛擬地址 14 15 boot_pgdir = pgdir; 16 17 /* Step 2*/ 18 pages = (struct Page *)alloc(npage * sizeof(struct Page), BY2PG, 1); 19 printf("to memory %x for struct Pages.\n", freemem); 20 21 n = ROUND(npage * sizeof(struct Page), BY2PG); 22 23 boot_map_segment(pgdir, UPAGES, n, PADDR(pages), PTE_R); 24 25 /* Step 3*/ 26 envs = (struct Env *)alloc(NENV * sizeof(struct Env), BY2PG, 1); 27 n = ROUND(NENV * sizeof(struct Env), BY2PG); 28 boot_map_segment(pgdir, UENVS, n, PADDR(envs), PTE_R); 29 30 printf("pmap.c:\t mips vm init success\n"); 31 }