Mailing List Archive

[PATCH v4 04/10] EPT: Make ept data structure or operations neutral
From: Zhang Xiantao <xiantao.zhang@intel.com>

Share the current EPT logic with nested EPT case, so
make the related data structure or operations netural
to comment EPT and nested EPT.

Signed-off-by: Zhang Xiantao <xiantao.zhang@intel.com>
---
xen/arch/x86/hvm/vmx/vmcs.c | 8 ++-
xen/arch/x86/hvm/vmx/vmx.c | 53 +-------------
xen/arch/x86/mm/p2m-ept.c | 104 ++++++++++++++++++++++------
xen/arch/x86/mm/p2m.c | 132 +++++++++++++++++++++++++-----------
xen/include/asm-x86/hvm/vmx/vmcs.h | 23 +++---
xen/include/asm-x86/hvm/vmx/vmx.h | 10 ++-
xen/include/asm-x86/p2m.h | 4 +
7 files changed, 208 insertions(+), 126 deletions(-)

diff --git a/xen/arch/x86/hvm/vmx/vmcs.c b/xen/arch/x86/hvm/vmx/vmcs.c
index 9adc7a4..de22e03 100644
--- a/xen/arch/x86/hvm/vmx/vmcs.c
+++ b/xen/arch/x86/hvm/vmx/vmcs.c
@@ -942,7 +942,13 @@ static int construct_vmcs(struct vcpu *v)
}

if ( paging_mode_hap(d) )
- __vmwrite(EPT_POINTER, d->arch.hvm_domain.vmx.ept_control.eptp);
+ {
+ struct p2m_domain *p2m = p2m_get_hostp2m(d);
+ struct ept_data *ept = &p2m->ept;
+
+ ept->asr = pagetable_get_pfn(p2m_get_pagetable(p2m));
+ __vmwrite(EPT_POINTER, ept_get_eptp(ept));
+ }

if ( cpu_has_vmx_pat && paging_mode_hap(d) )
{
diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c
index 4abfa90..d74aae0 100644
--- a/xen/arch/x86/hvm/vmx/vmx.c
+++ b/xen/arch/x86/hvm/vmx/vmx.c
@@ -74,38 +74,19 @@ static void vmx_fpu_dirty_intercept(void);
static int vmx_msr_read_intercept(unsigned int msr, uint64_t *msr_content);
static int vmx_msr_write_intercept(unsigned int msr, uint64_t msr_content);
static void vmx_invlpg_intercept(unsigned long vaddr);
-static void __ept_sync_domain(void *info);

static int vmx_domain_initialise(struct domain *d)
{
int rc;

- /* Set the memory type used when accessing EPT paging structures. */
- d->arch.hvm_domain.vmx.ept_control.ept_mt = EPT_DEFAULT_MT;
-
- /* set EPT page-walk length, now it's actual walk length - 1, i.e. 3 */
- d->arch.hvm_domain.vmx.ept_control.ept_wl = 3;
-
- d->arch.hvm_domain.vmx.ept_control.asr =
- pagetable_get_pfn(p2m_get_pagetable(p2m_get_hostp2m(d)));
-
- if ( !zalloc_cpumask_var(&d->arch.hvm_domain.vmx.ept_synced) )
- return -ENOMEM;
-
if ( (rc = vmx_alloc_vlapic_mapping(d)) != 0 )
- {
- free_cpumask_var(d->arch.hvm_domain.vmx.ept_synced);
return rc;
- }

return 0;
}

static void vmx_domain_destroy(struct domain *d)
{
- if ( paging_mode_hap(d) )
- on_each_cpu(__ept_sync_domain, d, 1);
- free_cpumask_var(d->arch.hvm_domain.vmx.ept_synced);
vmx_free_vlapic_mapping(d);
}

@@ -641,6 +622,7 @@ static void vmx_ctxt_switch_to(struct vcpu *v)
{
struct domain *d = v->domain;
unsigned long old_cr4 = read_cr4(), new_cr4 = mmu_cr4_features;
+ struct ept_data *ept_data = &p2m_get_hostp2m(d)->ept;

/* HOST_CR4 in VMCS is always mmu_cr4_features. Sync CR4 now. */
if ( old_cr4 != new_cr4 )
@@ -650,10 +632,10 @@ static void vmx_ctxt_switch_to(struct vcpu *v)
{
unsigned int cpu = smp_processor_id();
/* Test-and-test-and-set this CPU in the EPT-is-synced mask. */
- if ( !cpumask_test_cpu(cpu, d->arch.hvm_domain.vmx.ept_synced) &&
+ if ( !cpumask_test_cpu(cpu, ept_get_synced_mask(ept_data)) &&
!cpumask_test_and_set_cpu(cpu,
- d->arch.hvm_domain.vmx.ept_synced) )
- __invept(INVEPT_SINGLE_CONTEXT, ept_get_eptp(d), 0);
+ ept_get_synced_mask(ept_data)) )
+ __invept(INVEPT_SINGLE_CONTEXT, ept_get_eptp(ept_data), 0);
}

vmx_restore_guest_msrs(v);
@@ -1216,33 +1198,6 @@ static void vmx_update_guest_efer(struct vcpu *v)
(v->arch.hvm_vcpu.guest_efer & EFER_SCE));
}

-static void __ept_sync_domain(void *info)
-{
- struct domain *d = info;
- __invept(INVEPT_SINGLE_CONTEXT, ept_get_eptp(d), 0);
-}
-
-void ept_sync_domain(struct domain *d)
-{
- /* Only if using EPT and this domain has some VCPUs to dirty. */
- if ( !paging_mode_hap(d) || !d->vcpu || !d->vcpu[0] )
- return;
-
- ASSERT(local_irq_is_enabled());
-
- /*
- * Flush active cpus synchronously. Flush others the next time this domain
- * is scheduled onto them. We accept the race of other CPUs adding to
- * the ept_synced mask before on_selected_cpus() reads it, resulting in
- * unnecessary extra flushes, to avoid allocating a cpumask_t on the stack.
- */
- cpumask_and(d->arch.hvm_domain.vmx.ept_synced,
- d->domain_dirty_cpumask, &cpu_online_map);
-
- on_selected_cpus(d->arch.hvm_domain.vmx.ept_synced,
- __ept_sync_domain, d, 1);
-}
-
void nvmx_enqueue_n2_exceptions(struct vcpu *v,
unsigned long intr_fields, int error_code)
{
diff --git a/xen/arch/x86/mm/p2m-ept.c b/xen/arch/x86/mm/p2m-ept.c
index c964f54..e33f415 100644
--- a/xen/arch/x86/mm/p2m-ept.c
+++ b/xen/arch/x86/mm/p2m-ept.c
@@ -291,9 +291,11 @@ ept_set_entry(struct p2m_domain *p2m, unsigned long gfn, mfn_t mfn,
int need_modify_vtd_table = 1;
int vtd_pte_present = 0;
int needs_sync = 1;
- struct domain *d = p2m->domain;
ept_entry_t old_entry = { .epte = 0 };
+ struct ept_data *ept = &p2m->ept;
+ struct domain *d = p2m->domain;

+ ASSERT(ept);
/*
* the caller must make sure:
* 1. passing valid gfn and mfn at order boundary.
@@ -301,17 +303,17 @@ ept_set_entry(struct p2m_domain *p2m, unsigned long gfn, mfn_t mfn,
* 3. passing a valid order.
*/
if ( ((gfn | mfn_x(mfn)) & ((1UL << order) - 1)) ||
- ((u64)gfn >> ((ept_get_wl(d) + 1) * EPT_TABLE_ORDER)) ||
+ ((u64)gfn >> ((ept_get_wl(ept) + 1) * EPT_TABLE_ORDER)) ||
(order % EPT_TABLE_ORDER) )
return 0;

- ASSERT((target == 2 && hvm_hap_has_1gb(d)) ||
- (target == 1 && hvm_hap_has_2mb(d)) ||
+ ASSERT((target == 2 && hvm_hap_has_1gb()) ||
+ (target == 1 && hvm_hap_has_2mb()) ||
(target == 0));

- table = map_domain_page(ept_get_asr(d));
+ table = map_domain_page(pagetable_get_pfn(p2m_get_pagetable(p2m)));

- for ( i = ept_get_wl(d); i > target; i-- )
+ for ( i = ept_get_wl(ept); i > target; i-- )
{
ret = ept_next_level(p2m, 0, &table, &gfn_remainder, i);
if ( !ret )
@@ -439,9 +441,11 @@ out:
unmap_domain_page(table);

if ( needs_sync )
- ept_sync_domain(p2m->domain);
+ ept_sync_domain(p2m);

- if ( rv && iommu_enabled && need_iommu(p2m->domain) && need_modify_vtd_table )
+ /* For non-nested p2m, may need to change VT-d page table.*/
+ if ( rv && !p2m_is_nestedp2m(p2m) && iommu_enabled && need_iommu(p2m->domain) &&
+ need_modify_vtd_table )
{
if ( iommu_hap_pt_share )
iommu_pte_flush(d, gfn, (u64*)ept_entry, order, vtd_pte_present);
@@ -488,14 +492,14 @@ static mfn_t ept_get_entry(struct p2m_domain *p2m,
unsigned long gfn, p2m_type_t *t, p2m_access_t* a,
p2m_query_t q, unsigned int *page_order)
{
- struct domain *d = p2m->domain;
- ept_entry_t *table = map_domain_page(ept_get_asr(d));
+ ept_entry_t *table = map_domain_page(pagetable_get_pfn(p2m_get_pagetable(p2m)));
unsigned long gfn_remainder = gfn;
ept_entry_t *ept_entry;
u32 index;
int i;
int ret = 0;
mfn_t mfn = _mfn(INVALID_MFN);
+ struct ept_data *ept = &p2m->ept;

*t = p2m_mmio_dm;
*a = p2m_access_n;
@@ -506,7 +510,7 @@ static mfn_t ept_get_entry(struct p2m_domain *p2m,

/* Should check if gfn obeys GAW here. */

- for ( i = ept_get_wl(d); i > 0; i-- )
+ for ( i = ept_get_wl(ept); i > 0; i-- )
{
retry:
ret = ept_next_level(p2m, 1, &table, &gfn_remainder, i);
@@ -588,19 +592,20 @@ out:
static ept_entry_t ept_get_entry_content(struct p2m_domain *p2m,
unsigned long gfn, int *level)
{
- ept_entry_t *table = map_domain_page(ept_get_asr(p2m->domain));
+ ept_entry_t *table = map_domain_page(pagetable_get_pfn(p2m_get_pagetable(p2m)));
unsigned long gfn_remainder = gfn;
ept_entry_t *ept_entry;
ept_entry_t content = { .epte = 0 };
u32 index;
int i;
int ret=0;
+ struct ept_data *ept = &p2m->ept;

/* This pfn is higher than the highest the p2m map currently holds */
if ( gfn > p2m->max_mapped_pfn )
goto out;

- for ( i = ept_get_wl(p2m->domain); i > 0; i-- )
+ for ( i = ept_get_wl(ept); i > 0; i-- )
{
ret = ept_next_level(p2m, 1, &table, &gfn_remainder, i);
if ( !ret || ret == GUEST_TABLE_POD_PAGE )
@@ -622,7 +627,8 @@ static ept_entry_t ept_get_entry_content(struct p2m_domain *p2m,
void ept_walk_table(struct domain *d, unsigned long gfn)
{
struct p2m_domain *p2m = p2m_get_hostp2m(d);
- ept_entry_t *table = map_domain_page(ept_get_asr(d));
+ struct ept_data *ept = &p2m->ept;
+ ept_entry_t *table = map_domain_page(pagetable_get_pfn(p2m_get_pagetable(p2m)));
unsigned long gfn_remainder = gfn;

int i;
@@ -638,7 +644,7 @@ void ept_walk_table(struct domain *d, unsigned long gfn)
goto out;
}

- for ( i = ept_get_wl(d); i >= 0; i-- )
+ for ( i = ept_get_wl(ept); i >= 0; i-- )
{
ept_entry_t *ept_entry, *next;
u32 index;
@@ -778,24 +784,76 @@ static void ept_change_entry_type_page(mfn_t ept_page_mfn, int ept_page_level,
static void ept_change_entry_type_global(struct p2m_domain *p2m,
p2m_type_t ot, p2m_type_t nt)
{
- struct domain *d = p2m->domain;
- if ( ept_get_asr(d) == 0 )
+ struct ept_data *ept = &p2m->ept;
+ if ( ept_get_asr(ept) == 0 )
return;

BUG_ON(p2m_is_grant(ot) || p2m_is_grant(nt));
BUG_ON(ot != nt && (ot == p2m_mmio_direct || nt == p2m_mmio_direct));

- ept_change_entry_type_page(_mfn(ept_get_asr(d)), ept_get_wl(d), ot, nt);
+ ept_change_entry_type_page(_mfn(ept_get_asr(ept)),
+ ept_get_wl(ept), ot, nt);
+
+ ept_sync_domain(p2m);
+}
+
+static void __ept_sync_domain(void *info)
+{
+ struct ept_data *ept = &((struct p2m_domain *)info)->ept;

- ept_sync_domain(d);
+ __invept(INVEPT_SINGLE_CONTEXT, ept_get_eptp(ept), 0);
}

-void ept_p2m_init(struct p2m_domain *p2m)
+void ept_sync_domain(struct p2m_domain *p2m)
{
+ struct domain *d = p2m->domain;
+ struct ept_data *ept = &p2m->ept;
+ /* Only if using EPT and this domain has some VCPUs to dirty. */
+ if ( !paging_mode_hap(d) || !d->vcpu || !d->vcpu[0] )
+ return;
+
+ ASSERT(local_irq_is_enabled());
+
+ /*
+ * Flush active cpus synchronously. Flush others the next time this domain
+ * is scheduled onto them. We accept the race of other CPUs adding to
+ * the ept_synced mask before on_selected_cpus() reads it, resulting in
+ * unnecessary extra flushes, to avoid allocating a cpumask_t on the stack.
+ */
+ cpumask_and(ept_get_synced_mask(ept),
+ d->domain_dirty_cpumask, &cpu_online_map);
+
+ on_selected_cpus(ept_get_synced_mask(ept),
+ __ept_sync_domain, p2m, 1);
+}
+
+int ept_p2m_init(struct p2m_domain *p2m)
+{
+ struct ept_data *ept = &p2m->ept;
+
p2m->set_entry = ept_set_entry;
p2m->get_entry = ept_get_entry;
p2m->change_entry_type_global = ept_change_entry_type_global;
p2m->audit_p2m = NULL;
+
+ /* Set the memory type used when accessing EPT paging structures. */
+ ept->ept_mt = EPT_DEFAULT_MT;
+
+ /* set EPT page-walk length, now it's actual walk length - 1, i.e. 3 */
+ ept->ept_wl = 3;
+
+ if ( !zalloc_cpumask_var(&ept->synced_mask) )
+ return -ENOMEM;
+
+ on_each_cpu(__ept_sync_domain, p2m, 1);
+
+ return 0;
+}
+
+void ept_p2m_uninit(struct p2m_domain *p2m)
+{
+ struct ept_data *ept = &p2m->ept;
+ free_cpumask_var(ept->synced_mask);
}

static void ept_dump_p2m_table(unsigned char key)
@@ -811,6 +869,7 @@ static void ept_dump_p2m_table(unsigned char key)
unsigned long gfn, gfn_remainder;
unsigned long record_counter = 0;
struct p2m_domain *p2m;
+ struct ept_data *ept;

for_each_domain(d)
{
@@ -818,15 +877,16 @@ static void ept_dump_p2m_table(unsigned char key)
continue;

p2m = p2m_get_hostp2m(d);
+ ept = &p2m->ept;
printk("\ndomain%d EPT p2m table: \n", d->domain_id);

for ( gfn = 0; gfn <= p2m->max_mapped_pfn; gfn += (1 << order) )
{
gfn_remainder = gfn;
mfn = _mfn(INVALID_MFN);
- table = map_domain_page(ept_get_asr(d));
+ table = map_domain_page(pagetable_get_pfn(p2m_get_pagetable(p2m)));

- for ( i = ept_get_wl(d); i > 0; i-- )
+ for ( i = ept_get_wl(ept); i > 0; i-- )
{
ret = ept_next_level(p2m, 1, &table, &gfn_remainder, i);
if ( ret != GUEST_TABLE_NORMAL_PAGE )
diff --git a/xen/arch/x86/mm/p2m.c b/xen/arch/x86/mm/p2m.c
index 41a461b..49eb8af 100644
--- a/xen/arch/x86/mm/p2m.c
+++ b/xen/arch/x86/mm/p2m.c
@@ -57,8 +57,10 @@ boolean_param("hap_2mb", opt_hap_2mb);


/* Init the datastructures for later use by the p2m code */
-static void p2m_initialise(struct domain *d, struct p2m_domain *p2m)
+static int p2m_initialise(struct domain *d, struct p2m_domain *p2m)
{
+ int ret = 0;
+
mm_rwlock_init(&p2m->lock);
mm_lock_init(&p2m->pod.lock);
INIT_LIST_HEAD(&p2m->np2m_list);
@@ -72,27 +74,81 @@ static void p2m_initialise(struct domain *d, struct p2m_domain *p2m)
p2m->np2m_base = P2M_BASE_EADDR;

if ( hap_enabled(d) && cpu_has_vmx )
- ept_p2m_init(p2m);
+ ret = ept_p2m_init(p2m);
else
p2m_pt_init(p2m);

- return;
+ return ret;
+}
+
+static struct p2m_domain *p2m_init_one(struct domain *d)
+{
+ struct p2m_domain *p2m = xzalloc(struct p2m_domain);
+
+ if ( !p2m )
+ return NULL;
+
+ if ( !zalloc_cpumask_var(&p2m->dirty_cpumask) )
+ goto free_p2m;
+
+ if ( p2m_initialise(d, p2m) )
+ goto free_cpumask;
+ return p2m;
+
+free_cpumask:
+ free_cpumask_var(p2m->dirty_cpumask);
+free_p2m:
+ xfree(p2m);
+ return NULL;
}

-static int
-p2m_init_nestedp2m(struct domain *d)
+static void p2m_free_one(struct p2m_domain *p2m)
+{
+ if ( hap_enabled(p2m->domain) && cpu_has_vmx )
+ ept_p2m_uninit(p2m);
+ free_cpumask_var(p2m->dirty_cpumask);
+ xfree(p2m);
+}
+
+static int p2m_init_hostp2m(struct domain *d)
+{
+ struct p2m_domain *p2m = p2m_init_one(d);
+
+ if ( p2m )
+ {
+ d->arch.p2m = p2m;
+ return 0;
+ }
+ return -ENOMEM;
+}
+
+static void p2m_teardown_hostp2m(struct domain *d)
+{
+ /* Iterate over all p2m tables per domain */
+ struct p2m_domain *p2m = p2m_get_hostp2m(d);
+
+ if ( p2m ) {
+ p2m_free_one(p2m);
+ d->arch.p2m = NULL;
+ }
+}
+
+static void p2m_teardown_nestedp2m(struct domain *d);
+
+static int p2m_init_nestedp2m(struct domain *d)
{
uint8_t i;
struct p2m_domain *p2m;

mm_lock_init(&d->arch.nested_p2m_lock);
- for (i = 0; i < MAX_NESTEDP2M; i++) {
- d->arch.nested_p2m[i] = p2m = xzalloc(struct p2m_domain);
- if (p2m == NULL)
- return -ENOMEM;
- if ( !zalloc_cpumask_var(&p2m->dirty_cpumask) )
+ for (i = 0; i < MAX_NESTEDP2M; i++)
+ {
+ d->arch.nested_p2m[i] = p2m = p2m_init_one(d);
+ if ( p2m == NULL )
+ {
+ p2m_teardown_nestedp2m(d);
return -ENOMEM;
- p2m_initialise(d, p2m);
+ }
p2m->write_p2m_entry = nestedp2m_write_p2m_entry;
list_add(&p2m->np2m_list, &p2m_get_hostp2m(d)->np2m_list);
}
@@ -100,27 +156,37 @@ p2m_init_nestedp2m(struct domain *d)
return 0;
}

-int p2m_init(struct domain *d)
+static void p2m_teardown_nestedp2m(struct domain *d)
{
+ uint8_t i;
struct p2m_domain *p2m;
- int rc;

- p2m_get_hostp2m(d) = p2m = xzalloc(struct p2m_domain);
- if ( p2m == NULL )
- return -ENOMEM;
- if ( !zalloc_cpumask_var(&p2m->dirty_cpumask) )
+ for (i = 0; i < MAX_NESTEDP2M; i++)
{
- xfree(p2m);
- return -ENOMEM;
+ if ( !d->arch.nested_p2m[i] )
+ continue;
+ p2m = d->arch.nested_p2m[i];
+ list_del(&p2m->np2m_list);
+ p2m_free_one(p2m);
+ d->arch.nested_p2m[i] = NULL;
}
- p2m_initialise(d, p2m);
+}
+
+int p2m_init(struct domain *d)
+{
+ int rc;
+
+ rc = p2m_init_hostp2m(d);
+ if ( rc )
+ return rc;

/* Must initialise nestedp2m unconditionally
* since nestedhvm_enabled(d) returns false here.
* (p2m_init runs too early for HVM_PARAM_* options) */
rc = p2m_init_nestedp2m(d);
- if ( rc )
- p2m_final_teardown(d);
+ if ( rc )
+ p2m_teardown_hostp2m(d);
+
return rc;
}

@@ -421,28 +487,12 @@ void p2m_teardown(struct p2m_domain *p2m)
p2m_unlock(p2m);
}

-static void p2m_teardown_nestedp2m(struct domain *d)
-{
- uint8_t i;
-
- for (i = 0; i < MAX_NESTEDP2M; i++) {
- if ( !d->arch.nested_p2m[i] )
- continue;
- free_cpumask_var(d->arch.nested_p2m[i]->dirty_cpumask);
- xfree(d->arch.nested_p2m[i]);
- d->arch.nested_p2m[i] = NULL;
- }
-}
-
void p2m_final_teardown(struct domain *d)
{
/* Iterate over all p2m tables per domain */
- if ( d->arch.p2m )
- {
- free_cpumask_var(d->arch.p2m->dirty_cpumask);
- xfree(d->arch.p2m);
- d->arch.p2m = NULL;
- }
+ struct p2m_domain *p2m = p2m_get_hostp2m(d);
+ if ( p2m )
+ p2m_teardown_hostp2m(d);

/* We must teardown unconditionally because
* we initialise them unconditionally.
diff --git a/xen/include/asm-x86/hvm/vmx/vmcs.h b/xen/include/asm-x86/hvm/vmx/vmcs.h
index 9a728b6..2d38b43 100644
--- a/xen/include/asm-x86/hvm/vmx/vmcs.h
+++ b/xen/include/asm-x86/hvm/vmx/vmcs.h
@@ -56,26 +56,27 @@ struct vmx_msr_state {

#define EPT_DEFAULT_MT MTRR_TYPE_WRBACK

-struct vmx_domain {
- unsigned long apic_access_mfn;
+struct ept_data{
union {
- struct {
+ struct {
u64 ept_mt :3,
ept_wl :3,
rsvd :6,
asr :52;
};
u64 eptp;
- } ept_control;
- cpumask_var_t ept_synced;
+ };
+ cpumask_var_t synced_mask;
+};
+
+struct vmx_domain {
+ unsigned long apic_access_mfn;
};

-#define ept_get_wl(d) \
- ((d)->arch.hvm_domain.vmx.ept_control.ept_wl)
-#define ept_get_asr(d) \
- ((d)->arch.hvm_domain.vmx.ept_control.asr)
-#define ept_get_eptp(d) \
- ((d)->arch.hvm_domain.vmx.ept_control.eptp)
+#define ept_get_wl(ept) ((ept)->ept_wl)
+#define ept_get_asr(ept) ((ept)->asr)
+#define ept_get_eptp(ept) ((ept)->eptp)
+#define ept_get_synced_mask(ept) ((ept)->synced_mask)

struct arch_vmx_struct {
/* Virtual address of VMCS. */
diff --git a/xen/include/asm-x86/hvm/vmx/vmx.h b/xen/include/asm-x86/hvm/vmx/vmx.h
index c73946f..d4d6feb 100644
--- a/xen/include/asm-x86/hvm/vmx/vmx.h
+++ b/xen/include/asm-x86/hvm/vmx/vmx.h
@@ -363,7 +363,7 @@ static inline void ept_sync_all(void)
__invept(INVEPT_ALL_CONTEXT, 0, 0);
}

-void ept_sync_domain(struct domain *d);
+void ept_sync_domain(struct p2m_domain *p2m);

static inline void vpid_sync_vcpu_gva(struct vcpu *v, unsigned long gva)
{
@@ -425,12 +425,18 @@ void vmx_get_segment_register(struct vcpu *, enum x86_segment,
void vmx_inject_extint(int trap);
void vmx_inject_nmi(void);

-void ept_p2m_init(struct p2m_domain *p2m);
+int ept_p2m_init(struct p2m_domain *p2m);
+void ept_p2m_uninit(struct p2m_domain *p2m);
+
void ept_walk_table(struct domain *d, unsigned long gfn);
void setup_ept_dump(void);

void update_guest_eip(void);

+int alloc_p2m_hap_data(struct p2m_domain *p2m);
+void free_p2m_hap_data(struct p2m_domain *p2m);
+void p2m_init_hap_data(struct p2m_domain *p2m);
+
/* EPT violation qualifications definitions */
#define _EPT_READ_VIOLATION 0
#define EPT_READ_VIOLATION (1UL<<_EPT_READ_VIOLATION)
diff --git a/xen/include/asm-x86/p2m.h b/xen/include/asm-x86/p2m.h
index ce26594..b6a84b6 100644
--- a/xen/include/asm-x86/p2m.h
+++ b/xen/include/asm-x86/p2m.h
@@ -277,6 +277,10 @@ struct p2m_domain {
mm_lock_t lock; /* Locking of private pod structs, *
* not relying on the p2m lock. */
} pod;
+ union {
+ struct ept_data ept;
+ /* NPT-equivalent structure could be added here. */
+ };
};

/* get host p2m table */
--
1.7.1


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel