ia64/xen-unstable

changeset 1093:d5fe78785e26

bitkeeper revision 1.727 (402fc94bvWV4StLy1t8mm8tbdu4SAQ)

memory.c, keyhandler.c:
Include page-frame audit code in debug builds.
author kaf24@scramble.cl.cam.ac.uk
date Sun Feb 15 19:32:27 2004 +0000 (2004-02-15)
parents 53b906cc1cba
children b3ff2e06510e
files xen/common/keyhandler.c xen/common/memory.c
line diff
     1.1 --- a/xen/common/keyhandler.c	Fri Feb 13 20:50:45 2004 +0000
     1.2 +++ b/xen/common/keyhandler.c	Sun Feb 15 19:32:27 2004 +0000
     1.3 @@ -131,6 +131,10 @@ extern void perfc_reset (u_char key, voi
     1.4  extern void dump_runq(u_char key, void *dev_id, struct pt_regs *regs);
     1.5  extern void print_sched_histo(u_char key, void *dev_id, struct pt_regs *regs);
     1.6  extern void reset_sched_histo(u_char key, void *dev_id, struct pt_regs *regs);
     1.7 +#ifndef NDEBUG
     1.8 +void reaudit_pages(u_char key, void *dev_id, struct pt_regs *regs);
     1.9 +void audit_all_pages(u_char key, void *dev_id, struct pt_regs *regs);
    1.10 +#endif
    1.11  
    1.12  
    1.13  void initialize_keytable() 
    1.14 @@ -152,5 +156,8 @@ void initialize_keytable()
    1.15      add_key_handler('r', dump_runq,      "dump run queues");
    1.16      add_key_handler('B', kill_dom0,      "reboot machine gracefully"); 
    1.17      add_key_handler('R', halt_machine,   "reboot machine ungracefully"); 
    1.18 -    return; 
    1.19 +#ifndef NDEBUG
    1.20 +    add_key_handler('m', reaudit_pages, "re-audit pages");
    1.21 +    add_key_handler('M', audit_all_pages, "audit all pages");
    1.22 +#endif
    1.23  }
     2.1 --- a/xen/common/memory.c	Fri Feb 13 20:50:45 2004 +0000
     2.2 +++ b/xen/common/memory.c	Sun Feb 15 19:32:27 2004 +0000
     2.3 @@ -1100,3 +1100,193 @@ int do_update_va_mapping(unsigned long p
     2.4      
     2.5      return err;
     2.6  }
     2.7 +
     2.8 +
     2.9 +#ifndef NDEBUG
    2.10 +/*
    2.11 + * below are various memory debugging functions: 
    2.12 + * __audit_page():    prints out all the ptes a pages is listed in
    2.13 + * audit_page():      in addition maintains a history of audited pages
    2.14 + * reaudit_pages():   re-audit previously audited pages
    2.15 + * audit_all_pages(): check the ref-count for all leaf pages
    2.16 + *                    also checks for zombie pages
    2.17 + * 
    2.18 + * reaudit_page() and audit_all_pages() are designed to be
    2.19 + * keyhandler functions so that they can be easily invoked from the console.
    2.20 + */
    2.21 +
    2.22 +
    2.23 +/*
    2.24 + * prints out all the pt's a page is listed in
    2.25 + */
    2.26 +void __audit_page(unsigned long pfn) {
    2.27 +    unsigned long     i, j;
    2.28 +    struct pfn_info  *page;
    2.29 +    unsigned long     page_addr;
    2.30 +    l1_pgentry_t     *pl1e, l1e;
    2.31 +    
    2.32 +    page = &frame_table[pfn];
    2.33 +    page_addr = pfn << PAGE_SHIFT;
    2.34 +
    2.35 +    printk("audit page: pfn=%lx info: cf=%lx tf=%lx ts=%lx dom=%lx\n", pfn,
    2.36 +           page->count_and_flags, page->type_and_flags,
    2.37 +           page->tlbflush_timestamp, (unsigned long)page->u.domain);
    2.38 +
    2.39 +    /* walk the frame table */
    2.40 +    for ( i = 0; i < max_page; i++ )
    2.41 +    {
    2.42 +        if ( (frame_table[i].count_and_flags & PGC_count_mask) == 0 )
    2.43 +            continue;
    2.44 +        if ( (frame_table[i].count_and_flags & PGC_zombie) != 0 )
    2.45 +            continue;
    2.46 +
    2.47 +        /* check if entry is a page table (L1 page table) and in use */
    2.48 +        if ( ((frame_table[i].type_and_flags & PGT_type_mask) ==
    2.49 +              PGT_l1_page_table) &&
    2.50 +             ((frame_table[i].type_and_flags & PGT_count_mask) != 0) )
    2.51 +        {
    2.52 +            pl1e = map_domain_mem(i << PAGE_SHIFT);
    2.53 +
    2.54 +            /* scan page table for page to audit */
    2.55 +            for ( j=0; j < ENTRIES_PER_L1_PAGETABLE; j++  )
    2.56 +            {
    2.57 +                l1e = pl1e[j];
    2.58 +                if ( l1_pgentry_empty(l1e) )
    2.59 +                    continue;
    2.60 +                if ( l1_pgentry_to_pagenr(l1e) == pfn )
    2.61 +                {
    2.62 +                    printk("  pte_pfn=%06lx cf=%08lx tf=%08lx dom=%08lx\n", 
    2.63 +                           i, frame_table[i].count_and_flags,
    2.64 +                           frame_table[i].type_and_flags,
    2.65 +                           (unsigned long)frame_table[i].u.domain);
    2.66 +                    printk("    pte_idx=%03lx *pte_idx=%08lx\n", 
    2.67 +                           j, l1_pgentry_val(l1e));
    2.68 +                }
    2.69 +            }
    2.70 +            unmap_domain_mem(pl1e);
    2.71 +        }
    2.72 +    }
    2.73 +
    2.74 +}
    2.75 +
    2.76 +/*
    2.77 + * audit a page and keep a history of audited pfns
    2.78 + */
    2.79 +#define LASTPAGES_SIZE 128
    2.80 +static long last_pages[LASTPAGES_SIZE];
    2.81 +static int  last_pages_idx = 0;
    2.82 +void audit_page(unsigned long pfn)
    2.83 +{
    2.84 +    unsigned long     i;
    2.85 +
    2.86 +    cli();
    2.87 +    __audit_page(pfn);
    2.88 +    sti();
    2.89 +    /* add pfn to last_pages cache if is not already present */
    2.90 +    for ( i = 0; i < LASTPAGES_SIZE; i++ )
    2.91 +        if ( last_pages[i] == pfn )
    2.92 +            return;
    2.93 +
    2.94 +    /* new entry */
    2.95 +    last_pages[last_pages_idx++] = pfn;
    2.96 +    if ( last_pages_idx >= LASTPAGES_SIZE ) 
    2.97 +        last_pages_idx = 0;
    2.98 +
    2.99 +}
   2.100 +
   2.101 +/*
   2.102 + * re-audit previously audited pages
   2.103 + */
   2.104 +void reaudit_pages(u_char key, void *dev_id, struct pt_regs *regs)
   2.105 +{
   2.106 +    int i;
   2.107 +
   2.108 +    printk("Dumping audited pages\n");
   2.109 +
   2.110 +    for ( i = 0; i < LASTPAGES_SIZE; i++ )
   2.111 +        if ( last_pages[i] != 0 )
   2.112 +            __audit_page(last_pages[i]);
   2.113 +}
   2.114 +
   2.115 +/*
   2.116 + * do various checks on all pages.
   2.117 + * Currently:
   2.118 + * - check for zombie pages
   2.119 + * - check for pages with corrupt ref-count
   2.120 + * Interrupts are diabled completely. use with care.
   2.121 + */
   2.122 +void audit_all_pages (u_char key, void *dev_id, struct pt_regs *regs)
   2.123 +{
   2.124 +    unsigned long     i, j, k;
   2.125 +    unsigned long     ref_count;
   2.126 +    l1_pgentry_t     *pl1e, l1e;
   2.127 +
   2.128 +    printk("audit_all_pages\n");
   2.129 +
   2.130 +    cli();
   2.131 +    
   2.132 +    /* walk the frame table */
   2.133 +    for ( i = 0; i < max_page; i++ )
   2.134 +    {
   2.135 +
   2.136 +        /* check for zombies */
   2.137 +        if ( ((frame_table[i].count_and_flags & PGC_count_mask) != 0) &&
   2.138 +             ((frame_table[i].count_and_flags & PGC_zombie) != 0) )
   2.139 +        { 
   2.140 +            printk("zombie: pfn=%08lx cf=%08lx tf=%08lx dom=%08lx\n", 
   2.141 +                   i, frame_table[i].count_and_flags,
   2.142 +                   frame_table[i].type_and_flags,
   2.143 +                   (unsigned long)frame_table[i].u.domain);
   2.144 +        }
   2.145 +
   2.146 +        /* check ref count for leaf pages */
   2.147 +        if ( ((frame_table[i].type_and_flags & PGT_type_mask) ==
   2.148 +               PGT_writeable_page) )
   2.149 +        {
   2.150 +            ref_count = 0;
   2.151 +
   2.152 +            /* find page tables */
   2.153 +            for ( j = 0; j < max_page; j++ )
   2.154 +            {
   2.155 +                if ( ((frame_table[j].type_and_flags & PGT_type_mask) ==
   2.156 +                      PGT_l1_page_table) &&
   2.157 +                     ((frame_table[j].type_and_flags & PGT_count_mask) != 0) )
   2.158 +                {
   2.159 +                    pl1e = map_domain_mem(j << PAGE_SHIFT);
   2.160 +
   2.161 +                    /* scan page table for page to audit */
   2.162 +                    for ( k=0; k < ENTRIES_PER_L1_PAGETABLE; k++  )
   2.163 +                    {
   2.164 +                        l1e = pl1e[k];
   2.165 +                        if ( l1_pgentry_empty(l1e) )
   2.166 +                            continue;
   2.167 +                        if ( l1_pgentry_to_pagenr(l1e) == i )
   2.168 +                        {
   2.169 +                            ref_count++;
   2.170 +                            /* page is in pagetable */
   2.171 +                        }
   2.172 +                    }
   2.173 +                    unmap_domain_mem(pl1e);
   2.174 +                }
   2.175 +
   2.176 +            }
   2.177 +
   2.178 +            /* check for PGC_ALLOCATED */
   2.179 +            if ( (frame_table[i].count_and_flags & PGC_allocated) != 0 )
   2.180 +                ref_count++;
   2.181 +
   2.182 +            if ( (frame_table[i].count_and_flags & PGC_count_mask) 
   2.183 +                 != ref_count )
   2.184 +            {
   2.185 +                printk("refcount error: pfn=%06lx cf=%08lx refcount=%lx\n",
   2.186 +                       i, frame_table[i].count_and_flags, ref_count);
   2.187 +                __audit_page(i);
   2.188 +                printk("\n");
   2.189 +            }
   2.190 +        } /* ref count error */
   2.191 +    }
   2.192 +    sti();
   2.193 +    
   2.194 +}
   2.195 +
   2.196 +#endif /* NDEBUG */