direct-io.hg
changeset 3815:5f7e800d87da
bitkeeper revision 1.1159.261.1 (420e14ceCymFrPEpDCTaPJueMUTvsg)
Improved check_pagetable checking.
Added check_all_pagetables as an alternative to check_pagetable().
Improved check_pagetable checking.
Added check_all_pagetables as an alternative to check_pagetable().
author | mafetter@fleming.research |
---|---|
date | Sat Feb 12 14:38:06 2005 +0000 (2005-02-12) |
parents | 7406a28a87bc |
children | 3f8766806bdd |
files | xen/arch/x86/shadow.c xen/include/asm-x86/shadow.h xen/include/xen/perfc_defn.h |
line diff
1.1 --- a/xen/arch/x86/shadow.c Tue Feb 08 17:49:09 2005 +0000 1.2 +++ b/xen/arch/x86/shadow.c Sat Feb 12 14:38:06 2005 +0000 1.3 @@ -758,10 +758,10 @@ void shadow_l2_normal_pt_update(unsigned 1.4 // BUG: these are not SMP safe... 1.5 static int sh_l2_present; 1.6 static int sh_l1_present; 1.7 -static int errors; 1.8 char * sh_check_name; 1.9 +int shadow_status_noswap; 1.10 1.11 -#define virt_to_phys2(adr) ({ \ 1.12 +#define v2m(adr) ({ \ 1.13 unsigned long _a = (unsigned long)(adr); \ 1.14 unsigned long _pte = l1_pgentry_val( \ 1.15 shadow_linear_pg_table[_a >> PAGE_SHIFT]); \ 1.16 @@ -771,23 +771,28 @@ char * sh_check_name; 1.17 1.18 #define FAIL(_f, _a...) \ 1.19 do { \ 1.20 - printk("XXX %s-FAIL (%d,%d)" _f " g=%p s=%p &g=%p &s=%p" \ 1.21 - " pa(&g)=%p pa(&s)=%p\n", \ 1.22 - sh_check_name, level, i, ## _a , gpte, spte, pgpte, pspte, \ 1.23 - virt_to_phys2(pgpte), virt_to_phys2(pspte)); \ 1.24 + printk("XXX %s-FAIL (%d,%d)" _f "\n" \ 1.25 + "g=%08lx s=%08lx &g=%08lx &s=%08lx" \ 1.26 + " v2m(&g)=%08lx v2m(&s)=%08lx ea=%08lx\n", \ 1.27 + sh_check_name, level, l1_idx, ## _a , \ 1.28 + gpte, spte, pgpte, pspte, \ 1.29 + v2m(pgpte), v2m(pspte), \ 1.30 + (l2_idx << L2_PAGETABLE_SHIFT) | \ 1.31 + (l1_idx << L1_PAGETABLE_SHIFT)); \ 1.32 errors++; \ 1.33 } while ( 0 ) 1.34 1.35 static int check_pte( 1.36 struct domain *d, unsigned long *pgpte, unsigned long *pspte, 1.37 - int level, int i) 1.38 + int level, int l2_idx, int l1_idx) 1.39 { 1.40 unsigned gpte = *pgpte; 1.41 unsigned spte = *pspte; 1.42 unsigned long mask, gpfn, smfn; 1.43 + int errors = 0; 1.44 1.45 if ( (spte == 0) || (spte == 0xdeadface) || (spte == 0x00000E00) ) 1.46 - return 1; /* always safe */ 1.47 + return errors; /* always safe */ 1.48 1.49 if ( !(spte & _PAGE_PRESENT) ) 1.50 FAIL("Non zero not present spte"); 1.51 @@ -833,72 +838,71 @@ static int check_pte( 1.52 __shadow_status(d, gpfn) ); 1.53 } 1.54 1.55 - return 1; 1.56 + return errors; 1.57 } 1.58 1.59 1.60 static int check_l1_table( 1.61 struct domain *d, 1.62 - unsigned long g2mfn, unsigned long s2mfn) 1.63 + unsigned long gmfn, unsigned long smfn, unsigned l2_idx) 1.64 { 1.65 int i; 1.66 unsigned long *gpl1e, *spl1e; 1.67 + int cpu = current->processor; 1.68 + int errors = 0; 1.69 1.70 - gpl1e = map_domain_mem(g2mfn << PAGE_SHIFT); 1.71 - spl1e = map_domain_mem(s2mfn << PAGE_SHIFT); 1.72 + // First check to see if this guest page is currently the active 1.73 + // PTWR page. If so, then we compare the (old) cached copy of the 1.74 + // guest page to the shadow, and not the currently writable (and 1.75 + // thus potentially out-of-sync) guest page. 1.76 + // 1.77 + if ( VM_ASSIST(d, VMASST_TYPE_writable_pagetables) ) 1.78 + { 1.79 + for ( i = 0; i < ARRAY_SIZE(ptwr_info->ptinfo); i++) 1.80 + { 1.81 + if ( ptwr_info[cpu].ptinfo[i].l1va && 1.82 + ((v2m(ptwr_info[cpu].ptinfo[i].pl1e) >> PAGE_SHIFT) == gmfn) ) 1.83 + { 1.84 + unsigned long old = gmfn; 1.85 + gmfn = (v2m(ptwr_info[cpu].ptinfo[i].page) >> PAGE_SHIFT); 1.86 + printk("hit1 ptwr_info[%d].ptinfo[%d].l1va, mfn=0x%08x, snapshot=0x%08x\n", 1.87 + cpu, i, old, gmfn); 1.88 + } 1.89 + } 1.90 + } 1.91 + 1.92 + gpl1e = map_domain_mem(gmfn << PAGE_SHIFT); 1.93 + spl1e = map_domain_mem(smfn << PAGE_SHIFT); 1.94 1.95 for ( i = 0; i < ENTRIES_PER_L1_PAGETABLE; i++ ) 1.96 - check_pte(d, &gpl1e[i], &spl1e[i], 1, i); 1.97 + errors += check_pte(d, &gpl1e[i], &spl1e[i], 1, l2_idx, i); 1.98 1.99 unmap_domain_mem(spl1e); 1.100 unmap_domain_mem(gpl1e); 1.101 1.102 - return 1; 1.103 + return errors; 1.104 } 1.105 1.106 -#define FAILPT(_f, _a...) \ 1.107 - do { \ 1.108 - printk("XXX FAIL %s-PT" _f "\n", s, ## _a ); \ 1.109 - errors++; \ 1.110 +#define FAILPT(_f, _a...) \ 1.111 + do { \ 1.112 + printk("XXX FAIL %s-PT " _f "\n", sh_check_name, ## _a ); \ 1.113 + errors++; \ 1.114 } while ( 0 ) 1.115 1.116 -void check_pagetable(struct domain *d, pagetable_t pt, char *s) 1.117 +int check_l2_table( 1.118 + struct domain *d, unsigned long gpfn, unsigned long smfn) 1.119 { 1.120 - unsigned long gptbase = pagetable_val(pt); 1.121 - unsigned long ptbase_pfn, smfn, ss; 1.122 - unsigned long i; 1.123 - l2_pgentry_t *gpl2e, *spl2e; 1.124 - unsigned long ptbase_mfn = 0; 1.125 - int cpu = current->processor; 1.126 - 1.127 - errors = 0; 1.128 - sh_check_name = s; 1.129 - 1.130 - SH_VVLOG("%s-PT Audit", s); 1.131 - 1.132 - sh_l2_present = sh_l1_present = 0; 1.133 - 1.134 - ptbase_pfn = gptbase >> PAGE_SHIFT; 1.135 - ptbase_mfn = __gpfn_to_mfn(d, ptbase_pfn); 1.136 + unsigned long gmfn = __gpfn_to_mfn(d, gpfn); 1.137 + l2_pgentry_t *gpl2e = (l2_pgentry_t *) map_domain_mem( gmfn << PAGE_SHIFT ); 1.138 + l2_pgentry_t *spl2e = (l2_pgentry_t *) map_domain_mem( smfn << PAGE_SHIFT ); 1.139 + int i; 1.140 + int errors = 0; 1.141 1.142 - ss = __shadow_status(d, ptbase_pfn); 1.143 - 1.144 - if ( ! (ss & PSH_shadowed) ) 1.145 - { 1.146 - printk("%s-PT %p not shadowed\n", s, gptbase); 1.147 - 1.148 - if ( ss != 0 ) 1.149 - BUG(); 1.150 - return; 1.151 - } 1.152 - 1.153 - smfn = ss & PSH_pfn_mask; 1.154 - 1.155 - if ( ss != (PSH_shadowed | smfn) ) 1.156 - FAILPT("ptbase shadow inconsistent1"); 1.157 - 1.158 - gpl2e = (l2_pgentry_t *) map_domain_mem( ptbase_mfn << PAGE_SHIFT ); 1.159 - spl2e = (l2_pgentry_t *) map_domain_mem( smfn << PAGE_SHIFT ); 1.160 + if ( page_get_owner(pfn_to_page(gmfn)) != d ) 1.161 + FAILPT("domain doesn't own page"); 1.162 + if ( page_get_owner(pfn_to_page(smfn)) != NULL ) 1.163 + FAILPT("shadow page mfn=0x%08x is owned by someone, domid=%d", 1.164 + smfn, page_get_owner(pfn_to_page(smfn))->id); 1.165 1.166 if ( memcmp(&spl2e[DOMAIN_ENTRIES_PER_L2_PAGETABLE], 1.167 &gpl2e[DOMAIN_ENTRIES_PER_L2_PAGETABLE], 1.168 @@ -918,24 +922,68 @@ void check_pagetable(struct domain *d, p 1.169 FAILPT("hypervisor linear map inconsistent"); 1.170 1.171 if ( (l2_pgentry_val(spl2e[SH_LINEAR_PT_VIRT_START >> 1.172 - L2_PAGETABLE_SHIFT]) != 1.173 + L2_PAGETABLE_SHIFT]) != 1.174 ((smfn << PAGE_SHIFT) | __PAGE_HYPERVISOR)) ) 1.175 FAILPT("hypervisor shadow linear map inconsistent %p %p", 1.176 l2_pgentry_val(spl2e[SH_LINEAR_PT_VIRT_START >> 1.177 - L2_PAGETABLE_SHIFT]), 1.178 + L2_PAGETABLE_SHIFT]), 1.179 (smfn << PAGE_SHIFT) | __PAGE_HYPERVISOR); 1.180 1.181 if ( shadow_mode(d) != SHM_full_32 ) { 1.182 - // BUG: this shouldn't be using exec_domain[0] here... 1.183 if ( (l2_pgentry_val(spl2e[PERDOMAIN_VIRT_START >> L2_PAGETABLE_SHIFT]) != 1.184 - ((__pa(page_get_owner(&frame_table[ptbase_pfn])->arch.mm_perdomain_pt) | 1.185 - __PAGE_HYPERVISOR))) ) 1.186 + ((v2m(page_get_owner(&frame_table[gmfn])->arch.mm_perdomain_pt) | 1.187 + __PAGE_HYPERVISOR))) ) 1.188 FAILPT("hypervisor per-domain map inconsistent"); 1.189 } 1.190 1.191 /* Check the whole L2. */ 1.192 for ( i = 0; i < DOMAIN_ENTRIES_PER_L2_PAGETABLE; i++ ) 1.193 - check_pte(d, &l2_pgentry_val(gpl2e[i]), &l2_pgentry_val(spl2e[i]), 2, i); 1.194 + errors += check_pte(d, &l2_pgentry_val(gpl2e[i]), &l2_pgentry_val(spl2e[i]), 2, i, 0); 1.195 + 1.196 + unmap_domain_mem(spl2e); 1.197 + unmap_domain_mem(gpl2e); 1.198 + 1.199 + return errors; 1.200 +} 1.201 + 1.202 +int _check_pagetable(struct domain *d, pagetable_t pt, char *s) 1.203 +{ 1.204 + unsigned long gptbase = pagetable_val(pt); 1.205 + unsigned long ptbase_pfn, smfn, ss; 1.206 + unsigned long i; 1.207 + l2_pgentry_t *gpl2e, *spl2e; 1.208 + unsigned long ptbase_mfn = 0; 1.209 + int errors = 0; 1.210 + 1.211 + sh_check_name = s; 1.212 + SH_VVLOG("%s-PT Audit", s); 1.213 + sh_l2_present = sh_l1_present = 0; 1.214 + perfc_incrc(check_pagetable); 1.215 + 1.216 + ptbase_pfn = gptbase >> PAGE_SHIFT; 1.217 + ptbase_mfn = __gpfn_to_mfn(d, ptbase_pfn); 1.218 + 1.219 + ss = __shadow_status(d, ptbase_pfn); 1.220 + 1.221 + if ( ! (ss & PSH_shadowed) ) 1.222 + { 1.223 + printk("%s-PT %p not shadowed\n", s, gptbase); 1.224 + errors++; 1.225 + 1.226 + if ( ss != 0 ) 1.227 + BUG(); 1.228 + return errors; 1.229 + } 1.230 + 1.231 + smfn = ss & PSH_pfn_mask; 1.232 + 1.233 + if ( ss != (PSH_shadowed | smfn) ) 1.234 + FAILPT("ptbase shadow inconsistent1"); 1.235 + 1.236 + errors += check_l2_table(d, ptbase_pfn, smfn); 1.237 + 1.238 + gpl2e = (l2_pgentry_t *) map_domain_mem( ptbase_mfn << PAGE_SHIFT ); 1.239 + spl2e = (l2_pgentry_t *) map_domain_mem( smfn << PAGE_SHIFT ); 1.240 1.241 /* Go back and recurse. */ 1.242 for ( i = 0; i < DOMAIN_ENTRIES_PER_L2_PAGETABLE; i++ ) 1.243 @@ -946,20 +994,7 @@ void check_pagetable(struct domain *d, p 1.244 1.245 if ( l2_pgentry_val(spl2e[i]) != 0 ) 1.246 { 1.247 - // First check to see if this guest page is currently the active 1.248 - // PTWR page. If so, then we compare the (old) cached copy of the 1.249 - // guest page to the shadow, and not the currently writable (and 1.250 - // thus potentially out-of-sync) guest page. 1.251 - // 1.252 - if ( ptwr_info[cpu].ptinfo[PTWR_PT_ACTIVE].l1va && 1.253 - (i == ptwr_info[cpu].ptinfo[PTWR_PT_ACTIVE].l2_idx) && 1.254 - likely(VM_ASSIST(d, VMASST_TYPE_writable_pagetables)) ) 1.255 - { 1.256 - gl1mfn = (__pa(ptwr_info[cpu].ptinfo[PTWR_PT_ACTIVE].page) >> 1.257 - PAGE_SHIFT); 1.258 - } 1.259 - 1.260 - check_l1_table(d, gl1mfn, sl1mfn); 1.261 + errors += check_l1_table(d, gl1mfn, sl1mfn, i); 1.262 } 1.263 } 1.264 1.265 @@ -969,10 +1004,104 @@ void check_pagetable(struct domain *d, p 1.266 SH_VVLOG("PT verified : l2_present = %d, l1_present = %d", 1.267 sh_l2_present, sh_l1_present); 1.268 1.269 +#if 1 1.270 if ( errors ) 1.271 BUG(); 1.272 +#endif 1.273 1.274 - return; 1.275 + return errors; 1.276 +} 1.277 + 1.278 +int _check_all_pagetables(struct domain *d, char *s) 1.279 +{ 1.280 + int i, j; 1.281 + struct shadow_status *a; 1.282 + unsigned long gmfn; 1.283 + int errors = 0; 1.284 + int cpu; 1.285 + 1.286 + shadow_status_noswap = 1; 1.287 + 1.288 + sh_check_name = s; 1.289 + SH_VVLOG("%s-PT Audit domid=%d", s, d->id); 1.290 + sh_l2_present = sh_l1_present = 0; 1.291 + perfc_incrc(check_all_pagetables); 1.292 + 1.293 + for (i = 0; i < shadow_ht_buckets; i++) 1.294 + { 1.295 + a = &d->arch.shadow_ht[i]; 1.296 + while ( a && a->pfn ) 1.297 + { 1.298 + gmfn = __gpfn_to_mfn(d, a->pfn); 1.299 + switch ( frame_table[a->pfn].u.inuse.type_info & PGT_type_mask ) 1.300 + { 1.301 + case PGT_l1_page_table: 1.302 + errors += check_l1_table(d, gmfn, a->smfn_and_flags & PSH_pfn_mask, 0); 1.303 + break; 1.304 + case PGT_l2_page_table: 1.305 + errors += check_l2_table(d, gmfn, a->smfn_and_flags & PSH_pfn_mask); 1.306 + break; 1.307 + default: 1.308 + errors++; 1.309 + printk("unexpected page type 0x%08x, pfn=0x%08x, gmfn=0x%08x\n", 1.310 + frame_table[gmfn].u.inuse.type_info, 1.311 + a->pfn, gmfn); 1.312 + BUG(); 1.313 + } 1.314 + a = a->next; 1.315 + } 1.316 + } 1.317 + 1.318 + shadow_status_noswap = 0; 1.319 + 1.320 + for (i = 0; i < 1024; i++) 1.321 + { 1.322 + if ( l2_pgentry_val(shadow_linear_l2_table[i]) & _PAGE_PRESENT ) 1.323 + { 1.324 + unsigned base = i << 10; 1.325 + for (j = 0; j < 1024; j++) 1.326 + { 1.327 + if ( (l1_pgentry_val(shadow_linear_pg_table[base + j]) & PAGE_MASK) == 0x0143d000 ) 1.328 + { 1.329 + printk("sh_ln_pg_tb[0x%08x] => 0x%08lx ", 1.330 + base + j, 1.331 + l1_pgentry_val(shadow_linear_pg_table[base + j])); 1.332 + if ( l1_pgentry_val(shadow_linear_pg_table[base + j]) & _PAGE_PRESENT ) 1.333 + printk(" first entry => 0x%08lx\n", 1.334 + *(unsigned long *)((base + j) << PAGE_SHIFT)); 1.335 + else 1.336 + printk(" page not present\n"); 1.337 + } 1.338 + } 1.339 + } 1.340 + } 1.341 + 1.342 + if ( errors ) 1.343 + { 1.344 + printk("VM_ASSIST(d, VMASST_TYPE_writable_pagetables) => %d\n", 1.345 + VM_ASSIST(d, VMASST_TYPE_writable_pagetables)); 1.346 + for ( cpu = 0; cpu < smp_num_cpus; cpu++ ) 1.347 + { 1.348 + for ( j = 0; j < ARRAY_SIZE(ptwr_info->ptinfo); j++) 1.349 + { 1.350 + printk("ptwr_info[%d].ptinfo[%d].l1va => 0x%08x\n", 1.351 + cpu, j, ptwr_info[cpu].ptinfo[j].l1va); 1.352 + printk("ptwr_info[%d].ptinfo[%d].pl1e => 0x%08x\n", 1.353 + cpu, j, ptwr_info[cpu].ptinfo[j].pl1e); 1.354 + if (cpu == smp_processor_id()) 1.355 + printk("v2m(ptwr_info[%d].ptinfo[%d].pl1e) => 0x%08x\n", 1.356 + cpu, j, v2m(ptwr_info[cpu].ptinfo[j].pl1e)); 1.357 + printk("ptwr_info[%d].ptinfo[%d].page => 0x%08x\n", 1.358 + cpu, j, ptwr_info[cpu].ptinfo[j].page); 1.359 + if (cpu == smp_processor_id()) 1.360 + printk("v2m(ptwr_info[%d].ptinfo[%d].page) => 0x%08x\n", 1.361 + cpu, j, v2m(ptwr_info[cpu].ptinfo[j].page)); 1.362 + } 1.363 + } 1.364 + BUG(); 1.365 + } 1.366 + 1.367 + return errors; 1.368 } 1.369 1.370 #endif // SHADOW_DEBUG
2.1 --- a/xen/include/asm-x86/shadow.h Tue Feb 08 17:49:09 2005 +0000 2.2 +++ b/xen/include/asm-x86/shadow.h Sat Feb 12 14:38:06 2005 +0000 2.3 @@ -73,9 +73,13 @@ static inline void shadow_invalidate(str 2.4 memset(ed->arch.shadow_vtable, 0, PAGE_SIZE); 2.5 } 2.6 2.7 -#define SHADOW_DEBUG 1 2.8 +#define SHADOW_DEBUG 0 2.9 #define SHADOW_VERBOSE_DEBUG 0 2.10 -#define SHADOW_HASH_DEBUG 1 2.11 +#define SHADOW_HASH_DEBUG 0 2.12 + 2.13 +#if SHADOW_DEBUG 2.14 +extern int shadow_status_noswap; 2.15 +#endif 2.16 2.17 struct shadow_status { 2.18 unsigned long pfn; /* Guest pfn. */ 2.19 @@ -88,7 +92,7 @@ struct shadow_status { 2.20 2.21 #ifdef VERBOSE 2.22 #define SH_LOG(_f, _a...) \ 2.23 -printk("DOM%uP%u: (file=shadow.c, line=%d) " _f "\n", \ 2.24 + printk("DOM%uP%u: SH_LOG(%d): " _f "\n", \ 2.25 current->domain->id , current->processor, __LINE__ , ## _a ) 2.26 #else 2.27 #define SH_LOG(_f, _a...) 2.28 @@ -96,7 +100,7 @@ printk("DOM%uP%u: (file=shadow.c, line=% 2.29 2.30 #if SHADOW_DEBUG 2.31 #define SH_VLOG(_f, _a...) \ 2.32 - printk("DOM%uP%u: (file=shadow.c, line=%d) " _f "\n", \ 2.33 + printk("DOM%uP%u: SH_VLOG(%d): " _f "\n", \ 2.34 current->domain->id, current->processor, __LINE__ , ## _a ) 2.35 #else 2.36 #define SH_VLOG(_f, _a...) 2.37 @@ -104,7 +108,7 @@ printk("DOM%uP%u: (file=shadow.c, line=% 2.38 2.39 #if SHADOW_VERBOSE_DEBUG 2.40 #define SH_VVLOG(_f, _a...) \ 2.41 - printk("DOM%uP%u: (file=shadow.c, line=%d) " _f "\n", \ 2.42 + printk("DOM%uP%u: SH_VVLOG(%d): " _f "\n", \ 2.43 current->domain->id, current->processor, __LINE__ , ## _a ) 2.44 #else 2.45 #define SH_VVLOG(_f, _a...) 2.46 @@ -426,6 +430,10 @@ static inline unsigned long __shadow_sta 2.47 2.48 if ( x->pfn == gpfn ) 2.49 { 2.50 +#if SHADOW_DEBUG 2.51 + if ( unlikely(shadow_status_noswap) ) 2.52 + return x->smfn_and_flags; 2.53 +#endif 2.54 /* Pull-to-front if 'x' isn't already the head item. */ 2.55 if ( unlikely(x != head) ) 2.56 { 2.57 @@ -726,9 +734,14 @@ static inline void shadow_mk_pagetable(s 2.58 } 2.59 2.60 #if SHADOW_DEBUG 2.61 -extern void check_pagetable(struct domain *d, pagetable_t pt, char *s); 2.62 +extern int _check_pagetable(struct domain *d, pagetable_t pt, char *s); 2.63 +extern int _check_all_pagetables(struct domain *d, char *s); 2.64 + 2.65 +#define check_pagetable(_d, _pt, _s) _check_pagetable(_d, _pt, _s) 2.66 +//#define check_pagetable(_d, _pt, _s) _check_all_pagetables(_d, _s) 2.67 + 2.68 #else 2.69 -#define check_pagetable(d, pt, s) ((void)0) 2.70 +#define check_pagetable(_d, _pt, _s) ((void)0) 2.71 #endif 2.72 2.73 #endif /* XEN_SHADOW_H */
3.1 --- a/xen/include/xen/perfc_defn.h Tue Feb 08 17:49:09 2005 +0000 3.2 +++ b/xen/include/xen/perfc_defn.h Sat Feb 12 14:38:06 2005 +0000 3.3 @@ -30,3 +30,6 @@ PERFCOUNTER_CPU( shadow_update_va_fail, 3.4 /* STATUS counters do not reset when 'P' is hit */ 3.5 PERFSTATUS( shadow_l2_pages, "current # shadow L2 pages" ) 3.6 PERFSTATUS( shadow_l1_pages, "current # shadow L1 pages" ) 3.7 + 3.8 +PERFCOUNTER_CPU( check_pagetable, "calls to check_pagetable" ) 3.9 +PERFCOUNTER_CPU( check_all_pagetables, "calls to check_all_pagetables" )