[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] Fix problems with direct-mapping handling especially when
# HG changeset patch # User kaf24@xxxxxxxxxxxxxxxxxxxx # Node ID a543a4778a7d9888fad13ffafff0aa9bc5541b48 # Parent bee659de2a369cbf1da2e7751c0eb5e2f0e11dec Fix problems with direct-mapping handling especially when VMX assist is used for real mode and protected mode. Signed-off-by: Jun Nakajima <jun.nakajima@xxxxxxxxx> Signed-off-by: Xin B Li <xin.b.li@xxxxxxxxx> Signed-off-by: Yunhong Jiang <yunhong.jiang@xxxxxxxxx> diff -r bee659de2a36 -r a543a4778a7d xen/arch/x86/hvm/svm/svm.c --- a/xen/arch/x86/hvm/svm/svm.c Thu Feb 16 15:35:09 2006 +++ b/xen/arch/x86/hvm/svm/svm.c Thu Feb 16 15:46:21 2006 @@ -799,6 +799,7 @@ struct domain *d = v->domain; if (d->arch.hvm_domain.shared_page_va) unmap_domain_page((void *)d->arch.hvm_domain.shared_page_va); + shadow_direct_map_clean(v); } destroy_vmcb(&v->arch.hvm_svm); @@ -1443,9 +1444,7 @@ put_page(mfn_to_page(old_base_mfn)); } #endif -#if CONFIG_PAGING_LEVELS == 2 - shadow_direct_map_clean(v); -#endif + /* Now arch.guest_table points to machine physical. */ v->arch.guest_table = mk_pagetable(mfn << PAGE_SHIFT); update_pagetables(v); diff -r bee659de2a36 -r a543a4778a7d xen/arch/x86/hvm/vmx/vmx.c --- a/xen/arch/x86/hvm/vmx/vmx.c Thu Feb 16 15:35:09 2006 +++ b/xen/arch/x86/hvm/vmx/vmx.c Thu Feb 16 15:46:21 2006 @@ -88,6 +88,7 @@ if ( d->arch.hvm_domain.shared_page_va ) unmap_domain_page_global( (void *)d->arch.hvm_domain.shared_page_va); + shadow_direct_map_clean(v); } vmx_request_clear_vmcs(v); @@ -1227,9 +1228,7 @@ __vmwrite(GUEST_CR4, crn | X86_CR4_PAE); } } -#if CONFIG_PAGING_LEVELS == 2 - shadow_direct_map_clean(v); -#endif + /* * Now arch.guest_table points to machine physical. */ diff -r bee659de2a36 -r a543a4778a7d xen/arch/x86/shadow.c --- a/xen/arch/x86/shadow.c Thu Feb 16 15:35:09 2006 +++ b/xen/arch/x86/shadow.c Thu Feb 16 15:46:21 2006 @@ -3743,6 +3743,7 @@ #if ( CONFIG_PAGING_LEVELS == 3 && !defined (GUEST_PGENTRY_32) ) || \ ( CONFIG_PAGING_LEVELS == 4 && defined (GUEST_PGENTRY_32) ) + /* * Use GUEST_PGENTRY_32 to force PAE_SHADOW_SELF_ENTRY for L4. * @@ -3756,8 +3757,8 @@ { struct vcpu *v = current; struct domain *d = v->domain; - l3_pgentry_t sl3e; - l2_pgentry_t sl2e; + l3_pgentry_t sl3e, *sl3e_p; + l2_pgentry_t sl2e, *sl2e_p; l1_pgentry_t sl1e; unsigned long mfn, smfn; struct page_info *page; @@ -3773,37 +3774,47 @@ shadow_lock(d); - __shadow_get_l3e(v, vpa, &sl3e); + __direct_get_l3e(v, vpa, &sl3e); if ( !(l3e_get_flags(sl3e) & _PAGE_PRESENT) ) { page = alloc_domheap_page(NULL); if ( !page ) - goto fail; + goto nomem; + smfn = page_to_mfn(page); sl3e = l3e_from_pfn(smfn, _PAGE_PRESENT); - __shadow_set_l3e(v, vpa, &sl3e); - } - - __shadow_get_l2e(v, vpa, &sl2e); + + sl3e_p = (l3_pgentry_t *)map_domain_page(smfn); + memset(sl3e_p, 0, PAGE_SIZE); + unmap_domain_page(sl3e_p); + + __direct_set_l3e(v, vpa, &sl3e); + } + + __direct_get_l2e(v, vpa, &sl2e); if ( !(l2e_get_flags(sl2e) & _PAGE_PRESENT) ) { page = alloc_domheap_page(NULL); if ( !page ) - goto fail; + goto nomem; + smfn = page_to_mfn(page); - sl2e = l2e_from_pfn(smfn, __PAGE_HYPERVISOR | _PAGE_USER); - __shadow_set_l2e(v, vpa, &sl2e); - } - - __shadow_get_l1e(v, vpa, &sl1e); + sl2e_p = (l2_pgentry_t *)map_domain_page(smfn); + memset(sl2e_p, 0, PAGE_SIZE); + unmap_domain_page(sl2e_p); + + __direct_set_l2e(v, vpa, &sl2e); + } + + __direct_get_l1e(v, vpa, &sl1e); if ( !(l1e_get_flags(sl1e) & _PAGE_PRESENT) ) { sl1e = l1e_from_pfn(mfn, __PAGE_HYPERVISOR | _PAGE_USER); - __shadow_set_l1e(v, vpa, &sl1e); + __direct_set_l1e(v, vpa, &sl1e); } shadow_unlock(d); @@ -3811,6 +3822,10 @@ fail: return 0; + +nomem: + shadow_direct_map_clean(v); + domain_crash_synchronous(); } #endif diff -r bee659de2a36 -r a543a4778a7d xen/arch/x86/shadow32.c --- a/xen/arch/x86/shadow32.c Thu Feb 16 15:35:09 2006 +++ b/xen/arch/x86/shadow32.c Thu Feb 16 15:46:21 2006 @@ -807,21 +807,99 @@ v->arch.monitor_vtable = 0; } +static int +map_p2m_entry( + l1_pgentry_t *l1tab, unsigned long va, unsigned long gpa, unsigned long mfn) +{ + unsigned long *l0tab = NULL; + l1_pgentry_t l1e = { 0 }; + struct page_info *page; + + l1e = l1tab[l1_table_offset(va)]; + if ( !(l1e_get_flags(l1e) & _PAGE_PRESENT) ) + { + page = alloc_domheap_page(NULL); + if ( !page ) + goto fail; + + if ( l0tab ) + unmap_domain_page(l0tab); + l0tab = map_domain_page(page_to_mfn(page)); + memset(l0tab, 0, PAGE_SIZE ); + l1e = l1tab[l1_table_offset(va)] = + l1e_from_page(page, __PAGE_HYPERVISOR); + } + else if ( l0tab == NULL) + l0tab = map_domain_page(l1e_get_pfn(l1e)); + + l0tab[gpa & ((PAGE_SIZE / sizeof (mfn)) - 1) ] = mfn; + + if ( l0tab ) + unmap_domain_page(l0tab); + + return 1; + +fail: + return 0; +} + int set_p2m_entry(struct domain *d, unsigned long pfn, unsigned long mfn, struct domain_mmap_cache *l2cache, struct domain_mmap_cache *l1cache) { - unsigned long tabpfn = pagetable_get_pfn(d->arch.phys_table); + unsigned long tabpfn; l2_pgentry_t *l2, l2e; l1_pgentry_t *l1; struct page_info *l1page; unsigned long va = pfn << PAGE_SHIFT; + int error; + + if ( shadow_mode_external(d) ) + { + tabpfn = pagetable_get_pfn(d->vcpu[0]->arch.monitor_table); + va = RO_MPT_VIRT_START + (pfn * sizeof (unsigned long)); + } + else + { + tabpfn = pagetable_get_pfn(d->arch.phys_table); + va = pfn << PAGE_SHIFT; + } ASSERT(tabpfn != 0); ASSERT(shadow_lock_is_acquired(d)); l2 = map_domain_page_with_cache(tabpfn, l2cache); + + /* + * The following code covers (SHM_translate | SHM_external) mode. + */ + + if ( shadow_mode_external(d) ) + { + l1_pgentry_t *l1tab = NULL; + l2_pgentry_t l2e; + + l2e = l2[l2_table_offset(va)]; + + ASSERT( l2e_get_flags(l2e) & _PAGE_PRESENT ); + + l1tab = map_domain_page(l2e_get_pfn(l2e)); + error = map_p2m_entry(l1tab, va, pfn, mfn); + if ( !error ) + domain_crash_synchronous(); + + unmap_domain_page(l1tab); + unmap_domain_page_with_cache(l2, l2cache); + + return 1; + } + + /* + * The following code covers SHM_translate mode. + */ + ASSERT(shadow_mode_translate(d)); + l2e = l2[l2_table_offset(va)]; if ( !(l2e_get_flags(l2e) & _PAGE_PRESENT) ) { @@ -856,13 +934,10 @@ l2_pgentry_t *l2tab = NULL; l1_pgentry_t *l1tab = NULL; - unsigned long *l0tab = NULL; l2_pgentry_t l2e = { 0 }; - l1_pgentry_t l1e = { 0 }; - struct page_info *page; - unsigned long pfn; - int i; + unsigned long gpfn, mfn; + int error; if ( pagetable_get_pfn(d->vcpu[0]->arch.monitor_table) ) { @@ -892,34 +967,22 @@ list_ent = d->page_list.next; - for ( i = 0; list_ent != &d->page_list; i++ ) + for ( gpfn = 0; list_ent != &d->page_list; gpfn++ ) { page = list_entry(list_ent, struct page_info, list); - pfn = page_to_mfn(page); - - l1e = l1tab[l1_table_offset(va)]; - if ( !(l1e_get_flags(l1e) & _PAGE_PRESENT) ) - { - page = alloc_domheap_page(NULL); - if ( l0tab ) - unmap_domain_page(l0tab); - l0tab = map_domain_page(page_to_mfn(page)); - memset(l0tab, 0, PAGE_SIZE ); - l1e = l1tab[l1_table_offset(va)] = - l1e_from_page(page, __PAGE_HYPERVISOR); - } - else if ( l0tab == NULL) - l0tab = map_domain_page(l1e_get_pfn(l1e)); - - l0tab[i & ((1 << PAGETABLE_ORDER) - 1) ] = pfn; - list_ent = frame_table[pfn].list.next; - va += sizeof(pfn); + mfn = page_to_mfn(page); + + error = map_p2m_entry(l1tab, va, gpfn, mfn); + if ( !error ) + domain_crash_synchronous(); + + list_ent = frame_table[mfn].list.next; + va += sizeof(mfn); } if (l2tab) unmap_domain_page(l2tab); unmap_domain_page(l1tab); - unmap_domain_page(l0tab); return 1; } @@ -981,21 +1044,26 @@ } shadow_lock(d); - - __shadow_get_l2e(v, vpa, &sl2e); - - if ( !(l2e_get_flags(sl2e) & _PAGE_PRESENT) ) + + __direct_get_l2e(v, vpa, &sl2e); + + if ( !(l2e_get_flags(sl2e) & _PAGE_PRESENT) ) { page = alloc_domheap_page(NULL); if ( !page ) - goto fail; + goto nomem; smfn = page_to_mfn(page); sl2e = l2e_from_pfn(smfn, __PAGE_HYPERVISOR | _PAGE_USER); - __shadow_set_l2e(v, vpa, sl2e); - } - - sple = (l1_pgentry_t *)map_domain_page(l2e_get_pfn(sl2e)); + + sple = (l1_pgentry_t *)map_domain_page(smfn); + memset(sple, 0, PAGE_SIZE); + __direct_set_l2e(v, vpa, sl2e); + } + + if ( !sple ) + sple = (l1_pgentry_t *)map_domain_page(l2e_get_pfn(sl2e)); + sl1e = sple[l1_table_offset(vpa)]; if ( !(l1e_get_flags(sl1e) & _PAGE_PRESENT) ) @@ -1003,13 +1071,19 @@ sl1e = l1e_from_pfn(mfn, __PAGE_HYPERVISOR | _PAGE_USER); sple[l1_table_offset(vpa)] = sl1e; } - unmap_domain_page(sple); + + if (sple) + unmap_domain_page(sple); + shadow_unlock(d); - return EXCRET_fault_fixed; fail: return 0; + +nomem: + shadow_direct_map_clean(v); + domain_crash_synchronous(); } @@ -1021,16 +1095,12 @@ if ( !(page = alloc_domheap_page(NULL)) ) goto fail; - root = map_domain_page_global(page_to_mfn(page)); + root = map_domain_page(page_to_mfn(page)); memset(root, 0, PAGE_SIZE); + unmap_domain_page(root); v->domain->arch.phys_table = mk_pagetable(page_to_maddr(page)); - /* - * We need to set shadow_vtable to get __shadow_set/get_xxx - * working - */ - v->arch.shadow_vtable = (l2_pgentry_t *) root; - v->arch.shadow_table = mk_pagetable(0); + return 1; fail: @@ -1042,9 +1112,8 @@ int i; l2_pgentry_t *l2e; - ASSERT ( v->arch.shadow_vtable ); - - l2e = v->arch.shadow_vtable; + l2e = map_domain_page( + pagetable_get_pfn(v->domain->arch.phys_table)); for ( i = 0; i < L2_PAGETABLE_ENTRIES; i++ ) { @@ -1055,8 +1124,7 @@ free_domheap_page( mfn_to_page(pagetable_get_pfn(v->domain->arch.phys_table))); - unmap_domain_page_global(v->arch.shadow_vtable); - v->arch.shadow_vtable = 0; + unmap_domain_page(l2e); v->domain->arch.phys_table = mk_pagetable(0); } @@ -1168,13 +1236,6 @@ printk("alloc_p2m_table failed (out-of-memory?)\n"); goto nomem; } - } - else - { - // external guests provide their own memory for their P2M maps. - // - ASSERT(d == page_get_owner(mfn_to_page(pagetable_get_pfn( - d->arch.phys_table)))); } } diff -r bee659de2a36 -r a543a4778a7d xen/arch/x86/shadow_public.c --- a/xen/arch/x86/shadow_public.c Thu Feb 16 15:35:09 2006 +++ b/xen/arch/x86/shadow_public.c Thu Feb 16 15:46:21 2006 @@ -44,33 +44,28 @@ if ( !(page = alloc_domheap_pages(NULL, 0, ALLOC_DOM_DMA)) ) goto fail; - root = map_domain_page_global(page_to_mfn(page)); + root = map_domain_page(page_to_mfn(page)); memset(root, 0, PAGE_SIZE); root[PAE_SHADOW_SELF_ENTRY] = l3e_from_page(page, __PAGE_HYPERVISOR); v->domain->arch.phys_table = mk_pagetable(page_to_maddr(page)); - /* - * We need to set shadow_vtable to get __shadow_set/get_xxx - * working - */ - v->arch.shadow_vtable = (l2_pgentry_t *) root; - + + unmap_domain_page(root); return 1; - + fail: return 0; } -static void shadow_direct_map_clean(struct vcpu *v) +void shadow_direct_map_clean(struct vcpu *v) { l2_pgentry_t *l2e; l3_pgentry_t *l3e; int i, j; - ASSERT ( v->arch.shadow_vtable ); - - l3e = (l3_pgentry_t *) v->arch.shadow_vtable; - + l3e = (l3_pgentry_t *)map_domain_page( + pagetable_get_pfn(v->domain->arch.phys_table)); + for ( i = 0; i < PAE_L3_PAGETABLE_ENTRIES; i++ ) { if ( l3e_get_flags(l3e[i]) & _PAGE_PRESENT ) @@ -90,8 +85,7 @@ free_domheap_page( mfn_to_page(pagetable_get_pfn(v->domain->arch.phys_table))); - unmap_domain_page_global(v->arch.shadow_vtable); - v->arch.shadow_vtable = 0; + unmap_domain_page(l3e); v->domain->arch.phys_table = mk_pagetable(0); } @@ -102,12 +96,7 @@ int shadow_set_guest_paging_levels(struct domain *d, int levels) { - struct vcpu *v = current; shadow_lock(d); - - if ( shadow_mode_translate(d) && - !(pagetable_get_paddr(v->domain->arch.phys_table)) ) - shadow_direct_map_clean(v); switch(levels) { #if CONFIG_PAGING_LEVELS == 4 @@ -1330,164 +1319,166 @@ return shadow_mode_refcounts(d); } -int -set_p2m_entry(struct domain *d, unsigned long pfn, unsigned long mfn, - struct domain_mmap_cache *l2cache, - struct domain_mmap_cache *l1cache) -{ - unsigned long tabpfn = pagetable_get_pfn(d->arch.phys_table); - l2_pgentry_t *l2, l2e; - l1_pgentry_t *l1; - struct page_info *l1page; - unsigned long va = pfn << PAGE_SHIFT; - - ASSERT(tabpfn != 0); - - l2 = map_domain_page_with_cache(tabpfn, l2cache); - l2e = l2[l2_table_offset(va)]; - if ( !(l2e_get_flags(l2e) & _PAGE_PRESENT) ) - { - l1page = alloc_domheap_page(NULL); - if ( !l1page ) - { - unmap_domain_page_with_cache(l2, l2cache); - return 0; - } - - l1 = map_domain_page_with_cache(page_to_mfn(l1page), l1cache); - memset(l1, 0, PAGE_SIZE); - unmap_domain_page_with_cache(l1, l1cache); - - l2e = l2e_from_page(l1page, __PAGE_HYPERVISOR); - l2[l2_table_offset(va)] = l2e; - } - unmap_domain_page_with_cache(l2, l2cache); - - l1 = map_domain_page_with_cache(l2e_get_pfn(l2e), l1cache); - l1[l1_table_offset(va)] = l1e_from_pfn(mfn, __PAGE_HYPERVISOR); - unmap_domain_page_with_cache(l1, l1cache); - - return 1; -} - -int -alloc_p2m_table(struct domain *d) -{ - struct list_head *list_ent; - unsigned long va = RO_MPT_VIRT_START; /* phys_to_machine_mapping */ - +static int +map_p2m_entry( + pgentry_64_t *top_tab, unsigned long va, unsigned long gpa, unsigned long mfn) +{ #if CONFIG_PAGING_LEVELS >= 4 - l4_pgentry_t *l4tab = NULL; - l4_pgentry_t l4e = { 0 }; + pgentry_64_t l4e = { 0 }; #endif #if CONFIG_PAGING_LEVELS >= 3 - l3_pgentry_t *l3tab = NULL; - l3_pgentry_t l3e = { 0 }; + pgentry_64_t *l3tab = NULL; + pgentry_64_t l3e = { 0 }; #endif l2_pgentry_t *l2tab = NULL; l1_pgentry_t *l1tab = NULL; unsigned long *l0tab = NULL; l2_pgentry_t l2e = { 0 }; l1_pgentry_t l1e = { 0 }; - - unsigned long pfn; - int i; + struct page_info *page; + +#if CONFIG_PAGING_LEVELS >= 4 + l4e = top_tab[l4_table_offset(va)]; + if ( !(entry_get_flags(l4e) & _PAGE_PRESENT) ) + { + page = alloc_domheap_page(NULL); + if ( !page ) + goto nomem; + + l3tab = map_domain_page(page_to_mfn(page)); + memset(l3tab, 0, PAGE_SIZE); + l4e = top_tab[l4_table_offset(va)] = + entry_from_page(page, __PAGE_HYPERVISOR); + } + else if ( l3tab == NULL) + l3tab = map_domain_page(entry_get_pfn(l4e)); + + l3e = l3tab[l3_table_offset(va)]; +#else + l3e = top_tab[l3_table_offset(va)]; +#endif + if ( !(entry_get_flags(l3e) & _PAGE_PRESENT) ) + { + page = alloc_domheap_page(NULL); + if ( !page ) + goto nomem; + + l2tab = map_domain_page(page_to_mfn(page)); + memset(l2tab, 0, PAGE_SIZE); + l3e = l3tab[l3_table_offset(va)] = + entry_from_page(page, __PAGE_HYPERVISOR); + } + else if ( l2tab == NULL) + l2tab = map_domain_page(entry_get_pfn(l3e)); + + l2e = l2tab[l2_table_offset(va)]; + if ( !(l2e_get_flags(l2e) & _PAGE_PRESENT) ) + { + page = alloc_domheap_page(NULL); + if ( !page ) + goto nomem; + + l1tab = map_domain_page(page_to_mfn(page)); + memset(l1tab, 0, PAGE_SIZE); + l2e = l2tab[l2_table_offset(va)] = + l2e_from_page(page, __PAGE_HYPERVISOR); + } + else if ( l1tab == NULL) + l1tab = map_domain_page(l2e_get_pfn(l2e)); + + l1e = l1tab[l1_table_offset(va)]; + if ( !(l1e_get_flags(l1e) & _PAGE_PRESENT) ) + { + page = alloc_domheap_page(NULL); + if ( !page ) + goto nomem; + + l0tab = map_domain_page(page_to_mfn(page)); + memset(l0tab, 0, PAGE_SIZE); + l1e = l1tab[l1_table_offset(va)] = + l1e_from_page(page, __PAGE_HYPERVISOR); + } + else if ( l0tab == NULL) + l0tab = map_domain_page(l1e_get_pfn(l1e)); + + l0tab[gpa & ((PAGE_SIZE / sizeof (mfn)) - 1) ] = mfn; + + if ( l2tab ) + { + unmap_domain_page(l2tab); + l2tab = NULL; + } + if ( l1tab ) + { + unmap_domain_page(l1tab); + l1tab = NULL; + } + if ( l0tab ) + { + unmap_domain_page(l0tab); + l0tab = NULL; + } + + return 1; + +nomem: + + return 0; +} + +int +set_p2m_entry(struct domain *d, unsigned long pfn, unsigned long mfn, + struct domain_mmap_cache *l2cache, + struct domain_mmap_cache *l1cache) +{ + unsigned long tabpfn = pagetable_get_pfn(d->vcpu[0]->arch.monitor_table); + pgentry_64_t *top; + unsigned long va = RO_MPT_VIRT_START + (pfn * sizeof (unsigned long)); + int error; + + ASSERT(tabpfn != 0); + ASSERT(shadow_lock_is_acquired(d)); + + top = map_domain_page_with_cache(tabpfn, l2cache); + error = map_p2m_entry(top, va, pfn, mfn); + unmap_domain_page_with_cache(top, l2cache); + + if ( !error ) + domain_crash_synchronous(); + + return 1; +} + +int +alloc_p2m_table(struct domain *d) +{ + struct list_head *list_ent; + unsigned long va = RO_MPT_VIRT_START; /* phys_to_machine_mapping */ + pgentry_64_t *top_tab = NULL; + unsigned long mfn; + int gpa; ASSERT ( pagetable_get_pfn(d->vcpu[0]->arch.monitor_table) ); -#if CONFIG_PAGING_LEVELS >= 4 - l4tab = map_domain_page( + top_tab = map_domain_page( pagetable_get_pfn(d->vcpu[0]->arch.monitor_table)); -#endif -#if CONFIG_PAGING_LEVELS >= 3 - l3tab = map_domain_page( - pagetable_get_pfn(d->vcpu[0]->arch.monitor_table)); -#endif + list_ent = d->page_list.next; - for ( i = 0; list_ent != &d->page_list; i++ ) + for ( gpa = 0; list_ent != &d->page_list; gpa++ ) { struct page_info *page; - page = list_entry(list_ent, struct page_info, list); - pfn = page_to_mfn(page); - -#if CONFIG_PAGING_LEVELS >= 4 - l4e = l4tab[l4_table_offset(va)]; - if ( !(l4e_get_flags(l4e) & _PAGE_PRESENT) ) - { - page = alloc_domheap_page(NULL); - l3tab = map_domain_page(page_to_mfn(page)); - memset(l3tab, 0, PAGE_SIZE); - l4e = l4tab[l4_table_offset(va)] = - l4e_from_page(page, __PAGE_HYPERVISOR); - } - else if ( l3tab == NULL) - l3tab = map_domain_page(l4e_get_pfn(l4e)); -#endif - l3e = l3tab[l3_table_offset(va)]; - if ( !(l3e_get_flags(l3e) & _PAGE_PRESENT) ) - { - page = alloc_domheap_page(NULL); - l2tab = map_domain_page(page_to_mfn(page)); - memset(l2tab, 0, PAGE_SIZE); - l3e = l3tab[l3_table_offset(va)] = - l3e_from_page(page, __PAGE_HYPERVISOR); - } - else if ( l2tab == NULL) - l2tab = map_domain_page(l3e_get_pfn(l3e)); - - l2e = l2tab[l2_table_offset(va)]; - if ( !(l2e_get_flags(l2e) & _PAGE_PRESENT) ) - { - page = alloc_domheap_page(NULL); - l1tab = map_domain_page(page_to_mfn(page)); - memset(l1tab, 0, PAGE_SIZE); - l2e = l2tab[l2_table_offset(va)] = - l2e_from_page(page, __PAGE_HYPERVISOR); - } - else if ( l1tab == NULL) - l1tab = map_domain_page(l2e_get_pfn(l2e)); - - l1e = l1tab[l1_table_offset(va)]; - if ( !(l1e_get_flags(l1e) & _PAGE_PRESENT) ) - { - page = alloc_domheap_page(NULL); - l0tab = map_domain_page(page_to_mfn(page)); - memset(l0tab, 0, PAGE_SIZE); - l1e = l1tab[l1_table_offset(va)] = - l1e_from_page(page, __PAGE_HYPERVISOR); - } - else if ( l0tab == NULL) - l0tab = map_domain_page(l1e_get_pfn(l1e)); - - l0tab[i & ((PAGE_SIZE / sizeof (pfn)) - 1) ] = pfn; - list_ent = frame_table[pfn].list.next; - va += sizeof (pfn); - - if ( l2tab ) - { - unmap_domain_page(l2tab); - l2tab = NULL; - } - if ( l1tab ) - { - unmap_domain_page(l1tab); - l1tab = NULL; - } - if ( l0tab ) - { - unmap_domain_page(l0tab); - l0tab = NULL; - } - } -#if CONFIG_PAGING_LEVELS >= 4 - unmap_domain_page(l4tab); -#endif -#if CONFIG_PAGING_LEVELS >= 3 - unmap_domain_page(l3tab); -#endif + mfn = page_to_mfn(page); + + map_p2m_entry(top_tab, va, gpa, mfn); + list_ent = frame_table[mfn].list.next; + va += sizeof(mfn); + } + + unmap_domain_page(top_tab); + return 1; } diff -r bee659de2a36 -r a543a4778a7d xen/include/asm-x86/shadow.h --- a/xen/include/asm-x86/shadow.h Thu Feb 16 15:35:09 2006 +++ b/xen/include/asm-x86/shadow.h Thu Feb 16 15:46:21 2006 @@ -115,9 +115,7 @@ #define SHADOW_ENCODE_MIN_MAX(_min, _max) ((((GUEST_L1_PAGETABLE_ENTRIES - 1) - (_max)) << 16) | (_min)) #define SHADOW_MIN(_encoded) ((_encoded) & ((1u<<16) - 1)) #define SHADOW_MAX(_encoded) ((GUEST_L1_PAGETABLE_ENTRIES - 1) - ((_encoded) >> 16)) -#if CONFIG_PAGING_LEVELS == 2 extern void shadow_direct_map_clean(struct vcpu *v); -#endif extern int shadow_direct_map_init(struct vcpu *v); extern int shadow_direct_map_fault( unsigned long vpa, struct cpu_user_regs *regs); @@ -556,6 +554,38 @@ update_hl2e(v, va); __mark_dirty(d, pagetable_get_pfn(v->arch.guest_table)); +} + +static inline void +__direct_get_l2e( + struct vcpu *v, unsigned long va, l2_pgentry_t *psl2e) +{ + l2_pgentry_t *phys_vtable; + + ASSERT(shadow_mode_enabled(v->domain)); + + phys_vtable = map_domain_page( + pagetable_get_pfn(v->domain->arch.phys_table)); + + *psl2e = phys_vtable[l2_table_offset(va)]; + + unmap_domain_page(phys_vtable); +} + +static inline void +__direct_set_l2e( + struct vcpu *v, unsigned long va, l2_pgentry_t value) +{ + l2_pgentry_t *phys_vtable; + + ASSERT(shadow_mode_enabled(v->domain)); + + phys_vtable = map_domain_page( + pagetable_get_pfn(v->domain->arch.phys_table)); + + phys_vtable[l2_table_offset(va)] = value; + + unmap_domain_page(phys_vtable); } static inline void diff -r bee659de2a36 -r a543a4778a7d xen/include/asm-x86/shadow_64.h --- a/xen/include/asm-x86/shadow_64.h Thu Feb 16 15:35:09 2006 +++ b/xen/include/asm-x86/shadow_64.h Thu Feb 16 15:46:21 2006 @@ -66,9 +66,12 @@ #define PAGING_L1 1UL #define L_MASK 0xff +#define PAE_PAGING_LEVELS 3 + #define ROOT_LEVEL_64 PAGING_L4 #define ROOT_LEVEL_32 PAGING_L2 +#define DIRECT_ENTRY (4UL << 16) #define SHADOW_ENTRY (2UL << 16) #define GUEST_ENTRY (1UL << 16) @@ -94,6 +97,7 @@ #define entry_empty() ((pgentry_64_t) { 0 }) #define entry_from_pfn(pfn, flags) \ ((pgentry_64_t) { ((intpte_t)(pfn) << PAGE_SHIFT) | put_pte_flags(flags) }) +#define entry_from_page(page, flags) (entry_from_pfn(page_to_mfn(page),(flags))) #define entry_add_flags(x, flags) ((x).lo |= put_pte_flags(flags)) #define entry_remove_flags(x, flags) ((x).lo &= ~put_pte_flags(flags)) #define entry_has_changed(x,y,flags) \ @@ -162,16 +166,24 @@ if ( flag & SHADOW_ENTRY ) { - root_level = ROOT_LEVEL_64; - index = table_offset_64(va, root_level); + root_level = ROOT_LEVEL_64; + index = table_offset_64(va, root_level); le_e = (pgentry_64_t *)&v->arch.shadow_vtable[index]; } - else /* guest entry */ + else if ( flag & GUEST_ENTRY ) { root_level = v->domain->arch.ops->guest_paging_levels; - index = table_offset_64(va, root_level); + index = table_offset_64(va, root_level); le_e = (pgentry_64_t *)&v->arch.guest_vtable[index]; } + else /* direct mode */ + { + root_level = PAE_PAGING_LEVELS; + index = table_offset_64(va, root_level); + le_e = (pgentry_64_t *)map_domain_page( + pagetable_get_pfn(v->domain->arch.phys_table)); + } + /* * If it's not external mode, then mfn should be machine physical. */ @@ -241,6 +253,20 @@ #define __guest_get_l3e(v, va, sl3e) \ __rw_entry(v, va, gl3e, GUEST_ENTRY | GET_ENTRY | PAGING_L3) +#define __direct_set_l3e(v, va, value) \ + __rw_entry(v, va, value, DIRECT_ENTRY | SET_ENTRY | PAGING_L3) +#define __direct_get_l3e(v, va, sl3e) \ + __rw_entry(v, va, sl3e, DIRECT_ENTRY | GET_ENTRY | PAGING_L3) +#define __direct_set_l2e(v, va, value) \ + __rw_entry(v, va, value, DIRECT_ENTRY | SET_ENTRY | PAGING_L2) +#define __direct_get_l2e(v, va, sl2e) \ + __rw_entry(v, va, sl2e, DIRECT_ENTRY | GET_ENTRY | PAGING_L2) +#define __direct_set_l1e(v, va, value) \ + __rw_entry(v, va, value, DIRECT_ENTRY | SET_ENTRY | PAGING_L1) +#define __direct_get_l1e(v, va, sl1e) \ + __rw_entry(v, va, sl1e, DIRECT_ENTRY | GET_ENTRY | PAGING_L1) + + static inline int __guest_set_l2e( struct vcpu *v, unsigned long va, void *value, int size) { _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |