xen-vtx-unstable

view xen/arch/x86/audit.c @ 6759:b5d91089e42c

Newer binutils is a bit stricter and errors out when you try
to use movl on a 16 bit word on x86_64. Using just a "mov"
compiles fine and should result in the same code.

{standard input}: Assembler messages:
{standard input}:2138: Error: suffix or operands invalid for `mov'
{standard input}:2140: Error: suffix or operands invalid for `mov'
{standard input}:2142: Error: suffix or operands invalid for `mov'
{standard input}:2144: Error: suffix or operands invalid for `mov'

Signed-off-by: Rik van Riel <riel@redhat.com>
author kaf24@firebug.cl.cam.ac.uk
date Tue Sep 13 10:21:22 2005 +0000 (2005-09-13)
parents dd668f7527cb
children
line source
1 /******************************************************************************
2 * arch/x86/audit.c
3 *
4 * Copyright (c) 2002-2005 K A Fraser
5 * Copyright (c) 2004 Christian Limpach
6 * Copyright (c) 2005 Michael A Fetterman
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
23 #include <xen/config.h>
24 #include <xen/init.h>
25 #include <xen/kernel.h>
26 #include <xen/lib.h>
27 #include <xen/mm.h>
28 #include <xen/perfc.h>
29 #include <asm/shadow.h>
30 #include <asm/page.h>
31 #include <asm/flushtlb.h>
33 /* XXX SMP bug -- these should not be statics... */
34 static int ttot=0, ctot=0, io_mappings=0, lowmem_mappings=0;
35 static int l1, l2, oos_count, page_count;
37 #define FILE_AND_LINE 0
39 #if FILE_AND_LINE
40 #define adjust(_p, _a) _adjust((_p), (_a), __FILE__, __LINE__)
41 #define ADJUST_EXTRA_ARGS ,const char *file, int line
42 #define APRINTK(_f, _a...) printk(_f " %s:%d\n", ## _a, file, line)
43 #else
44 #define adjust _adjust
45 #define ADJUST_EXTRA_ARGS
46 #define APRINTK(_f, _a...) printk(_f "\n", ##_a)
47 #endif
49 int audit_adjust_pgtables(struct domain *d, int dir, int noisy)
50 {
51 int errors = 0;
52 int shadow_refcounts = !!shadow_mode_refcounts(d);
53 int shadow_enabled = !!shadow_mode_enabled(d);
54 int l2limit;
56 void _adjust(struct pfn_info *page, int adjtype ADJUST_EXTRA_ARGS)
57 {
58 if ( adjtype )
59 {
60 // adjust the type count
61 //
62 int tcount = page->u.inuse.type_info & PGT_count_mask;
63 tcount += dir;
64 ttot++;
66 if ( page_get_owner(page) == NULL )
67 {
68 APRINTK("adjust(mfn=%lx, dir=%d, adjtype=%d) owner=NULL",
69 page_to_pfn(page), dir, adjtype);
70 errors++;
71 }
73 if ( tcount < 0 )
74 {
75 APRINTK("Audit %d: type count went below zero "
76 "mfn=%lx t=%" PRtype_info " ot=%x",
77 d->domain_id, page_to_pfn(page),
78 page->u.inuse.type_info,
79 page->tlbflush_timestamp);
80 errors++;
81 }
82 else if ( (tcount & ~PGT_count_mask) != 0 )
83 {
84 APRINTK("Audit %d: type count overflowed "
85 "mfn=%lx t=%" PRtype_info " ot=%x",
86 d->domain_id, page_to_pfn(page),
87 page->u.inuse.type_info,
88 page->tlbflush_timestamp);
89 errors++;
90 }
91 else
92 page->u.inuse.type_info += dir;
93 }
95 // adjust the general count
96 //
97 int count = page->count_info & PGC_count_mask;
98 count += dir;
99 ctot++;
101 if ( count < 0 )
102 {
103 APRINTK("Audit %d: general count went below zero "
104 "mfn=%lx t=%" PRtype_info " ot=%x",
105 d->domain_id, page_to_pfn(page),
106 page->u.inuse.type_info,
107 page->tlbflush_timestamp);
108 errors++;
109 }
110 else if ( (count & ~PGT_count_mask) != 0 )
111 {
112 APRINTK("Audit %d: general count overflowed "
113 "mfn=%lx t=%" PRtype_info " ot=%x",
114 d->domain_id, page_to_pfn(page),
115 page->u.inuse.type_info,
116 page->tlbflush_timestamp);
117 errors++;
118 }
119 else
120 page->count_info += dir;
121 }
123 void adjust_l2_page(unsigned long mfn, int shadow)
124 {
125 unsigned long *pt = map_domain_page(mfn);
126 int i;
128 for ( i = 0; i < l2limit; i++ )
129 {
130 if ( pt[i] & _PAGE_PRESENT )
131 {
132 unsigned long l1mfn = pt[i] >> PAGE_SHIFT;
133 struct pfn_info *l1page = pfn_to_page(l1mfn);
135 if ( noisy )
136 {
137 if ( shadow )
138 {
139 if ( page_get_owner(l1page) != NULL )
140 {
141 printk("L2: Bizarre shadow L1 page mfn=%lx "
142 "belonging to a domain %p (id=%d)\n",
143 l1mfn,
144 page_get_owner(l1page),
145 page_get_owner(l1page)->domain_id);
146 errors++;
147 continue;
148 }
150 u32 page_type = l1page->u.inuse.type_info & PGT_type_mask;
152 if ( page_type != PGT_l1_shadow )
153 {
154 printk("Audit %d: [Shadow L2 mfn=%lx i=%x] "
155 "Expected Shadow L1 t=%" PRtype_info
156 " mfn=%lx\n",
157 d->domain_id, mfn, i,
158 l1page->u.inuse.type_info, l1mfn);
159 errors++;
160 }
161 }
162 else
163 {
164 if ( page_get_owner(l1page) != d )
165 {
166 printk("L2: Skip bizarre L1 page mfn=%lx "
167 "belonging to other dom %p (id=%d)\n",
168 l1mfn,
169 page_get_owner(l1page),
170 (page_get_owner(l1page)
171 ? page_get_owner(l1page)->domain_id
172 : -1));
173 errors++;
174 continue;
175 }
177 u32 page_type = l1page->u.inuse.type_info & PGT_type_mask;
179 if ( page_type == PGT_l2_page_table )
180 {
181 printk("Audit %d: [%x] Found %s Linear PT "
182 "t=%" PRtype_info " mfn=%lx\n",
183 d->domain_id, i, (l1mfn==mfn) ? "Self" : "Other",
184 l1page->u.inuse.type_info, l1mfn);
185 }
186 else if ( page_type != PGT_l1_page_table )
187 {
188 printk("Audit %d: [L2 mfn=%lx i=%x] "
189 "Expected L1 t=%" PRtype_info " mfn=%lx\n",
190 d->domain_id, mfn, i,
191 l1page->u.inuse.type_info, l1mfn);
192 errors++;
193 }
194 }
195 }
197 adjust(l1page, !shadow);
198 }
199 }
201 if ( shadow_mode_translate(d) && !shadow_mode_external(d) )
202 {
203 unsigned long hl2mfn =
204 pt[l2_table_offset(LINEAR_PT_VIRT_START)] >> PAGE_SHIFT;
205 struct pfn_info *hl2page = pfn_to_page(hl2mfn);
206 adjust(hl2page, 0);
207 }
209 unmap_domain_page(pt);
210 }
212 void adjust_hl2_page(unsigned long hl2mfn)
213 {
214 unsigned long *pt = map_domain_page(hl2mfn);
215 int i;
217 for ( i = 0; i < l2limit; i++ )
218 {
219 if ( pt[i] & _PAGE_PRESENT )
220 {
221 unsigned long gmfn = pt[i] >> PAGE_SHIFT;
222 struct pfn_info *gpage = pfn_to_page(gmfn);
224 if ( gmfn < 0x100 )
225 {
226 lowmem_mappings++;
227 continue;
228 }
230 if ( gmfn > max_page )
231 {
232 io_mappings++;
233 continue;
234 }
236 if ( noisy )
237 {
238 if ( page_get_owner(gpage) != d )
239 {
240 printk("Audit %d: [hl2mfn=%lx,i=%x] Skip foreign page "
241 "dom=%p (id=%d) mfn=%lx c=%08x t=%"
242 PRtype_info "\n",
243 d->domain_id, hl2mfn, i,
244 page_get_owner(gpage),
245 page_get_owner(gpage)->domain_id,
246 gmfn,
247 gpage->count_info,
248 gpage->u.inuse.type_info);
249 continue;
250 }
251 }
252 adjust(gpage, 0);
253 }
254 }
256 unmap_domain_page(pt);
257 }
259 void adjust_l1_page(unsigned long l1mfn)
260 {
261 unsigned long *pt = map_domain_page(l1mfn);
262 int i;
264 for ( i = 0; i < L1_PAGETABLE_ENTRIES; i++ )
265 {
266 if ( pt[i] & _PAGE_PRESENT )
267 {
268 unsigned long gmfn = pt[i] >> PAGE_SHIFT;
269 struct pfn_info *gpage = pfn_to_page(gmfn);
271 if ( gmfn < 0x100 )
272 {
273 lowmem_mappings++;
274 continue;
275 }
277 if ( gmfn > max_page )
278 {
279 io_mappings++;
280 continue;
281 }
283 if ( noisy )
284 {
285 if ( pt[i] & _PAGE_RW )
286 {
287 // If it's not a writable page, complain.
288 //
289 if ( !((gpage->u.inuse.type_info & PGT_type_mask) ==
290 PGT_writable_page) )
291 {
292 printk("Audit %d: [l1mfn=%lx, i=%x] Illegal RW "
293 "t=%" PRtype_info " mfn=%lx\n",
294 d->domain_id, l1mfn, i,
295 gpage->u.inuse.type_info, gmfn);
296 errors++;
297 }
299 if ( shadow_refcounts &&
300 page_is_page_table(gpage) &&
301 ! page_out_of_sync(gpage) )
302 {
303 printk("Audit %d: [l1mfn=%lx, i=%x] Illegal RW of "
304 "page table gmfn=%lx\n",
305 d->domain_id, l1mfn, i, gmfn);
306 errors++;
307 }
308 }
310 if ( page_get_owner(gpage) != d )
311 {
312 printk("Audit %d: [l1mfn=%lx,i=%x] Skip foreign page "
313 "dom=%p (id=%d) mfn=%lx c=%08x t=%"
314 PRtype_info "\n",
315 d->domain_id, l1mfn, i,
316 page_get_owner(gpage),
317 page_get_owner(gpage)->domain_id,
318 gmfn,
319 gpage->count_info,
320 gpage->u.inuse.type_info);
321 continue;
322 }
323 }
325 adjust(gpage, (pt[i] & _PAGE_RW) ? 1 : 0);
326 }
327 }
329 unmap_domain_page(pt);
330 }
332 void adjust_shadow_tables()
333 {
334 struct shadow_status *a;
335 unsigned long smfn, gmfn;
336 struct pfn_info *page;
337 int i;
339 for ( i = 0; i < shadow_ht_buckets; i++ )
340 {
341 a = &d->arch.shadow_ht[i];
342 while ( a && a->gpfn_and_flags )
343 {
344 gmfn = __gpfn_to_mfn(d, a->gpfn_and_flags & PGT_mfn_mask);
345 smfn = a->smfn;
346 page = &frame_table[smfn];
348 switch ( a->gpfn_and_flags & PGT_type_mask ) {
349 case PGT_writable_pred:
350 break;
351 case PGT_snapshot:
352 adjust(pfn_to_page(gmfn), 0);
353 break;
354 case PGT_l1_shadow:
355 adjust(pfn_to_page(gmfn), 0);
356 if ( shadow_refcounts )
357 adjust_l1_page(smfn);
358 if ( page->u.inuse.type_info & PGT_pinned )
359 adjust(page, 0);
360 break;
361 case PGT_hl2_shadow:
362 adjust(pfn_to_page(gmfn), 0);
363 if ( shadow_refcounts )
364 adjust_hl2_page(smfn);
365 if ( page->u.inuse.type_info & PGT_pinned )
366 adjust(page, 0);
367 break;
368 case PGT_l2_shadow:
369 adjust(pfn_to_page(gmfn), 0);
370 adjust_l2_page(smfn, 1);
371 if ( page->u.inuse.type_info & PGT_pinned )
372 adjust(page, 0);
373 break;
374 default:
375 BUG();
376 break;
377 }
379 a = a->next;
380 }
381 }
382 }
384 void adjust_oos_list()
385 {
386 struct out_of_sync_entry *oos;
388 if ( (oos = d->arch.out_of_sync) )
389 ASSERT(shadow_enabled);
391 while ( oos )
392 {
393 adjust(pfn_to_page(oos->gmfn), 0);
395 // Only use entries that have low bits clear...
396 //
397 if ( !(oos->writable_pl1e & (sizeof(l1_pgentry_t)-1)) )
398 adjust(pfn_to_page(oos->writable_pl1e >> PAGE_SHIFT), 0);
400 if ( oos->snapshot_mfn != SHADOW_SNAPSHOT_ELSEWHERE )
401 adjust(pfn_to_page(oos->snapshot_mfn), 0);
403 oos = oos->next;
404 oos_count++;
405 }
406 }
408 void adjust_for_pgtbase()
409 {
410 struct vcpu *v;
412 for_each_vcpu(d, v)
413 {
414 if ( pagetable_get_paddr(v->arch.guest_table) )
415 adjust(&frame_table[pagetable_get_pfn(v->arch.guest_table)], 1);
416 if ( pagetable_get_paddr(v->arch.shadow_table) )
417 adjust(&frame_table[pagetable_get_pfn(v->arch.shadow_table)], 0);
418 if ( v->arch.monitor_shadow_ref )
419 adjust(&frame_table[v->arch.monitor_shadow_ref], 0);
420 }
421 }
423 void adjust_guest_pages()
424 {
425 struct list_head *list_ent = d->page_list.next;
426 struct pfn_info *page;
427 unsigned long mfn, snapshot_mfn;
429 while ( list_ent != &d->page_list )
430 {
431 u32 page_type;
433 page = list_entry(list_ent, struct pfn_info, list);
434 snapshot_mfn = mfn = page_to_pfn(page);
435 page_type = page->u.inuse.type_info & PGT_type_mask;
437 BUG_ON(page_get_owner(page) != d);
439 page_count++;
441 if ( shadow_enabled && !shadow_refcounts &&
442 page_out_of_sync(page) )
443 {
444 unsigned long gpfn = __mfn_to_gpfn(d, mfn);
445 ASSERT( VALID_M2P(gpfn) );
446 snapshot_mfn = __shadow_status(d, gpfn, PGT_snapshot);
447 ASSERT( snapshot_mfn );
448 }
450 switch ( page_type )
451 {
452 case PGT_l2_page_table:
453 l2++;
455 if ( noisy )
456 {
457 if ( shadow_refcounts )
458 {
459 printk("Audit %d: found an L2 guest page "
460 "mfn=%lx t=%" PRtype_info " c=%08x while in shadow mode\n",
461 d->domain_id, mfn, page->u.inuse.type_info,
462 page->count_info);
463 errors++;
464 }
466 if ( (page->u.inuse.type_info & PGT_count_mask) != 0 )
467 {
468 if ( (page->u.inuse.type_info & PGT_validated) !=
469 PGT_validated )
470 {
471 printk("Audit %d: L2 mfn=%lx not validated %"
472 PRtype_info "\n",
473 d->domain_id, mfn, page->u.inuse.type_info);
474 errors++;
475 }
477 if ( (page->u.inuse.type_info & PGT_pinned) != PGT_pinned )
478 {
479 printk("Audit %d: L2 mfn=%lx not pinned t=%"
480 PRtype_info "\n",
481 d->domain_id, mfn, page->u.inuse.type_info);
482 errors++;
483 }
484 }
485 }
487 if ( page->u.inuse.type_info & PGT_pinned )
488 adjust(page, 1);
490 if ( page->u.inuse.type_info & PGT_validated )
491 adjust_l2_page(snapshot_mfn, 0);
493 break;
495 case PGT_l1_page_table:
496 l1++;
498 if ( noisy )
499 {
500 if ( shadow_refcounts )
501 {
502 printk("found an L1 guest page mfn=%lx t=%"
503 PRtype_info " c=%08x "
504 "while in shadow mode\n",
505 mfn, page->u.inuse.type_info, page->count_info);
506 errors++;
507 }
509 if ( (page->u.inuse.type_info & PGT_count_mask) != 0 )
510 {
511 if ( (page->u.inuse.type_info & PGT_validated) !=
512 PGT_validated )
513 {
514 printk("Audit %d: L1 not validated mfn=%lx t=%"
515 PRtype_info "\n",
516 d->domain_id, mfn, page->u.inuse.type_info);
517 errors++;
518 }
520 if ( (page->u.inuse.type_info & PGT_pinned) != PGT_pinned )
521 {
522 if ( !VM_ASSIST(d, VMASST_TYPE_writable_pagetables) )
523 {
524 printk("Audit %d: L1 mfn=%lx not pinned t=%"
525 PRtype_info "\n",
526 d->domain_id, mfn, page->u.inuse.type_info);
527 }
528 }
529 }
530 }
532 if ( page->u.inuse.type_info & PGT_pinned )
533 adjust(page, 1);
535 if ( page->u.inuse.type_info & PGT_validated )
536 adjust_l1_page(snapshot_mfn);
538 break;
540 case PGT_gdt_page:
541 ASSERT( !page_out_of_sync(page) );
542 adjust(page, 1);
543 break;
545 case PGT_ldt_page:
546 ASSERT( !page_out_of_sync(page) );
547 adjust(page, 1);
548 break;
550 case PGT_writable_page:
551 if ( shadow_refcounts )
552 {
553 // In shadow mode, writable pages can get pinned by
554 // paravirtualized guests that think they are pinning
555 // their L1s and/or L2s.
556 //
557 if ( page->u.inuse.type_info & PGT_pinned )
558 adjust(page, 1);
559 }
560 }
562 list_ent = page->list.next;
563 }
564 }
566 #ifdef __i386__
567 if ( shadow_mode_external(d) )
568 l2limit = L2_PAGETABLE_ENTRIES;
569 else
570 l2limit = DOMAIN_ENTRIES_PER_L2_PAGETABLE;
571 #else
572 l2limit = 0; /* XXX x86/64 XXX */
573 #endif
575 adjust_for_pgtbase();
577 adjust_guest_pages();
579 if ( shadow_enabled )
580 {
581 adjust_oos_list();
582 adjust_shadow_tables();
583 }
585 adjust(virt_to_page(d->shared_info), 1);
587 return errors;
588 }
591 #ifndef NDEBUG
593 void audit_pagelist(struct domain *d)
594 {
595 struct list_head *list_ent;
596 int xenpages, totpages;
598 list_ent = d->xenpage_list.next;
599 for ( xenpages = 0; (list_ent != &d->xenpage_list); xenpages++ )
600 {
601 list_ent = list_ent->next;
602 }
603 list_ent = d->page_list.next;
604 for ( totpages = 0; (list_ent != &d->page_list); totpages++ )
605 {
606 list_ent = list_ent->next;
607 }
609 if ( xenpages != d->xenheap_pages ||
610 totpages != d->tot_pages )
611 {
612 printk("ARGH! dom %d: xen=%d %d, pages=%d %d\n", d->domain_id,
613 xenpages, d->xenheap_pages,
614 totpages, d->tot_pages );
615 }
616 }
618 void _audit_domain(struct domain *d, int flags)
619 {
620 int shadow_refcounts = !!shadow_mode_refcounts(d);
622 void scan_for_pfn_in_mfn(struct domain *d, unsigned long xmfn,
623 unsigned long mfn)
624 {
625 struct pfn_info *page = &frame_table[mfn];
626 unsigned long *pt = map_domain_page(mfn);
627 int i;
629 for ( i = 0; i < L1_PAGETABLE_ENTRIES; i++ )
630 {
631 if ( (pt[i] & _PAGE_PRESENT) && ((pt[i] >> PAGE_SHIFT) == xmfn) )
632 printk(" found dom=%d mfn=%lx t=%" PRtype_info " c=%08x "
633 "pt[i=%x]=%lx\n",
634 d->domain_id, mfn, page->u.inuse.type_info,
635 page->count_info, i, pt[i]);
636 }
638 unmap_domain_page(pt);
639 }
641 void scan_for_pfn_in_grant_table(struct domain *d, unsigned xmfn)
642 {
643 int i;
644 active_grant_entry_t *act = d->grant_table->active;
646 spin_lock(&d->grant_table->lock);
648 for ( i = 0; i < NR_GRANT_ENTRIES; i++ )
649 {
650 if ( act[i].pin && (act[i].frame == xmfn) )
651 {
652 printk(" found active grant table entry i=%d dom=%d pin=%d\n",
653 i, act[i].domid, act[i].pin);
654 }
655 }
657 spin_unlock(&d->grant_table->lock);
658 }
660 void scan_for_pfn(struct domain *d, unsigned long xmfn)
661 {
662 scan_for_pfn_in_grant_table(d, xmfn);
664 if ( !shadow_mode_enabled(d) )
665 {
666 struct list_head *list_ent = d->page_list.next;
667 struct pfn_info *page;
669 while ( list_ent != &d->page_list )
670 {
671 page = list_entry(list_ent, struct pfn_info, list);
673 switch ( page->u.inuse.type_info & PGT_type_mask )
674 {
675 case PGT_l1_page_table:
676 case PGT_l2_page_table:
677 scan_for_pfn_in_mfn(d, xmfn, page_to_pfn(page));
678 break;
679 default:
680 break;
681 }
683 list_ent = page->list.next;
684 }
685 }
686 else
687 {
688 struct shadow_status *a;
689 int i;
691 for ( i = 0; i < shadow_ht_buckets; i++ )
692 {
693 a = &d->arch.shadow_ht[i];
694 while ( a && a->gpfn_and_flags )
695 {
696 switch ( a->gpfn_and_flags & PGT_type_mask )
697 {
698 case PGT_l1_shadow:
699 case PGT_l2_shadow:
700 case PGT_hl2_shadow:
701 scan_for_pfn_in_mfn(d, xmfn, a->smfn);
702 break;
703 case PGT_snapshot:
704 case PGT_writable_pred:
705 break;
706 default:
707 BUG();
708 break;
709 }
710 a = a->next;
711 }
712 }
713 }
714 }
716 void scan_for_pfn_remote(unsigned long xmfn)
717 {
718 struct domain *e;
719 for_each_domain ( e )
720 scan_for_pfn( e, xmfn );
721 }
723 unsigned long mfn;
724 struct list_head *list_ent;
725 struct pfn_info *page;
726 int errors = 0;
728 if ( (d != current->domain) && shadow_mode_translate(d) )
729 {
730 printk("skipping audit domain of translated domain %d "
731 "from other context\n",
732 d->domain_id);
733 return;
734 }
736 if ( d != current->domain )
737 domain_pause(d);
739 // Maybe we should just be using BIGLOCK?
740 //
741 if ( !(flags & AUDIT_SHADOW_ALREADY_LOCKED) )
742 shadow_lock(d);
744 spin_lock(&d->page_alloc_lock);
746 audit_pagelist(d);
748 /* PHASE 0 */
750 list_ent = d->page_list.next;
751 while ( list_ent != &d->page_list )
752 {
753 u32 page_type;
755 page = list_entry(list_ent, struct pfn_info, list);
756 mfn = page_to_pfn(page);
757 page_type = page->u.inuse.type_info & PGT_type_mask;
759 BUG_ON(page_get_owner(page) != d);
761 if ( (page->u.inuse.type_info & PGT_count_mask) >
762 (page->count_info & PGC_count_mask) )
763 {
764 printk("taf(%" PRtype_info ") > caf(%08x) mfn=%lx\n",
765 page->u.inuse.type_info, page->count_info, mfn);
766 errors++;
767 }
769 if ( shadow_mode_refcounts(d) &&
770 (page_type == PGT_writable_page) &&
771 !(page->u.inuse.type_info & PGT_validated) )
772 {
773 printk("shadow mode writable page not validated mfn=%lx "
774 "t=%" PRtype_info " c=%08x\n",
775 mfn, page->u.inuse.type_info, page->count_info);
776 errors++;
777 }
779 #if 0 /* SYSV shared memory pages plus writeable files. */
780 if ( page_type == PGT_writable_page &&
781 (page->u.inuse.type_info & PGT_count_mask) > 1 )
782 {
783 printk("writeable page with type count >1: "
784 "mfn=%lx t=%" PRtype_info " c=%08x\n",
785 mfn,
786 page->u.inuse.type_info,
787 page->count_info );
788 errors++;
789 scan_for_pfn_remote(mfn);
790 }
791 #endif
793 if ( page_type == PGT_none &&
794 (page->u.inuse.type_info & PGT_count_mask) > 0 )
795 {
796 printk("normal page with type count >0: mfn=%lx t=%" PRtype_info " c=%08x\n",
797 mfn,
798 page->u.inuse.type_info,
799 page->count_info );
800 errors++;
801 }
803 if ( page_out_of_sync(page) )
804 {
805 if ( !page_is_page_table(page) )
806 {
807 printk("out of sync page mfn=%lx is not a page table\n", mfn);
808 errors++;
809 }
810 unsigned long pfn = __mfn_to_gpfn(d, mfn);
811 if ( !__shadow_status(d, pfn, PGT_snapshot) )
812 {
813 printk("out of sync page mfn=%lx doesn't have a snapshot\n",
814 mfn);
815 errors++;
816 }
817 if ( shadow_refcounts
818 ? (page_type != PGT_writable_page)
819 : !(page_type && (page_type <= PGT_l4_page_table)) )
820 {
821 printk("out of sync page mfn=%lx has strange type "
822 "t=%" PRtype_info " c=%08x\n",
823 mfn, page->u.inuse.type_info, page->count_info);
824 errors++;
825 }
826 }
828 /* Use tlbflush_timestamp to store original type_info. */
829 page->tlbflush_timestamp = page->u.inuse.type_info;
831 list_ent = page->list.next;
832 }
834 /* PHASE 1 */
835 io_mappings = lowmem_mappings = 0;
837 errors += audit_adjust_pgtables(d, -1, 1);
839 if ( !(flags & AUDIT_QUIET) &&
840 ((io_mappings > 0) || (lowmem_mappings > 0)) )
841 printk("Audit %d: Found %d lowmem mappings and %d io mappings\n",
842 d->domain_id, lowmem_mappings, io_mappings);
844 /* PHASE 2 */
846 list_ent = d->page_list.next;
847 while ( list_ent != &d->page_list )
848 {
849 page = list_entry(list_ent, struct pfn_info, list);
850 mfn = page_to_pfn(page);
852 switch ( page->u.inuse.type_info & PGT_type_mask)
853 {
854 case PGT_l1_page_table:
855 case PGT_l2_page_table:
856 case PGT_l3_page_table:
857 case PGT_l4_page_table:
858 if ( (page->u.inuse.type_info & PGT_count_mask) != 0 )
859 {
860 printk("Audit %d: type count!=0 t=%" PRtype_info " ot=%x c=%x mfn=%lx\n",
861 d->domain_id, page->u.inuse.type_info,
862 page->tlbflush_timestamp,
863 page->count_info, mfn);
864 errors++;
865 scan_for_pfn_remote(mfn);
866 }
867 break;
868 case PGT_none:
869 case PGT_writable_page:
870 case PGT_gdt_page:
871 case PGT_ldt_page:
872 if ( (page->u.inuse.type_info & PGT_count_mask) != 0 )
873 {
874 printk("Audit %d: type count!=0 t=%" PRtype_info " ot=%x c=%x mfn=%lx\n",
875 d->domain_id, page->u.inuse.type_info,
876 page->tlbflush_timestamp,
877 page->count_info, mfn);
878 //errors++;
879 }
880 break;
881 default:
882 BUG(); // XXX fix me...
883 }
885 if ( (page->count_info & PGC_count_mask) != 1 )
886 {
887 printk("Audit %d: gen count!=1 (c=%x) t=%" PRtype_info " ot=%x mfn=%lx\n",
888 d->domain_id,
889 page->count_info,
890 page->u.inuse.type_info,
891 page->tlbflush_timestamp, mfn );
892 //errors++;
893 scan_for_pfn_remote(mfn);
894 }
896 list_ent = page->list.next;
897 }
899 if ( shadow_mode_enabled(d) )
900 {
901 struct shadow_status *a;
902 struct pfn_info *page;
903 u32 page_type;
904 int i;
906 for ( i = 0; i < shadow_ht_buckets; i++ )
907 {
908 a = &d->arch.shadow_ht[i];
909 while ( a && a->gpfn_and_flags )
910 {
911 page = pfn_to_page(a->smfn);
912 page_type = a->gpfn_and_flags & PGT_type_mask;
914 switch ( page_type ) {
915 case PGT_l1_shadow:
916 case PGT_l2_shadow:
917 case PGT_hl2_shadow:
918 case PGT_snapshot:
919 if ( ((page->u.inuse.type_info & PGT_type_mask) != page_type ) ||
920 (page->count_info != 0) )
921 {
922 printk("Audit %d: shadow page counts wrong "
923 "mfn=%lx t=%" PRtype_info " c=%08x\n",
924 d->domain_id, page_to_pfn(page),
925 page->u.inuse.type_info,
926 page->count_info);
927 printk("a->gpfn_and_flags=%p\n",
928 (void *)a->gpfn_and_flags);
929 errors++;
930 }
931 break;
932 case PGT_writable_pred:
933 // XXX - nothing to check?
934 break;
936 default:
937 BUG();
938 break;
939 }
941 a = a->next;
942 }
943 }
944 }
946 /* PHASE 3 */
947 ctot = ttot = page_count = l1 = l2 = oos_count = 0;
949 audit_adjust_pgtables(d, 1, 0);
951 #if 0
952 // This covers our sins of trashing the tlbflush_timestamps...
953 //
954 local_flush_tlb();
955 #endif
957 spin_unlock(&d->page_alloc_lock);
959 if ( !(flags & AUDIT_QUIET) )
960 printk("Audit dom%d Done. "
961 "pages=%d oos=%d l1=%d l2=%d ctot=%d ttot=%d\n",
962 d->domain_id, page_count, oos_count, l1, l2, ctot, ttot);
964 if ( !(flags & AUDIT_SHADOW_ALREADY_LOCKED) )
965 shadow_unlock(d);
967 if ( d != current->domain )
968 domain_unpause(d);
970 if ( errors && !(flags & AUDIT_ERRORS_OK) )
971 BUG();
972 }
974 void audit_domains(void)
975 {
976 struct domain *d;
977 for_each_domain ( d )
978 audit_domain(d);
979 }
981 void audit_domains_key(unsigned char key)
982 {
983 audit_domains();
984 }
985 #endif