我试图通过X86主机中的虚拟化找出Linux系统中EPT PTE与主机PTE之间的关系。
例如,当虚拟机管理程序通过提供主机内存页面来设置EPT条目时,来宾将其写入来宾时会发生什么?
在上述情况下,EPT条目为“脏”,该主机页面的主机PTE条目是否仍然脏?
我写了一个简单的Linux虚拟机管理程序,它支持EPT。我发现来宾写入页面时,在EPT条目中设置了脏位,但是通过检查主机PTE条目,我没有找到脏位集。
在EPT违规处理程序中,我调用kmalloc获取来宾的主机页面。然后,我使用以下代码检查该页面的主机PTE条目。
void pgtable_walk(unsigned long addr)
{
pgd_t *pgd;
pud_t *pud;
pmd_t *pmd;
pte_t *pte;
pte_t cpte;
unsigned long page_mask;
unsigned int level;
phys_addr_t phys_addr;
unsigned long offset;
pgd = pgd_offset(current->mm, addr);
printk(KERN_ALERT "pgd is : %lx\n", (unsigned long)pgd->pgd);
printk(KERN_ALERT "pgd index: %lx\n", (unsigned long)pgd_index(addr));
pud = pud_offset(pgd, addr);
printk(KERN_ALERT "pud is : %lx\n", (unsigned long)pud->pud);
printk(KERN_ALERT "pud index: %lx\n", (unsigned long)pud_index(addr));
pmd = pmd_offset(pud, addr);
printk(KERN_ALERT "pmd is : %lx\n", (unsigned long)pmd->pmd);
printk(KERN_ALERT "pmd index: %lx\n", (unsigned long)pmd_index(addr));
if(!pmd_large(*pmd)) {
pte = pte_offset_kernel(pmd, addr);
printk(KERN_ALERT "pte is : %lx\n", (unsigned long)pte->pte);
printk(KERN_ALERT "pte index: %lx\n", (unsigned long)pte_index(addr));
level = 2;
} else {
pte = (pte_t *)pmd;
level = 1;
}
page_mask = page_level_mask(level);
phys_addr = pte_pfn(*pte) << PAGE_SHIFT;
offset = addr & ~page_mask;
printk("Final Phys Addr: %lx, dirty=%x, pte=%lx\n",
(unsigned long)(phys_addr | offset), pte_dirty(*pte), pte_val(*pte));
}
如果是,Linux如何知道哪个页面脏了?
答案 0 :(得分:2)
在执行写操作时,处理器只能在用于转换虚拟地址的PTE中设置脏位。因此,当来宾写入页面时,处理器会在来宾PTE和EPT中设置脏位。*在来宾中进行写操作时,处理器没有指向主机页表的指针,也没有指向宿主页表的指针。它是否知道页面是否甚至映射到任何主机页面表中。因此,如果主机中的软件想要确定页面是否脏了,则必须查看EPT。
*仅当可选的EPT A / D功能可用时,才设置EPT脏位,并通过将VMCS的EPTP字段中的位6置位来启用。 (请参阅Intel SDM的28.2.5节。)