diff options
author | Keir Fraser <keir.fraser@citrix.com> | 2010-01-08 11:24:18 +0000 |
---|---|---|
committer | Keir Fraser <keir.fraser@citrix.com> | 2010-01-08 11:24:18 +0000 |
commit | 925a248ade6f810aa9534ebf9864bc7ebcc8f0b5 (patch) | |
tree | 2e88098ac1064d95943eb0dc0b972a32c99418dd | |
parent | 445386cebbf2303c23e06557ef016ccd8fc90cae (diff) | |
download | xen-925a248ade6f810aa9534ebf9864bc7ebcc8f0b5.tar.gz xen-925a248ade6f810aa9534ebf9864bc7ebcc8f0b5.tar.bz2 xen-925a248ade6f810aa9534ebf9864bc7ebcc8f0b5.zip |
EPT: Walk and print EPT tables on an unexpected EPT violation
Wrote this when I was tracking down the HAP-PoD problem, figured it
might come in handy sometime.
Signed-off-by: George Dunlap <george.dunlap@eu.citrix.com>
-rw-r--r-- | xen/arch/x86/hvm/vmx/vmx.c | 2 | ||||
-rw-r--r-- | xen/arch/x86/mm/hap/p2m-ept.c | 49 | ||||
-rw-r--r-- | xen/include/asm-x86/hvm/vmx/vmx.h | 1 |
3 files changed, 52 insertions, 0 deletions
diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c index 330cf7c31e..48cd0d6665 100644 --- a/xen/arch/x86/hvm/vmx/vmx.c +++ b/xen/arch/x86/hvm/vmx/vmx.c @@ -2116,6 +2116,8 @@ static void ept_handle_violation(unsigned long qualification, paddr_t gpa) (qualification & EPT_EFFECTIVE_EXEC) ? 'x' : '-', gpa, mfn_x(mfn), p2mt); + ept_walk_table(current->domain, gfn); + if ( qualification & EPT_GLA_VALID ) { gla = __vmread(GUEST_LINEAR_ADDRESS); diff --git a/xen/arch/x86/mm/hap/p2m-ept.c b/xen/arch/x86/mm/hap/p2m-ept.c index a7f8db4186..ffc0dc56f1 100644 --- a/xen/arch/x86/mm/hap/p2m-ept.c +++ b/xen/arch/x86/mm/hap/p2m-ept.c @@ -496,6 +496,55 @@ static ept_entry_t ept_get_entry_content(struct domain *d, unsigned long gfn) return content; } +void ept_walk_table(struct domain *d, unsigned long gfn) +{ + ept_entry_t *table = + map_domain_page(mfn_x(pagetable_get_mfn(d->arch.phys_table))); + unsigned long gfn_remainder = gfn; + + int i; + + gdprintk(XENLOG_ERR, "Walking EPT tables for domain %d gfn %lx\n", + d->domain_id, gfn); + + /* This pfn is higher than the highest the p2m map currently holds */ + if ( gfn > d->arch.p2m->max_mapped_pfn ) + { + gdprintk(XENLOG_ERR, " gfn exceeds max_mapped_pfn %lx\n", + d->arch.p2m->max_mapped_pfn); + goto out; + } + + for ( i = EPT_DEFAULT_GAW; i >= 0; i-- ) + { + ept_entry_t *ept_entry, *next; + u32 index; + + /* Stolen from ept_next_level */ + index = gfn_remainder >> (i*EPT_TABLE_ORDER); + ept_entry = table + index; + + gdprintk(XENLOG_ERR, " epte %"PRIx64"\n", ept_entry->epte); + + if ( i==0 || !(ept_entry->epte & 0x7) || ept_entry->sp_avail) + goto out; + else + { + gfn_remainder &= (1UL << (i*EPT_TABLE_ORDER)) - 1; + + next = map_domain_page(ept_entry->mfn); + + unmap_domain_page(*table); + + table = next; + } + } + +out: + unmap_domain_page(table); + return; +} + static mfn_t ept_get_entry_current(unsigned long gfn, p2m_type_t *t, p2m_query_t q) { diff --git a/xen/include/asm-x86/hvm/vmx/vmx.h b/xen/include/asm-x86/hvm/vmx/vmx.h index 28e61ef413..bf1154eeb9 100644 --- a/xen/include/asm-x86/hvm/vmx/vmx.h +++ b/xen/include/asm-x86/hvm/vmx/vmx.h @@ -357,6 +357,7 @@ void vmx_inject_extint(int trap); void vmx_inject_nmi(void); void ept_p2m_init(struct domain *d); +void ept_walk_table(struct domain *d, unsigned long gfn); /* EPT violation qualifications definitions */ #define _EPT_READ_VIOLATION 0 |