基于PowerPC的Linux内核之旅:__secondary_start(start_here)-下


上篇中()介绍了基于PowerPC的Linux第二阶段启动过程的一部分,由于MMU的初始化涉及的内容较多,而且代码量很大,所以这部分分为上下两部。本部分继续阐述MMU硬件的初始化和最终真正使能MMU的过程。

    在开始之前,先指出前面文章出现的一个错误,在对mmu_off函数中的RFI指令的介绍时,我简单的认为是中断返回,但后来想想,CPU初始化时,中断还没有使能,所以中断返回的说法是不正确的,查了下资料,原来使用RFI指令也可以做程序跳转使用,使用RFI进行程序跳转的好处是,程序跳转后将自动执行isync指令,以保证指令空间的同步,在Linux的初始化阶段,使用RFI指令进行程序跳转比较常见,这里的RFI指令与中断返回是没有任何关系的。造成误解请见谅。

    另外,最近被工作上的事情困扰的有些力不从心了,感觉这篇对MMU的硬件初始化分析写的极其的烂,待以后收拾了心情,我一定会加以改进的,当然,也希望高手能不吝指教,就当交个朋友吧。

    先来看一下MMU_init_hw的详细代码(位于mm/ppc_mmu_32.c):

  1. void __init MMU_init_hw(void)  
  2. {  
  3.     unsigned int hmask, mb, mb2;  
  4.     unsigned int n_hpteg, lg_n_hpteg;  
  5.     /*定义于hash_low_32.S,填充和清除Hash表*/  
  6.     extern unsigned int hash_page_patch_A[];  
  7.     extern unsigned int hash_page_patch_B[], hash_page_patch_C[];  
  8.     extern unsigned int hash_page[];  
  9.     extern unsigned int flush_hash_patch_A[], flush_hash_patch_B[];  
  10.   
  11.     if (!mmu_has_feature(MMU_FTR_HPTE_TABLE)) {  
  12. /*在hash_page的开始处放置blr指令,因为在603处理器中仍能接收到DSI(Data Storage Interrupt)异常*/  
  13.         hash_page[0] = 0x4e800020;  
  14.         flush_icache_range((unsigned long) &hash_page[0],  
  15.                    (unsigned long) &hash_page[1]);  /*清空指令cache*/  
  16.         return;  
  17.     }  
  18.   
  19.     if ( ppc_md.progress ) ppc_md.progress("hash:enter", 0x105);  
  20.   
  21. #define LG_HPTEG_SIZE   6       /* 每个PTEG为64个字节 */   
  22. #define SDR1_LOW_BITS   ((n_hpteg - 1) >> 10)   
  23. #define MIN_N_HPTEG 1024        /* min 64kB hash table */   
  24.   
  25.     /*允许每页内存都有一个HPTE*/  
  26.     n_hpteg = total_memory / (PAGE_SIZE * 8);  
  27.     if (n_hpteg < MIN_N_HPTEG)  
  28.         n_hpteg = MIN_N_HPTEG;  
  29.     lg_n_hpteg = __ilog2(n_hpteg);  
  30.     if (n_hpteg & (n_hpteg - 1)) {  
  31.         ++lg_n_hpteg;       /* round up if not power of 2 */  
  32.         n_hpteg = 1 << lg_n_hpteg;  
  33.     }  
  34.     Hash_size = n_hpteg << LG_HPTEG_SIZE;  
  35.   
  36.     /*为哈希表申请内存地址,这两步就类似于malloc和memset*/  
  37.     if ( ppc_md.progress ) ppc_md.progress("hash:find piece", 0x322);  
  38.     Hash = __va(memblock_alloc_base(Hash_size, Hash_size,  
  39.                    __initial_memory_limit_addr));  
  40.     cacheable_memzero(Hash, Hash_size);  
  41.     _SDR1 = __pa(Hash) | SDR1_LOW_BITS;  
  42.   
  43.     Hash_end = (struct hash_pte *) ((unsigned long)Hash + Hash_size);  
  44.   
  45.     /*Patch up the instructions in hash_low_32.S:create_hpte*/  
  46.     if ( ppc_md.progress ) ppc_md.progress("hash:patch", 0x345);  
  47.     Hash_mask = n_hpteg - 1;  
  48.     hmask = Hash_mask >> (16 - LG_HPTEG_SIZE);  
  49.     mb2 = mb = 32 - LG_HPTEG_SIZE - lg_n_hpteg;  
  50.     if (lg_n_hpteg > 16)  
  51.         mb2 = 16 - LG_HPTEG_SIZE;  
  52.   
  53.     hash_page_patch_A[0] = (hash_page_patch_A[0] & ~0xffff)  
  54.         | ((unsigned int)(Hash) >> 16);  
  55.     hash_page_patch_A[1] = (hash_page_patch_A[1] & ~0x7c0) | (mb << 6);  
  56.     hash_page_patch_A[2] = (hash_page_patch_A[2] & ~0x7c0) | (mb2 << 6);  
  57.     hash_page_patch_B[0] = (hash_page_patch_B[0] & ~0xffff) | hmask;  
  58.     hash_page_patch_C[0] = (hash_page_patch_C[0] & ~0xffff) | hmask;  
  59.   
  60.     /*确保patch过的地方是否从数据cache中保存,并清除指令cache*/  
  61.     flush_icache_range((unsigned long) &hash_page_patch_A[0],  
  62.                (unsigned long) &hash_page_patch_C[1]);  
  63.   
  64.     /*Patch up the instructions in hash_low_32.S:flush_hash_page*/  
  65.     flush_hash_patch_A[0] = (flush_hash_patch_A[0] & ~0xffff)  
  66.         | ((unsigned int)(Hash) >> 16);  
  67.     flush_hash_patch_A[1] = (flush_hash_patch_A[1] & ~0x7c0) | (mb << 6);  
  68.     flush_hash_patch_A[2] = (flush_hash_patch_A[2] & ~0x7c0) | (mb2 << 6);  
  69.     flush_hash_patch_B[0] = (flush_hash_patch_B[0] & ~0xffff) | hmask;  
  70.     flush_icache_range((unsigned long) &flush_hash_patch_A[0],  
  71.                (unsigned long) &flush_hash_patch_B[1]);  
  72.   
  73.     if ( ppc_md.progress ) ppc_md.progress("hash:done", 0x205);  
  74. }     
  • 1
  • 2
  • 3
  • 下一页

相关内容