Home  >  Article  >  Database  >  虚拟MMU---客户机页表遍历

虚拟MMU---客户机页表遍历

WBOY
WBOYOriginal
2016-06-07 15:36:221154browse

客户 机页表的遍历 MMU的功能: 虚拟 机地址转换为物理地址,下面函数模拟此过程。 1.数据结构 struct guest_walker { int level; gfn_t table_gfn[PT_MAX_FULL_LEVELS]; pt_element_t ptes[PT_MAX_FULL_LEVELS]; gpa_t pte_gpa[PT_MAX_FULL_LEVELS]; unsign

客户机页表的遍历

MMU的功能:虚拟机地址转换为物理地址,下面函数模拟此过程。

1.数据结构

 struct guest_walker {
        int level;
        gfn_t table_gfn[PT_MAX_FULL_LEVELS];
        pt_element_t ptes[PT_MAX_FULL_LEVELS];
        gpa_t pte_gpa[PT_MAX_FULL_LEVELS];
        unsigned pt_access;
        unsigned pte_access;
        gfn_t gfn;
        u32 error_code;
};
           +-------+
           |       |
           +-------+
           |   c   |
           |-------|            |       |
           +-------+
           |-------|      
           |-------|       
           +-------+             某级页表
a:页表项基地址
b:index的地址
c:index的地址内容

遍历完成后,数据结构内容为
gfn:客户机页表转换后物理地址页框号
假设PT_MAX_FULL_LEVELS=4
table_gfn【0-3】存放 4级页表项基地址
pte_gpa【0-3】  存放4级页表项中index基地址
ptes【0-3】     存放4级页表项中index基地址内容
pt_access:     gfn的访问权限
pte_access:    gfn的访问权限

2:客户机页表的遍历,也是虚拟MMU
static int FNAME(walk_addr)(struct guest_walker *walker,
                            struct kvm_vcpu *vcpu, gva_t addr,
                            int write_fault, int user_fault, int fetch_fault)
   walker->level = vcpu->arch.mmu.root_level;//64位客户机系统,页表级数为4.
   pte = vcpu->arch.cr3; //页目录基地址
   for (;;) { //从64位客户机页目录开始遍历,最后到页表
                index = PT_INDEX(addr, walker->level);

                table_gfn = gpte_to_gfn(pte);
                pte_gpa = gfn_to_gpa(table_gfn);
                pte_gpa += index * sizeof(pt_element_t);

                walker->table_gfn[walker->level - 1] = table_gfn; //存放页表基地址 
                walker->pte_gpa[walker->level - 1] = pte_gpa;     //存放页表index基地址

                if (kvm_read_guest(vcpu->kvm, pte_gpa, &pte, sizeof(pte)))//获取存放页表index基地址页表项
                        goto not_present;
                 pte_access = pt_access & FNAME(gpte_access)(vcpu, pte);//获取存放页表index基地址页表项权限

                walker->ptes[walker->level - 1] = pte;//存放存放页表index基地址页表项

                if ((walker->level == PT_PAGE_TABLE_LEVEL)//页表的最后一级存放客户机物理页地址
                {
                        int lvl = walker->level;

                        walker->gfn = gpte_to_gfn_lvl(pte, lvl);//转换客户机物理页地址为客户机物理页框号
                        walker->gfn += (addr & PT_LVL_OFFSET_MASK(lvl))
                                        >> PAGE_SHIFT;
                        break;
                }

               pt_access = pte_access;
                --walker->level; //遍历下一级页表
             }
        //页表遍历完成后,获取页表的访问权限,存放到数据结构中
        walker->pt_access = pt_access;
        walker->pte_access = pte_access;
        pgprintk("%s: pte %llx pte_access %x pt_access %x\n",
                 __func__, (u64)pte, pt_access, pte_access);
        return 1;
}



Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn