ia64/xen-unstable
changeset 2458:d3c0c3c96dc0
bitkeeper revision 1.1159.1.137 (413f0665_0jsl7Ps44McAAquhcKOIQ)
Writable pagetables v2.
Writable pagetables v2.
author | cl349@freefall.cl.cam.ac.uk |
---|---|
date | Wed Sep 08 13:17:25 2004 +0000 (2004-09-08) |
parents | 1ae6a24623a9 |
children | 0aadba2b9bc3 9c7d7819508a |
files | xen/arch/x86/memory.c xen/include/asm-x86/mm.h |
line diff
1.1 --- a/xen/arch/x86/memory.c Wed Sep 08 09:49:46 2004 +0000 1.2 +++ b/xen/arch/x86/memory.c Wed Sep 08 13:17:25 2004 +0000 1.3 @@ -144,6 +144,7 @@ static struct domain *dom_xen, *dom_io; 1.4 void arch_init_memory(void) 1.5 { 1.6 unsigned long mfn; 1.7 + int i; 1.8 1.9 /* 1.10 * We are rather picky about the layout of 'struct pfn_info'. The 1.11 @@ -164,9 +165,6 @@ void arch_init_memory(void) 1.12 1.13 memset(percpu_info, 0, sizeof(percpu_info)); 1.14 1.15 - vm_assist_info[VMASST_TYPE_writable_pagetables].enable = NULL; 1.16 - vm_assist_info[VMASST_TYPE_writable_pagetables].disable = NULL; 1.17 - 1.18 for ( mfn = 0; mfn < max_page; mfn++ ) 1.19 frame_table[mfn].count_info |= PGC_always_set; 1.20 1.21 @@ -200,6 +198,15 @@ void arch_init_memory(void) 1.22 frame_table[mfn].u.inuse.type_info = PGT_gdt_page | 1; /* non-RW */ 1.23 frame_table[mfn].u.inuse.domain = dom_xen; 1.24 } 1.25 + 1.26 + vm_assist_info[VMASST_TYPE_writable_pagetables].enable = NULL; 1.27 + vm_assist_info[VMASST_TYPE_writable_pagetables].disable = NULL; 1.28 + 1.29 + for ( i = 0; i < smp_num_cpus; i++ ) 1.30 + { 1.31 + ptwr_info[i].disconnected_page = (void *)alloc_xenheap_page(); 1.32 + ptwr_info[i].writable_page = (void *)alloc_xenheap_page(); 1.33 + } 1.34 } 1.35 1.36 static void __invalidate_shadow_ldt(struct domain *d) 1.37 @@ -1487,22 +1494,28 @@ ptwr_info_t ptwr_info[NR_CPUS] = 1.38 { [ 0 ... NR_CPUS-1 ] = 1.39 { 1.40 .disconnected_pteidx = -1, 1.41 + .disconnected_page = 0, 1.42 .writable_l1va = 0, 1.43 + .writable_page = 0, 1.44 } 1.45 }; 1.46 1.47 #ifdef VERBOSE 1.48 -int ptwr_debug = 0; 1.49 -#define PTWR_PRINTK(x) if (ptwr_debug) printk x 1.50 +int ptwr_debug = 0x0; 1.51 +#define PTWR_PRINTK(w, x) if (ptwr_debug & (w)) printk x 1.52 +#define PP_ALL 0xff 1.53 +#define PP_A 0x1 1.54 +#define PP_I 0x2 1.55 #else 1.56 -#define PTWR_PRINTK(x) 1.57 +#define PTWR_PRINTK(w, x) 1.58 #endif 1.59 1.60 void ptwr_reconnect_disconnected(void) 1.61 { 1.62 unsigned long pte; 1.63 +#ifdef VERBOSE 1.64 unsigned long pfn; 1.65 - struct pfn_info *page; 1.66 +#endif 1.67 l2_pgentry_t *pl2e, nl2e; 1.68 l1_pgentry_t *pl1e; 1.69 int cpu = smp_processor_id(); 1.70 @@ -1510,38 +1523,35 @@ void ptwr_reconnect_disconnected(void) 1.71 unsigned long *writable_pte = (unsigned long *)&linear_pg_table 1.72 [ptwr_info[cpu].disconnected_l1va>>PAGE_SHIFT]; 1.73 1.74 - PTWR_PRINTK(("[A] page fault in disconn space %08lx\n", 1.75 - ptwr_info[cpu].disconnected_pteidx << L2_PAGETABLE_SHIFT)); 1.76 + PTWR_PRINTK(PP_A, ("[A] page fault in disconn space %08lx\n", 1.77 + ptwr_info[cpu].disconnected_pteidx << 1.78 + L2_PAGETABLE_SHIFT)); 1.79 pl2e = &linear_l2_table[ptwr_info[cpu].disconnected_pteidx]; 1.80 1.81 - if (__get_user(pte, writable_pte)) { 1.82 - MEM_LOG("ptwr: Could not read pte at %p\n", writable_pte); 1.83 - domain_crash(); 1.84 - } 1.85 - pfn = pte >> PAGE_SHIFT; 1.86 - page = &frame_table[pfn]; 1.87 - 1.88 - /* reconnect l1 page */ 1.89 - PTWR_PRINTK(("[A] pl2e %p l2e %08lx pfn %08lx taf %08x/%08x/%u\n", 1.90 - pl2e, l2_pgentry_val(*pl2e), 1.91 - l1_pgentry_val(linear_pg_table[(unsigned long)pl2e >> 1.92 - PAGE_SHIFT]) >> PAGE_SHIFT, 1.93 - frame_table[pfn].u.inuse.type_info, 1.94 - frame_table[pfn].count_info, 1.95 - frame_table[pfn].u.inuse.domain->domain)); 1.96 +#ifdef VERBOSE 1.97 + pfn = ptwr_info[cpu].disconnected_pte >> PAGE_SHIFT; 1.98 +#endif 1.99 + PTWR_PRINTK(PP_A, ("[A] pl2e %p l2e %08lx pfn %08lx taf %08x/%08x\n", 1.100 + pl2e, l2_pgentry_val(*pl2e), l1_pgentry_val( 1.101 + linear_pg_table[(unsigned long)pl2e >> 1.102 + PAGE_SHIFT]) >> PAGE_SHIFT, 1.103 + frame_table[pfn].u.inuse.type_info, 1.104 + frame_table[pfn].count_info)); 1.105 1.106 nl2e = mk_l2_pgentry(l2_pgentry_val(*pl2e) | _PAGE_PRESENT); 1.107 - pl1e = map_domain_mem(l2_pgentry_to_pagenr(nl2e) << PAGE_SHIFT); 1.108 + pl1e = ptwr_info[cpu].disconnected_pl1e; 1.109 for ( i = 0; i < ENTRIES_PER_L1_PAGETABLE; i++ ) { 1.110 l1_pgentry_t ol1e, nl1e; 1.111 - ol1e = ptwr_info[cpu].disconnected_page[i]; 1.112 - nl1e = pl1e[i]; 1.113 + nl1e = ptwr_info[cpu].disconnected_page[i]; 1.114 + ol1e = pl1e[i]; 1.115 if (likely(l1_pgentry_val(nl1e) == l1_pgentry_val(ol1e))) 1.116 continue; 1.117 if (likely(l1_pgentry_val(nl1e) == (l1_pgentry_val(ol1e) | _PAGE_RW))) 1.118 { 1.119 - if (likely(readonly_page_from_l1e(nl1e))) 1.120 + if (likely(readonly_page_from_l1e(nl1e))) { 1.121 + pl1e[i] = ptwr_info[cpu].disconnected_page[i]; 1.122 continue; 1.123 + } 1.124 } 1.125 if (unlikely(l1_pgentry_val(ol1e) & _PAGE_PRESENT)) 1.126 put_page_from_l1e(ol1e, current); 1.127 @@ -1549,58 +1559,52 @@ void ptwr_reconnect_disconnected(void) 1.128 MEM_LOG("ptwr: Could not re-validate l1 page\n"); 1.129 domain_crash(); 1.130 } 1.131 + pl1e[i] = ptwr_info[cpu].disconnected_page[i]; 1.132 } 1.133 unmap_domain_mem(pl1e); 1.134 + /* reconnect l1 page */ 1.135 update_l2e(pl2e, *pl2e, nl2e); 1.136 1.137 - PTWR_PRINTK(("[A] now pl2e %p l2e %08lx taf %08x/%08x/%u\n", 1.138 + PTWR_PRINTK(PP_A, 1.139 + ("[A] now pl2e %p l2e %08lx taf %08x/%08x\n", 1.140 pl2e, l2_pgentry_val(*pl2e), 1.141 frame_table[pfn].u.inuse.type_info, 1.142 - frame_table[pfn].count_info, 1.143 - frame_table[pfn].u.inuse.domain->domain)); 1.144 + frame_table[pfn].count_info)); 1.145 ptwr_info[cpu].disconnected_pteidx = -1; 1.146 + 1.147 /* make pt page write protected */ 1.148 if (__get_user(pte, writable_pte)) { 1.149 MEM_LOG("ptwr: Could not read pte at %p\n", writable_pte); 1.150 domain_crash(); 1.151 } 1.152 - PTWR_PRINTK(("[A] disconnected_l1va at %p is %08lx\n", 1.153 - writable_pte, pte)); 1.154 - pte &= ~_PAGE_RW; 1.155 + PTWR_PRINTK(PP_A, ("[A] disconnected_l1va at %p is %08lx\n", 1.156 + writable_pte, pte)); 1.157 + pte = (ptwr_info[cpu].disconnected_pte & PAGE_MASK) | 1.158 + (pte & ~(PAGE_MASK|_PAGE_RW)); 1.159 if (__put_user(pte, writable_pte)) { 1.160 MEM_LOG("ptwr: Could not update pte at %p\n", writable_pte); 1.161 domain_crash(); 1.162 } 1.163 __flush_tlb_one(ptwr_info[cpu].disconnected_l1va); 1.164 - PTWR_PRINTK(("[A] disconnected_l1va at %p now %08lx\n", 1.165 - writable_pte, pte)); 1.166 - /* and try again */ 1.167 - return; 1.168 + PTWR_PRINTK(PP_A, ("[A] disconnected_l1va at %p now %08lx\n", 1.169 + writable_pte, pte)); 1.170 + 1.171 } 1.172 1.173 void ptwr_flush_inactive(void) 1.174 { 1.175 - unsigned long pte, pfn; 1.176 - struct pfn_info *page; 1.177 + unsigned long pte; 1.178 l1_pgentry_t *pl1e; 1.179 int cpu = smp_processor_id(); 1.180 int i; 1.181 - 1.182 unsigned long *writable_pte = (unsigned long *)&linear_pg_table 1.183 [ptwr_info[cpu].writable_l1va>>PAGE_SHIFT]; 1.184 - if (__get_user(pte, writable_pte)) { 1.185 - MEM_LOG("ptwr: Could not read pte at %p\n", writable_pte); 1.186 - domain_crash(); 1.187 - } 1.188 - pfn = pte >> PAGE_SHIFT; 1.189 - page = &frame_table[pfn]; 1.190 - PTWR_PRINTK(("[I] alloc l1 page %p\n", page)); 1.191 1.192 - pl1e = map_domain_mem(pfn << PAGE_SHIFT); 1.193 + pl1e = ptwr_info[cpu].writable_pl1e; 1.194 for ( i = 0; i < ENTRIES_PER_L1_PAGETABLE; i++ ) { 1.195 l1_pgentry_t ol1e, nl1e; 1.196 - ol1e = ptwr_info[cpu].writable_page[i]; 1.197 - nl1e = pl1e[i]; 1.198 + nl1e = ptwr_info[cpu].writable_page[i]; 1.199 + ol1e = pl1e[i]; 1.200 if (likely(l1_pgentry_val(ol1e) == l1_pgentry_val(nl1e))) 1.201 continue; 1.202 if (unlikely(l1_pgentry_val(ol1e) & _PAGE_PRESENT)) 1.203 @@ -1609,20 +1613,26 @@ void ptwr_flush_inactive(void) 1.204 MEM_LOG("ptwr: Could not re-validate l1 page\n"); 1.205 domain_crash(); 1.206 } 1.207 + pl1e[i] = ptwr_info[cpu].writable_page[i]; 1.208 } 1.209 unmap_domain_mem(pl1e); 1.210 1.211 /* make pt page writable */ 1.212 - PTWR_PRINTK(("[I] disconnected_l1va at %p is %08lx\n", 1.213 - writable_pte, pte)); 1.214 - pte &= ~_PAGE_RW; 1.215 + if (__get_user(pte, writable_pte)) { 1.216 + MEM_LOG("ptwr: Could not read pte at %p\n", writable_pte); 1.217 + domain_crash(); 1.218 + } 1.219 + PTWR_PRINTK(PP_I, ("[I] disconnected_l1va at %p is %08lx\n", 1.220 + writable_pte, pte)); 1.221 + pte = (ptwr_info[cpu].writable_pte & PAGE_MASK) | 1.222 + (pte & ~(PAGE_MASK|_PAGE_RW)); 1.223 if (__put_user(pte, writable_pte)) { 1.224 MEM_LOG("ptwr: Could not update pte at %p\n", writable_pte); 1.225 domain_crash(); 1.226 } 1.227 __flush_tlb_one(ptwr_info[cpu].writable_l1va); 1.228 - PTWR_PRINTK(("[I] disconnected_l1va at %p now %08lx\n", 1.229 - writable_pte, pte)); 1.230 + PTWR_PRINTK(PP_I, ("[I] disconnected_l1va at %p now %08lx\n", 1.231 + writable_pte, pte)); 1.232 1.233 ptwr_info[cpu].writable_l1va = 0; 1.234 } 1.235 @@ -1636,8 +1646,8 @@ int ptwr_do_page_fault(unsigned long add 1.236 int cpu = smp_processor_id(); 1.237 1.238 #if 0 1.239 - PTWR_PRINTK(("get user %p for va %08lx\n", 1.240 - &linear_pg_table[addr>>PAGE_SHIFT], addr)); 1.241 + PTWR_PRINTK(PP_ALL, ("get user %p for va %08lx\n", 1.242 + &linear_pg_table[addr>>PAGE_SHIFT], addr)); 1.243 #endif 1.244 1.245 /* Testing for page_present in the L2 avoids lots of unncessary fixups */ 1.246 @@ -1648,72 +1658,80 @@ int ptwr_do_page_fault(unsigned long add 1.247 { 1.248 pfn = pte >> PAGE_SHIFT; 1.249 #if 0 1.250 - PTWR_PRINTK(("check pte %08lx = pfn %08lx for va %08lx\n", pte, pfn, 1.251 - addr)); 1.252 + PTWR_PRINTK(PP_ALL, ("check pte %08lx = pfn %08lx for va %08lx\n", pte, 1.253 + pfn, addr)); 1.254 #endif 1.255 page = &frame_table[pfn]; 1.256 if ( (page->u.inuse.type_info & PGT_type_mask) == PGT_l1_page_table ) 1.257 { 1.258 pl2e = &linear_l2_table[(page->u.inuse.type_info & 1.259 PGT_va_mask) >> PGT_va_shift]; 1.260 - PTWR_PRINTK(("page_fault on l1 pt at va %08lx, pt for %08x, " 1.261 - "pfn %08lx\n", addr, 1.262 - ((page->u.inuse.type_info & PGT_va_mask) >> 1.263 - PGT_va_shift) << L2_PAGETABLE_SHIFT, pfn)); 1.264 + PTWR_PRINTK(PP_ALL, ("page_fault on l1 pt at va %08lx, pt for %08x" 1.265 + ", pfn %08lx\n", addr, 1.266 + ((page->u.inuse.type_info & PGT_va_mask) >> 1.267 + PGT_va_shift) << L2_PAGETABLE_SHIFT, pfn)); 1.268 1.269 if ( l2_pgentry_val(*pl2e) >> PAGE_SHIFT != pfn ) 1.270 { 1.271 /* this L1 is not in the current address space */ 1.272 - l1_pgentry_t *pl1e; 1.273 - PTWR_PRINTK(("[I] freeing l1 page %p taf %08x/%08x\n", page, 1.274 - page->u.inuse.type_info, 1.275 - page->count_info)); 1.276 + PTWR_PRINTK(PP_I, ("[I] freeing l1 page %p taf %08x/%08x\n", 1.277 + page, page->u.inuse.type_info, 1.278 + page->count_info)); 1.279 if (ptwr_info[cpu].writable_l1va) 1.280 ptwr_flush_inactive(); 1.281 ptwr_info[cpu].writable_l1va = addr | 1; 1.282 1.283 - pl1e = map_domain_mem(pfn << PAGE_SHIFT); 1.284 - memcpy(&ptwr_info[cpu].writable_page[0], 1.285 - pl1e, ENTRIES_PER_L1_PAGETABLE * sizeof(l1_pgentry_t)); 1.286 - unmap_domain_mem(pl1e); 1.287 + ptwr_info[cpu].writable_pl1e = 1.288 + map_domain_mem(pfn << PAGE_SHIFT); 1.289 + memcpy(ptwr_info[cpu].writable_page, 1.290 + ptwr_info[cpu].writable_pl1e, 1.291 + ENTRIES_PER_L1_PAGETABLE * sizeof(l1_pgentry_t)); 1.292 + 1.293 + /* make pt page writable */ 1.294 + ptwr_info[cpu].writable_pte = pte; 1.295 + pte = (virt_to_phys(ptwr_info[cpu].writable_page) & 1.296 + PAGE_MASK) | _PAGE_RW | (pte & ~PAGE_MASK); 1.297 } 1.298 else 1.299 { 1.300 l2_pgentry_t nl2e; 1.301 - l1_pgentry_t *pl1e; 1.302 + 1.303 if ( ptwr_info[cpu].disconnected_pteidx >= 0 ) 1.304 ptwr_reconnect_disconnected(); 1.305 - PTWR_PRINTK(("[A] pl2e %p l2e %08lx pfn %08lx " 1.306 - "taf %08x/%08x/%u\n", pl2e, l2_pgentry_val(*pl2e), 1.307 - l1_pgentry_val(linear_pg_table[(unsigned long)pl2e 1.308 - >> PAGE_SHIFT]) >> 1.309 - PAGE_SHIFT, 1.310 - frame_table[pfn].u.inuse.type_info, 1.311 - frame_table[pfn].count_info, 1.312 - frame_table[pfn].u.inuse.domain->domain)); 1.313 + PTWR_PRINTK(PP_A, ("[A] pl2e %p l2e %08lx pfn %08lx " 1.314 + "taf %08x/%08x\n", pl2e, 1.315 + l2_pgentry_val(*pl2e), 1.316 + l1_pgentry_val(linear_pg_table 1.317 + [(unsigned long)pl2e >> 1.318 + PAGE_SHIFT]) >> PAGE_SHIFT, 1.319 + frame_table[pfn].u.inuse.type_info, 1.320 + frame_table[pfn].count_info)); 1.321 /* disconnect l1 page */ 1.322 nl2e = mk_l2_pgentry((l2_pgentry_val(*pl2e) & ~_PAGE_PRESENT)); 1.323 update_l2e(pl2e, *pl2e, nl2e); 1.324 1.325 ptwr_info[cpu].disconnected_pteidx = 1.326 (page->u.inuse.type_info & PGT_va_mask) >> PGT_va_shift; 1.327 - PTWR_PRINTK(("[A] now pl2e %p l2e %08lx " 1.328 - "taf %08x/%08x/%u\n", pl2e, l2_pgentry_val(*pl2e), 1.329 - frame_table[pfn].u.inuse.type_info, 1.330 - frame_table[pfn].count_info, 1.331 - frame_table[pfn].u.inuse.domain->domain)); 1.332 + PTWR_PRINTK(PP_A, ("[A] now pl2e %p l2e %08lx " 1.333 + "taf %08x/%08x\n", pl2e, 1.334 + l2_pgentry_val(*pl2e), 1.335 + frame_table[pfn].u.inuse.type_info, 1.336 + frame_table[pfn].count_info)); 1.337 ptwr_info[cpu].disconnected_l1va = addr; 1.338 - pl1e = map_domain_mem(l2_pgentry_to_pagenr(nl2e) << 1.339 - PAGE_SHIFT); 1.340 - memcpy(&ptwr_info[cpu].disconnected_page[0], pl1e, 1.341 + ptwr_info[cpu].disconnected_pl1e = 1.342 + map_domain_mem(l2_pgentry_to_pagenr(nl2e) << PAGE_SHIFT); 1.343 + memcpy(&ptwr_info[cpu].disconnected_page[0], 1.344 + ptwr_info[cpu].disconnected_pl1e, 1.345 ENTRIES_PER_L1_PAGETABLE * sizeof(l1_pgentry_t)); 1.346 - unmap_domain_mem(pl1e); 1.347 + 1.348 + /* make pt page writable */ 1.349 + ptwr_info[cpu].disconnected_pte = pte; 1.350 + pte = (virt_to_phys(ptwr_info[cpu].disconnected_page) & 1.351 + PAGE_MASK) | _PAGE_RW | (pte & ~PAGE_MASK); 1.352 } 1.353 1.354 - /* make pt page writable */ 1.355 - pte |= _PAGE_RW; 1.356 - PTWR_PRINTK(("update %p pte to %08lx\n", 1.357 - &linear_pg_table[addr>>PAGE_SHIFT], pte)); 1.358 + PTWR_PRINTK(PP_ALL, ("update %p pte to %08lx\n", 1.359 + &linear_pg_table[addr>>PAGE_SHIFT], pte)); 1.360 if ( __put_user(pte, (unsigned long *) 1.361 &linear_pg_table[addr>>PAGE_SHIFT]) ) { 1.362 MEM_LOG("ptwr: Could not update pte at %p\n", (unsigned long *) 1.363 @@ -1765,13 +1783,14 @@ void ptwr_status(void) 1.364 pfn = pte >> PAGE_SHIFT; 1.365 page = &frame_table[pfn]; 1.366 1.367 - PTWR_PRINTK((" pl2e %p l2e %08lx pfn %08lx taf %08x/%08x/%u\n", pl2e, 1.368 - l2_pgentry_val(*pl2e), 1.369 - l1_pgentry_val(linear_pg_table[(unsigned long)pl2e >> 1.370 - PAGE_SHIFT]) >> PAGE_SHIFT, 1.371 - frame_table[l2_pgentry_to_pagenr(*pl2e)].u.inuse.type_info, 1.372 - frame_table[pfn].u.inuse.type_info, 1.373 - frame_table[pfn].u.inuse.domain->domain)); 1.374 + PTWR_PRINTK(PP_ALL, (" pl2e %p l2e %08lx pfn %08lx taf %08x/%08x\n", 1.375 + pl2e, l2_pgentry_val(*pl2e), l1_pgentry_val( 1.376 + linear_pg_table[(unsigned long)pl2e >> 1.377 + PAGE_SHIFT]) >> PAGE_SHIFT, 1.378 + frame_table[ 1.379 + l2_pgentry_to_pagenr(*pl2e)].u.inuse.type_info, 1.380 + frame_table[pfn].u.inuse.type_info, 1.381 + frame_table[pfn].u.inuse.domain->domain)); 1.382 } 1.383 1.384
2.1 --- a/xen/include/asm-x86/mm.h Wed Sep 08 09:49:46 2004 +0000 2.2 +++ b/xen/include/asm-x86/mm.h Wed Sep 08 13:17:25 2004 +0000 2.3 @@ -371,11 +371,15 @@ extern vm_assist_info_t vm_assist_info[] 2.4 2.5 /* Writable Pagetables */ 2.6 typedef struct { 2.7 + unsigned long disconnected_l1va; 2.8 + l1_pgentry_t *disconnected_page; 2.9 long disconnected_pteidx; 2.10 - l1_pgentry_t disconnected_page[ENTRIES_PER_L1_PAGETABLE]; 2.11 - unsigned long disconnected_l1va; 2.12 + unsigned long disconnected_pte; 2.13 + l1_pgentry_t *disconnected_pl1e; 2.14 unsigned long writable_l1va; 2.15 - l1_pgentry_t writable_page[ENTRIES_PER_L1_PAGETABLE]; 2.16 + l1_pgentry_t *writable_page; 2.17 + unsigned long writable_pte; 2.18 + l1_pgentry_t *writable_pl1e; 2.19 } __cacheline_aligned ptwr_info_t; 2.20 2.21 extern ptwr_info_t ptwr_info[];