ia64/xen-unstable
changeset 8868:a543a4778a7d
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@intel.com>
Signed-off-by: Xin B Li <xin.b.li@intel.com>
Signed-off-by: Yunhong Jiang <yunhong.jiang@intel.com>
VMX assist is used for real mode and protected mode.
Signed-off-by: Jun Nakajima <jun.nakajima@intel.com>
Signed-off-by: Xin B Li <xin.b.li@intel.com>
Signed-off-by: Yunhong Jiang <yunhong.jiang@intel.com>
author | kaf24@firebug.cl.cam.ac.uk |
---|---|
date | Thu Feb 16 16:46:21 2006 +0100 (2006-02-16) |
parents | bee659de2a36 |
children | 18fa851b6dc6 |
files | xen/arch/x86/hvm/svm/svm.c xen/arch/x86/hvm/vmx/vmx.c xen/arch/x86/shadow.c xen/arch/x86/shadow32.c xen/arch/x86/shadow_public.c xen/include/asm-x86/shadow.h xen/include/asm-x86/shadow_64.h |
line diff
1.1 --- a/xen/arch/x86/hvm/svm/svm.c Thu Feb 16 16:35:09 2006 +0100 1.2 +++ b/xen/arch/x86/hvm/svm/svm.c Thu Feb 16 16:46:21 2006 +0100 1.3 @@ -799,6 +799,7 @@ void svm_relinquish_resources(struct vcp 1.4 struct domain *d = v->domain; 1.5 if (d->arch.hvm_domain.shared_page_va) 1.6 unmap_domain_page((void *)d->arch.hvm_domain.shared_page_va); 1.7 + shadow_direct_map_clean(v); 1.8 } 1.9 1.10 destroy_vmcb(&v->arch.hvm_svm); 1.11 @@ -1443,9 +1444,7 @@ static int svm_set_cr0(unsigned long val 1.12 put_page(mfn_to_page(old_base_mfn)); 1.13 } 1.14 #endif 1.15 -#if CONFIG_PAGING_LEVELS == 2 1.16 - shadow_direct_map_clean(v); 1.17 -#endif 1.18 + 1.19 /* Now arch.guest_table points to machine physical. */ 1.20 v->arch.guest_table = mk_pagetable(mfn << PAGE_SHIFT); 1.21 update_pagetables(v);
2.1 --- a/xen/arch/x86/hvm/vmx/vmx.c Thu Feb 16 16:35:09 2006 +0100 2.2 +++ b/xen/arch/x86/hvm/vmx/vmx.c Thu Feb 16 16:46:21 2006 +0100 2.3 @@ -88,6 +88,7 @@ void vmx_relinquish_resources(struct vcp 2.4 if ( d->arch.hvm_domain.shared_page_va ) 2.5 unmap_domain_page_global( 2.6 (void *)d->arch.hvm_domain.shared_page_va); 2.7 + shadow_direct_map_clean(v); 2.8 } 2.9 2.10 vmx_request_clear_vmcs(v); 2.11 @@ -1227,9 +1228,7 @@ static int vmx_set_cr0(unsigned long val 2.12 __vmwrite(GUEST_CR4, crn | X86_CR4_PAE); 2.13 } 2.14 } 2.15 -#if CONFIG_PAGING_LEVELS == 2 2.16 - shadow_direct_map_clean(v); 2.17 -#endif 2.18 + 2.19 /* 2.20 * Now arch.guest_table points to machine physical. 2.21 */
3.1 --- a/xen/arch/x86/shadow.c Thu Feb 16 16:35:09 2006 +0100 3.2 +++ b/xen/arch/x86/shadow.c Thu Feb 16 16:46:21 2006 +0100 3.3 @@ -3743,6 +3743,7 @@ struct shadow_ops MODE_32_2_HANDLER = { 3.4 #if ( CONFIG_PAGING_LEVELS == 3 && !defined (GUEST_PGENTRY_32) ) || \ 3.5 ( CONFIG_PAGING_LEVELS == 4 && defined (GUEST_PGENTRY_32) ) 3.6 3.7 + 3.8 /* 3.9 * Use GUEST_PGENTRY_32 to force PAE_SHADOW_SELF_ENTRY for L4. 3.10 * 3.11 @@ -3756,8 +3757,8 @@ int shadow_direct_map_fault(unsigned lon 3.12 { 3.13 struct vcpu *v = current; 3.14 struct domain *d = v->domain; 3.15 - l3_pgentry_t sl3e; 3.16 - l2_pgentry_t sl2e; 3.17 + l3_pgentry_t sl3e, *sl3e_p; 3.18 + l2_pgentry_t sl2e, *sl2e_p; 3.19 l1_pgentry_t sl1e; 3.20 unsigned long mfn, smfn; 3.21 struct page_info *page; 3.22 @@ -3773,37 +3774,47 @@ int shadow_direct_map_fault(unsigned lon 3.23 3.24 shadow_lock(d); 3.25 3.26 - __shadow_get_l3e(v, vpa, &sl3e); 3.27 + __direct_get_l3e(v, vpa, &sl3e); 3.28 3.29 if ( !(l3e_get_flags(sl3e) & _PAGE_PRESENT) ) 3.30 { 3.31 page = alloc_domheap_page(NULL); 3.32 if ( !page ) 3.33 - goto fail; 3.34 + goto nomem; 3.35 + 3.36 smfn = page_to_mfn(page); 3.37 sl3e = l3e_from_pfn(smfn, _PAGE_PRESENT); 3.38 - __shadow_set_l3e(v, vpa, &sl3e); 3.39 + 3.40 + sl3e_p = (l3_pgentry_t *)map_domain_page(smfn); 3.41 + memset(sl3e_p, 0, PAGE_SIZE); 3.42 + unmap_domain_page(sl3e_p); 3.43 + 3.44 + __direct_set_l3e(v, vpa, &sl3e); 3.45 } 3.46 3.47 - __shadow_get_l2e(v, vpa, &sl2e); 3.48 + __direct_get_l2e(v, vpa, &sl2e); 3.49 3.50 if ( !(l2e_get_flags(sl2e) & _PAGE_PRESENT) ) 3.51 { 3.52 page = alloc_domheap_page(NULL); 3.53 if ( !page ) 3.54 - goto fail; 3.55 + goto nomem; 3.56 + 3.57 smfn = page_to_mfn(page); 3.58 - 3.59 sl2e = l2e_from_pfn(smfn, __PAGE_HYPERVISOR | _PAGE_USER); 3.60 - __shadow_set_l2e(v, vpa, &sl2e); 3.61 + sl2e_p = (l2_pgentry_t *)map_domain_page(smfn); 3.62 + memset(sl2e_p, 0, PAGE_SIZE); 3.63 + unmap_domain_page(sl2e_p); 3.64 + 3.65 + __direct_set_l2e(v, vpa, &sl2e); 3.66 } 3.67 3.68 - __shadow_get_l1e(v, vpa, &sl1e); 3.69 + __direct_get_l1e(v, vpa, &sl1e); 3.70 3.71 if ( !(l1e_get_flags(sl1e) & _PAGE_PRESENT) ) 3.72 { 3.73 sl1e = l1e_from_pfn(mfn, __PAGE_HYPERVISOR | _PAGE_USER); 3.74 - __shadow_set_l1e(v, vpa, &sl1e); 3.75 + __direct_set_l1e(v, vpa, &sl1e); 3.76 } 3.77 3.78 shadow_unlock(d); 3.79 @@ -3811,6 +3822,10 @@ int shadow_direct_map_fault(unsigned lon 3.80 3.81 fail: 3.82 return 0; 3.83 + 3.84 +nomem: 3.85 + shadow_direct_map_clean(v); 3.86 + domain_crash_synchronous(); 3.87 } 3.88 #endif 3.89
4.1 --- a/xen/arch/x86/shadow32.c Thu Feb 16 16:35:09 2006 +0100 4.2 +++ b/xen/arch/x86/shadow32.c Thu Feb 16 16:46:21 2006 +0100 4.3 @@ -807,21 +807,99 @@ void free_monitor_pagetable(struct vcpu 4.4 v->arch.monitor_vtable = 0; 4.5 } 4.6 4.7 +static int 4.8 +map_p2m_entry( 4.9 + l1_pgentry_t *l1tab, unsigned long va, unsigned long gpa, unsigned long mfn) 4.10 +{ 4.11 + unsigned long *l0tab = NULL; 4.12 + l1_pgentry_t l1e = { 0 }; 4.13 + struct page_info *page; 4.14 + 4.15 + l1e = l1tab[l1_table_offset(va)]; 4.16 + if ( !(l1e_get_flags(l1e) & _PAGE_PRESENT) ) 4.17 + { 4.18 + page = alloc_domheap_page(NULL); 4.19 + if ( !page ) 4.20 + goto fail; 4.21 + 4.22 + if ( l0tab ) 4.23 + unmap_domain_page(l0tab); 4.24 + l0tab = map_domain_page(page_to_mfn(page)); 4.25 + memset(l0tab, 0, PAGE_SIZE ); 4.26 + l1e = l1tab[l1_table_offset(va)] = 4.27 + l1e_from_page(page, __PAGE_HYPERVISOR); 4.28 + } 4.29 + else if ( l0tab == NULL) 4.30 + l0tab = map_domain_page(l1e_get_pfn(l1e)); 4.31 + 4.32 + l0tab[gpa & ((PAGE_SIZE / sizeof (mfn)) - 1) ] = mfn; 4.33 + 4.34 + if ( l0tab ) 4.35 + unmap_domain_page(l0tab); 4.36 + 4.37 + return 1; 4.38 + 4.39 +fail: 4.40 + return 0; 4.41 +} 4.42 + 4.43 int 4.44 set_p2m_entry(struct domain *d, unsigned long pfn, unsigned long mfn, 4.45 struct domain_mmap_cache *l2cache, 4.46 struct domain_mmap_cache *l1cache) 4.47 { 4.48 - unsigned long tabpfn = pagetable_get_pfn(d->arch.phys_table); 4.49 + unsigned long tabpfn; 4.50 l2_pgentry_t *l2, l2e; 4.51 l1_pgentry_t *l1; 4.52 struct page_info *l1page; 4.53 unsigned long va = pfn << PAGE_SHIFT; 4.54 + int error; 4.55 + 4.56 + if ( shadow_mode_external(d) ) 4.57 + { 4.58 + tabpfn = pagetable_get_pfn(d->vcpu[0]->arch.monitor_table); 4.59 + va = RO_MPT_VIRT_START + (pfn * sizeof (unsigned long)); 4.60 + } 4.61 + else 4.62 + { 4.63 + tabpfn = pagetable_get_pfn(d->arch.phys_table); 4.64 + va = pfn << PAGE_SHIFT; 4.65 + } 4.66 4.67 ASSERT(tabpfn != 0); 4.68 ASSERT(shadow_lock_is_acquired(d)); 4.69 4.70 l2 = map_domain_page_with_cache(tabpfn, l2cache); 4.71 + 4.72 + /* 4.73 + * The following code covers (SHM_translate | SHM_external) mode. 4.74 + */ 4.75 + 4.76 + if ( shadow_mode_external(d) ) 4.77 + { 4.78 + l1_pgentry_t *l1tab = NULL; 4.79 + l2_pgentry_t l2e; 4.80 + 4.81 + l2e = l2[l2_table_offset(va)]; 4.82 + 4.83 + ASSERT( l2e_get_flags(l2e) & _PAGE_PRESENT ); 4.84 + 4.85 + l1tab = map_domain_page(l2e_get_pfn(l2e)); 4.86 + error = map_p2m_entry(l1tab, va, pfn, mfn); 4.87 + if ( !error ) 4.88 + domain_crash_synchronous(); 4.89 + 4.90 + unmap_domain_page(l1tab); 4.91 + unmap_domain_page_with_cache(l2, l2cache); 4.92 + 4.93 + return 1; 4.94 + } 4.95 + 4.96 + /* 4.97 + * The following code covers SHM_translate mode. 4.98 + */ 4.99 + ASSERT(shadow_mode_translate(d)); 4.100 + 4.101 l2e = l2[l2_table_offset(va)]; 4.102 if ( !(l2e_get_flags(l2e) & _PAGE_PRESENT) ) 4.103 { 4.104 @@ -856,13 +934,10 @@ alloc_p2m_table(struct domain *d) 4.105 4.106 l2_pgentry_t *l2tab = NULL; 4.107 l1_pgentry_t *l1tab = NULL; 4.108 - unsigned long *l0tab = NULL; 4.109 l2_pgentry_t l2e = { 0 }; 4.110 - l1_pgentry_t l1e = { 0 }; 4.111 - 4.112 struct page_info *page; 4.113 - unsigned long pfn; 4.114 - int i; 4.115 + unsigned long gpfn, mfn; 4.116 + int error; 4.117 4.118 if ( pagetable_get_pfn(d->vcpu[0]->arch.monitor_table) ) 4.119 { 4.120 @@ -892,34 +967,22 @@ alloc_p2m_table(struct domain *d) 4.121 4.122 list_ent = d->page_list.next; 4.123 4.124 - for ( i = 0; list_ent != &d->page_list; i++ ) 4.125 + for ( gpfn = 0; list_ent != &d->page_list; gpfn++ ) 4.126 { 4.127 page = list_entry(list_ent, struct page_info, list); 4.128 - pfn = page_to_mfn(page); 4.129 - 4.130 - l1e = l1tab[l1_table_offset(va)]; 4.131 - if ( !(l1e_get_flags(l1e) & _PAGE_PRESENT) ) 4.132 - { 4.133 - page = alloc_domheap_page(NULL); 4.134 - if ( l0tab ) 4.135 - unmap_domain_page(l0tab); 4.136 - l0tab = map_domain_page(page_to_mfn(page)); 4.137 - memset(l0tab, 0, PAGE_SIZE ); 4.138 - l1e = l1tab[l1_table_offset(va)] = 4.139 - l1e_from_page(page, __PAGE_HYPERVISOR); 4.140 - } 4.141 - else if ( l0tab == NULL) 4.142 - l0tab = map_domain_page(l1e_get_pfn(l1e)); 4.143 - 4.144 - l0tab[i & ((1 << PAGETABLE_ORDER) - 1) ] = pfn; 4.145 - list_ent = frame_table[pfn].list.next; 4.146 - va += sizeof(pfn); 4.147 + mfn = page_to_mfn(page); 4.148 + 4.149 + error = map_p2m_entry(l1tab, va, gpfn, mfn); 4.150 + if ( !error ) 4.151 + domain_crash_synchronous(); 4.152 + 4.153 + list_ent = frame_table[mfn].list.next; 4.154 + va += sizeof(mfn); 4.155 } 4.156 4.157 if (l2tab) 4.158 unmap_domain_page(l2tab); 4.159 unmap_domain_page(l1tab); 4.160 - unmap_domain_page(l0tab); 4.161 4.162 return 1; 4.163 } 4.164 @@ -981,21 +1044,26 @@ int shadow_direct_map_fault(unsigned lon 4.165 } 4.166 4.167 shadow_lock(d); 4.168 - 4.169 - __shadow_get_l2e(v, vpa, &sl2e); 4.170 - 4.171 - if ( !(l2e_get_flags(sl2e) & _PAGE_PRESENT) ) 4.172 + 4.173 + __direct_get_l2e(v, vpa, &sl2e); 4.174 + 4.175 + if ( !(l2e_get_flags(sl2e) & _PAGE_PRESENT) ) 4.176 { 4.177 page = alloc_domheap_page(NULL); 4.178 if ( !page ) 4.179 - goto fail; 4.180 + goto nomem; 4.181 4.182 smfn = page_to_mfn(page); 4.183 sl2e = l2e_from_pfn(smfn, __PAGE_HYPERVISOR | _PAGE_USER); 4.184 - __shadow_set_l2e(v, vpa, sl2e); 4.185 - } 4.186 - 4.187 - sple = (l1_pgentry_t *)map_domain_page(l2e_get_pfn(sl2e)); 4.188 + 4.189 + sple = (l1_pgentry_t *)map_domain_page(smfn); 4.190 + memset(sple, 0, PAGE_SIZE); 4.191 + __direct_set_l2e(v, vpa, sl2e); 4.192 + } 4.193 + 4.194 + if ( !sple ) 4.195 + sple = (l1_pgentry_t *)map_domain_page(l2e_get_pfn(sl2e)); 4.196 + 4.197 sl1e = sple[l1_table_offset(vpa)]; 4.198 4.199 if ( !(l1e_get_flags(sl1e) & _PAGE_PRESENT) ) 4.200 @@ -1003,13 +1071,19 @@ int shadow_direct_map_fault(unsigned lon 4.201 sl1e = l1e_from_pfn(mfn, __PAGE_HYPERVISOR | _PAGE_USER); 4.202 sple[l1_table_offset(vpa)] = sl1e; 4.203 } 4.204 - unmap_domain_page(sple); 4.205 + 4.206 + if (sple) 4.207 + unmap_domain_page(sple); 4.208 + 4.209 shadow_unlock(d); 4.210 - 4.211 return EXCRET_fault_fixed; 4.212 4.213 fail: 4.214 return 0; 4.215 + 4.216 +nomem: 4.217 + shadow_direct_map_clean(v); 4.218 + domain_crash_synchronous(); 4.219 } 4.220 4.221 4.222 @@ -1021,16 +1095,12 @@ int shadow_direct_map_init(struct vcpu * 4.223 if ( !(page = alloc_domheap_page(NULL)) ) 4.224 goto fail; 4.225 4.226 - root = map_domain_page_global(page_to_mfn(page)); 4.227 + root = map_domain_page(page_to_mfn(page)); 4.228 memset(root, 0, PAGE_SIZE); 4.229 + unmap_domain_page(root); 4.230 4.231 v->domain->arch.phys_table = mk_pagetable(page_to_maddr(page)); 4.232 - /* 4.233 - * We need to set shadow_vtable to get __shadow_set/get_xxx 4.234 - * working 4.235 - */ 4.236 - v->arch.shadow_vtable = (l2_pgentry_t *) root; 4.237 - v->arch.shadow_table = mk_pagetable(0); 4.238 + 4.239 return 1; 4.240 4.241 fail: 4.242 @@ -1042,9 +1112,8 @@ void shadow_direct_map_clean(struct vcpu 4.243 int i; 4.244 l2_pgentry_t *l2e; 4.245 4.246 - ASSERT ( v->arch.shadow_vtable ); 4.247 - 4.248 - l2e = v->arch.shadow_vtable; 4.249 + l2e = map_domain_page( 4.250 + pagetable_get_pfn(v->domain->arch.phys_table)); 4.251 4.252 for ( i = 0; i < L2_PAGETABLE_ENTRIES; i++ ) 4.253 { 4.254 @@ -1055,8 +1124,7 @@ void shadow_direct_map_clean(struct vcpu 4.255 free_domheap_page( 4.256 mfn_to_page(pagetable_get_pfn(v->domain->arch.phys_table))); 4.257 4.258 - unmap_domain_page_global(v->arch.shadow_vtable); 4.259 - v->arch.shadow_vtable = 0; 4.260 + unmap_domain_page(l2e); 4.261 v->domain->arch.phys_table = mk_pagetable(0); 4.262 } 4.263 4.264 @@ -1169,13 +1237,6 @@ int __shadow_mode_enable(struct domain * 4.265 goto nomem; 4.266 } 4.267 } 4.268 - else 4.269 - { 4.270 - // external guests provide their own memory for their P2M maps. 4.271 - // 4.272 - ASSERT(d == page_get_owner(mfn_to_page(pagetable_get_pfn( 4.273 - d->arch.phys_table)))); 4.274 - } 4.275 } 4.276 4.277 // Get rid of any shadow pages from any previous shadow mode.
5.1 --- a/xen/arch/x86/shadow_public.c Thu Feb 16 16:35:09 2006 +0100 5.2 +++ b/xen/arch/x86/shadow_public.c Thu Feb 16 16:46:21 2006 +0100 5.3 @@ -44,33 +44,28 @@ int shadow_direct_map_init(struct vcpu * 5.4 if ( !(page = alloc_domheap_pages(NULL, 0, ALLOC_DOM_DMA)) ) 5.5 goto fail; 5.6 5.7 - root = map_domain_page_global(page_to_mfn(page)); 5.8 + root = map_domain_page(page_to_mfn(page)); 5.9 memset(root, 0, PAGE_SIZE); 5.10 root[PAE_SHADOW_SELF_ENTRY] = l3e_from_page(page, __PAGE_HYPERVISOR); 5.11 5.12 v->domain->arch.phys_table = mk_pagetable(page_to_maddr(page)); 5.13 - /* 5.14 - * We need to set shadow_vtable to get __shadow_set/get_xxx 5.15 - * working 5.16 - */ 5.17 - v->arch.shadow_vtable = (l2_pgentry_t *) root; 5.18 5.19 + unmap_domain_page(root); 5.20 return 1; 5.21 - 5.22 + 5.23 fail: 5.24 return 0; 5.25 } 5.26 5.27 -static void shadow_direct_map_clean(struct vcpu *v) 5.28 +void shadow_direct_map_clean(struct vcpu *v) 5.29 { 5.30 l2_pgentry_t *l2e; 5.31 l3_pgentry_t *l3e; 5.32 int i, j; 5.33 5.34 - ASSERT ( v->arch.shadow_vtable ); 5.35 + l3e = (l3_pgentry_t *)map_domain_page( 5.36 + pagetable_get_pfn(v->domain->arch.phys_table)); 5.37 5.38 - l3e = (l3_pgentry_t *) v->arch.shadow_vtable; 5.39 - 5.40 for ( i = 0; i < PAE_L3_PAGETABLE_ENTRIES; i++ ) 5.41 { 5.42 if ( l3e_get_flags(l3e[i]) & _PAGE_PRESENT ) 5.43 @@ -90,8 +85,7 @@ static void shadow_direct_map_clean(stru 5.44 free_domheap_page( 5.45 mfn_to_page(pagetable_get_pfn(v->domain->arch.phys_table))); 5.46 5.47 - unmap_domain_page_global(v->arch.shadow_vtable); 5.48 - v->arch.shadow_vtable = 0; 5.49 + unmap_domain_page(l3e); 5.50 v->domain->arch.phys_table = mk_pagetable(0); 5.51 } 5.52 5.53 @@ -102,13 +96,8 @@ static void shadow_direct_map_clean(stru 5.54 5.55 int shadow_set_guest_paging_levels(struct domain *d, int levels) 5.56 { 5.57 - struct vcpu *v = current; 5.58 shadow_lock(d); 5.59 5.60 - if ( shadow_mode_translate(d) && 5.61 - !(pagetable_get_paddr(v->domain->arch.phys_table)) ) 5.62 - shadow_direct_map_clean(v); 5.63 - 5.64 switch(levels) { 5.65 #if CONFIG_PAGING_LEVELS == 4 5.66 case 4: 5.67 @@ -1330,43 +1319,133 @@ int _shadow_mode_refcounts(struct domain 5.68 return shadow_mode_refcounts(d); 5.69 } 5.70 5.71 +static int 5.72 +map_p2m_entry( 5.73 + pgentry_64_t *top_tab, unsigned long va, unsigned long gpa, unsigned long mfn) 5.74 +{ 5.75 +#if CONFIG_PAGING_LEVELS >= 4 5.76 + pgentry_64_t l4e = { 0 }; 5.77 +#endif 5.78 +#if CONFIG_PAGING_LEVELS >= 3 5.79 + pgentry_64_t *l3tab = NULL; 5.80 + pgentry_64_t l3e = { 0 }; 5.81 +#endif 5.82 + l2_pgentry_t *l2tab = NULL; 5.83 + l1_pgentry_t *l1tab = NULL; 5.84 + unsigned long *l0tab = NULL; 5.85 + l2_pgentry_t l2e = { 0 }; 5.86 + l1_pgentry_t l1e = { 0 }; 5.87 + struct page_info *page; 5.88 + 5.89 +#if CONFIG_PAGING_LEVELS >= 4 5.90 + l4e = top_tab[l4_table_offset(va)]; 5.91 + if ( !(entry_get_flags(l4e) & _PAGE_PRESENT) ) 5.92 + { 5.93 + page = alloc_domheap_page(NULL); 5.94 + if ( !page ) 5.95 + goto nomem; 5.96 + 5.97 + l3tab = map_domain_page(page_to_mfn(page)); 5.98 + memset(l3tab, 0, PAGE_SIZE); 5.99 + l4e = top_tab[l4_table_offset(va)] = 5.100 + entry_from_page(page, __PAGE_HYPERVISOR); 5.101 + } 5.102 + else if ( l3tab == NULL) 5.103 + l3tab = map_domain_page(entry_get_pfn(l4e)); 5.104 + 5.105 + l3e = l3tab[l3_table_offset(va)]; 5.106 +#else 5.107 + l3e = top_tab[l3_table_offset(va)]; 5.108 +#endif 5.109 + if ( !(entry_get_flags(l3e) & _PAGE_PRESENT) ) 5.110 + { 5.111 + page = alloc_domheap_page(NULL); 5.112 + if ( !page ) 5.113 + goto nomem; 5.114 + 5.115 + l2tab = map_domain_page(page_to_mfn(page)); 5.116 + memset(l2tab, 0, PAGE_SIZE); 5.117 + l3e = l3tab[l3_table_offset(va)] = 5.118 + entry_from_page(page, __PAGE_HYPERVISOR); 5.119 + } 5.120 + else if ( l2tab == NULL) 5.121 + l2tab = map_domain_page(entry_get_pfn(l3e)); 5.122 + 5.123 + l2e = l2tab[l2_table_offset(va)]; 5.124 + if ( !(l2e_get_flags(l2e) & _PAGE_PRESENT) ) 5.125 + { 5.126 + page = alloc_domheap_page(NULL); 5.127 + if ( !page ) 5.128 + goto nomem; 5.129 + 5.130 + l1tab = map_domain_page(page_to_mfn(page)); 5.131 + memset(l1tab, 0, PAGE_SIZE); 5.132 + l2e = l2tab[l2_table_offset(va)] = 5.133 + l2e_from_page(page, __PAGE_HYPERVISOR); 5.134 + } 5.135 + else if ( l1tab == NULL) 5.136 + l1tab = map_domain_page(l2e_get_pfn(l2e)); 5.137 + 5.138 + l1e = l1tab[l1_table_offset(va)]; 5.139 + if ( !(l1e_get_flags(l1e) & _PAGE_PRESENT) ) 5.140 + { 5.141 + page = alloc_domheap_page(NULL); 5.142 + if ( !page ) 5.143 + goto nomem; 5.144 + 5.145 + l0tab = map_domain_page(page_to_mfn(page)); 5.146 + memset(l0tab, 0, PAGE_SIZE); 5.147 + l1e = l1tab[l1_table_offset(va)] = 5.148 + l1e_from_page(page, __PAGE_HYPERVISOR); 5.149 + } 5.150 + else if ( l0tab == NULL) 5.151 + l0tab = map_domain_page(l1e_get_pfn(l1e)); 5.152 + 5.153 + l0tab[gpa & ((PAGE_SIZE / sizeof (mfn)) - 1) ] = mfn; 5.154 + 5.155 + if ( l2tab ) 5.156 + { 5.157 + unmap_domain_page(l2tab); 5.158 + l2tab = NULL; 5.159 + } 5.160 + if ( l1tab ) 5.161 + { 5.162 + unmap_domain_page(l1tab); 5.163 + l1tab = NULL; 5.164 + } 5.165 + if ( l0tab ) 5.166 + { 5.167 + unmap_domain_page(l0tab); 5.168 + l0tab = NULL; 5.169 + } 5.170 + 5.171 + return 1; 5.172 + 5.173 +nomem: 5.174 + 5.175 + return 0; 5.176 +} 5.177 + 5.178 int 5.179 set_p2m_entry(struct domain *d, unsigned long pfn, unsigned long mfn, 5.180 struct domain_mmap_cache *l2cache, 5.181 struct domain_mmap_cache *l1cache) 5.182 { 5.183 - unsigned long tabpfn = pagetable_get_pfn(d->arch.phys_table); 5.184 - l2_pgentry_t *l2, l2e; 5.185 - l1_pgentry_t *l1; 5.186 - struct page_info *l1page; 5.187 - unsigned long va = pfn << PAGE_SHIFT; 5.188 + unsigned long tabpfn = pagetable_get_pfn(d->vcpu[0]->arch.monitor_table); 5.189 + pgentry_64_t *top; 5.190 + unsigned long va = RO_MPT_VIRT_START + (pfn * sizeof (unsigned long)); 5.191 + int error; 5.192 5.193 ASSERT(tabpfn != 0); 5.194 - 5.195 - l2 = map_domain_page_with_cache(tabpfn, l2cache); 5.196 - l2e = l2[l2_table_offset(va)]; 5.197 - if ( !(l2e_get_flags(l2e) & _PAGE_PRESENT) ) 5.198 - { 5.199 - l1page = alloc_domheap_page(NULL); 5.200 - if ( !l1page ) 5.201 - { 5.202 - unmap_domain_page_with_cache(l2, l2cache); 5.203 - return 0; 5.204 - } 5.205 + ASSERT(shadow_lock_is_acquired(d)); 5.206 5.207 - l1 = map_domain_page_with_cache(page_to_mfn(l1page), l1cache); 5.208 - memset(l1, 0, PAGE_SIZE); 5.209 - unmap_domain_page_with_cache(l1, l1cache); 5.210 + top = map_domain_page_with_cache(tabpfn, l2cache); 5.211 + error = map_p2m_entry(top, va, pfn, mfn); 5.212 + unmap_domain_page_with_cache(top, l2cache); 5.213 5.214 - l2e = l2e_from_page(l1page, __PAGE_HYPERVISOR); 5.215 - l2[l2_table_offset(va)] = l2e; 5.216 - } 5.217 - unmap_domain_page_with_cache(l2, l2cache); 5.218 - 5.219 - l1 = map_domain_page_with_cache(l2e_get_pfn(l2e), l1cache); 5.220 - l1[l1_table_offset(va)] = l1e_from_pfn(mfn, __PAGE_HYPERVISOR); 5.221 - unmap_domain_page_with_cache(l1, l1cache); 5.222 - 5.223 + if ( !error ) 5.224 + domain_crash_synchronous(); 5.225 + 5.226 return 1; 5.227 } 5.228 5.229 @@ -1375,119 +1454,31 @@ alloc_p2m_table(struct domain *d) 5.230 { 5.231 struct list_head *list_ent; 5.232 unsigned long va = RO_MPT_VIRT_START; /* phys_to_machine_mapping */ 5.233 - 5.234 -#if CONFIG_PAGING_LEVELS >= 4 5.235 - l4_pgentry_t *l4tab = NULL; 5.236 - l4_pgentry_t l4e = { 0 }; 5.237 -#endif 5.238 -#if CONFIG_PAGING_LEVELS >= 3 5.239 - l3_pgentry_t *l3tab = NULL; 5.240 - l3_pgentry_t l3e = { 0 }; 5.241 -#endif 5.242 - l2_pgentry_t *l2tab = NULL; 5.243 - l1_pgentry_t *l1tab = NULL; 5.244 - unsigned long *l0tab = NULL; 5.245 - l2_pgentry_t l2e = { 0 }; 5.246 - l1_pgentry_t l1e = { 0 }; 5.247 - 5.248 - unsigned long pfn; 5.249 - int i; 5.250 + pgentry_64_t *top_tab = NULL; 5.251 + unsigned long mfn; 5.252 + int gpa; 5.253 5.254 ASSERT ( pagetable_get_pfn(d->vcpu[0]->arch.monitor_table) ); 5.255 5.256 -#if CONFIG_PAGING_LEVELS >= 4 5.257 - l4tab = map_domain_page( 5.258 + top_tab = map_domain_page( 5.259 pagetable_get_pfn(d->vcpu[0]->arch.monitor_table)); 5.260 -#endif 5.261 -#if CONFIG_PAGING_LEVELS >= 3 5.262 - l3tab = map_domain_page( 5.263 - pagetable_get_pfn(d->vcpu[0]->arch.monitor_table)); 5.264 -#endif 5.265 + 5.266 5.267 list_ent = d->page_list.next; 5.268 5.269 - for ( i = 0; list_ent != &d->page_list; i++ ) 5.270 + for ( gpa = 0; list_ent != &d->page_list; gpa++ ) 5.271 { 5.272 struct page_info *page; 5.273 - 5.274 page = list_entry(list_ent, struct page_info, list); 5.275 - pfn = page_to_mfn(page); 5.276 - 5.277 -#if CONFIG_PAGING_LEVELS >= 4 5.278 - l4e = l4tab[l4_table_offset(va)]; 5.279 - if ( !(l4e_get_flags(l4e) & _PAGE_PRESENT) ) 5.280 - { 5.281 - page = alloc_domheap_page(NULL); 5.282 - l3tab = map_domain_page(page_to_mfn(page)); 5.283 - memset(l3tab, 0, PAGE_SIZE); 5.284 - l4e = l4tab[l4_table_offset(va)] = 5.285 - l4e_from_page(page, __PAGE_HYPERVISOR); 5.286 - } 5.287 - else if ( l3tab == NULL) 5.288 - l3tab = map_domain_page(l4e_get_pfn(l4e)); 5.289 -#endif 5.290 - l3e = l3tab[l3_table_offset(va)]; 5.291 - if ( !(l3e_get_flags(l3e) & _PAGE_PRESENT) ) 5.292 - { 5.293 - page = alloc_domheap_page(NULL); 5.294 - l2tab = map_domain_page(page_to_mfn(page)); 5.295 - memset(l2tab, 0, PAGE_SIZE); 5.296 - l3e = l3tab[l3_table_offset(va)] = 5.297 - l3e_from_page(page, __PAGE_HYPERVISOR); 5.298 - } 5.299 - else if ( l2tab == NULL) 5.300 - l2tab = map_domain_page(l3e_get_pfn(l3e)); 5.301 + mfn = page_to_mfn(page); 5.302 5.303 - l2e = l2tab[l2_table_offset(va)]; 5.304 - if ( !(l2e_get_flags(l2e) & _PAGE_PRESENT) ) 5.305 - { 5.306 - page = alloc_domheap_page(NULL); 5.307 - l1tab = map_domain_page(page_to_mfn(page)); 5.308 - memset(l1tab, 0, PAGE_SIZE); 5.309 - l2e = l2tab[l2_table_offset(va)] = 5.310 - l2e_from_page(page, __PAGE_HYPERVISOR); 5.311 - } 5.312 - else if ( l1tab == NULL) 5.313 - l1tab = map_domain_page(l2e_get_pfn(l2e)); 5.314 - 5.315 - l1e = l1tab[l1_table_offset(va)]; 5.316 - if ( !(l1e_get_flags(l1e) & _PAGE_PRESENT) ) 5.317 - { 5.318 - page = alloc_domheap_page(NULL); 5.319 - l0tab = map_domain_page(page_to_mfn(page)); 5.320 - memset(l0tab, 0, PAGE_SIZE); 5.321 - l1e = l1tab[l1_table_offset(va)] = 5.322 - l1e_from_page(page, __PAGE_HYPERVISOR); 5.323 - } 5.324 - else if ( l0tab == NULL) 5.325 - l0tab = map_domain_page(l1e_get_pfn(l1e)); 5.326 + map_p2m_entry(top_tab, va, gpa, mfn); 5.327 + list_ent = frame_table[mfn].list.next; 5.328 + va += sizeof(mfn); 5.329 + } 5.330 5.331 - l0tab[i & ((PAGE_SIZE / sizeof (pfn)) - 1) ] = pfn; 5.332 - list_ent = frame_table[pfn].list.next; 5.333 - va += sizeof (pfn); 5.334 + unmap_domain_page(top_tab); 5.335 5.336 - if ( l2tab ) 5.337 - { 5.338 - unmap_domain_page(l2tab); 5.339 - l2tab = NULL; 5.340 - } 5.341 - if ( l1tab ) 5.342 - { 5.343 - unmap_domain_page(l1tab); 5.344 - l1tab = NULL; 5.345 - } 5.346 - if ( l0tab ) 5.347 - { 5.348 - unmap_domain_page(l0tab); 5.349 - l0tab = NULL; 5.350 - } 5.351 - } 5.352 -#if CONFIG_PAGING_LEVELS >= 4 5.353 - unmap_domain_page(l4tab); 5.354 -#endif 5.355 -#if CONFIG_PAGING_LEVELS >= 3 5.356 - unmap_domain_page(l3tab); 5.357 -#endif 5.358 return 1; 5.359 } 5.360
6.1 --- a/xen/include/asm-x86/shadow.h Thu Feb 16 16:35:09 2006 +0100 6.2 +++ b/xen/include/asm-x86/shadow.h Thu Feb 16 16:46:21 2006 +0100 6.3 @@ -115,9 +115,7 @@ do { 6.4 #define SHADOW_ENCODE_MIN_MAX(_min, _max) ((((GUEST_L1_PAGETABLE_ENTRIES - 1) - (_max)) << 16) | (_min)) 6.5 #define SHADOW_MIN(_encoded) ((_encoded) & ((1u<<16) - 1)) 6.6 #define SHADOW_MAX(_encoded) ((GUEST_L1_PAGETABLE_ENTRIES - 1) - ((_encoded) >> 16)) 6.7 -#if CONFIG_PAGING_LEVELS == 2 6.8 extern void shadow_direct_map_clean(struct vcpu *v); 6.9 -#endif 6.10 extern int shadow_direct_map_init(struct vcpu *v); 6.11 extern int shadow_direct_map_fault( 6.12 unsigned long vpa, struct cpu_user_regs *regs); 6.13 @@ -559,6 +557,38 @@ static inline void 6.14 } 6.15 6.16 static inline void 6.17 +__direct_get_l2e( 6.18 + struct vcpu *v, unsigned long va, l2_pgentry_t *psl2e) 6.19 +{ 6.20 + l2_pgentry_t *phys_vtable; 6.21 + 6.22 + ASSERT(shadow_mode_enabled(v->domain)); 6.23 + 6.24 + phys_vtable = map_domain_page( 6.25 + pagetable_get_pfn(v->domain->arch.phys_table)); 6.26 + 6.27 + *psl2e = phys_vtable[l2_table_offset(va)]; 6.28 + 6.29 + unmap_domain_page(phys_vtable); 6.30 +} 6.31 + 6.32 +static inline void 6.33 +__direct_set_l2e( 6.34 + struct vcpu *v, unsigned long va, l2_pgentry_t value) 6.35 +{ 6.36 + l2_pgentry_t *phys_vtable; 6.37 + 6.38 + ASSERT(shadow_mode_enabled(v->domain)); 6.39 + 6.40 + phys_vtable = map_domain_page( 6.41 + pagetable_get_pfn(v->domain->arch.phys_table)); 6.42 + 6.43 + phys_vtable[l2_table_offset(va)] = value; 6.44 + 6.45 + unmap_domain_page(phys_vtable); 6.46 +} 6.47 + 6.48 +static inline void 6.49 update_hl2e(struct vcpu *v, unsigned long va) 6.50 { 6.51 int index = l2_table_offset(va);
7.1 --- a/xen/include/asm-x86/shadow_64.h Thu Feb 16 16:35:09 2006 +0100 7.2 +++ b/xen/include/asm-x86/shadow_64.h Thu Feb 16 16:46:21 2006 +0100 7.3 @@ -66,9 +66,12 @@ typedef struct { intpte_t l4; } l4_pgent 7.4 #define PAGING_L1 1UL 7.5 #define L_MASK 0xff 7.6 7.7 +#define PAE_PAGING_LEVELS 3 7.8 + 7.9 #define ROOT_LEVEL_64 PAGING_L4 7.10 #define ROOT_LEVEL_32 PAGING_L2 7.11 7.12 +#define DIRECT_ENTRY (4UL << 16) 7.13 #define SHADOW_ENTRY (2UL << 16) 7.14 #define GUEST_ENTRY (1UL << 16) 7.15 7.16 @@ -94,6 +97,7 @@ typedef struct { intpte_t lo; } pgentry_ 7.17 #define entry_empty() ((pgentry_64_t) { 0 }) 7.18 #define entry_from_pfn(pfn, flags) \ 7.19 ((pgentry_64_t) { ((intpte_t)(pfn) << PAGE_SHIFT) | put_pte_flags(flags) }) 7.20 +#define entry_from_page(page, flags) (entry_from_pfn(page_to_mfn(page),(flags))) 7.21 #define entry_add_flags(x, flags) ((x).lo |= put_pte_flags(flags)) 7.22 #define entry_remove_flags(x, flags) ((x).lo &= ~put_pte_flags(flags)) 7.23 #define entry_has_changed(x,y,flags) \ 7.24 @@ -162,16 +166,24 @@ static inline int __entry( 7.25 7.26 if ( flag & SHADOW_ENTRY ) 7.27 { 7.28 - root_level = ROOT_LEVEL_64; 7.29 - index = table_offset_64(va, root_level); 7.30 + root_level = ROOT_LEVEL_64; 7.31 + index = table_offset_64(va, root_level); 7.32 le_e = (pgentry_64_t *)&v->arch.shadow_vtable[index]; 7.33 } 7.34 - else /* guest entry */ 7.35 + else if ( flag & GUEST_ENTRY ) 7.36 { 7.37 root_level = v->domain->arch.ops->guest_paging_levels; 7.38 - index = table_offset_64(va, root_level); 7.39 + index = table_offset_64(va, root_level); 7.40 le_e = (pgentry_64_t *)&v->arch.guest_vtable[index]; 7.41 } 7.42 + else /* direct mode */ 7.43 + { 7.44 + root_level = PAE_PAGING_LEVELS; 7.45 + index = table_offset_64(va, root_level); 7.46 + le_e = (pgentry_64_t *)map_domain_page( 7.47 + pagetable_get_pfn(v->domain->arch.phys_table)); 7.48 + } 7.49 + 7.50 /* 7.51 * If it's not external mode, then mfn should be machine physical. 7.52 */ 7.53 @@ -241,6 +253,20 @@ static inline int __rw_entry( 7.54 #define __guest_get_l3e(v, va, sl3e) \ 7.55 __rw_entry(v, va, gl3e, GUEST_ENTRY | GET_ENTRY | PAGING_L3) 7.56 7.57 +#define __direct_set_l3e(v, va, value) \ 7.58 + __rw_entry(v, va, value, DIRECT_ENTRY | SET_ENTRY | PAGING_L3) 7.59 +#define __direct_get_l3e(v, va, sl3e) \ 7.60 + __rw_entry(v, va, sl3e, DIRECT_ENTRY | GET_ENTRY | PAGING_L3) 7.61 +#define __direct_set_l2e(v, va, value) \ 7.62 + __rw_entry(v, va, value, DIRECT_ENTRY | SET_ENTRY | PAGING_L2) 7.63 +#define __direct_get_l2e(v, va, sl2e) \ 7.64 + __rw_entry(v, va, sl2e, DIRECT_ENTRY | GET_ENTRY | PAGING_L2) 7.65 +#define __direct_set_l1e(v, va, value) \ 7.66 + __rw_entry(v, va, value, DIRECT_ENTRY | SET_ENTRY | PAGING_L1) 7.67 +#define __direct_get_l1e(v, va, sl1e) \ 7.68 + __rw_entry(v, va, sl1e, DIRECT_ENTRY | GET_ENTRY | PAGING_L1) 7.69 + 7.70 + 7.71 static inline int __guest_set_l2e( 7.72 struct vcpu *v, unsigned long va, void *value, int size) 7.73 {