aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2010-01-08 11:24:18 +0000
committerKeir Fraser <keir.fraser@citrix.com>2010-01-08 11:24:18 +0000
commit925a248ade6f810aa9534ebf9864bc7ebcc8f0b5 (patch)
tree2e88098ac1064d95943eb0dc0b972a32c99418dd
parent445386cebbf2303c23e06557ef016ccd8fc90cae (diff)
downloadxen-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.c2
-rw-r--r--xen/arch/x86/mm/hap/p2m-ept.c49
-rw-r--r--xen/include/asm-x86/hvm/vmx/vmx.h1
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