debuggers.hg

view xen/arch/x86/shadow.c @ 3705:4294cfa9fad3

bitkeeper revision 1.1159.212.95 (4204aa0ee0re5Xx1zWrJ9ejxzgRs3w)

Various cleanups. Remove PDB pending simpler GDB stub and/or NetBSD debugger.
Force emacs mode to appropriate tabbing in various files.
Signed-off-by: keir.fraser@cl.cam.ac.uk
author kaf24@scramble.cl.cam.ac.uk
date Sat Feb 05 11:12:14 2005 +0000 (2005-02-05)
parents 677cb76cff18
children d93748c50893
line source
1 /* -*- Mode:C; c-basic-offset:4; tab-width:4; indent-tabs-mode:nil -*- */
3 #include <xen/config.h>
4 #include <xen/types.h>
5 #include <xen/mm.h>
6 #include <asm/shadow.h>
7 #include <asm/domain_page.h>
8 #include <asm/page.h>
9 #include <xen/event.h>
10 #include <xen/trace.h>
12 /********
14 To use these shadow page tables, guests must not rely on the ACCESSED
15 and DIRTY bits on L2 pte's being accurate -- they will typically all be set.
17 I doubt this will break anything. (If guests want to use the va_update
18 mechanism they've signed up for this anyhow...)
20 There's a per-domain shadow table spin lock which works fine for SMP
21 hosts. We don't have to worry about interrupts as no shadow operations
22 happen in an interrupt context. It's probably not quite ready for SMP
23 guest operation as we have to worry about synchonisation between gpte
24 and spte updates. Its possible that this might only happen in a
25 hypercall context, in which case we'll probably at have a per-domain
26 hypercall lock anyhow (at least initially).
28 ********/
30 static inline void free_shadow_page(
31 struct mm_struct *m, struct pfn_info *page)
32 {
33 m->shadow_page_count--;
35 switch ( page->u.inuse.type_info & PGT_type_mask )
36 {
37 case PGT_l1_page_table:
38 perfc_decr(shadow_l1_pages);
39 break;
41 case PGT_l2_page_table:
42 perfc_decr(shadow_l2_pages);
43 break;
45 default:
46 printk("Free shadow weird page type pfn=%08x type=%08x\n",
47 frame_table-page, page->u.inuse.type_info);
48 break;
49 }
51 free_domheap_page(page);
52 }
54 static void free_shadow_state(struct mm_struct *m)
55 {
56 int i, free = 0;
57 struct shadow_status *x, *n;
59 /*
60 * WARNING! The shadow page table must not currently be in use!
61 * e.g., You are expected to have paused the domain and synchronized CR3.
62 */
64 shadow_audit(m, 1);
66 /* Free each hash chain in turn. */
67 for ( i = 0; i < shadow_ht_buckets; i++ )
68 {
69 /* Skip empty buckets. */
70 x = &m->shadow_ht[i];
71 if ( x->pfn == 0 )
72 continue;
74 /* Free the head page. */
75 free_shadow_page(
76 m, &frame_table[x->spfn_and_flags & PSH_pfn_mask]);
78 /* Reinitialise the head node. */
79 x->pfn = 0;
80 x->spfn_and_flags = 0;
81 n = x->next;
82 x->next = NULL;
84 free++;
86 /* Iterate over non-head nodes. */
87 for ( x = n; x != NULL; x = n )
88 {
89 /* Free the shadow page. */
90 free_shadow_page(
91 m, &frame_table[x->spfn_and_flags & PSH_pfn_mask]);
93 /* Re-initialise the chain node. */
94 x->pfn = 0;
95 x->spfn_and_flags = 0;
97 /* Add to the free list. */
98 n = x->next;
99 x->next = m->shadow_ht_free;
100 m->shadow_ht_free = x;
102 free++;
103 }
105 shadow_audit(m, 0);
106 }
108 SH_LOG("Free shadow table. Freed=%d.", free);
109 }
111 static inline int clear_shadow_page(
112 struct mm_struct *m, struct shadow_status *x)
113 {
114 unsigned long *p;
115 int restart = 0;
116 struct pfn_info *spage = &frame_table[x->spfn_and_flags & PSH_pfn_mask];
118 switch ( spage->u.inuse.type_info & PGT_type_mask )
119 {
120 /* We clear L2 pages by zeroing the guest entries. */
121 case PGT_l2_page_table:
122 p = map_domain_mem((spage - frame_table) << PAGE_SHIFT);
123 if (m->shadow_mode == SHM_full_32)
124 memset(p, 0, ENTRIES_PER_L2_PAGETABLE * sizeof(*p));
125 else
126 memset(p, 0, DOMAIN_ENTRIES_PER_L2_PAGETABLE * sizeof(*p));
127 unmap_domain_mem(p);
128 break;
130 /* We clear L1 pages by freeing them: no benefit from zeroing them. */
131 case PGT_l1_page_table:
132 delete_shadow_status(m, x->pfn);
133 free_shadow_page(m, spage);
134 restart = 1; /* We need to go to start of list again. */
135 break;
136 }
138 return restart;
139 }
141 static void clear_shadow_state(struct mm_struct *m)
142 {
143 int i;
144 struct shadow_status *x;
146 shadow_audit(m, 1);
148 for ( i = 0; i < shadow_ht_buckets; i++ )
149 {
150 retry:
151 /* Skip empty buckets. */
152 x = &m->shadow_ht[i];
153 if ( x->pfn == 0 )
154 continue;
156 if ( clear_shadow_page(m, x) )
157 goto retry;
159 for ( x = x->next; x != NULL; x = x->next )
160 if ( clear_shadow_page(m, x) )
161 goto retry;
163 shadow_audit(m, 0);
164 }
166 SH_VLOG("Scan shadow table. l1=%d l2=%d",
167 perfc_value(shadow_l1_pages), perfc_value(shadow_l2_pages));
168 }
171 void shadow_mode_init(void)
172 {
173 }
175 int shadow_mode_enable(struct domain *p, unsigned int mode)
176 {
177 struct mm_struct *m = &p->exec_domain[0]->mm;
179 m->shadow_ht = xmalloc_array(struct shadow_status, shadow_ht_buckets);
180 if ( m->shadow_ht == NULL )
181 goto nomem;
182 memset(m->shadow_ht, 0, shadow_ht_buckets * sizeof(struct shadow_status));
184 if ( mode == SHM_logdirty )
185 {
186 m->shadow_dirty_bitmap_size = (p->max_pages + 63) & ~63;
187 m->shadow_dirty_bitmap =
188 xmalloc_array(unsigned long, m->shadow_dirty_bitmap_size /
189 (8 * sizeof(unsigned long)));
190 if ( m->shadow_dirty_bitmap == NULL )
191 {
192 m->shadow_dirty_bitmap_size = 0;
193 goto nomem;
194 }
195 memset(m->shadow_dirty_bitmap, 0, m->shadow_dirty_bitmap_size/8);
196 }
198 m->shadow_mode = mode;
200 __shadow_mk_pagetable(m);
201 return 0;
203 nomem:
204 if ( m->shadow_ht != NULL )
205 xfree( m->shadow_ht );
206 m->shadow_ht = NULL;
207 return -ENOMEM;
208 }
210 void __shadow_mode_disable(struct domain *d)
211 {
212 struct mm_struct *m = &d->exec_domain[0]->mm;
213 struct shadow_status *x, *n;
215 free_shadow_state(m);
216 m->shadow_mode = 0;
218 SH_VLOG("freed tables count=%d l1=%d l2=%d",
219 m->shadow_page_count, perfc_value(shadow_l1_pages),
220 perfc_value(shadow_l2_pages));
222 n = m->shadow_ht_extras;
223 while ( (x = n) != NULL )
224 {
225 m->shadow_extras_count--;
226 n = *((struct shadow_status **)(&x[shadow_ht_extra_size]));
227 xfree(x);
228 }
230 m->shadow_ht_extras = NULL;
231 ASSERT(m->shadow_extras_count == 0);
232 SH_LOG("freed extras, now %d", m->shadow_extras_count);
234 if ( m->shadow_dirty_bitmap != NULL )
235 {
236 xfree(m->shadow_dirty_bitmap);
237 m->shadow_dirty_bitmap = 0;
238 m->shadow_dirty_bitmap_size = 0;
239 }
241 xfree(m->shadow_ht);
242 m->shadow_ht = NULL;
243 }
245 static int shadow_mode_table_op(
246 struct domain *d, dom0_shadow_control_t *sc)
247 {
248 unsigned int op = sc->op;
249 struct mm_struct *m = &d->exec_domain[0]->mm;
250 int i, rc = 0;
252 ASSERT(spin_is_locked(&m->shadow_lock));
254 SH_VLOG("shadow mode table op %08lx %08lx count %d",
255 pagetable_val(m->pagetable), pagetable_val(m->shadow_table),
256 m->shadow_page_count);
258 shadow_audit(m, 1);
260 switch ( op )
261 {
262 case DOM0_SHADOW_CONTROL_OP_FLUSH:
263 free_shadow_state(m);
265 m->shadow_fault_count = 0;
266 m->shadow_dirty_count = 0;
267 m->shadow_dirty_net_count = 0;
268 m->shadow_dirty_block_count = 0;
270 break;
272 case DOM0_SHADOW_CONTROL_OP_CLEAN:
273 clear_shadow_state(m);
275 sc->stats.fault_count = m->shadow_fault_count;
276 sc->stats.dirty_count = m->shadow_dirty_count;
277 sc->stats.dirty_net_count = m->shadow_dirty_net_count;
278 sc->stats.dirty_block_count = m->shadow_dirty_block_count;
280 m->shadow_fault_count = 0;
281 m->shadow_dirty_count = 0;
282 m->shadow_dirty_net_count = 0;
283 m->shadow_dirty_block_count = 0;
285 if ( (d->max_pages > sc->pages) ||
286 (sc->dirty_bitmap == NULL) ||
287 (m->shadow_dirty_bitmap == NULL) )
288 {
289 rc = -EINVAL;
290 break;
291 }
293 sc->pages = d->max_pages;
295 #define chunk (8*1024) /* Transfer and clear in 1kB chunks for L1 cache. */
296 for ( i = 0; i < d->max_pages; i += chunk )
297 {
298 int bytes = ((((d->max_pages - i) > chunk) ?
299 chunk : (d->max_pages - i)) + 7) / 8;
301 if (copy_to_user(
302 sc->dirty_bitmap + (i/(8*sizeof(unsigned long))),
303 m->shadow_dirty_bitmap +(i/(8*sizeof(unsigned long))),
304 bytes))
305 {
306 // copy_to_user can fail when copying to guest app memory.
307 // app should zero buffer after mallocing, and pin it
308 rc = -EINVAL;
309 memset(
310 m->shadow_dirty_bitmap + (i/(8*sizeof(unsigned long))),
311 0, (d->max_pages/8) - (i/(8*sizeof(unsigned long))));
312 break;
313 }
315 memset(
316 m->shadow_dirty_bitmap + (i/(8*sizeof(unsigned long))),
317 0, bytes);
318 }
320 break;
322 case DOM0_SHADOW_CONTROL_OP_PEEK:
323 sc->stats.fault_count = m->shadow_fault_count;
324 sc->stats.dirty_count = m->shadow_dirty_count;
325 sc->stats.dirty_net_count = m->shadow_dirty_net_count;
326 sc->stats.dirty_block_count = m->shadow_dirty_block_count;
328 if ( (d->max_pages > sc->pages) ||
329 (sc->dirty_bitmap == NULL) ||
330 (m->shadow_dirty_bitmap == NULL) )
331 {
332 rc = -EINVAL;
333 break;
334 }
336 sc->pages = d->max_pages;
337 if (copy_to_user(
338 sc->dirty_bitmap, m->shadow_dirty_bitmap, (d->max_pages+7)/8))
339 {
340 rc = -EINVAL;
341 break;
342 }
344 break;
346 default:
347 rc = -EINVAL;
348 break;
349 }
351 SH_VLOG("shadow mode table op : page count %d", m->shadow_page_count);
352 shadow_audit(m, 1);
353 __shadow_mk_pagetable(m);
354 return rc;
355 }
357 int shadow_mode_control(struct domain *d, dom0_shadow_control_t *sc)
358 {
359 unsigned int op = sc->op;
360 int rc = 0;
362 if ( unlikely(d == current->domain) )
363 {
364 DPRINTK("Don't try to do a shadow op on yourself!\n");
365 return -EINVAL;
366 }
368 domain_pause(d);
369 synchronise_pagetables(~0UL);
371 shadow_lock(&d->exec_domain[0]->mm);
373 switch ( op )
374 {
375 case DOM0_SHADOW_CONTROL_OP_OFF:
376 shadow_mode_disable(d);
377 break;
379 case DOM0_SHADOW_CONTROL_OP_ENABLE_TEST:
380 shadow_mode_disable(d);
381 rc = shadow_mode_enable(d, SHM_test);
382 break;
384 case DOM0_SHADOW_CONTROL_OP_ENABLE_LOGDIRTY:
385 shadow_mode_disable(d);
386 rc = shadow_mode_enable(d, SHM_logdirty);
387 break;
389 default:
390 rc = shadow_mode(d->exec_domain[0]) ? shadow_mode_table_op(d, sc) : -EINVAL;
391 break;
392 }
394 shadow_unlock(&d->exec_domain[0]->mm);
396 domain_unpause(d);
398 return rc;
399 }
401 static inline struct pfn_info *alloc_shadow_page(struct mm_struct *m)
402 {
403 struct pfn_info *page = alloc_domheap_page(NULL);
405 m->shadow_page_count++;
407 if ( unlikely(page == NULL) )
408 {
409 printk("Couldn't alloc shadow page! count=%d\n",
410 m->shadow_page_count);
411 SH_VLOG("Shadow tables l1=%d l2=%d",
412 perfc_value(shadow_l1_pages),
413 perfc_value(shadow_l2_pages));
414 BUG(); /* XXX FIXME: try a shadow flush to free up some memory. */
415 }
417 return page;
418 }
420 void unshadow_table(unsigned long gpfn, unsigned int type)
421 {
422 unsigned long spfn;
423 struct domain *d = page_get_owner(&frame_table[gpfn]);
425 SH_VLOG("unshadow_table type=%08x gpfn=%08lx", type, gpfn);
427 perfc_incrc(unshadow_table_count);
429 /*
430 * This function is the same for all p.t. pages. Even for multi-processor
431 * guests there won't be a race here as this CPU was the one that
432 * cmpxchg'ed the page to invalid.
433 */
434 spfn = __shadow_status(&d->exec_domain[0]->mm, gpfn) & PSH_pfn_mask;
435 delete_shadow_status(&d->exec_domain[0]->mm, gpfn);
436 free_shadow_page(&d->exec_domain[0]->mm, &frame_table[spfn]);
437 }
439 #ifdef CONFIG_VMX
440 void vmx_shadow_clear_state(struct mm_struct *m)
441 {
442 SH_VVLOG("vmx_clear_shadow_state: \n");
443 clear_shadow_state(m);
444 }
445 #endif
448 unsigned long shadow_l2_table(
449 struct mm_struct *m, unsigned long gpfn)
450 {
451 struct pfn_info *spfn_info;
452 unsigned long spfn;
453 l2_pgentry_t *spl2e = 0;
454 unsigned long guest_gpfn;
456 __get_machine_to_phys(m, guest_gpfn, gpfn);
458 SH_VVLOG("shadow_l2_table( %08lx )", gpfn);
460 perfc_incrc(shadow_l2_table_count);
462 if ( (spfn_info = alloc_shadow_page(m)) == NULL )
463 BUG(); /* XXX Deal gracefully with failure. */
465 spfn_info->u.inuse.type_info = PGT_l2_page_table;
466 perfc_incr(shadow_l2_pages);
468 spfn = spfn_info - frame_table;
469 /* Mark pfn as being shadowed; update field to point at shadow. */
470 set_shadow_status(m, guest_gpfn, spfn | PSH_shadowed);
472 #ifdef __i386__
473 /* Install hypervisor and 2x linear p.t. mapings. */
474 if ( m->shadow_mode == SHM_full_32 )
475 {
476 vmx_update_shadow_state(m, gpfn, spfn);
477 }
478 else
479 {
480 spl2e = (l2_pgentry_t *)map_domain_mem(spfn << PAGE_SHIFT);
481 /*
482 * We could proactively fill in PDEs for pages that are already
483 * shadowed. However, we tried it and it didn't help performance.
484 * This is simpler.
485 */
486 memset(spl2e, 0, DOMAIN_ENTRIES_PER_L2_PAGETABLE*sizeof(l2_pgentry_t));
488 /* Install hypervisor and 2x linear p.t. mapings. */
489 memcpy(&spl2e[DOMAIN_ENTRIES_PER_L2_PAGETABLE],
490 &idle_pg_table[DOMAIN_ENTRIES_PER_L2_PAGETABLE],
491 HYPERVISOR_ENTRIES_PER_L2_PAGETABLE * sizeof(l2_pgentry_t));
492 spl2e[LINEAR_PT_VIRT_START >> L2_PAGETABLE_SHIFT] =
493 mk_l2_pgentry((gpfn << PAGE_SHIFT) | __PAGE_HYPERVISOR);
494 spl2e[SH_LINEAR_PT_VIRT_START >> L2_PAGETABLE_SHIFT] =
495 mk_l2_pgentry((spfn << PAGE_SHIFT) | __PAGE_HYPERVISOR);
496 spl2e[PERDOMAIN_VIRT_START >> L2_PAGETABLE_SHIFT] =
497 mk_l2_pgentry(__pa(page_get_owner(&frame_table[gpfn])->mm_perdomain_pt) |
498 __PAGE_HYPERVISOR);
499 }
500 #endif
502 if ( m->shadow_mode != SHM_full_32 )
503 unmap_domain_mem(spl2e);
505 SH_VLOG("shadow_l2_table( %08lx -> %08lx)", gpfn, spfn);
506 return spfn;
507 }
509 static void shadow_map_l1_into_current_l2(unsigned long va)
510 {
511 struct mm_struct *m = &current->mm;
512 unsigned long *gpl1e, *spl1e, gpl2e, spl2e, gl1pfn, sl1pfn=0, sl1ss;
513 struct pfn_info *sl1pfn_info;
514 int i;
516 __guest_get_pl2e(m, va, &gpl2e);
518 gl1pfn = gpl2e >> PAGE_SHIFT;
520 sl1ss = __shadow_status(m, gl1pfn);
521 if ( !(sl1ss & PSH_shadowed) )
522 {
523 /* This L1 is NOT already shadowed so we need to shadow it. */
524 SH_VVLOG("4a: l1 not shadowed ( %08lx )", sl1pfn);
526 sl1pfn_info = alloc_shadow_page(m);
527 sl1pfn_info->u.inuse.type_info = PGT_l1_page_table;
529 sl1pfn = sl1pfn_info - frame_table;
531 perfc_incrc(shadow_l1_table_count);
532 perfc_incr(shadow_l1_pages);
534 set_shadow_status(m, gl1pfn, PSH_shadowed | sl1pfn);
536 l2pde_general(m, &gpl2e, &spl2e, sl1pfn);
538 __guest_set_pl2e(m, va, gpl2e);
539 __shadow_set_pl2e(m, va, spl2e);
541 gpl1e = (unsigned long *) &(linear_pg_table[
542 (va>>L1_PAGETABLE_SHIFT) & ~(ENTRIES_PER_L1_PAGETABLE-1)]);
544 spl1e = (unsigned long *) &(shadow_linear_pg_table[
545 (va>>L1_PAGETABLE_SHIFT) & ~(ENTRIES_PER_L1_PAGETABLE-1)]);
547 for ( i = 0; i < ENTRIES_PER_L1_PAGETABLE; i++ )
548 l1pte_propagate_from_guest(m, &gpl1e[i], &spl1e[i]);
549 }
550 else
551 {
552 /* This L1 is shadowed already, but the L2 entry is missing. */
553 SH_VVLOG("4b: was shadowed, l2 missing ( %08lx )", sl1pfn);
555 sl1pfn = sl1ss & PSH_pfn_mask;
556 l2pde_general(m, &gpl2e, &spl2e, sl1pfn);
557 __guest_set_pl2e(m, va, gpl2e);
558 __shadow_set_pl2e(m, va, spl2e);
559 }
560 }
562 #ifdef CONFIG_VMX
563 void vmx_shadow_invlpg(struct mm_struct *m, unsigned long va)
564 {
565 unsigned long gpte, spte, host_pfn;
567 if (__put_user(0L, (unsigned long *)
568 &shadow_linear_pg_table[va >> PAGE_SHIFT])) {
569 vmx_shadow_clear_state(m);
570 return;
571 }
573 if (__get_user(gpte, (unsigned long *)
574 &linear_pg_table[va >> PAGE_SHIFT])) {
575 return;
576 }
578 host_pfn = phys_to_machine_mapping[gpte >> PAGE_SHIFT];
579 spte = (host_pfn << PAGE_SHIFT) | (gpte & ~PAGE_MASK);
581 if (__put_user(spte, (unsigned long *)
582 &shadow_linear_pg_table[va >> PAGE_SHIFT])) {
583 return;
584 }
585 }
586 #endif
588 int shadow_fault(unsigned long va, long error_code)
589 {
590 unsigned long gpte, spte;
591 struct mm_struct *m = &current->mm;
593 SH_VVLOG("shadow_fault( va=%08lx, code=%ld )", va, error_code );
595 check_pagetable(m, current->mm.pagetable, "pre-sf");
597 /*
598 * STEP 1. A fast-reject set of checks with no locking.
599 */
601 if ( unlikely(__get_user(gpte, (unsigned long *)
602 &linear_pg_table[va >> PAGE_SHIFT])) )
603 {
604 SH_VVLOG("shadow_fault - EXIT: read gpte faulted" );
605 return 0;
606 }
608 if ( !(gpte & _PAGE_PRESENT) )
609 {
610 SH_VVLOG("shadow_fault - EXIT: gpte not present (%lx)",gpte );
611 return 0;
612 }
614 if ( (error_code & 2) && !(gpte & _PAGE_RW) )
615 {
616 /* Write fault on a read-only mapping. */
617 return 0;
618 }
620 /*
621 * STEP 2. Take the shadow lock and re-check the guest PTE.
622 */
624 shadow_lock(m);
626 if ( unlikely(__get_user(gpte, (unsigned long *)
627 &linear_pg_table[va >> PAGE_SHIFT])) )
628 {
629 SH_VVLOG("shadow_fault - EXIT: read gpte faulted" );
630 shadow_unlock(m);
631 return 0;
632 }
634 if ( unlikely(!(gpte & _PAGE_PRESENT)) )
635 {
636 SH_VVLOG("shadow_fault - EXIT: gpte not present (%lx)",gpte );
637 shadow_unlock(m);
638 return 0;
639 }
641 /* Write fault? */
642 if ( error_code & 2 )
643 {
644 if ( unlikely(!(gpte & _PAGE_RW)) )
645 {
646 /* Write fault on a read-only mapping. */
647 SH_VVLOG("shadow_fault - EXIT: wr fault on RO page (%lx)", gpte);
648 shadow_unlock(m);
649 return 0;
650 }
652 l1pte_write_fault(m, &gpte, &spte);
653 }
654 else
655 {
656 l1pte_read_fault(m, &gpte, &spte);
657 }
659 /*
660 * STEP 3. Write the modified shadow PTE and guest PTE back to the tables.
661 */
663 /* XXX Watch out for read-only L2 entries! (not used in Linux). */
664 if ( unlikely(__put_user(gpte, (unsigned long *)
665 &linear_pg_table[va >> PAGE_SHIFT])) )
666 domain_crash();
668 /*
669 * Update of shadow PTE can fail because the L1 p.t. is not shadowed,
670 * or because the shadow isn't linked into this shadow L2 p.t.
671 */
672 if ( unlikely(__put_user(spte, (unsigned long *)
673 &shadow_linear_pg_table[va >> PAGE_SHIFT])) )
674 {
675 SH_VVLOG("3: not shadowed/mapped gpte=%08lx spte=%08lx", gpte, spte);
676 shadow_map_l1_into_current_l2(va);
677 shadow_linear_pg_table[va >> PAGE_SHIFT] = mk_l1_pgentry(spte);
678 }
680 perfc_incrc(shadow_fixup_count);
681 m->shadow_fault_count++;
683 shadow_unlock(m);
685 check_pagetable(m, current->mm.pagetable, "post-sf");
686 return EXCRET_fault_fixed;
687 }
690 void shadow_l1_normal_pt_update(
691 unsigned long pa, unsigned long gpte,
692 unsigned long *prev_spfn_ptr,
693 l1_pgentry_t **prev_spl1e_ptr)
694 {
695 unsigned long spfn, spte, prev_spfn = *prev_spfn_ptr;
696 l1_pgentry_t *spl1e, *prev_spl1e = *prev_spl1e_ptr;
698 /* N.B. To get here, we know the l1 page *must* be shadowed. */
699 SH_VVLOG("shadow_l1_normal_pt_update pa=%08lx, gpte=%08lx, "
700 "prev_spfn=%08lx, prev_spl1e=%p\n",
701 pa, gpte, prev_spfn, prev_spl1e);
703 spfn = __shadow_status(&current->mm, pa >> PAGE_SHIFT) & PSH_pfn_mask;
705 if ( spfn == prev_spfn )
706 {
707 spl1e = prev_spl1e;
708 }
709 else
710 {
711 if ( prev_spl1e != NULL )
712 unmap_domain_mem( prev_spl1e );
713 spl1e = (l1_pgentry_t *)map_domain_mem(spfn << PAGE_SHIFT);
714 *prev_spfn_ptr = spfn;
715 *prev_spl1e_ptr = spl1e;
716 }
718 l1pte_propagate_from_guest(&current->mm, &gpte, &spte);
719 spl1e[(pa & ~PAGE_MASK) / sizeof(l1_pgentry_t)] = mk_l1_pgentry(spte);
720 }
722 void shadow_l2_normal_pt_update(unsigned long pa, unsigned long gpte)
723 {
724 unsigned long spfn, spte;
725 l2_pgentry_t *spl2e;
726 unsigned long s_sh;
728 /* N.B. To get here, we know the l2 page *must* be shadowed. */
729 SH_VVLOG("shadow_l2_normal_pt_update pa=%08lx, gpte=%08lx",pa,gpte);
731 spfn = __shadow_status(&current->mm, pa >> PAGE_SHIFT) & PSH_pfn_mask;
733 s_sh = (gpte & _PAGE_PRESENT) ?
734 __shadow_status(&current->mm, gpte >> PAGE_SHIFT) : 0;
736 /* XXXX Should mark guest pte as DIRTY and ACCESSED too! */
737 l2pde_general(&current->mm, &gpte, &spte, s_sh);
738 spl2e = (l2_pgentry_t *)map_domain_mem(spfn << PAGE_SHIFT);
739 spl2e[(pa & ~PAGE_MASK) / sizeof(l2_pgentry_t)] = mk_l2_pgentry(spte);
740 unmap_domain_mem(spl2e);
741 }
746 /************************************************************************/
747 /************************************************************************/
748 /************************************************************************/
750 #if SHADOW_DEBUG
752 static int sh_l2_present;
753 static int sh_l1_present;
754 char * sh_check_name;
756 #define FAIL(_f, _a...) \
757 do { \
758 printk("XXX %s-FAIL (%d,%d)" _f " g=%08lx s=%08lx\n", \
759 sh_check_name, level, i, ## _a , gpte, spte); \
760 BUG(); \
761 } while ( 0 )
763 static int check_pte(
764 struct mm_struct *m, unsigned long gpte, unsigned long spte,
765 int level, int i)
766 {
767 unsigned long mask, gpfn, spfn;
768 #ifdef CONFIG_VMX
769 unsigned long guest_gpfn;
770 #endif
772 if ( (spte == 0) || (spte == 0xdeadface) || (spte == 0x00000E00) )
773 return 1; /* always safe */
775 if ( !(spte & _PAGE_PRESENT) )
776 FAIL("Non zero not present spte");
778 if ( level == 2 ) sh_l2_present++;
779 if ( level == 1 ) sh_l1_present++;
781 if ( !(gpte & _PAGE_PRESENT) )
782 FAIL("Guest not present yet shadow is");
784 mask = ~(_PAGE_DIRTY|_PAGE_ACCESSED|_PAGE_RW|0xFFFFF000);
786 if ( (spte & mask) != (gpte & mask) )
787 FAIL("Corrupt?");
789 if ( (spte & _PAGE_DIRTY ) && !(gpte & _PAGE_DIRTY) )
790 FAIL("Dirty coherence");
792 if ( (spte & _PAGE_ACCESSED ) && !(gpte & _PAGE_ACCESSED) )
793 FAIL("Accessed coherence");
795 if ( (spte & _PAGE_RW ) && !(gpte & _PAGE_RW) )
796 FAIL("RW coherence");
798 if ( (spte & _PAGE_RW ) && !((gpte & _PAGE_RW) && (gpte & _PAGE_DIRTY)) )
799 FAIL("RW2 coherence");
801 spfn = spte >> PAGE_SHIFT;
802 gpfn = gpte >> PAGE_SHIFT;
804 if ( gpfn == spfn )
805 {
806 if ( level > 1 )
807 FAIL("Linear map ???"); /* XXX this will fail on BSD */
808 }
809 else
810 {
811 if ( level < 2 )
812 FAIL("Shadow in L1 entry?");
814 if (m->shadow_mode == SHM_full_32) {
816 guest_gpfn = phys_to_machine_mapping[gpfn];
818 if ( __shadow_status(m, guest_gpfn) != (PSH_shadowed | spfn) )
819 FAIL("spfn problem g.sf=%08lx",
820 __shadow_status(m, guest_gpfn) );
822 } else {
823 if ( __shadow_status(m, gpfn) != (PSH_shadowed | spfn) )
824 FAIL("spfn problem g.sf=%08lx",
825 __shadow_status(m, gpfn) );
826 }
828 }
830 return 1;
831 }
834 static int check_l1_table(
835 struct mm_struct *m, unsigned long va,
836 unsigned long g2, unsigned long s2)
837 {
838 int i;
839 unsigned long *gpl1e, *spl1e;
841 gpl1e = map_domain_mem(g2 << PAGE_SHIFT);
842 spl1e = map_domain_mem(s2 << PAGE_SHIFT);
844 for ( i = 0; i < ENTRIES_PER_L1_PAGETABLE; i++ )
845 check_pte(m, gpl1e[i], spl1e[i], 1, i);
847 unmap_domain_mem(spl1e);
848 unmap_domain_mem(gpl1e);
850 return 1;
851 }
853 #define FAILPT(_f, _a...) \
854 do { \
855 printk("XXX FAIL %s-PT" _f "\n", s, ## _a ); \
856 BUG(); \
857 } while ( 0 )
859 int check_pagetable(struct mm_struct *m, pagetable_t pt, char *s)
860 {
861 unsigned long gptbase = pagetable_val(pt);
862 unsigned long gpfn, spfn;
863 int i;
864 l2_pgentry_t *gpl2e, *spl2e;
865 unsigned long host_gpfn = 0;
867 sh_check_name = s;
869 SH_VVLOG("%s-PT Audit", s);
871 sh_l2_present = sh_l1_present = 0;
873 gpfn = gptbase >> PAGE_SHIFT;
875 __get_phys_to_machine(m, host_gpfn, gpfn);
877 if ( ! (__shadow_status(m, gpfn) & PSH_shadowed) )
878 {
879 printk("%s-PT %08lx not shadowed\n", s, gptbase);
881 if( __shadow_status(m, gpfn) != 0 ) BUG();
882 return 0;
883 }
885 spfn = __shadow_status(m, gpfn) & PSH_pfn_mask;
887 if ( ! __shadow_status(m, gpfn) == (PSH_shadowed | spfn) )
888 FAILPT("ptbase shadow inconsistent1");
890 if (m->shadow_mode == SHM_full_32)
891 {
892 host_gpfn = phys_to_machine_mapping[gpfn];
893 gpl2e = (l2_pgentry_t *) map_domain_mem( host_gpfn << PAGE_SHIFT );
895 } else
896 gpl2e = (l2_pgentry_t *) map_domain_mem( gpfn << PAGE_SHIFT );
898 spl2e = (l2_pgentry_t *) map_domain_mem( spfn << PAGE_SHIFT );
900 if ( memcmp(&spl2e[DOMAIN_ENTRIES_PER_L2_PAGETABLE],
901 &gpl2e[DOMAIN_ENTRIES_PER_L2_PAGETABLE],
902 ((SH_LINEAR_PT_VIRT_START >> L2_PAGETABLE_SHIFT) -
903 DOMAIN_ENTRIES_PER_L2_PAGETABLE) * sizeof(l2_pgentry_t)) )
904 {
905 for ( i = DOMAIN_ENTRIES_PER_L2_PAGETABLE;
906 i < (SH_LINEAR_PT_VIRT_START >> L2_PAGETABLE_SHIFT);
907 i++ )
908 printk("+++ (%d) %08lx %08lx\n",i,
909 l2_pgentry_val(gpl2e[i]), l2_pgentry_val(spl2e[i]));
910 FAILPT("hypervisor entries inconsistent");
911 }
913 if ( (l2_pgentry_val(spl2e[LINEAR_PT_VIRT_START >> L2_PAGETABLE_SHIFT]) !=
914 l2_pgentry_val(gpl2e[LINEAR_PT_VIRT_START >> L2_PAGETABLE_SHIFT])) )
915 FAILPT("hypervisor linear map inconsistent");
917 if ( (l2_pgentry_val(spl2e[SH_LINEAR_PT_VIRT_START >>
918 L2_PAGETABLE_SHIFT]) !=
919 ((spfn << PAGE_SHIFT) | __PAGE_HYPERVISOR)) )
920 FAILPT("hypervisor shadow linear map inconsistent %08lx %08lx",
921 l2_pgentry_val(spl2e[SH_LINEAR_PT_VIRT_START >>
922 L2_PAGETABLE_SHIFT]),
923 (spfn << PAGE_SHIFT) | __PAGE_HYPERVISOR);
925 if (m->shadow_mode != SHM_full_32) {
926 if ( (l2_pgentry_val(spl2e[PERDOMAIN_VIRT_START >> L2_PAGETABLE_SHIFT]) !=
927 ((__pa(page_get_owner(&frame_table[gpfn])->mm.perdomain_pt) |
928 __PAGE_HYPERVISOR))) )
929 FAILPT("hypervisor per-domain map inconsistent");
930 }
932 /* Check the whole L2. */
933 for ( i = 0; i < DOMAIN_ENTRIES_PER_L2_PAGETABLE; i++ )
934 check_pte(m, l2_pgentry_val(gpl2e[i]), l2_pgentry_val(spl2e[i]), 2, i);
936 /* Go back and recurse. */
937 for ( i = 0; i < DOMAIN_ENTRIES_PER_L2_PAGETABLE; i++ )
938 {
939 if ( l2_pgentry_val(spl2e[i]) != 0 )
940 check_l1_table(
941 m, i << L2_PAGETABLE_SHIFT,
942 l2_pgentry_val(gpl2e[i]) >> PAGE_SHIFT,
943 l2_pgentry_val(spl2e[i]) >> PAGE_SHIFT);
944 }
946 unmap_domain_mem(spl2e);
947 unmap_domain_mem(gpl2e);
949 SH_VVLOG("PT verified : l2_present = %d, l1_present = %d\n",
950 sh_l2_present, sh_l1_present);
952 return 1;
953 }
955 #endif