ia64/xen-unstable

changeset 3821:c858d3b58040

bitkeeper revision 1.1195 (420e5ff3SFUc-sHp8lfCe-xCoUlk-A)

Hand merge
author mafetter@fleming.research
date Sat Feb 12 19:58:43 2005 +0000 (2005-02-12)
parents c695b365394d 5fe5f4c3da20
children 1413266e3117
files linux-2.4.29-xen-sparse/arch/xen/kernel/setup.c linux-2.6.10-xen-sparse/arch/xen/i386/kernel/setup.c linux-2.6.10-xen-sparse/drivers/xen/blkfront/block.h linux-2.6.10-xen-sparse/drivers/xen/netback/netback.c linux-2.6.10-xen-sparse/drivers/xen/netfront/netfront.c xen/arch/x86/domain.c xen/arch/x86/extable.c xen/arch/x86/mm.c xen/arch/x86/shadow.c xen/arch/x86/x86_32/entry.S xen/common/keyhandler.c xen/drivers/char/console.c xen/include/asm-x86/config.h xen/include/asm-x86/shadow.h xen/include/xen/console.h xen/include/xen/perfc_defn.h xen/include/xen/serial.h
line diff
     1.1 --- a/xen/arch/x86/mm.c	Sat Feb 12 03:11:43 2005 +0000
     1.2 +++ b/xen/arch/x86/mm.c	Sat Feb 12 19:58:43 2005 +0000
     1.3 @@ -1969,10 +1969,26 @@ int do_update_va_mapping(unsigned long v
     1.4              &shadow_linear_pg_table[l1_linear_offset(va)])))) )
     1.5          {
     1.6              /*
     1.7 -             * Since L2's are guranteed RW, failure indicates the page was not 
     1.8 -             * shadowed, so ignore.
     1.9 +             * Since L2's are guranteed RW, failure indicates either that the
    1.10 +             * page was not shadowed, or that the L2 entry has not yet been
    1.11 +             * updated to reflect the shadow.
    1.12               */
    1.13 -            perfc_incrc(shadow_update_va_fail);
    1.14 +            l2_pgentry_t gpde = linear_l2_table[l2_table_offset(va)];
    1.15 +            unsigned long gpfn = l2_pgentry_val(gpde) >> PAGE_SHIFT;
    1.16 +
    1.17 +            if (get_shadow_status(d, gpfn))
    1.18 +            {
    1.19 +                unsigned long gmfn = __gpfn_to_mfn(d, gpfn);
    1.20 +                unsigned long *gl1e = map_domain_mem(gmfn << PAGE_SHIFT);
    1.21 +                unsigned l1_idx = l1_table_offset(va);
    1.22 +                gl1e[l1_idx] = sval;
    1.23 +                unmap_domain_mem(gl1e);
    1.24 +                put_shadow_status(d);
    1.25 +
    1.26 +                perfc_incrc(shadow_update_va_fail1);
    1.27 +            }
    1.28 +            else
    1.29 +                perfc_incrc(shadow_update_va_fail2);
    1.30          }
    1.31  
    1.32          /*
     2.1 --- a/xen/arch/x86/shadow.c	Sat Feb 12 03:11:43 2005 +0000
     2.2 +++ b/xen/arch/x86/shadow.c	Sat Feb 12 19:58:43 2005 +0000
     2.3 @@ -762,10 +762,10 @@ void shadow_l2_normal_pt_update(unsigned
     2.4  // BUG: these are not SMP safe...
     2.5  static int sh_l2_present;
     2.6  static int sh_l1_present;
     2.7 -static int errors;
     2.8  char * sh_check_name;
     2.9 +int shadow_status_noswap;
    2.10  
    2.11 -#define virt_to_phys2(adr) ({                                            \
    2.12 +#define v2m(adr) ({                                                      \
    2.13      unsigned long _a = (unsigned long)(adr);                             \
    2.14      unsigned long _pte = l1_pgentry_val(                                 \
    2.15                              shadow_linear_pg_table[_a >> PAGE_SHIFT]);   \
    2.16 @@ -775,23 +775,28 @@ char * sh_check_name;
    2.17  
    2.18  #define FAIL(_f, _a...)                                                      \
    2.19      do {                                                                     \
    2.20 -        printk("XXX %s-FAIL (%d,%d)" _f " g=%p s=%p &g=%p &s=%p" \
    2.21 -               " pa(&g)=%p pa(&s)=%p\n",                               \
    2.22 -               sh_check_name, level, i, ## _a , gpte, spte, pgpte, pspte,    \
    2.23 -               virt_to_phys2(pgpte), virt_to_phys2(pspte));                  \
    2.24 +        printk("XXX %s-FAIL (%d,%d)" _f "\n"                                 \
    2.25 +               "g=%08lx s=%08lx &g=%08lx &s=%08lx"                           \
    2.26 +               " v2m(&g)=%08lx v2m(&s)=%08lx ea=%08lx\n",                    \
    2.27 +               sh_check_name, level, l1_idx, ## _a ,                         \
    2.28 +               gpte, spte, pgpte, pspte,                                     \
    2.29 +               v2m(pgpte), v2m(pspte),                                       \
    2.30 +               (l2_idx << L2_PAGETABLE_SHIFT) |                              \
    2.31 +               (l1_idx << L1_PAGETABLE_SHIFT));                              \
    2.32          errors++;                                                            \
    2.33      } while ( 0 )
    2.34  
    2.35  static int check_pte(
    2.36      struct domain *d, unsigned long *pgpte, unsigned long *pspte, 
    2.37 -    int level, int i)
    2.38 +    int level, int l2_idx, int l1_idx)
    2.39  {
    2.40      unsigned gpte = *pgpte;
    2.41      unsigned spte = *pspte;
    2.42      unsigned long mask, gpfn, smfn;
    2.43 +    int errors = 0;
    2.44  
    2.45      if ( (spte == 0) || (spte == 0xdeadface) || (spte == 0x00000E00) )
    2.46 -        return 1;  /* always safe */
    2.47 +        return errors;  /* always safe */
    2.48  
    2.49      if ( !(spte & _PAGE_PRESENT) )
    2.50          FAIL("Non zero not present spte");
    2.51 @@ -837,71 +842,71 @@ static int check_pte(
    2.52                   __shadow_status(d, gpfn) );
    2.53      }
    2.54  
    2.55 -    return 1;
    2.56 +    return errors;
    2.57  }
    2.58  
    2.59  
    2.60  static int check_l1_table(
    2.61      struct domain *d,
    2.62 -    unsigned long g2mfn, unsigned long s2mfn)
    2.63 +    unsigned long gmfn, unsigned long smfn, unsigned l2_idx)
    2.64  {
    2.65      int i;
    2.66      unsigned long *gpl1e, *spl1e;
    2.67 +    int cpu = current->processor;
    2.68 +    int errors = 0;
    2.69  
    2.70 -    gpl1e = map_domain_mem(g2mfn << PAGE_SHIFT);
    2.71 -    spl1e = map_domain_mem(s2mfn << PAGE_SHIFT);
    2.72 +    // First check to see if this guest page is currently the active
    2.73 +    // PTWR page.  If so, then we compare the (old) cached copy of the
    2.74 +    // guest page to the shadow, and not the currently writable (and
    2.75 +    // thus potentially out-of-sync) guest page.
    2.76 +    //
    2.77 +    if ( VM_ASSIST(d, VMASST_TYPE_writable_pagetables) )
    2.78 +    {
    2.79 +        for ( i = 0; i < ARRAY_SIZE(ptwr_info->ptinfo); i++)
    2.80 +        {
    2.81 +            if ( ptwr_info[cpu].ptinfo[i].l1va &&
    2.82 +                 ((v2m(ptwr_info[cpu].ptinfo[i].pl1e) >> PAGE_SHIFT) == gmfn) )
    2.83 +            {
    2.84 +                unsigned long old = gmfn;
    2.85 +                gmfn = (v2m(ptwr_info[cpu].ptinfo[i].page) >> PAGE_SHIFT);
    2.86 +                printk("hit1 ptwr_info[%d].ptinfo[%d].l1va, mfn=0x%08x, snapshot=0x%08x\n",
    2.87 +                       cpu, i, old, gmfn);
    2.88 +            }
    2.89 +        }
    2.90 +    }
    2.91 +
    2.92 +    gpl1e = map_domain_mem(gmfn << PAGE_SHIFT);
    2.93 +    spl1e = map_domain_mem(smfn << PAGE_SHIFT);
    2.94  
    2.95      for ( i = 0; i < L1_PAGETABLE_ENTRIES; i++ )
    2.96 -        check_pte(d, &gpl1e[i], &spl1e[i], 1, i);
    2.97 +        errors += check_pte(d, &gpl1e[i], &spl1e[i], 1, l2_idx, i);
    2.98   
    2.99      unmap_domain_mem(spl1e);
   2.100      unmap_domain_mem(gpl1e);
   2.101  
   2.102 -    return 1;
   2.103 +    return errors;
   2.104  }
   2.105  
   2.106 -#define FAILPT(_f, _a...)                                      \
   2.107 -    do {                                                       \
   2.108 -        printk("XXX FAIL %s-PT" _f "\n", s, ## _a );           \
   2.109 -        errors++;                                              \
   2.110 +#define FAILPT(_f, _a...)                                         \
   2.111 +    do {                                                          \
   2.112 +        printk("XXX FAIL %s-PT " _f "\n", sh_check_name, ## _a ); \
   2.113 +        errors++;                                                 \
   2.114      } while ( 0 )
   2.115  
   2.116 -void check_pagetable(struct domain *d, pagetable_t pt, char *s)
   2.117 +int check_l2_table(
   2.118 +    struct domain *d, unsigned long gpfn, unsigned long smfn)
   2.119  {
   2.120 -    unsigned long gptbase = pagetable_val(pt);
   2.121 -    unsigned long ptbase_pfn, smfn, ss;
   2.122 -    unsigned long i;
   2.123 -    l2_pgentry_t *gpl2e, *spl2e;
   2.124 -    unsigned long ptbase_mfn = 0;
   2.125 -    int cpu = current->processor;
   2.126 -
   2.127 -    errors = 0;
   2.128 -    sh_check_name = s;
   2.129 -
   2.130 -    SH_VVLOG("%s-PT Audit", s);
   2.131 -
   2.132 -    sh_l2_present = sh_l1_present = 0;
   2.133 +    unsigned long gmfn = __gpfn_to_mfn(d, gpfn);
   2.134 +    l2_pgentry_t *gpl2e = (l2_pgentry_t *) map_domain_mem( gmfn << PAGE_SHIFT );
   2.135 +    l2_pgentry_t *spl2e = (l2_pgentry_t *) map_domain_mem( smfn << PAGE_SHIFT );
   2.136 +    int i;
   2.137 +    int errors = 0;
   2.138  
   2.139 -    ptbase_pfn = gptbase >> PAGE_SHIFT;
   2.140 -    ptbase_mfn = __gpfn_to_mfn(d, ptbase_pfn);
   2.141 -
   2.142 -    ss = __shadow_status(d, ptbase_pfn);
   2.143 -  
   2.144 -    if ( ! (ss & PSH_shadowed) )
   2.145 -    {
   2.146 -        /*printk("%s-PT %p not shadowed\n", s, gptbase);*/
   2.147 -        if ( ss != 0 )
   2.148 -            BUG();
   2.149 -        return;
   2.150 -    }   
   2.151 - 
   2.152 -    smfn = ss & PSH_pfn_mask;
   2.153 -
   2.154 -    if ( ss != (PSH_shadowed | smfn) )
   2.155 -        FAILPT("ptbase shadow inconsistent1");
   2.156 -
   2.157 -    gpl2e = (l2_pgentry_t *) map_domain_mem( ptbase_mfn << PAGE_SHIFT );
   2.158 -    spl2e = (l2_pgentry_t *) map_domain_mem( smfn << PAGE_SHIFT );
   2.159 +    if ( page_get_owner(pfn_to_page(gmfn)) != d )
   2.160 +        FAILPT("domain doesn't own page");
   2.161 +    if ( page_get_owner(pfn_to_page(smfn)) != NULL )
   2.162 +        FAILPT("shadow page mfn=0x%08x is owned by someone, domid=%d",
   2.163 +               smfn, page_get_owner(pfn_to_page(smfn))->id);
   2.164  
   2.165      if ( memcmp(&spl2e[DOMAIN_ENTRIES_PER_L2_PAGETABLE],
   2.166                  &gpl2e[DOMAIN_ENTRIES_PER_L2_PAGETABLE], 
   2.167 @@ -921,24 +926,68 @@ void check_pagetable(struct domain *d, p
   2.168          FAILPT("hypervisor linear map inconsistent");
   2.169  
   2.170      if ( (l2_pgentry_val(spl2e[SH_LINEAR_PT_VIRT_START >> 
   2.171 -                              L2_PAGETABLE_SHIFT]) != 
   2.172 +                               L2_PAGETABLE_SHIFT]) != 
   2.173            ((smfn << PAGE_SHIFT) | __PAGE_HYPERVISOR)) )
   2.174          FAILPT("hypervisor shadow linear map inconsistent %p %p",
   2.175                 l2_pgentry_val(spl2e[SH_LINEAR_PT_VIRT_START >>
   2.176 -                                   L2_PAGETABLE_SHIFT]),
   2.177 +                                    L2_PAGETABLE_SHIFT]),
   2.178                 (smfn << PAGE_SHIFT) | __PAGE_HYPERVISOR);
   2.179  
   2.180      if ( shadow_mode(d) != SHM_full_32 ) {
   2.181 -        // BUG: this shouldn't be using exec_domain[0] here...
   2.182          if ( (l2_pgentry_val(spl2e[PERDOMAIN_VIRT_START >> L2_PAGETABLE_SHIFT]) !=
   2.183 -              ((__pa(page_get_owner(&frame_table[ptbase_pfn])->arch.mm_perdomain_pt) | 
   2.184 -            __PAGE_HYPERVISOR))) )
   2.185 +              ((v2m(page_get_owner(&frame_table[gmfn])->arch.mm_perdomain_pt) |
   2.186 +                __PAGE_HYPERVISOR))) )
   2.187              FAILPT("hypervisor per-domain map inconsistent");
   2.188      }
   2.189  
   2.190      /* Check the whole L2. */
   2.191      for ( i = 0; i < DOMAIN_ENTRIES_PER_L2_PAGETABLE; i++ )
   2.192 -        check_pte(d, &l2_pgentry_val(gpl2e[i]), &l2_pgentry_val(spl2e[i]), 2, i);
   2.193 +        errors += check_pte(d, &l2_pgentry_val(gpl2e[i]), &l2_pgentry_val(spl2e[i]), 2, i, 0);
   2.194 +
   2.195 +    unmap_domain_mem(spl2e);
   2.196 +    unmap_domain_mem(gpl2e);
   2.197 +
   2.198 +    return errors;
   2.199 +}
   2.200 +
   2.201 +int _check_pagetable(struct domain *d, pagetable_t pt, char *s)
   2.202 +{
   2.203 +    unsigned long gptbase = pagetable_val(pt);
   2.204 +    unsigned long ptbase_pfn, smfn, ss;
   2.205 +    unsigned long i;
   2.206 +    l2_pgentry_t *gpl2e, *spl2e;
   2.207 +    unsigned long ptbase_mfn = 0;
   2.208 +    int errors = 0;
   2.209 +
   2.210 +    sh_check_name = s;
   2.211 +    SH_VVLOG("%s-PT Audit", s);
   2.212 +    sh_l2_present = sh_l1_present = 0;
   2.213 +    perfc_incrc(check_pagetable);
   2.214 +
   2.215 +    ptbase_pfn = gptbase >> PAGE_SHIFT;
   2.216 +    ptbase_mfn = __gpfn_to_mfn(d, ptbase_pfn);
   2.217 +
   2.218 +    ss = __shadow_status(d, ptbase_pfn);
   2.219 +  
   2.220 +    if ( ! (ss & PSH_shadowed) )
   2.221 +    {
   2.222 +        printk("%s-PT %p not shadowed\n", s, gptbase);
   2.223 +        errors++;
   2.224 +
   2.225 +        if ( ss != 0 )
   2.226 +            BUG();
   2.227 +        return errors;
   2.228 +    }   
   2.229 + 
   2.230 +    smfn = ss & PSH_pfn_mask;
   2.231 +
   2.232 +    if ( ss != (PSH_shadowed | smfn) )
   2.233 +        FAILPT("ptbase shadow inconsistent1");
   2.234 +
   2.235 +    errors += check_l2_table(d, ptbase_pfn, smfn);
   2.236 +
   2.237 +    gpl2e = (l2_pgentry_t *) map_domain_mem( ptbase_mfn << PAGE_SHIFT );
   2.238 +    spl2e = (l2_pgentry_t *) map_domain_mem( smfn << PAGE_SHIFT );
   2.239  
   2.240      /* Go back and recurse. */
   2.241      for ( i = 0; i < DOMAIN_ENTRIES_PER_L2_PAGETABLE; i++ )
   2.242 @@ -949,20 +998,7 @@ void check_pagetable(struct domain *d, p
   2.243  
   2.244          if ( l2_pgentry_val(spl2e[i]) != 0 )
   2.245          {
   2.246 -            // First check to see if this guest page is currently the active
   2.247 -            // PTWR page.  If so, then we compare the (old) cached copy of the
   2.248 -            // guest page to the shadow, and not the currently writable (and
   2.249 -            // thus potentially out-of-sync) guest page.
   2.250 -            //
   2.251 -            if ( ptwr_info[cpu].ptinfo[PTWR_PT_ACTIVE].l1va &&
   2.252 -                 (i == ptwr_info[cpu].ptinfo[PTWR_PT_ACTIVE].l2_idx) &&
   2.253 -                 likely(VM_ASSIST(d, VMASST_TYPE_writable_pagetables)) )
   2.254 -            {
   2.255 -                gl1mfn = (__pa(ptwr_info[cpu].ptinfo[PTWR_PT_ACTIVE].page) >>
   2.256 -                          PAGE_SHIFT);
   2.257 -            }
   2.258 -
   2.259 -            check_l1_table(d, gl1mfn, sl1mfn);
   2.260 +            errors += check_l1_table(d, gl1mfn, sl1mfn, i);
   2.261          }
   2.262      }
   2.263  
   2.264 @@ -972,10 +1008,104 @@ void check_pagetable(struct domain *d, p
   2.265      SH_VVLOG("PT verified : l2_present = %d, l1_present = %d",
   2.266               sh_l2_present, sh_l1_present);
   2.267   
   2.268 +#if 1
   2.269      if ( errors )
   2.270          BUG();
   2.271 +#endif
   2.272  
   2.273 -    return;
   2.274 +    return errors;
   2.275 +}
   2.276 +
   2.277 +int _check_all_pagetables(struct domain *d, char *s)
   2.278 +{
   2.279 +    int i, j;
   2.280 +    struct shadow_status *a;
   2.281 +    unsigned long gmfn;
   2.282 +    int errors = 0;
   2.283 +    int cpu;
   2.284 +
   2.285 +    shadow_status_noswap = 1;
   2.286 +
   2.287 +    sh_check_name = s;
   2.288 +    SH_VVLOG("%s-PT Audit domid=%d", s, d->id);
   2.289 +    sh_l2_present = sh_l1_present = 0;
   2.290 +    perfc_incrc(check_all_pagetables);
   2.291 +
   2.292 +    for (i = 0; i < shadow_ht_buckets; i++)
   2.293 +    {
   2.294 +        a = &d->arch.shadow_ht[i];
   2.295 +        while ( a && a->pfn )
   2.296 +        {
   2.297 +            gmfn = __gpfn_to_mfn(d, a->pfn);
   2.298 +            switch ( frame_table[a->pfn].u.inuse.type_info & PGT_type_mask )
   2.299 +            {
   2.300 +            case PGT_l1_page_table:
   2.301 +                errors += check_l1_table(d, gmfn, a->smfn_and_flags & PSH_pfn_mask, 0);
   2.302 +                break;
   2.303 +            case PGT_l2_page_table:
   2.304 +                errors += check_l2_table(d, gmfn, a->smfn_and_flags & PSH_pfn_mask);
   2.305 +                break;
   2.306 +            default:
   2.307 +                errors++;
   2.308 +                printk("unexpected page type 0x%08x, pfn=0x%08x, gmfn=0x%08x\n",
   2.309 +                       frame_table[gmfn].u.inuse.type_info,
   2.310 +                       a->pfn, gmfn);
   2.311 +                BUG();
   2.312 +            }
   2.313 +            a = a->next;
   2.314 +        }
   2.315 +    }
   2.316 +
   2.317 +    shadow_status_noswap = 0;
   2.318 +
   2.319 +    for (i = 0; i < 1024; i++)
   2.320 +    {
   2.321 +        if ( l2_pgentry_val(shadow_linear_l2_table[i]) & _PAGE_PRESENT )
   2.322 +        {
   2.323 +            unsigned base = i << 10;
   2.324 +            for (j = 0; j < 1024; j++)
   2.325 +            {
   2.326 +                if ( (l1_pgentry_val(shadow_linear_pg_table[base + j]) & PAGE_MASK) == 0x0143d000 )
   2.327 +                {
   2.328 +                    printk("sh_ln_pg_tb[0x%08x] => 0x%08lx ",
   2.329 +                           base + j,
   2.330 +                           l1_pgentry_val(shadow_linear_pg_table[base + j]));
   2.331 +                    if ( l1_pgentry_val(shadow_linear_pg_table[base + j]) & _PAGE_PRESENT )
   2.332 +                        printk(" first entry => 0x%08lx\n",
   2.333 +                               *(unsigned long *)((base + j) << PAGE_SHIFT));
   2.334 +                    else
   2.335 +                        printk(" page not present\n");
   2.336 +                }
   2.337 +            }
   2.338 +        }
   2.339 +    }
   2.340 +
   2.341 +    if ( errors )
   2.342 +    {
   2.343 +        printk("VM_ASSIST(d, VMASST_TYPE_writable_pagetables) => %d\n",
   2.344 +               VM_ASSIST(d, VMASST_TYPE_writable_pagetables));
   2.345 +        for ( cpu = 0; cpu < smp_num_cpus; cpu++ )
   2.346 +        {
   2.347 +            for ( j = 0; j < ARRAY_SIZE(ptwr_info->ptinfo); j++)
   2.348 +            {
   2.349 +                printk("ptwr_info[%d].ptinfo[%d].l1va => 0x%08x\n",
   2.350 +                       cpu, j, ptwr_info[cpu].ptinfo[j].l1va);
   2.351 +                printk("ptwr_info[%d].ptinfo[%d].pl1e => 0x%08x\n",
   2.352 +                       cpu, j, ptwr_info[cpu].ptinfo[j].pl1e);
   2.353 +                if (cpu == smp_processor_id())
   2.354 +                    printk("v2m(ptwr_info[%d].ptinfo[%d].pl1e) => 0x%08x\n",
   2.355 +                           cpu, j, v2m(ptwr_info[cpu].ptinfo[j].pl1e));
   2.356 +                printk("ptwr_info[%d].ptinfo[%d].page => 0x%08x\n",
   2.357 +                       cpu, j, ptwr_info[cpu].ptinfo[j].page);
   2.358 +                if (cpu == smp_processor_id())
   2.359 +                    printk("v2m(ptwr_info[%d].ptinfo[%d].page) => 0x%08x\n",
   2.360 +                           cpu, j, v2m(ptwr_info[cpu].ptinfo[j].page));
   2.361 +            }
   2.362 +        }
   2.363 +        BUG();
   2.364 +    }
   2.365 +
   2.366 +    return errors;
   2.367  }
   2.368  
   2.369  #endif // SHADOW_DEBUG
     3.1 --- a/xen/common/keyhandler.c	Sat Feb 12 03:11:43 2005 +0000
     3.2 +++ b/xen/common/keyhandler.c	Sat Feb 12 19:58:43 2005 +0000
     3.3 @@ -75,12 +75,14 @@ void register_irq_keyhandler(
     3.4  static void show_handlers(unsigned char key)
     3.5  {
     3.6      int i; 
     3.7 +    int buffer_enable = sercon_buffer_bypass();
     3.8      printk("'%c' pressed -> showing installed handlers\n", key);
     3.9      for ( i = 0; i < KEY_MAX; i++ ) 
    3.10          if ( key_table[i].u.handler != NULL ) 
    3.11              printk(" key '%c' (ascii '%02x') => %s\n", 
    3.12                     (i<33 || i>126)?(' '):(i),i,
    3.13                     key_table[i].desc);
    3.14 +    sercon_buffer_set(buffer_enable);
    3.15  }
    3.16  
    3.17  static void dump_registers(unsigned char key, struct xen_regs *regs)
    3.18 @@ -177,6 +179,10 @@ void initialize_keytable(void)
    3.19  #ifndef NDEBUG
    3.20      register_keyhandler(
    3.21          'o', audit_domains_key,  "audit domains >0 EXPERIMENTAL"); 
    3.22 +
    3.23 +    register_keyhandler(
    3.24 +        'c', sercon_buffer_toggle,
    3.25 +        "toggle serial console output vs ring buffer capture");
    3.26  #endif
    3.27  
    3.28  #ifdef PERF_COUNTERS
     4.1 --- a/xen/drivers/char/console.c	Sat Feb 12 03:11:43 2005 +0000
     4.2 +++ b/xen/drivers/char/console.c	Sat Feb 12 19:58:43 2005 +0000
     4.3 @@ -51,6 +51,17 @@ static int vgacon_enabled = 0;
     4.4  
     4.5  spinlock_t console_lock = SPIN_LOCK_UNLOCKED;
     4.6  
     4.7 +#ifndef NDEBUG
     4.8 +static unsigned char *sercon_buffer      = NULL;
     4.9 +static unsigned char *sercon_buffer_end  = NULL;
    4.10 +static unsigned char *sercon_buffer_head = NULL;
    4.11 +static unsigned char *sercon_buffer_next = NULL;
    4.12 +
    4.13 +static unsigned int opt_sercon_buffer_size = 128; /* kbytes */
    4.14 +integer_param("conbuf", opt_sercon_buffer_size);
    4.15 +
    4.16 +static void sercon_buffer_puts(const unsigned char *s);
    4.17 +#endif
    4.18  
    4.19  /*
    4.20   * *******************************************************
    4.21 @@ -254,9 +265,13 @@ static void switch_serial_input(void)
    4.22      static char *input_str[2] = { "DOM0", "Xen" };
    4.23      xen_rx = !xen_rx;
    4.24      if ( SWITCH_CODE != 0 )
    4.25 +    {
    4.26 +        int buffer_enable = sercon_buffer_bypass();
    4.27          printk("*** Serial input -> %s "
    4.28                 "(type 'CTRL-%c' three times to switch input to %s).\n",
    4.29                 input_str[xen_rx], opt_conswitch[0], input_str[!xen_rx]);
    4.30 +        sercon_buffer_set(buffer_enable);
    4.31 +    }
    4.32  }
    4.33  
    4.34  static void __serial_rx(unsigned char c, struct xen_regs *regs)
    4.35 @@ -353,7 +368,14 @@ long do_console_io(int cmd, int count, c
    4.36  static inline void __putstr(const char *str)
    4.37  {
    4.38      int c;
    4.39 -    serial_puts(sercon_handle, str);
    4.40 +
    4.41 +#ifndef NDEBUG
    4.42 +    if ( sercon_handle & SERHND_BUFFERED )
    4.43 +        sercon_buffer_puts(str);
    4.44 +    else
    4.45 +#endif
    4.46 +        serial_puts(sercon_handle, str);
    4.47 +
    4.48      while ( (c = *str++) != '\0' )
    4.49      {
    4.50          putchar_console(c);
    4.51 @@ -463,16 +485,19 @@ void console_force_lock(void)
    4.52      spin_lock(&console_lock);
    4.53  }
    4.54  
    4.55 +// 09Feb2005: this appears to be unused...
    4.56  void console_putc(char c)
    4.57  {
    4.58      serial_putc(sercon_handle, c);
    4.59  }
    4.60  
    4.61 +// 09Feb2005: this appears to be unused...
    4.62  int console_getc(void)
    4.63  {
    4.64      return serial_getc(sercon_handle);
    4.65  }
    4.66  
    4.67 +// 09Feb2005: this appears to be unused...
    4.68  int irq_console_getc(void)
    4.69  {
    4.70      return irq_serial_getc(sercon_handle);
    4.71 @@ -481,6 +506,116 @@ int irq_console_getc(void)
    4.72  
    4.73  /*
    4.74   * **************************************************************
    4.75 + * *************** serial console ring buffer *******************
    4.76 + * **************************************************************
    4.77 + */
    4.78 +
    4.79 +#ifndef NDEBUG
    4.80 +static void sercon_buffer_putc(const unsigned char c)
    4.81 +{
    4.82 +    if ( !sercon_buffer )
    4.83 +        return;
    4.84 +    if ( !c )
    4.85 +        return;
    4.86 +
    4.87 +    if ( sercon_buffer_next == sercon_buffer_end )
    4.88 +    {
    4.89 +        // buffer wrap-around case...
    4.90 +        sercon_buffer_head = sercon_buffer + 1;
    4.91 +        sercon_buffer_next = sercon_buffer;
    4.92 +    }
    4.93 +    if ( sercon_buffer_head == sercon_buffer_next + 1 )
    4.94 +    {
    4.95 +        // the buffer is already full...
    4.96 +        sercon_buffer_head++;
    4.97 +    }
    4.98 +    *sercon_buffer_next++ = c;
    4.99 +    *sercon_buffer_next = 0;
   4.100 +}
   4.101 +
   4.102 +static void sercon_buffer_puts(const unsigned char *s)
   4.103 +{
   4.104 +    // inefficient but simple...
   4.105 +    while ( *s )
   4.106 +        sercon_buffer_putc(*s++);
   4.107 +}
   4.108 +
   4.109 +static void sercon_buffer_reset(void)
   4.110 +{
   4.111 +    sercon_buffer_head = sercon_buffer;
   4.112 +    sercon_buffer_next = sercon_buffer;
   4.113 +    sercon_buffer_head[0] = 0;
   4.114 +}
   4.115 +
   4.116 +static void sercon_buffer_flush(void)
   4.117 +{
   4.118 +    serial_puts(sercon_handle, sercon_buffer_head);
   4.119 +    if ( sercon_buffer_head != sercon_buffer )
   4.120 +        serial_puts(sercon_handle, sercon_buffer);
   4.121 +    sercon_buffer_reset();
   4.122 +}
   4.123 +
   4.124 +void _sercon_buffer_dump(void)
   4.125 +{
   4.126 +    sercon_buffer_flush();
   4.127 +    sercon_handle &= ~SERHND_BUFFERED;
   4.128 +}
   4.129 +
   4.130 +void sercon_buffer_toggle(unsigned char key)
   4.131 +{
   4.132 +    if ( !sercon_buffer )
   4.133 +    {
   4.134 +        printk("serial console buffer not allocated\n");
   4.135 +        return;
   4.136 +    }
   4.137 +
   4.138 +    if ( sercon_handle & SERHND_BUFFERED )
   4.139 +        sercon_buffer_flush();
   4.140 +    sercon_handle ^= SERHND_BUFFERED;
   4.141 +}
   4.142 +
   4.143 +void _sercon_buffer_set(int enable)
   4.144 +{
   4.145 +    if (enable)
   4.146 +        sercon_handle |= SERHND_BUFFERED;
   4.147 +    else
   4.148 +        sercon_handle &= ~SERHND_BUFFERED;
   4.149 +}
   4.150 +
   4.151 +int _sercon_buffer_bypass(void)
   4.152 +{
   4.153 +    int buffering = !!(sercon_handle & SERHND_BUFFERED);
   4.154 +    sercon_handle &= ~SERHND_BUFFERED;
   4.155 +
   4.156 +    return buffering;
   4.157 +}
   4.158 +
   4.159 +static int __init sercon_buffer_init(void)
   4.160 +{
   4.161 +    int order;
   4.162 +    int kbytes = opt_sercon_buffer_size;
   4.163 +
   4.164 +    if ( !kbytes )
   4.165 +        return 0;
   4.166 +
   4.167 +    order = get_order(kbytes * 1024);
   4.168 +    sercon_buffer = (void *)alloc_xenheap_pages(order);
   4.169 +    ASSERT( sercon_buffer );
   4.170 +
   4.171 +    sercon_buffer_end = sercon_buffer + kbytes*1024 - 1;
   4.172 +    *sercon_buffer_end = 0;
   4.173 +
   4.174 +    sercon_buffer_reset();
   4.175 +
   4.176 +    return 0;
   4.177 +}
   4.178 +__initcall(sercon_buffer_init);
   4.179 +
   4.180 +#endif /* not NDEBUG */
   4.181 +
   4.182 +
   4.183 +/*
   4.184 + * **************************************************************
   4.185   * *************** Debugging/tracing/error-report ***************
   4.186   * **************************************************************
   4.187   */
   4.188 @@ -513,6 +648,8 @@ void panic(const char *fmt, ...)
   4.189      spin_unlock_irqrestore(&console_lock, flags);
   4.190  
   4.191      watchdog_on = 0;
   4.192 +    sercon_buffer_dump();
   4.193 +
   4.194      mdelay(5000);
   4.195      machine_restart(0);
   4.196  }
     5.1 --- a/xen/include/asm-x86/config.h	Sat Feb 12 03:11:43 2005 +0000
     5.2 +++ b/xen/include/asm-x86/config.h	Sat Feb 12 19:58:43 2005 +0000
     5.3 @@ -99,10 +99,19 @@ extern void __out_of_line_bug(int line) 
     5.4  #define out_of_line_bug() __out_of_line_bug(__LINE__)
     5.5  #endif /* __ASSEMBLY__ */
     5.6  
     5.7 +#ifndef __ASSEMBLY__
     5.8 +#ifndef NDEBUG
     5.9 +extern void _sercon_buffer_dump(void);
    5.10 +#define sercon_buffer_dump() _sercon_buffer_dump()
    5.11 +#else
    5.12 +#define sercon_buffer_dump() ((void)0)
    5.13 +#endif
    5.14  #define BUG() do {					\
    5.15  	printk("BUG at %s:%d\n", __FILE__, __LINE__);	\
    5.16 -	__asm__ __volatile__("ud2");			\
    5.17 +        watchdog_on = 0;                                \
    5.18 +        sercon_buffer_dump();                           \
    5.19  } while (0)
    5.20 +#endif /* __ASSEMBLY__ */
    5.21  
    5.22  #if defined(__x86_64__)
    5.23  
     6.1 --- a/xen/include/asm-x86/shadow.h	Sat Feb 12 03:11:43 2005 +0000
     6.2 +++ b/xen/include/asm-x86/shadow.h	Sat Feb 12 19:58:43 2005 +0000
     6.3 @@ -77,6 +77,10 @@ static inline void shadow_invalidate(str
     6.4  #define SHADOW_VERBOSE_DEBUG 0
     6.5  #define SHADOW_HASH_DEBUG 0
     6.6  
     6.7 +#if SHADOW_DEBUG
     6.8 +extern int shadow_status_noswap;
     6.9 +#endif
    6.10 +
    6.11  struct shadow_status {
    6.12      unsigned long pfn;            /* Guest pfn.             */
    6.13      unsigned long smfn_and_flags; /* Shadow mfn plus flags. */
    6.14 @@ -88,7 +92,7 @@ struct shadow_status {
    6.15  
    6.16  #ifdef VERBOSE
    6.17  #define SH_LOG(_f, _a...)                                               \
    6.18 -printk("DOM%uP%u: (file=shadow.c, line=%d) " _f "\n",                   \
    6.19 +    printk("DOM%uP%u: SH_LOG(%d): " _f "\n",                            \
    6.20         current->domain->id , current->processor, __LINE__ , ## _a )
    6.21  #else
    6.22  #define SH_LOG(_f, _a...) 
    6.23 @@ -96,7 +100,7 @@ printk("DOM%uP%u: (file=shadow.c, line=%
    6.24  
    6.25  #if SHADOW_DEBUG
    6.26  #define SH_VLOG(_f, _a...)                                              \
    6.27 -    printk("DOM%uP%u: (file=shadow.c, line=%d) " _f "\n",               \
    6.28 +    printk("DOM%uP%u: SH_VLOG(%d): " _f "\n",                           \
    6.29             current->domain->id, current->processor, __LINE__ , ## _a )
    6.30  #else
    6.31  #define SH_VLOG(_f, _a...) 
    6.32 @@ -104,7 +108,7 @@ printk("DOM%uP%u: (file=shadow.c, line=%
    6.33  
    6.34  #if SHADOW_VERBOSE_DEBUG
    6.35  #define SH_VVLOG(_f, _a...)                                             \
    6.36 -    printk("DOM%uP%u: (file=shadow.c, line=%d) " _f "\n",               \
    6.37 +    printk("DOM%uP%u: SH_VVLOG(%d): " _f "\n",                          \
    6.38             current->domain->id, current->processor, __LINE__ , ## _a )
    6.39  #else
    6.40  #define SH_VVLOG(_f, _a...)
    6.41 @@ -428,6 +432,10 @@ static inline unsigned long __shadow_sta
    6.42  
    6.43          if ( x->pfn == gpfn )
    6.44          {
    6.45 +#if SHADOW_DEBUG
    6.46 +            if ( unlikely(shadow_status_noswap) )
    6.47 +                return x->smfn_and_flags;
    6.48 +#endif
    6.49              /* Pull-to-front if 'x' isn't already the head item. */
    6.50              if ( unlikely(x != head) )
    6.51              {
    6.52 @@ -763,9 +771,14 @@ static inline void shadow_mk_pagetable(s
    6.53  }
    6.54  
    6.55  #if SHADOW_DEBUG
    6.56 -extern void check_pagetable(struct domain *d, pagetable_t pt, char *s);
    6.57 +extern int _check_pagetable(struct domain *d, pagetable_t pt, char *s);
    6.58 +extern int _check_all_pagetables(struct domain *d, char *s);
    6.59 +
    6.60 +#define check_pagetable(_d, _pt, _s) _check_pagetable(_d, _pt, _s)
    6.61 +//#define check_pagetable(_d, _pt, _s) _check_all_pagetables(_d, _s)
    6.62 +
    6.63  #else
    6.64 -#define check_pagetable(d, pt, s) ((void)0)
    6.65 +#define check_pagetable(_d, _pt, _s) ((void)0)
    6.66  #endif
    6.67  
    6.68  #endif /* XEN_SHADOW_H */
     7.1 --- a/xen/include/xen/console.h	Sat Feb 12 03:11:43 2005 +0000
     7.2 +++ b/xen/include/xen/console.h	Sat Feb 12 19:58:43 2005 +0000
     7.3 @@ -26,4 +26,22 @@ void console_putc(char c);
     7.4  int console_getc(void);
     7.5  int irq_console_getc(void);
     7.6  
     7.7 +#ifdef NDEBUG
     7.8 +#define sercon_buffer_bypass() (0)
     7.9 +#else
    7.10 +#define sercon_buffer_bypass() _sercon_buffer_bypass()
    7.11 +int _sercon_buffer_bypass(void);
    7.12  #endif
    7.13 +
    7.14 +#ifdef NDEBUG
    7.15 +#define sercon_buffer_set(_enable) ((void)(0 && (_enable)));
    7.16 +#else
    7.17 +#define sercon_buffer_set(_enable) _sercon_buffer_set(_enable)
    7.18 +void _sercon_buffer_set(int enable);
    7.19 +#endif
    7.20 +
    7.21 +#ifndef NDEBUG
    7.22 +void sercon_buffer_toggle(unsigned char key);
    7.23 +#endif
    7.24 +
    7.25 +#endif /* __CONSOLE_H__ */
     8.1 --- a/xen/include/xen/perfc_defn.h	Sat Feb 12 03:11:43 2005 +0000
     8.2 +++ b/xen/include/xen/perfc_defn.h	Sat Feb 12 19:58:43 2005 +0000
     8.3 @@ -25,12 +25,16 @@ PERFCOUNTER_CPU( shadow_l2_table_count, 
     8.4  PERFCOUNTER_CPU( shadow_l1_table_count, "shadow_l1_table count" )
     8.5  PERFCOUNTER_CPU( unshadow_table_count, "unshadow_table count" )
     8.6  PERFCOUNTER_CPU( shadow_fixup_count, "shadow_fixup count" )
     8.7 -PERFCOUNTER_CPU( shadow_update_va_fail, "shadow_update_va_fail" )
     8.8 +PERFCOUNTER_CPU( shadow_update_va_fail1, "shadow_update_va_fail1" )
     8.9 +PERFCOUNTER_CPU( shadow_update_va_fail2, "shadow_update_va_fail2" )
    8.10  
    8.11  /* STATUS counters do not reset when 'P' is hit */
    8.12  PERFSTATUS( shadow_l2_pages, "current # shadow L2 pages" )
    8.13  PERFSTATUS( shadow_l1_pages, "current # shadow L1 pages" )
    8.14  
    8.15 +PERFCOUNTER_CPU( check_pagetable, "calls to check_pagetable" )
    8.16 +PERFCOUNTER_CPU( check_all_pagetables, "calls to check_all_pagetables" )
    8.17 +
    8.18  #define VMX_PERF_EXIT_REASON_SIZE 37
    8.19  #define VMX_PERF_VECTOR_SIZE 0x20
    8.20  PERFCOUNTER_ARRAY(vmexits, "vmexits", VMX_PERF_EXIT_REASON_SIZE )
     9.1 --- a/xen/include/xen/serial.h	Sat Feb 12 03:11:43 2005 +0000
     9.2 +++ b/xen/include/xen/serial.h	Sat Feb 12 19:58:43 2005 +0000
     9.3 @@ -18,6 +18,7 @@
     9.4  #define SERHND_HI       (1<<1) /* Mux/demux each transferred char by MSB. */
     9.5  #define SERHND_LO       (1<<2) /* Ditto, except that the MSB is cleared.  */
     9.6  #define SERHND_COOKED   (1<<3) /* Newline/carriage-return translation?    */
     9.7 +#define SERHND_BUFFERED (1<<4) /* Console serial port ring buffered?      */
     9.8  
     9.9  /* Two-stage initialisation (before/after IRQ-subsystem initialisation). */
    9.10  void serial_init_stage1(void);