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
     8.1 --- a/xen/arch/x86/mm.c	Sat Feb 12 03:11:43 2005 +0000
     8.2 +++ b/xen/arch/x86/mm.c	Sat Feb 12 19:58:43 2005 +0000
     8.3 @@ -1969,10 +1969,26 @@ int do_update_va_mapping(unsigned long v
     8.4              &shadow_linear_pg_table[l1_linear_offset(va)])))) )
     8.5          {
     8.6              /*
     8.7 -             * Since L2's are guranteed RW, failure indicates the page was not 
     8.8 -             * shadowed, so ignore.
     8.9 +             * Since L2's are guranteed RW, failure indicates either that the
    8.10 +             * page was not shadowed, or that the L2 entry has not yet been
    8.11 +             * updated to reflect the shadow.
    8.12               */
    8.13 -            perfc_incrc(shadow_update_va_fail);
    8.14 +            l2_pgentry_t gpde = linear_l2_table[l2_table_offset(va)];
    8.15 +            unsigned long gpfn = l2_pgentry_val(gpde) >> PAGE_SHIFT;
    8.16 +
    8.17 +            if (get_shadow_status(d, gpfn))
    8.18 +            {
    8.19 +                unsigned long gmfn = __gpfn_to_mfn(d, gpfn);
    8.20 +                unsigned long *gl1e = map_domain_mem(gmfn << PAGE_SHIFT);
    8.21 +                unsigned l1_idx = l1_table_offset(va);
    8.22 +                gl1e[l1_idx] = sval;
    8.23 +                unmap_domain_mem(gl1e);
    8.24 +                put_shadow_status(d);
    8.25 +
    8.26 +                perfc_incrc(shadow_update_va_fail1);
    8.27 +            }
    8.28 +            else
    8.29 +                perfc_incrc(shadow_update_va_fail2);
    8.30          }
    8.31  
    8.32          /*
     9.1 --- a/xen/arch/x86/shadow.c	Sat Feb 12 03:11:43 2005 +0000
     9.2 +++ b/xen/arch/x86/shadow.c	Sat Feb 12 19:58:43 2005 +0000
     9.3 @@ -762,10 +762,10 @@ void shadow_l2_normal_pt_update(unsigned
     9.4  // BUG: these are not SMP safe...
     9.5  static int sh_l2_present;
     9.6  static int sh_l1_present;
     9.7 -static int errors;
     9.8  char * sh_check_name;
     9.9 +int shadow_status_noswap;
    9.10  
    9.11 -#define virt_to_phys2(adr) ({                                            \
    9.12 +#define v2m(adr) ({                                                      \
    9.13      unsigned long _a = (unsigned long)(adr);                             \
    9.14      unsigned long _pte = l1_pgentry_val(                                 \
    9.15                              shadow_linear_pg_table[_a >> PAGE_SHIFT]);   \
    9.16 @@ -775,23 +775,28 @@ char * sh_check_name;
    9.17  
    9.18  #define FAIL(_f, _a...)                                                      \
    9.19      do {                                                                     \
    9.20 -        printk("XXX %s-FAIL (%d,%d)" _f " g=%p s=%p &g=%p &s=%p" \
    9.21 -               " pa(&g)=%p pa(&s)=%p\n",                               \
    9.22 -               sh_check_name, level, i, ## _a , gpte, spte, pgpte, pspte,    \
    9.23 -               virt_to_phys2(pgpte), virt_to_phys2(pspte));                  \
    9.24 +        printk("XXX %s-FAIL (%d,%d)" _f "\n"                                 \
    9.25 +               "g=%08lx s=%08lx &g=%08lx &s=%08lx"                           \
    9.26 +               " v2m(&g)=%08lx v2m(&s)=%08lx ea=%08lx\n",                    \
    9.27 +               sh_check_name, level, l1_idx, ## _a ,                         \
    9.28 +               gpte, spte, pgpte, pspte,                                     \
    9.29 +               v2m(pgpte), v2m(pspte),                                       \
    9.30 +               (l2_idx << L2_PAGETABLE_SHIFT) |                              \
    9.31 +               (l1_idx << L1_PAGETABLE_SHIFT));                              \
    9.32          errors++;                                                            \
    9.33      } while ( 0 )
    9.34  
    9.35  static int check_pte(
    9.36      struct domain *d, unsigned long *pgpte, unsigned long *pspte, 
    9.37 -    int level, int i)
    9.38 +    int level, int l2_idx, int l1_idx)
    9.39  {
    9.40      unsigned gpte = *pgpte;
    9.41      unsigned spte = *pspte;
    9.42      unsigned long mask, gpfn, smfn;
    9.43 +    int errors = 0;
    9.44  
    9.45      if ( (spte == 0) || (spte == 0xdeadface) || (spte == 0x00000E00) )
    9.46 -        return 1;  /* always safe */
    9.47 +        return errors;  /* always safe */
    9.48  
    9.49      if ( !(spte & _PAGE_PRESENT) )
    9.50          FAIL("Non zero not present spte");
    9.51 @@ -837,71 +842,71 @@ static int check_pte(
    9.52                   __shadow_status(d, gpfn) );
    9.53      }
    9.54  
    9.55 -    return 1;
    9.56 +    return errors;
    9.57  }
    9.58  
    9.59  
    9.60  static int check_l1_table(
    9.61      struct domain *d,
    9.62 -    unsigned long g2mfn, unsigned long s2mfn)
    9.63 +    unsigned long gmfn, unsigned long smfn, unsigned l2_idx)
    9.64  {
    9.65      int i;
    9.66      unsigned long *gpl1e, *spl1e;
    9.67 +    int cpu = current->processor;
    9.68 +    int errors = 0;
    9.69  
    9.70 -    gpl1e = map_domain_mem(g2mfn << PAGE_SHIFT);
    9.71 -    spl1e = map_domain_mem(s2mfn << PAGE_SHIFT);
    9.72 +    // First check to see if this guest page is currently the active
    9.73 +    // PTWR page.  If so, then we compare the (old) cached copy of the
    9.74 +    // guest page to the shadow, and not the currently writable (and
    9.75 +    // thus potentially out-of-sync) guest page.
    9.76 +    //
    9.77 +    if ( VM_ASSIST(d, VMASST_TYPE_writable_pagetables) )
    9.78 +    {
    9.79 +        for ( i = 0; i < ARRAY_SIZE(ptwr_info->ptinfo); i++)
    9.80 +        {
    9.81 +            if ( ptwr_info[cpu].ptinfo[i].l1va &&
    9.82 +                 ((v2m(ptwr_info[cpu].ptinfo[i].pl1e) >> PAGE_SHIFT) == gmfn) )
    9.83 +            {
    9.84 +                unsigned long old = gmfn;
    9.85 +                gmfn = (v2m(ptwr_info[cpu].ptinfo[i].page) >> PAGE_SHIFT);
    9.86 +                printk("hit1 ptwr_info[%d].ptinfo[%d].l1va, mfn=0x%08x, snapshot=0x%08x\n",
    9.87 +                       cpu, i, old, gmfn);
    9.88 +            }
    9.89 +        }
    9.90 +    }
    9.91 +
    9.92 +    gpl1e = map_domain_mem(gmfn << PAGE_SHIFT);
    9.93 +    spl1e = map_domain_mem(smfn << PAGE_SHIFT);
    9.94  
    9.95      for ( i = 0; i < L1_PAGETABLE_ENTRIES; i++ )
    9.96 -        check_pte(d, &gpl1e[i], &spl1e[i], 1, i);
    9.97 +        errors += check_pte(d, &gpl1e[i], &spl1e[i], 1, l2_idx, i);
    9.98   
    9.99      unmap_domain_mem(spl1e);
   9.100      unmap_domain_mem(gpl1e);
   9.101  
   9.102 -    return 1;
   9.103 +    return errors;
   9.104  }
   9.105  
   9.106 -#define FAILPT(_f, _a...)                                      \
   9.107 -    do {                                                       \
   9.108 -        printk("XXX FAIL %s-PT" _f "\n", s, ## _a );           \
   9.109 -        errors++;                                              \
   9.110 +#define FAILPT(_f, _a...)                                         \
   9.111 +    do {                                                          \
   9.112 +        printk("XXX FAIL %s-PT " _f "\n", sh_check_name, ## _a ); \
   9.113 +        errors++;                                                 \
   9.114      } while ( 0 )
   9.115  
   9.116 -void check_pagetable(struct domain *d, pagetable_t pt, char *s)
   9.117 +int check_l2_table(
   9.118 +    struct domain *d, unsigned long gpfn, unsigned long smfn)
   9.119  {
   9.120 -    unsigned long gptbase = pagetable_val(pt);
   9.121 -    unsigned long ptbase_pfn, smfn, ss;
   9.122 -    unsigned long i;
   9.123 -    l2_pgentry_t *gpl2e, *spl2e;
   9.124 -    unsigned long ptbase_mfn = 0;
   9.125 -    int cpu = current->processor;
   9.126 -
   9.127 -    errors = 0;
   9.128 -    sh_check_name = s;
   9.129 -
   9.130 -    SH_VVLOG("%s-PT Audit", s);
   9.131 -
   9.132 -    sh_l2_present = sh_l1_present = 0;
   9.133 +    unsigned long gmfn = __gpfn_to_mfn(d, gpfn);
   9.134 +    l2_pgentry_t *gpl2e = (l2_pgentry_t *) map_domain_mem( gmfn << PAGE_SHIFT );
   9.135 +    l2_pgentry_t *spl2e = (l2_pgentry_t *) map_domain_mem( smfn << PAGE_SHIFT );
   9.136 +    int i;
   9.137 +    int errors = 0;
   9.138  
   9.139 -    ptbase_pfn = gptbase >> PAGE_SHIFT;
   9.140 -    ptbase_mfn = __gpfn_to_mfn(d, ptbase_pfn);
   9.141 -
   9.142 -    ss = __shadow_status(d, ptbase_pfn);
   9.143 -  
   9.144 -    if ( ! (ss & PSH_shadowed) )
   9.145 -    {
   9.146 -        /*printk("%s-PT %p not shadowed\n", s, gptbase);*/
   9.147 -        if ( ss != 0 )
   9.148 -            BUG();
   9.149 -        return;
   9.150 -    }   
   9.151 - 
   9.152 -    smfn = ss & PSH_pfn_mask;
   9.153 -
   9.154 -    if ( ss != (PSH_shadowed | smfn) )
   9.155 -        FAILPT("ptbase shadow inconsistent1");
   9.156 -
   9.157 -    gpl2e = (l2_pgentry_t *) map_domain_mem( ptbase_mfn << PAGE_SHIFT );
   9.158 -    spl2e = (l2_pgentry_t *) map_domain_mem( smfn << PAGE_SHIFT );
   9.159 +    if ( page_get_owner(pfn_to_page(gmfn)) != d )
   9.160 +        FAILPT("domain doesn't own page");
   9.161 +    if ( page_get_owner(pfn_to_page(smfn)) != NULL )
   9.162 +        FAILPT("shadow page mfn=0x%08x is owned by someone, domid=%d",
   9.163 +               smfn, page_get_owner(pfn_to_page(smfn))->id);
   9.164  
   9.165      if ( memcmp(&spl2e[DOMAIN_ENTRIES_PER_L2_PAGETABLE],
   9.166                  &gpl2e[DOMAIN_ENTRIES_PER_L2_PAGETABLE], 
   9.167 @@ -921,24 +926,68 @@ void check_pagetable(struct domain *d, p
   9.168          FAILPT("hypervisor linear map inconsistent");
   9.169  
   9.170      if ( (l2_pgentry_val(spl2e[SH_LINEAR_PT_VIRT_START >> 
   9.171 -                              L2_PAGETABLE_SHIFT]) != 
   9.172 +                               L2_PAGETABLE_SHIFT]) != 
   9.173            ((smfn << PAGE_SHIFT) | __PAGE_HYPERVISOR)) )
   9.174          FAILPT("hypervisor shadow linear map inconsistent %p %p",
   9.175                 l2_pgentry_val(spl2e[SH_LINEAR_PT_VIRT_START >>
   9.176 -                                   L2_PAGETABLE_SHIFT]),
   9.177 +                                    L2_PAGETABLE_SHIFT]),
   9.178                 (smfn << PAGE_SHIFT) | __PAGE_HYPERVISOR);
   9.179  
   9.180      if ( shadow_mode(d) != SHM_full_32 ) {
   9.181 -        // BUG: this shouldn't be using exec_domain[0] here...
   9.182          if ( (l2_pgentry_val(spl2e[PERDOMAIN_VIRT_START >> L2_PAGETABLE_SHIFT]) !=
   9.183 -              ((__pa(page_get_owner(&frame_table[ptbase_pfn])->arch.mm_perdomain_pt) | 
   9.184 -            __PAGE_HYPERVISOR))) )
   9.185 +              ((v2m(page_get_owner(&frame_table[gmfn])->arch.mm_perdomain_pt) |
   9.186 +                __PAGE_HYPERVISOR))) )
   9.187              FAILPT("hypervisor per-domain map inconsistent");
   9.188      }
   9.189  
   9.190      /* Check the whole L2. */
   9.191      for ( i = 0; i < DOMAIN_ENTRIES_PER_L2_PAGETABLE; i++ )
   9.192 -        check_pte(d, &l2_pgentry_val(gpl2e[i]), &l2_pgentry_val(spl2e[i]), 2, i);
   9.193 +        errors += check_pte(d, &l2_pgentry_val(gpl2e[i]), &l2_pgentry_val(spl2e[i]), 2, i, 0);
   9.194 +
   9.195 +    unmap_domain_mem(spl2e);
   9.196 +    unmap_domain_mem(gpl2e);
   9.197 +
   9.198 +    return errors;
   9.199 +}
   9.200 +
   9.201 +int _check_pagetable(struct domain *d, pagetable_t pt, char *s)
   9.202 +{
   9.203 +    unsigned long gptbase = pagetable_val(pt);
   9.204 +    unsigned long ptbase_pfn, smfn, ss;
   9.205 +    unsigned long i;
   9.206 +    l2_pgentry_t *gpl2e, *spl2e;
   9.207 +    unsigned long ptbase_mfn = 0;
   9.208 +    int errors = 0;
   9.209 +
   9.210 +    sh_check_name = s;
   9.211 +    SH_VVLOG("%s-PT Audit", s);
   9.212 +    sh_l2_present = sh_l1_present = 0;
   9.213 +    perfc_incrc(check_pagetable);
   9.214 +
   9.215 +    ptbase_pfn = gptbase >> PAGE_SHIFT;
   9.216 +    ptbase_mfn = __gpfn_to_mfn(d, ptbase_pfn);
   9.217 +
   9.218 +    ss = __shadow_status(d, ptbase_pfn);
   9.219 +  
   9.220 +    if ( ! (ss & PSH_shadowed) )
   9.221 +    {
   9.222 +        printk("%s-PT %p not shadowed\n", s, gptbase);
   9.223 +        errors++;
   9.224 +
   9.225 +        if ( ss != 0 )
   9.226 +            BUG();
   9.227 +        return errors;
   9.228 +    }   
   9.229 + 
   9.230 +    smfn = ss & PSH_pfn_mask;
   9.231 +
   9.232 +    if ( ss != (PSH_shadowed | smfn) )
   9.233 +        FAILPT("ptbase shadow inconsistent1");
   9.234 +
   9.235 +    errors += check_l2_table(d, ptbase_pfn, smfn);
   9.236 +
   9.237 +    gpl2e = (l2_pgentry_t *) map_domain_mem( ptbase_mfn << PAGE_SHIFT );
   9.238 +    spl2e = (l2_pgentry_t *) map_domain_mem( smfn << PAGE_SHIFT );
   9.239  
   9.240      /* Go back and recurse. */
   9.241      for ( i = 0; i < DOMAIN_ENTRIES_PER_L2_PAGETABLE; i++ )
   9.242 @@ -949,20 +998,7 @@ void check_pagetable(struct domain *d, p
   9.243  
   9.244          if ( l2_pgentry_val(spl2e[i]) != 0 )
   9.245          {
   9.246 -            // First check to see if this guest page is currently the active
   9.247 -            // PTWR page.  If so, then we compare the (old) cached copy of the
   9.248 -            // guest page to the shadow, and not the currently writable (and
   9.249 -            // thus potentially out-of-sync) guest page.
   9.250 -            //
   9.251 -            if ( ptwr_info[cpu].ptinfo[PTWR_PT_ACTIVE].l1va &&
   9.252 -                 (i == ptwr_info[cpu].ptinfo[PTWR_PT_ACTIVE].l2_idx) &&
   9.253 -                 likely(VM_ASSIST(d, VMASST_TYPE_writable_pagetables)) )
   9.254 -            {
   9.255 -                gl1mfn = (__pa(ptwr_info[cpu].ptinfo[PTWR_PT_ACTIVE].page) >>
   9.256 -                          PAGE_SHIFT);
   9.257 -            }
   9.258 -
   9.259 -            check_l1_table(d, gl1mfn, sl1mfn);
   9.260 +            errors += check_l1_table(d, gl1mfn, sl1mfn, i);
   9.261          }
   9.262      }
   9.263  
   9.264 @@ -972,10 +1008,104 @@ void check_pagetable(struct domain *d, p
   9.265      SH_VVLOG("PT verified : l2_present = %d, l1_present = %d",
   9.266               sh_l2_present, sh_l1_present);
   9.267   
   9.268 +#if 1
   9.269      if ( errors )
   9.270          BUG();
   9.271 +#endif
   9.272  
   9.273 -    return;
   9.274 +    return errors;
   9.275 +}
   9.276 +
   9.277 +int _check_all_pagetables(struct domain *d, char *s)
   9.278 +{
   9.279 +    int i, j;
   9.280 +    struct shadow_status *a;
   9.281 +    unsigned long gmfn;
   9.282 +    int errors = 0;
   9.283 +    int cpu;
   9.284 +
   9.285 +    shadow_status_noswap = 1;
   9.286 +
   9.287 +    sh_check_name = s;
   9.288 +    SH_VVLOG("%s-PT Audit domid=%d", s, d->id);
   9.289 +    sh_l2_present = sh_l1_present = 0;
   9.290 +    perfc_incrc(check_all_pagetables);
   9.291 +
   9.292 +    for (i = 0; i < shadow_ht_buckets; i++)
   9.293 +    {
   9.294 +        a = &d->arch.shadow_ht[i];
   9.295 +        while ( a && a->pfn )
   9.296 +        {
   9.297 +            gmfn = __gpfn_to_mfn(d, a->pfn);
   9.298 +            switch ( frame_table[a->pfn].u.inuse.type_info & PGT_type_mask )
   9.299 +            {
   9.300 +            case PGT_l1_page_table:
   9.301 +                errors += check_l1_table(d, gmfn, a->smfn_and_flags & PSH_pfn_mask, 0);
   9.302 +                break;
   9.303 +            case PGT_l2_page_table:
   9.304 +                errors += check_l2_table(d, gmfn, a->smfn_and_flags & PSH_pfn_mask);
   9.305 +                break;
   9.306 +            default:
   9.307 +                errors++;
   9.308 +                printk("unexpected page type 0x%08x, pfn=0x%08x, gmfn=0x%08x\n",
   9.309 +                       frame_table[gmfn].u.inuse.type_info,
   9.310 +                       a->pfn, gmfn);
   9.311 +                BUG();
   9.312 +            }
   9.313 +            a = a->next;
   9.314 +        }
   9.315 +    }
   9.316 +
   9.317 +    shadow_status_noswap = 0;
   9.318 +
   9.319 +    for (i = 0; i < 1024; i++)
   9.320 +    {
   9.321 +        if ( l2_pgentry_val(shadow_linear_l2_table[i]) & _PAGE_PRESENT )
   9.322 +        {
   9.323 +            unsigned base = i << 10;
   9.324 +            for (j = 0; j < 1024; j++)
   9.325 +            {
   9.326 +                if ( (l1_pgentry_val(shadow_linear_pg_table[base + j]) & PAGE_MASK) == 0x0143d000 )
   9.327 +                {
   9.328 +                    printk("sh_ln_pg_tb[0x%08x] => 0x%08lx ",
   9.329 +                           base + j,
   9.330 +                           l1_pgentry_val(shadow_linear_pg_table[base + j]));
   9.331 +                    if ( l1_pgentry_val(shadow_linear_pg_table[base + j]) & _PAGE_PRESENT )
   9.332 +                        printk(" first entry => 0x%08lx\n",
   9.333 +                               *(unsigned long *)((base + j) << PAGE_SHIFT));
   9.334 +                    else
   9.335 +                        printk(" page not present\n");
   9.336 +                }
   9.337 +            }
   9.338 +        }
   9.339 +    }
   9.340 +
   9.341 +    if ( errors )
   9.342 +    {
   9.343 +        printk("VM_ASSIST(d, VMASST_TYPE_writable_pagetables) => %d\n",
   9.344 +               VM_ASSIST(d, VMASST_TYPE_writable_pagetables));
   9.345 +        for ( cpu = 0; cpu < smp_num_cpus; cpu++ )
   9.346 +        {
   9.347 +            for ( j = 0; j < ARRAY_SIZE(ptwr_info->ptinfo); j++)
   9.348 +            {
   9.349 +                printk("ptwr_info[%d].ptinfo[%d].l1va => 0x%08x\n",
   9.350 +                       cpu, j, ptwr_info[cpu].ptinfo[j].l1va);
   9.351 +                printk("ptwr_info[%d].ptinfo[%d].pl1e => 0x%08x\n",
   9.352 +                       cpu, j, ptwr_info[cpu].ptinfo[j].pl1e);
   9.353 +                if (cpu == smp_processor_id())
   9.354 +                    printk("v2m(ptwr_info[%d].ptinfo[%d].pl1e) => 0x%08x\n",
   9.355 +                           cpu, j, v2m(ptwr_info[cpu].ptinfo[j].pl1e));
   9.356 +                printk("ptwr_info[%d].ptinfo[%d].page => 0x%08x\n",
   9.357 +                       cpu, j, ptwr_info[cpu].ptinfo[j].page);
   9.358 +                if (cpu == smp_processor_id())
   9.359 +                    printk("v2m(ptwr_info[%d].ptinfo[%d].page) => 0x%08x\n",
   9.360 +                           cpu, j, v2m(ptwr_info[cpu].ptinfo[j].page));
   9.361 +            }
   9.362 +        }
   9.363 +        BUG();
   9.364 +    }
   9.365 +
   9.366 +    return errors;
   9.367  }
   9.368  
   9.369  #endif // SHADOW_DEBUG
    11.1 --- a/xen/common/keyhandler.c	Sat Feb 12 03:11:43 2005 +0000
    11.2 +++ b/xen/common/keyhandler.c	Sat Feb 12 19:58:43 2005 +0000
    11.3 @@ -75,12 +75,14 @@ void register_irq_keyhandler(
    11.4  static void show_handlers(unsigned char key)
    11.5  {
    11.6      int i; 
    11.7 +    int buffer_enable = sercon_buffer_bypass();
    11.8      printk("'%c' pressed -> showing installed handlers\n", key);
    11.9      for ( i = 0; i < KEY_MAX; i++ ) 
   11.10          if ( key_table[i].u.handler != NULL ) 
   11.11              printk(" key '%c' (ascii '%02x') => %s\n", 
   11.12                     (i<33 || i>126)?(' '):(i),i,
   11.13                     key_table[i].desc);
   11.14 +    sercon_buffer_set(buffer_enable);
   11.15  }
   11.16  
   11.17  static void dump_registers(unsigned char key, struct xen_regs *regs)
   11.18 @@ -177,6 +179,10 @@ void initialize_keytable(void)
   11.19  #ifndef NDEBUG
   11.20      register_keyhandler(
   11.21          'o', audit_domains_key,  "audit domains >0 EXPERIMENTAL"); 
   11.22 +
   11.23 +    register_keyhandler(
   11.24 +        'c', sercon_buffer_toggle,
   11.25 +        "toggle serial console output vs ring buffer capture");
   11.26  #endif
   11.27  
   11.28  #ifdef PERF_COUNTERS
    12.1 --- a/xen/drivers/char/console.c	Sat Feb 12 03:11:43 2005 +0000
    12.2 +++ b/xen/drivers/char/console.c	Sat Feb 12 19:58:43 2005 +0000
    12.3 @@ -51,6 +51,17 @@ static int vgacon_enabled = 0;
    12.4  
    12.5  spinlock_t console_lock = SPIN_LOCK_UNLOCKED;
    12.6  
    12.7 +#ifndef NDEBUG
    12.8 +static unsigned char *sercon_buffer      = NULL;
    12.9 +static unsigned char *sercon_buffer_end  = NULL;
   12.10 +static unsigned char *sercon_buffer_head = NULL;
   12.11 +static unsigned char *sercon_buffer_next = NULL;
   12.12 +
   12.13 +static unsigned int opt_sercon_buffer_size = 128; /* kbytes */
   12.14 +integer_param("conbuf", opt_sercon_buffer_size);
   12.15 +
   12.16 +static void sercon_buffer_puts(const unsigned char *s);
   12.17 +#endif
   12.18  
   12.19  /*
   12.20   * *******************************************************
   12.21 @@ -254,9 +265,13 @@ static void switch_serial_input(void)
   12.22      static char *input_str[2] = { "DOM0", "Xen" };
   12.23      xen_rx = !xen_rx;
   12.24      if ( SWITCH_CODE != 0 )
   12.25 +    {
   12.26 +        int buffer_enable = sercon_buffer_bypass();
   12.27          printk("*** Serial input -> %s "
   12.28                 "(type 'CTRL-%c' three times to switch input to %s).\n",
   12.29                 input_str[xen_rx], opt_conswitch[0], input_str[!xen_rx]);
   12.30 +        sercon_buffer_set(buffer_enable);
   12.31 +    }
   12.32  }
   12.33  
   12.34  static void __serial_rx(unsigned char c, struct xen_regs *regs)
   12.35 @@ -353,7 +368,14 @@ long do_console_io(int cmd, int count, c
   12.36  static inline void __putstr(const char *str)
   12.37  {
   12.38      int c;
   12.39 -    serial_puts(sercon_handle, str);
   12.40 +
   12.41 +#ifndef NDEBUG
   12.42 +    if ( sercon_handle & SERHND_BUFFERED )
   12.43 +        sercon_buffer_puts(str);
   12.44 +    else
   12.45 +#endif
   12.46 +        serial_puts(sercon_handle, str);
   12.47 +
   12.48      while ( (c = *str++) != '\0' )
   12.49      {
   12.50          putchar_console(c);
   12.51 @@ -463,16 +485,19 @@ void console_force_lock(void)
   12.52      spin_lock(&console_lock);
   12.53  }
   12.54  
   12.55 +// 09Feb2005: this appears to be unused...
   12.56  void console_putc(char c)
   12.57  {
   12.58      serial_putc(sercon_handle, c);
   12.59  }
   12.60  
   12.61 +// 09Feb2005: this appears to be unused...
   12.62  int console_getc(void)
   12.63  {
   12.64      return serial_getc(sercon_handle);
   12.65  }
   12.66  
   12.67 +// 09Feb2005: this appears to be unused...
   12.68  int irq_console_getc(void)
   12.69  {
   12.70      return irq_serial_getc(sercon_handle);
   12.71 @@ -481,6 +506,116 @@ int irq_console_getc(void)
   12.72  
   12.73  /*
   12.74   * **************************************************************
   12.75 + * *************** serial console ring buffer *******************
   12.76 + * **************************************************************
   12.77 + */
   12.78 +
   12.79 +#ifndef NDEBUG
   12.80 +static void sercon_buffer_putc(const unsigned char c)
   12.81 +{
   12.82 +    if ( !sercon_buffer )
   12.83 +        return;
   12.84 +    if ( !c )
   12.85 +        return;
   12.86 +
   12.87 +    if ( sercon_buffer_next == sercon_buffer_end )
   12.88 +    {
   12.89 +        // buffer wrap-around case...
   12.90 +        sercon_buffer_head = sercon_buffer + 1;
   12.91 +        sercon_buffer_next = sercon_buffer;
   12.92 +    }
   12.93 +    if ( sercon_buffer_head == sercon_buffer_next + 1 )
   12.94 +    {
   12.95 +        // the buffer is already full...
   12.96 +        sercon_buffer_head++;
   12.97 +    }
   12.98 +    *sercon_buffer_next++ = c;
   12.99 +    *sercon_buffer_next = 0;
  12.100 +}
  12.101 +
  12.102 +static void sercon_buffer_puts(const unsigned char *s)
  12.103 +{
  12.104 +    // inefficient but simple...
  12.105 +    while ( *s )
  12.106 +        sercon_buffer_putc(*s++);
  12.107 +}
  12.108 +
  12.109 +static void sercon_buffer_reset(void)
  12.110 +{
  12.111 +    sercon_buffer_head = sercon_buffer;
  12.112 +    sercon_buffer_next = sercon_buffer;
  12.113 +    sercon_buffer_head[0] = 0;
  12.114 +}
  12.115 +
  12.116 +static void sercon_buffer_flush(void)
  12.117 +{
  12.118 +    serial_puts(sercon_handle, sercon_buffer_head);
  12.119 +    if ( sercon_buffer_head != sercon_buffer )
  12.120 +        serial_puts(sercon_handle, sercon_buffer);
  12.121 +    sercon_buffer_reset();
  12.122 +}
  12.123 +
  12.124 +void _sercon_buffer_dump(void)
  12.125 +{
  12.126 +    sercon_buffer_flush();
  12.127 +    sercon_handle &= ~SERHND_BUFFERED;
  12.128 +}
  12.129 +
  12.130 +void sercon_buffer_toggle(unsigned char key)
  12.131 +{
  12.132 +    if ( !sercon_buffer )
  12.133 +    {
  12.134 +        printk("serial console buffer not allocated\n");
  12.135 +        return;
  12.136 +    }
  12.137 +
  12.138 +    if ( sercon_handle & SERHND_BUFFERED )
  12.139 +        sercon_buffer_flush();
  12.140 +    sercon_handle ^= SERHND_BUFFERED;
  12.141 +}
  12.142 +
  12.143 +void _sercon_buffer_set(int enable)
  12.144 +{
  12.145 +    if (enable)
  12.146 +        sercon_handle |= SERHND_BUFFERED;
  12.147 +    else
  12.148 +        sercon_handle &= ~SERHND_BUFFERED;
  12.149 +}
  12.150 +
  12.151 +int _sercon_buffer_bypass(void)
  12.152 +{
  12.153 +    int buffering = !!(sercon_handle & SERHND_BUFFERED);
  12.154 +    sercon_handle &= ~SERHND_BUFFERED;
  12.155 +
  12.156 +    return buffering;
  12.157 +}
  12.158 +
  12.159 +static int __init sercon_buffer_init(void)
  12.160 +{
  12.161 +    int order;
  12.162 +    int kbytes = opt_sercon_buffer_size;
  12.163 +
  12.164 +    if ( !kbytes )
  12.165 +        return 0;
  12.166 +
  12.167 +    order = get_order(kbytes * 1024);
  12.168 +    sercon_buffer = (void *)alloc_xenheap_pages(order);
  12.169 +    ASSERT( sercon_buffer );
  12.170 +
  12.171 +    sercon_buffer_end = sercon_buffer + kbytes*1024 - 1;
  12.172 +    *sercon_buffer_end = 0;
  12.173 +
  12.174 +    sercon_buffer_reset();
  12.175 +
  12.176 +    return 0;
  12.177 +}
  12.178 +__initcall(sercon_buffer_init);
  12.179 +
  12.180 +#endif /* not NDEBUG */
  12.181 +
  12.182 +
  12.183 +/*
  12.184 + * **************************************************************
  12.185   * *************** Debugging/tracing/error-report ***************
  12.186   * **************************************************************
  12.187   */
  12.188 @@ -513,6 +648,8 @@ void panic(const char *fmt, ...)
  12.189      spin_unlock_irqrestore(&console_lock, flags);
  12.190  
  12.191      watchdog_on = 0;
  12.192 +    sercon_buffer_dump();
  12.193 +
  12.194      mdelay(5000);
  12.195      machine_restart(0);
  12.196  }
    13.1 --- a/xen/include/asm-x86/config.h	Sat Feb 12 03:11:43 2005 +0000
    13.2 +++ b/xen/include/asm-x86/config.h	Sat Feb 12 19:58:43 2005 +0000
    13.3 @@ -99,10 +99,19 @@ extern void __out_of_line_bug(int line) 
    13.4  #define out_of_line_bug() __out_of_line_bug(__LINE__)
    13.5  #endif /* __ASSEMBLY__ */
    13.6  
    13.7 +#ifndef __ASSEMBLY__
    13.8 +#ifndef NDEBUG
    13.9 +extern void _sercon_buffer_dump(void);
   13.10 +#define sercon_buffer_dump() _sercon_buffer_dump()
   13.11 +#else
   13.12 +#define sercon_buffer_dump() ((void)0)
   13.13 +#endif
   13.14  #define BUG() do {					\
   13.15  	printk("BUG at %s:%d\n", __FILE__, __LINE__);	\
   13.16 -	__asm__ __volatile__("ud2");			\
   13.17 +        watchdog_on = 0;                                \
   13.18 +        sercon_buffer_dump();                           \
   13.19  } while (0)
   13.20 +#endif /* __ASSEMBLY__ */
   13.21  
   13.22  #if defined(__x86_64__)
   13.23  
    14.1 --- a/xen/include/asm-x86/shadow.h	Sat Feb 12 03:11:43 2005 +0000
    14.2 +++ b/xen/include/asm-x86/shadow.h	Sat Feb 12 19:58:43 2005 +0000
    14.3 @@ -77,6 +77,10 @@ static inline void shadow_invalidate(str
    14.4  #define SHADOW_VERBOSE_DEBUG 0
    14.5  #define SHADOW_HASH_DEBUG 0
    14.6  
    14.7 +#if SHADOW_DEBUG
    14.8 +extern int shadow_status_noswap;
    14.9 +#endif
   14.10 +
   14.11  struct shadow_status {
   14.12      unsigned long pfn;            /* Guest pfn.             */
   14.13      unsigned long smfn_and_flags; /* Shadow mfn plus flags. */
   14.14 @@ -88,7 +92,7 @@ struct shadow_status {
   14.15  
   14.16  #ifdef VERBOSE
   14.17  #define SH_LOG(_f, _a...)                                               \
   14.18 -printk("DOM%uP%u: (file=shadow.c, line=%d) " _f "\n",                   \
   14.19 +    printk("DOM%uP%u: SH_LOG(%d): " _f "\n",                            \
   14.20         current->domain->id , current->processor, __LINE__ , ## _a )
   14.21  #else
   14.22  #define SH_LOG(_f, _a...) 
   14.23 @@ -96,7 +100,7 @@ printk("DOM%uP%u: (file=shadow.c, line=%
   14.24  
   14.25  #if SHADOW_DEBUG
   14.26  #define SH_VLOG(_f, _a...)                                              \
   14.27 -    printk("DOM%uP%u: (file=shadow.c, line=%d) " _f "\n",               \
   14.28 +    printk("DOM%uP%u: SH_VLOG(%d): " _f "\n",                           \
   14.29             current->domain->id, current->processor, __LINE__ , ## _a )
   14.30  #else
   14.31  #define SH_VLOG(_f, _a...) 
   14.32 @@ -104,7 +108,7 @@ printk("DOM%uP%u: (file=shadow.c, line=%
   14.33  
   14.34  #if SHADOW_VERBOSE_DEBUG
   14.35  #define SH_VVLOG(_f, _a...)                                             \
   14.36 -    printk("DOM%uP%u: (file=shadow.c, line=%d) " _f "\n",               \
   14.37 +    printk("DOM%uP%u: SH_VVLOG(%d): " _f "\n",                          \
   14.38             current->domain->id, current->processor, __LINE__ , ## _a )
   14.39  #else
   14.40  #define SH_VVLOG(_f, _a...)
   14.41 @@ -428,6 +432,10 @@ static inline unsigned long __shadow_sta
   14.42  
   14.43          if ( x->pfn == gpfn )
   14.44          {
   14.45 +#if SHADOW_DEBUG
   14.46 +            if ( unlikely(shadow_status_noswap) )
   14.47 +                return x->smfn_and_flags;
   14.48 +#endif
   14.49              /* Pull-to-front if 'x' isn't already the head item. */
   14.50              if ( unlikely(x != head) )
   14.51              {
   14.52 @@ -763,9 +771,14 @@ static inline void shadow_mk_pagetable(s
   14.53  }
   14.54  
   14.55  #if SHADOW_DEBUG
   14.56 -extern void check_pagetable(struct domain *d, pagetable_t pt, char *s);
   14.57 +extern int _check_pagetable(struct domain *d, pagetable_t pt, char *s);
   14.58 +extern int _check_all_pagetables(struct domain *d, char *s);
   14.59 +
   14.60 +#define check_pagetable(_d, _pt, _s) _check_pagetable(_d, _pt, _s)
   14.61 +//#define check_pagetable(_d, _pt, _s) _check_all_pagetables(_d, _s)
   14.62 +
   14.63  #else
   14.64 -#define check_pagetable(d, pt, s) ((void)0)
   14.65 +#define check_pagetable(_d, _pt, _s) ((void)0)
   14.66  #endif
   14.67  
   14.68  #endif /* XEN_SHADOW_H */
    15.1 --- a/xen/include/xen/console.h	Sat Feb 12 03:11:43 2005 +0000
    15.2 +++ b/xen/include/xen/console.h	Sat Feb 12 19:58:43 2005 +0000
    15.3 @@ -26,4 +26,22 @@ void console_putc(char c);
    15.4  int console_getc(void);
    15.5  int irq_console_getc(void);
    15.6  
    15.7 +#ifdef NDEBUG
    15.8 +#define sercon_buffer_bypass() (0)
    15.9 +#else
   15.10 +#define sercon_buffer_bypass() _sercon_buffer_bypass()
   15.11 +int _sercon_buffer_bypass(void);
   15.12  #endif
   15.13 +
   15.14 +#ifdef NDEBUG
   15.15 +#define sercon_buffer_set(_enable) ((void)(0 && (_enable)));
   15.16 +#else
   15.17 +#define sercon_buffer_set(_enable) _sercon_buffer_set(_enable)
   15.18 +void _sercon_buffer_set(int enable);
   15.19 +#endif
   15.20 +
   15.21 +#ifndef NDEBUG
   15.22 +void sercon_buffer_toggle(unsigned char key);
   15.23 +#endif
   15.24 +
   15.25 +#endif /* __CONSOLE_H__ */
    16.1 --- a/xen/include/xen/perfc_defn.h	Sat Feb 12 03:11:43 2005 +0000
    16.2 +++ b/xen/include/xen/perfc_defn.h	Sat Feb 12 19:58:43 2005 +0000
    16.3 @@ -25,12 +25,16 @@ PERFCOUNTER_CPU( shadow_l2_table_count, 
    16.4  PERFCOUNTER_CPU( shadow_l1_table_count, "shadow_l1_table count" )
    16.5  PERFCOUNTER_CPU( unshadow_table_count, "unshadow_table count" )
    16.6  PERFCOUNTER_CPU( shadow_fixup_count, "shadow_fixup count" )
    16.7 -PERFCOUNTER_CPU( shadow_update_va_fail, "shadow_update_va_fail" )
    16.8 +PERFCOUNTER_CPU( shadow_update_va_fail1, "shadow_update_va_fail1" )
    16.9 +PERFCOUNTER_CPU( shadow_update_va_fail2, "shadow_update_va_fail2" )
   16.10  
   16.11  /* STATUS counters do not reset when 'P' is hit */
   16.12  PERFSTATUS( shadow_l2_pages, "current # shadow L2 pages" )
   16.13  PERFSTATUS( shadow_l1_pages, "current # shadow L1 pages" )
   16.14  
   16.15 +PERFCOUNTER_CPU( check_pagetable, "calls to check_pagetable" )
   16.16 +PERFCOUNTER_CPU( check_all_pagetables, "calls to check_all_pagetables" )
   16.17 +
   16.18  #define VMX_PERF_EXIT_REASON_SIZE 37
   16.19  #define VMX_PERF_VECTOR_SIZE 0x20
   16.20  PERFCOUNTER_ARRAY(vmexits, "vmexits", VMX_PERF_EXIT_REASON_SIZE )
    17.1 --- a/xen/include/xen/serial.h	Sat Feb 12 03:11:43 2005 +0000
    17.2 +++ b/xen/include/xen/serial.h	Sat Feb 12 19:58:43 2005 +0000
    17.3 @@ -18,6 +18,7 @@
    17.4  #define SERHND_HI       (1<<1) /* Mux/demux each transferred char by MSB. */
    17.5  #define SERHND_LO       (1<<2) /* Ditto, except that the MSB is cleared.  */
    17.6  #define SERHND_COOKED   (1<<3) /* Newline/carriage-return translation?    */
    17.7 +#define SERHND_BUFFERED (1<<4) /* Console serial port ring buffered?      */
    17.8  
    17.9  /* Two-stage initialisation (before/after IRQ-subsystem initialisation). */
   17.10  void serial_init_stage1(void);