欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  数据库

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

程序员文章站 2022-04-22 07:53:24
...

客户 机页表的遍历 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;
}