原帖由 kikanjuu 于 2008-2-22 18:33 发表
请问在完全内存虚拟化(Full Memory Virtualization,包括使用影子页表Shadow Page Table)中,处理缺页异常的流程是什么?
例如,KVM, VMWare都是使用完全内存虚拟化技术来虚拟化物理内存的。请问它们处理缺页 ...
原帖由 kikanjuu 于 2008-2-22 20:12 发表
这样啊,你看过3.0.2的代码吗?
若看过,可不可以告诉我full virtualization的do_page_fault在哪里有?
或者告诉我怎么搜到也行。
3x
175.11 KB, 下载次数: 886
174.46 KB, 下载次数: 221
原帖由 kikanjuu 于 2008-2-26 10:58 发表
另外,为什么要在guest_walk_tables()中把Guest Page Table (GPT)设为只读?
并且,当前这次将GPT设为只读所在的Page Fault又是如何触发的呢?
原帖由 kikanjuu 于 2008-2-26 14:14 发表
是不是客户操作系统修改客户页表会引发两次Page Fault?
第一次:
因为还没有建立起客户页表对应的影子页表,即客户页表的guest physical frame还没有对应的machine frame for guest page table,所以引起Pa ...
gmfn = pagetable_get_mfn(v->arch.guest_table); |
#if GUEST_PAGING_LEVELS == 2 if ( sh_remove_write_access(v, gmfn, 2, 0) != 0 ) flush_tlb_mask(v->domain->domain_dirty_cpumask); sh_set_toplevel_shadow(v, 0, gmfn, SH_type_l2_shadow); #elif GUEST_PAGING_LEVELS == 3 |
if ( guest_op && sh_remove_write_access(v, gw->l2mfn, 2, va) != 0 ) flush_tlb_mask(v->domain->domain_dirty_cpumask); |
/* Need to emulate accesses to page tables */ /* 需要模拟对客户页表的写操作 */ if ( sh_mfn_is_a_page_table(gmfn) ) { if ( ft == ft_demand_write ) { perfc_incr(shadow_fault_emulate_write); goto emulate; } else if ( shadow_mode_trap_reads(d) && ft == ft_demand_read ) { /* Xen 暂时不支持读页表的模拟 */ perfc_incr(shadow_fault_emulate_read); goto emulate; } } |
由此保证了当前domain所有顶级页表对应的页面,在SPT中只读。
之后每次捕获#PF进行的客户页表遍历时,Xen总是同时将遍历客户页表对应的机器页面设置为只读,
代码来自guest_walk_tables():
if ( guest_op && sh_remove_write_access(v, gw->l2mfn, 2, va) != 0 )
flush_tlb_mask(v->domain->domain_dirty_cpumask);
通过这种渐进的方式确保了所有客户页表所在页面在SPT中的映射项都是只读的,
之后如果客户操作系统试图修改客户页表会引发#PF,
此时由Xen捕获并模拟其执行,在模拟的同时同步SPT与GPT:
代码来自sh_page_fault()
原帖由 kikanjuu 于 2008-2-27 09:44 发表
写保护的是客户页表页对应的影子页表页的机器物理页,而不是客户页表页本身的机器物理页,对吗?
在这里guest_walk_tables()之前,客户页表页对应的影子页表页的机器页尚未被写保护,那么这个导致执行guest_ ...
int sh_remove_write_accesss(struct vcpu *v, mfn_t gmfn, unsigned int level, unsigned long fault_addr) { /* callbacks与callback_mask都是为hash_foreach()准备的参数 */ /* Dispatch table for getting per-type functions */ static hash_callback_t callbacks[SH_type_unused] = { NULL, /* none */ #if CONFIG_PAGING_LEVELS == 2 SHADOW_INTERNAL_NAME(sh_rm_write_access_from_l1,2,2), /* l1_32 */ SHADOW_INTERNAL_NAME(sh_rm_write_access_from_l1,2,2), /* fl1_32 */ ...... #endif ...... /* Brute-force search of all the shadows, by walking the hash */ perfc_incr(shadow_writeable_bf); /* 靠遍历hash,蛮力搜索所有的shadows*/ hash_foreach(v, callback_mask, callbacks, gmfn); ...... return 1; } |
mfn_t shadow_alloc(struct domain *d, u32 shadow_type, unsigned long backpointer) { ..... p = sh_map_domain_page(shadow_page_to_mfn(sp+i)); ASSERT(p != NULL); clear_page(p); sh_unmap_domain_page(p); INIT_LIST_HEAD(&sp[i].list); sp[i].type = shadow_type; sp[i].pinned = 0; sp[i].count = 0; sp[i].backpointer = backpointer; sp[i].next_shadow = NULL; perfc_incr(shadow_alloc_count); ...... } |
对客户操作系统页面的寻址,最终要经过sl1e,
所以只需要将对应的sl1e设为R即可.
原帖由 kikanjuu 于 2008-2-27 15:20 发表
非常感谢!辛苦你了。
我想问的是,设置sl1e为R的这次PF是怎么发生的呢?或者说,Xen在什么时候将系统中所有SPT中映射到gmfn对应的smfn的所有sl1e都设为R?
原帖由 kikanjuu 于 2008-2-27 16:11 发表
哦,就是说GOS改cr3被截获,其cr3对应的客户页表的l2 mfn在SPT中的pte被设为只读。
当GOS想将l1 gfn挂到l2 gfn上时,由于相应的客户页表的l2 mfn在SPT中的映射先前已为只读,所以发生PF被截获,
同理,当GO ...
Xen并非对每一个VCPU维护一个与其对应的SPT,而是针对每一个客户页表以及这个客户页表在地址翻译中的层次维护与其对应的一个shadow。
由于可以使用不同的线性地址访问同一个物理页面,所以在不同的客户页表中可能存在到同一个gmfn的映射,由于Xen要监控对客户页表的写操作做,
原帖由 kikanjuu 于 2008-2-27 20:53 发表
什么是“这个客户页表在地址翻译中的层次”?
这里的“所以在不同的客户页表中可能存在到同一个gmfn的映射”应该是“所以在不同的影子页表中可能存在到同一个gmfn的映射”吧?
143.26 KB, 下载次数: 451
原帖由 kikanjuu 于 2008-3-3 15:14 发表
再问个问题:
对于非最低级的客户机页表项,为什么监控程序提供了哈希表,以客户机物理地址和该页表项所在页表的层次为键值,查找影子页表中相应的影子页表项中的影子页表页的宿主机物理地址?
这里为什么需 ...
原帖由 kikanjuu 于 2008-3-3 15:14 发表
再问个问题:
对于非最低级的客户机页表项,为什么监控程序提供了哈希表,以客户机物理地址和该页表项所在页表的层次为键值,查找影子页表中相应的影子页表项中的影子页表页的宿主机物理地址?
这里为什么需 ...
欢迎光临 Chinaunix (http://bbs.chinaunix.net/) | Powered by Discuz! X3.2 |