for_each_shadow_entry宏分析

for_each_shadow_entr三個參數的含義

_vcpu:對應kvm_vcpu結構體的指針。

_addr:如果是ETP的話,是GuestOS的物理地址

_walker:遊標

 

 

#define for_each_shadow_entry(_vcpu, _addr, _walker)    /
 for (shadow_walk_init(&(_walker), _vcpu, _addr); /
      shadow_walk_okay(&(_walker));   /
      shadow_walk_next(&(_walker)))

可以看出for_each_shadow_entry通過宏來實現.

 

首先介紹iterator參數的含義

struct kvm_shadow_walk_iterator {
 u64 addr;   //尋找的GuestOS物理地址
 hpa_t shadow_addr; //指向對應下一個要找的EPT頁表的指針
 int level; //當前查找所處的頁表級別
 u64 *sptep; //執行對應頁表項的指針
 unsigned index; //對應所在頁表的頁表項的索引
};

static void shadow_walk_init(struct kvm_shadow_walk_iterator *iterator,
        struct kvm_vcpu *vcpu, u64 addr)
{
 iterator->addr = addr;  //把要找的地址賦給addr
 iterator->shadow_addr = vcpu->arch.mmu.root_hpa; //初始化時,下一個要找的頁表就是當前VCPU的根頁表目錄。
 iterator->level = vcpu->arch.mmu.shadow_root_level; //guestos對應的頁表是幾級頁表。

 

 if (iterator->level == PT64_ROOT_LEVEL &&
     vcpu->arch.mmu.root_level < PT64_ROOT_LEVEL &&
     !vcpu->arch.mmu.direct_map)
  --iterator->level;

 

 if (iterator->level == PT32E_ROOT_LEVEL) {
  iterator->shadow_addr
   = vcpu->arch.mmu.pae_root[(addr >> 30) & 3];
  iterator->shadow_addr &= PT64_BASE_ADDR_MASK;
  --iterator->level;
  if (!iterator->shadow_addr)
   iterator->level = 0;
 }

這部分代碼要看懂還需要了解64位和PAE的頁表結構。


}

 

 

 

static bool shadow_walk_okay(struct kvm_shadow_walk_iterator *iterator)
{
 if (iterator->level < PT_PAGE_TABLE_LEVEL)
  return false;

 if (iterator->level == PT_PAGE_TABLE_LEVEL)
  if (is_large_pte(*iterator->sptep))
   return false;

 iterator->index = SHADOW_PT_INDEX(iterator->addr, iterator->level);
 iterator->sptep = ((u64 *)__va(iterator->shadow_addr)) + iterator->index;  //獲取GuestOS物理地址在EPT頁表對應級別的頁表項地址。
 return true;
}

 

static void shadow_walk_next(struct kvm_shadow_walk_iterator *iterator)
{
 iterator->shadow_addr = *iterator->sptep & PT64_BASE_ADDR_MASK;  //這個是下一級頁表的物理地址。
 --iterator->level; 級別減少1級
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章