[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH RFC 44/44] misc debugging
Keyhandlers for the following: '1' - Walk idle_pg_table[] '2' - Walk each percpu_mappings '3' - Dump PT shadow stats --- xen/arch/x86/hvm/save.c | 4 - xen/arch/x86/mm/p2m-ept.c | 5 +- xen/arch/x86/pv/pt-shadow.c | 19 ++++ xen/arch/x86/traps.c | 199 +++++++++++++++++++++++++++++++++++++ xen/arch/x86/x86_64/mm.c | 6 ++ xen/include/asm-x86/pv/pt-shadow.h | 17 ++++ 6 files changed, 244 insertions(+), 6 deletions(-) diff --git a/xen/arch/x86/hvm/save.c b/xen/arch/x86/hvm/save.c index 8984a23..fbdae05 100644 --- a/xen/arch/x86/hvm/save.c +++ b/xen/arch/x86/hvm/save.c @@ -223,8 +223,6 @@ int hvm_save(struct domain *d, hvm_domain_context_t *h) handler = hvm_sr_handlers[i].save; if ( handler != NULL ) { - printk(XENLOG_G_INFO "HVM%d save: %s\n", - d->domain_id, hvm_sr_handlers[i].name); if ( handler(d, h) != 0 ) { printk(XENLOG_G_ERR @@ -297,8 +295,6 @@ int hvm_load(struct domain *d, hvm_domain_context_t *h) } /* Load the entry */ - printk(XENLOG_G_INFO "HVM%d restore: %s %"PRIu16"\n", d->domain_id, - hvm_sr_handlers[desc->typecode].name, desc->instance); if ( handler(d, h) != 0 ) { printk(XENLOG_G_ERR "HVM%d restore: failed to load entry %u/%u\n", diff --git a/xen/arch/x86/mm/p2m-ept.c b/xen/arch/x86/mm/p2m-ept.c index b4996ce..4167d29 100644 --- a/xen/arch/x86/mm/p2m-ept.c +++ b/xen/arch/x86/mm/p2m-ept.c @@ -1285,7 +1285,7 @@ void ept_p2m_uninit(struct p2m_domain *p2m) free_cpumask_var(ept->invalidate); } -static const char *memory_type_to_str(unsigned int x) +const char *memory_type_to_str(unsigned int x) { static const char memory_types[8][3] = { [MTRR_TYPE_UNCACHABLE] = "UC", @@ -1293,7 +1293,8 @@ static const char *memory_type_to_str(unsigned int x) [MTRR_TYPE_WRTHROUGH] = "WT", [MTRR_TYPE_WRPROT] = "WP", [MTRR_TYPE_WRBACK] = "WB", - [MTRR_NUM_TYPES] = "??" + [PAT_TYPE_UC_MINUS] = "U-", + /* [MTRR_NUM_TYPES] = "??", */ }; ASSERT(x < ARRAY_SIZE(memory_types)); diff --git a/xen/arch/x86/pv/pt-shadow.c b/xen/arch/x86/pv/pt-shadow.c index d550ae1..f4c522f 100644 --- a/xen/arch/x86/pv/pt-shadow.c +++ b/xen/arch/x86/pv/pt-shadow.c @@ -28,6 +28,8 @@ #undef page_to_mfn #define page_to_mfn(pg) _mfn(__page_to_mfn(pg)) +struct ptstats ptstats; + /* * To use percpu linear ranges, we require that no two pcpus have %cr3 * pointing at the same L4 pagetable at the same time. @@ -224,7 +226,10 @@ unsigned long pt_maybe_shadow(struct vcpu *v) /* No shadowing necessary? Run on the intended pagetable. */ if ( !pt_need_shadow(v->domain) ) + { + ptstat(&ptstats.sync_none); return new_cr3; + } ptsh->domain = v->domain; @@ -259,6 +264,11 @@ unsigned long pt_maybe_shadow(struct vcpu *v) } } local_irq_restore(flags); + + if ( cache_idx ) + ptstat(&ptstats.sync_shuffle); + else + ptstat(&ptstats.sync_noshuffle); } else { @@ -293,6 +303,7 @@ unsigned long pt_maybe_shadow(struct vcpu *v) sizeof(*l4t) * (L4_PAGETABLE_ENTRIES - (slot + 1))); unmap_domain_page(vcpu_l4t); + ptstat(&ptstats.sync_full); } ASSERT(ptsh->cache[0].cr3_mfn == (new_cr3 >> PAGE_SHIFT)); @@ -320,13 +331,19 @@ static void _pt_shadow_ipi(void *arg) /* No longer shadowing state from this domain? Nothing to do. */ if ( info->d != ptsh->domain ) + { + ptstat(&ptstats.ipi_dom_miss); return; + } ent = pt_cache_lookup(ptsh, page_to_maddr(info->pg)); /* Not shadowing this frame? Nothing to do. */ if ( ent == NULL ) + { + ptstat(&ptstats.ipi_cache_miss); return; + } switch ( info->op ) { @@ -340,6 +357,7 @@ static void _pt_shadow_ipi(void *arg) l4t[info->slot] = vcpu_l4t[info->slot]; unmap_domain_page(vcpu_l4t); + ptstat(&ptstats.ipi_write); break; case PTSH_IPI_INVLPG: @@ -357,6 +375,7 @@ static void _pt_shadow_ipi(void *arg) case 2: ptsh->cache[2] = ptsh->cache[3]; case 3: ptsh->cache[3] = (pt_cache_entry_t){ shadow_idx }; } + ptstat(&ptstats.ipi_invlpg); break; default: diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c index 6b02a5f..095bf97 100644 --- a/xen/arch/x86/traps.c +++ b/xen/arch/x86/traps.c @@ -955,6 +955,7 @@ void cpuid_hypervisor_leaves(const struct vcpu *v, uint32_t leaf, break; res->b = flsl(get_upper_mfn_bound()) + PAGE_SHIFT; + res->c = v->vcpu_id; break; default: @@ -2074,6 +2075,204 @@ void asm_domain_crash_synchronous(unsigned long addr) __domain_crash_synchronous(); } +#include <xen/keyhandler.h> +#include <asm/pv/pt-shadow.h> + +const char *memory_type_to_str(unsigned int x); +static void decode_intpte(unsigned int level, unsigned int slot, intpte_t pte) +{ + unsigned int pat_idx = ((pte >> 3) & 3) | + ((pte >> ((level > 1 && (pte & _PAGE_PSE)) ? 10 : 5)) & 4); + + unsigned int mem_type = (host_pat >> (pat_idx << 3)) & 0xff; + + printk("%*sL%u[%03u] %"PRIpte" %*s%s %s%s%s%s%s%s\n", + (4 - level) * 2, "", + level, slot, pte, + (level - 1) * 2, "", + + memory_type_to_str(mem_type), + + pte & 0x8000000000000000ULL ? " Nx" : "", + pte & _PAGE_GLOBAL ? " G" : "", + (level > 1 && pte & _PAGE_PSE) ? " +" : "", + pte & _PAGE_USER ? " U" : "", + pte & _PAGE_RW ? " W" : "", + pte & _PAGE_PRESENT ? " P" : ""); +} + +static bool is_poison(intpte_t pte) +{ + return (pte & ~0xfff0000) == 0x800f868600000063; +} + +static void dump_l3t(l3_pgentry_t *l3t, bool decend) +{ + unsigned int l3i, l2i, l1i; + l2_pgentry_t *l2; + l1_pgentry_t *l1; + + for ( l3i = 0; l3i < 512; ++l3i ) + { + if ( !(l3t[l3i].l3 & _PAGE_PRESENT) ) + continue; + + decode_intpte(3, l3i, l3t[l3i].l3); + + if ( is_poison(l3t[l3i].l3) ) + continue; + + if ( l3t[l3i].l3 & _PAGE_PSE ) + continue; + + if ( !decend ) + continue; + + l2 = l3e_to_l2e(l3t[l3i]); + for ( l2i = 0; l2i < 512; ++l2i ) + { + if ( !(l2[l2i].l2 & _PAGE_PRESENT) ) + continue; + + decode_intpte(2, l2i, l2[l2i].l2); + + if ( is_poison(l2[l2i].l2) ) + continue; + + if ( l2[l2i].l2 & _PAGE_PSE ) + continue; + + l1 = l2e_to_l1e(l2[l2i]); + for ( l1i = 0; l1i < 512; ++l1i ) + { + if ( !(l1[l1i].l1 & _PAGE_PRESENT) ) + continue; + + decode_intpte(1, l1i, l1[l1i].l1); + } + + process_pending_softirqs(); + } + + process_pending_softirqs(); + } + +} + +static void dump_l4t(l4_pgentry_t *l4t, bool decend) +{ + unsigned int l4i; + + for ( l4i = 0; l4i < 512; ++l4i ) + { + if ( !(l4t[l4i].l4 & _PAGE_PRESENT) ) + continue; + + decode_intpte(4, l4i, l4t[l4i].l4); + + if ( is_poison(l4t[l4i].l4) ) + continue; + + if ( decend && + l4i != l4_table_offset(LINEAR_PT_VIRT_START) && + l4i != l4_table_offset(SH_LINEAR_PT_VIRT_START) ) + dump_l3t(l4e_to_l3e(l4t[l4i]), true); + } +} + +static void do_extreme_debug(unsigned char key) +{ + unsigned int cpu; + + printk("'%c' pressed -> Extreme debugging in progress...\n", key); + + watchdog_disable(); + console_start_log_everything(); + + switch ( key ) + { + case '1': + dump_l4t(idle_pg_table, true); + break; + + case '2': + printk("idle_pg_table[]\n"); + dump_l4t(idle_pg_table, false); + + for_each_online_cpu ( cpu ) + { + paddr_t l4 = per_cpu(percpu_idle_pt, cpu); + l4_pgentry_t mappings = per_cpu(percpu_mappings, cpu); + l4_pgentry_t *l4t; + l3_pgentry_t *l3t; + + printk("CPU #%u per-pcpu l4 %"PRIpaddr", mappings %"PRIpte"\n", + cpu, l4, mappings.l4); + + if ( !l4 ) + { + printk(" BAD l4\n"); + continue; + } + if ( !mappings.l4 ) + { + printk(" Bad mappings\n"); + continue; + } + + printk("Dumping L4:\n"); + l4t = map_domain_page(_mfn(paddr_to_pfn(l4))); + dump_l4t(l4t, false); + unmap_domain_page(l4t); + + printk("Dumping L3:\n"); + l3t = map_domain_page(l4e_get_mfn(mappings)); + dump_l3t(l3t, true); + unmap_domain_page(l3t); + } + break; + + case '3': + printk("pt_shadow() stats:\n" + " sync_none: %20lu\n" + " sync_noshuffle: %20lu\n" + " sync_shuffle: %20lu\n" + " sync_full: %20lu\n" + " ipi_dom_miss: %20lu\n" + " ipi_cache_miss: %20lu\n" + " ipi_ipi_write: %20lu\n" + " ipi_ipi_invlpg: %20lu\n", + ptstats.sync_none, ptstats.sync_noshuffle, + ptstats.sync_shuffle, ptstats.sync_full, + ptstats.ipi_dom_miss, ptstats.ipi_cache_miss, + ptstats.ipi_write, ptstats.ipi_invlpg); + break; + } + + console_end_log_everything(); + watchdog_enable(); +} + +static struct timer stats; +static void stats_fn(void *unused) +{ + do_extreme_debug('3'); + set_timer(&stats, NOW() + SECONDS(10)); +} + +static int __init extreme_debug_keyhandler_init(void) +{ + register_keyhandler('1', &do_extreme_debug, "Extreme debugging 1", 0); + register_keyhandler('2', &do_extreme_debug, "Extreme debugging 2", 0); + register_keyhandler('3', &do_extreme_debug, "Extreme debugging 3", 0); + + init_timer(&stats, stats_fn, NULL, 0); + /* set_timer(&stats, NOW() + SECONDS(10)); */ + + return 0; +} +__initcall(extreme_debug_keyhandler_init); + /* * Local variables: * mode: C diff --git a/xen/arch/x86/x86_64/mm.c b/xen/arch/x86/x86_64/mm.c index aae721b..a3e81ac 100644 --- a/xen/arch/x86/x86_64/mm.c +++ b/xen/arch/x86/x86_64/mm.c @@ -874,6 +874,12 @@ void __init subarch_init_memory(void) } } + /* Poison specific entries. */ + idle_pg_table[271].l4 = 0x800f868602710063; + idle_pg_table[272].l4 = 0x800f868602720063; + idle_pg_table[510].l4 = 0x800f868605100063; + idle_pg_table[511].l4 = 0x800f868605110063; + /* Create an L3 table for the MMCFG region, or remap it NX. */ pl4e = &idle_pg_table[l4_table_offset(PCI_MCFG_VIRT_START)]; if ( !(l4e_get_flags(*pl4e) & _PAGE_PRESENT) ) diff --git a/xen/include/asm-x86/pv/pt-shadow.h b/xen/include/asm-x86/pv/pt-shadow.h index d5576f4..399ebeb 100644 --- a/xen/include/asm-x86/pv/pt-shadow.h +++ b/xen/include/asm-x86/pv/pt-shadow.h @@ -23,6 +23,23 @@ #include <xen/sched.h> +extern struct ptstats { + unsigned long sync_none; + unsigned long sync_noshuffle; + unsigned long sync_shuffle; + unsigned long sync_full; + + unsigned long ipi_dom_miss; + unsigned long ipi_cache_miss; + unsigned long ipi_write; + unsigned long ipi_invlpg; +} ptstats; + +static inline void ptstat(unsigned long *stat) +{ + asm volatile ("lock; add $1, %0" : "+m" (*stat)); +} + #ifdef CONFIG_PV /* -- 2.1.4 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |