Я пытаюсь выяснить связь между PTE EPT и PTE хоста в системе Linux с виртуализацией на хосте X86.
Например, когда гипервизор устанавливает запись 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 узнает, какая страница грязная или нет?