static int __direct_map(struct kvm_vcpu *vcpu, gpa_t v, int write,
int level, gfn_t gfn, pfn_t pfn)
/*
vcpu:對應vcpu的kvm_vcpu結構指針。
v:對應guestos物理地址在頁幀的偏移量。
write:
level:設定頁表的級別
gfn:guest os 的頁幀號
pfn : host os 的頁幀號。
*/
{
struct kvm_shadow_walk_iterator iterator;
struct kvm_mmu_page *sp;
int pt_write = 0;
gfn_t pseudo_gfn;
for_each_shadow_entry(vcpu, (u64)gfn << PAGE_SHIFT, iterator) {
/*
循環遍歷guest os頁幀號在影子頁表中的頁表項。
*/
if (iterator.level == level) {
/*
如果等於要設置的頁表級別,設置對應的頁表。
*/
mmu_set_spte(vcpu, iterator.sptep, ACC_ALL, ACC_ALL,
0, write, 1, &pt_write,
level, gfn, pfn, false, true);
direct_pte_prefetch(vcpu, iterator.sptep);
++vcpu->stat.pf_fixed;
break;
}
/*
如果設置的頁表之前的頁表項爲空,那麼要建立頁表。
*/
if (*iterator.sptep == shadow_trap_nonpresent_pte) {
u64 base_addr = iterator.addr;
base_addr &= PT64_LVL_ADDR_MASK(iterator.level);
pseudo_gfn = base_addr >> PAGE_SHIFT;
/*
分配一個新的頁表。
*/
sp = kvm_mmu_get_page(vcpu, pseudo_gfn, iterator.addr,
iterator.level - 1,
1, ACC_ALL, iterator.sptep);
if (!sp) {
pgprintk("nonpaging_map: ENOMEM/n");
kvm_release_pfn_clean(pfn);
return -ENOMEM;
}
/*
設定之前不可用的頁表項,指向新分配的下一級頁表。
*/
__set_spte(iterator.sptep,
__pa(sp->spt)
| PT_PRESENT_MASK | PT_WRITABLE_MASK
| shadow_user_mask | shadow_x_mask
| shadow_accessed_mask);
}
}
return pt_write;
}