# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1233835954 0
# Node ID 5fd1a6951801382c483043579620ae4da9949757
# Parent 416197f0292b62425beb8277e122c41c645d9ab6
x86: EPT cleanups.
Signed-off-by: Xin, Xiaohui <xiaohui.xin@xxxxxxxxx>
---
xen/arch/x86/mm/hap/p2m-ept.c | 86 ++++++++++++++++++++++----------------
xen/include/asm-x86/hvm/vmx/vmx.h | 6 ++
2 files changed, 56 insertions(+), 36 deletions(-)
diff -r 416197f0292b -r 5fd1a6951801 xen/arch/x86/mm/hap/p2m-ept.c
--- a/xen/arch/x86/mm/hap/p2m-ept.c Thu Feb 05 12:09:10 2009 +0000
+++ b/xen/arch/x86/mm/hap/p2m-ept.c Thu Feb 05 12:12:34 2009 +0000
@@ -116,12 +116,12 @@ static int ept_next_level(struct domain
}
/*
- * TODO: ept_set_entry() computes 'need_modify_vtd_table' for itself,
+ * ept_set_entry() computes 'need_modify_vtd_table' for itself,
* by observing whether any gfn->mfn translations are modified.
*/
static int
-_ept_set_entry(struct domain *d, unsigned long gfn, mfn_t mfn,
- unsigned int order, p2m_type_t p2mt, int need_modify_vtd_table)
+ept_set_entry(struct domain *d, unsigned long gfn, mfn_t mfn,
+ unsigned int order, p2m_type_t p2mt)
{
ept_entry_t *table = NULL;
unsigned long gfn_remainder = gfn, offset = 0;
@@ -131,6 +131,7 @@ _ept_set_entry(struct domain *d, unsigne
int walk_level = order / EPT_TABLE_ORDER;
int direct_mmio = (p2mt == p2m_mmio_direct);
uint8_t igmt = 0;
+ int need_modify_vtd_table = 1;
/* we only support 4k and 2m pages now */
@@ -171,14 +172,23 @@ _ept_set_entry(struct domain *d, unsigne
if ( ret == GUEST_TABLE_SUPER_PAGE )
{
- ept_entry->mfn = mfn_x(mfn) - offset;
+ if ( ept_entry->mfn == (mfn_x(mfn) - offset) )
+ need_modify_vtd_table = 0;
+ else
+ ept_entry->mfn = mfn_x(mfn) - offset;
+
if ( ept_entry->avail1 == p2m_ram_logdirty &&
p2mt == p2m_ram_rw )
for ( i = 0; i < 512; i++ )
paging_mark_dirty(d, mfn_x(mfn)-offset+i);
}
else
- ept_entry->mfn = mfn_x(mfn);
+ {
+ if ( ept_entry->mfn == mfn_x(mfn) )
+ need_modify_vtd_table = 0;
+ else
+ ept_entry->mfn = mfn_x(mfn);
+ }
ept_entry->avail1 = p2mt;
ept_entry->rsvd = 0;
@@ -239,7 +249,10 @@ _ept_set_entry(struct domain *d, unsigne
&igmt, direct_mmio);
split_ept_entry->igmt = igmt;
- split_ept_entry->mfn = mfn_x(mfn);
+ if ( split_ept_entry->mfn == mfn_x(mfn) )
+ need_modify_vtd_table = 0;
+ else
+ split_ept_entry->mfn = mfn_x(mfn);
split_ept_entry->avail1 = p2mt;
ept_p2m_type_to_flags(split_ept_entry, p2mt);
@@ -287,17 +300,6 @@ out:
}
return rv;
-}
-
-static int
-ept_set_entry(struct domain *d, unsigned long gfn, mfn_t mfn,
- unsigned int order, p2m_type_t p2mt)
-{
- /* ept_set_entry() are called from set_entry(),
- * We should always create VT-d page table acording
- * to the gfn to mfn translations changes.
- */
- return _ept_set_entry(d, gfn, mfn, order, p2mt, 1);
}
/* Read ept p2m entries */
@@ -393,6 +395,21 @@ static mfn_t ept_get_entry_current(unsig
return ept_get_entry(current->domain, gfn, t, q);
}
+/* To test if the new emt type is the same with old,
+ * return 1 to not to reset ept entry.
+ */
+static int need_modify_ept_entry(struct domain *d, unsigned long gfn,
+ unsigned long mfn, uint8_t o_igmt,
+ uint8_t o_emt, p2m_type_t p2mt)
+{
+ uint8_t igmt, emt;
+ emt = epte_get_entry_emt(d, gfn, mfn, &igmt,
+ (p2mt == p2m_mmio_direct));
+ if ( (emt == o_emt) && (igmt == o_igmt) )
+ return 0;
+ return 1;
+}
+
void ept_change_entry_emt_with_range(struct domain *d, unsigned long start_gfn,
unsigned long end_gfn)
{
@@ -401,6 +418,7 @@ void ept_change_entry_emt_with_range(str
uint64_t epte;
int order = 0;
unsigned long mfn;
+ uint8_t o_igmt, o_emt;
for ( gfn = start_gfn; gfn <= end_gfn; gfn++ )
{
@@ -410,7 +428,9 @@ void ept_change_entry_emt_with_range(str
mfn = (epte & EPTE_MFN_MASK) >> PAGE_SHIFT;
if ( !mfn_valid(mfn) )
continue;
- p2mt = (epte & EPTE_AVAIL1_MASK) >> 8;
+ p2mt = (epte & EPTE_AVAIL1_MASK) >> EPTE_AVAIL1_SHIFT;
+ o_igmt = (epte & EPTE_IGMT_MASK) >> EPTE_IGMT_SHIFT;
+ o_emt = (epte & EPTE_EMT_MASK) >> EPTE_EMT_SHIFT;
order = 0;
if ( epte & EPTE_SUPER_PAGE_MASK )
@@ -422,30 +442,26 @@ void ept_change_entry_emt_with_range(str
* Set emt for super page.
*/
order = EPT_TABLE_ORDER;
- /* vmx_set_uc_mode() dont' touch the gfn to mfn
- * translations, only modify the emt field of the EPT entries.
- * so we need not modify the current VT-d page tables.
- */
- _ept_set_entry(d, gfn, _mfn(mfn), order, p2mt, 0);
+ if ( need_modify_ept_entry(d, gfn, mfn,
+ o_igmt, o_emt, p2mt) )
+ ept_set_entry(d, gfn, _mfn(mfn), order, p2mt);
gfn += 0x1FF;
}
else
{
- /* 1)change emt for partial entries of the 2m area.
- * 2)vmx_set_uc_mode() dont' touch the gfn to mfn
- * translations, only modify the emt field of the EPT entries.
- * so we need not modify the current VT-d page tables.
- */
- _ept_set_entry(d, gfn, _mfn(mfn), order, p2mt,0);
+ /* change emt for partial entries of the 2m area. */
+ if ( need_modify_ept_entry(d, gfn, mfn,
+ o_igmt, o_emt, p2mt) )
+ ept_set_entry(d, gfn, _mfn(mfn), order, p2mt);
gfn = ((gfn >> EPT_TABLE_ORDER) << EPT_TABLE_ORDER) + 0x1FF;
}
}
- else /* 1)gfn assigned with 4k
- * 2)vmx_set_uc_mode() dont' touch the gfn to mfn
- * translations, only modify the emt field of the EPT entries.
- * so we need not modify the current VT-d page tables.
- */
- _ept_set_entry(d, gfn, _mfn(mfn), order, p2mt, 0);
+ else /* gfn assigned with 4k */
+ {
+ if ( need_modify_ept_entry(d, gfn, mfn,
+ o_igmt, o_emt, p2mt) )
+ ept_set_entry(d, gfn, _mfn(mfn), order, p2mt);
+ }
}
}
diff -r 416197f0292b -r 5fd1a6951801 xen/include/asm-x86/hvm/vmx/vmx.h
--- a/xen/include/asm-x86/hvm/vmx/vmx.h Thu Feb 05 12:09:10 2009 +0000
+++ b/xen/include/asm-x86/hvm/vmx/vmx.h Thu Feb 05 12:12:34 2009 +0000
@@ -48,7 +48,11 @@ typedef union {
#define EPTE_SUPER_PAGE_MASK 0x80
#define EPTE_MFN_MASK 0x1fffffffffff000
#define EPTE_AVAIL1_MASK 0xF00
-#define EPTE_EMT_MASK 0x78
+#define EPTE_EMT_MASK 0x38
+#define EPTE_IGMT_MASK 0x40
+#define EPTE_AVAIL1_SHIFT 8
+#define EPTE_EMT_SHIFT 3
+#define EPTE_IGMT_SHIFT 6
void vmx_asm_vmexit_handler(struct cpu_user_regs);
void vmx_asm_do_vmentry(void);
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|