list_add_tail(&pg->list, &d->arch.p2m->pages);
ept_entry->emt = 0;
+ ept_entry->igmt = 0;
ept_entry->sp_avail = 0;
ept_entry->avail1 = 0;
ept_entry->mfn = page_to_mfn(pg);
}
}
+/*
+ * TODO: 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)
+_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_entry_t *table = NULL;
unsigned long gfn_remainder = gfn, offset = 0;
u32 index;
int i, rv = 0, ret = 0;
int walk_level = order / EPT_TABLE_ORDER;
+ int direct_mmio = (p2mt == p2m_mmio_direct);
+ uint8_t igmt = 0;
/* we only support 4k and 2m pages now */
{
if ( mfn_valid(mfn_x(mfn)) || (p2mt == p2m_mmio_direct) )
{
- ept_entry->emt = epte_get_entry_emt(d, gfn, mfn_x(mfn));
+ ept_entry->emt = epte_get_entry_emt(d, gfn, mfn_x(mfn),
+ &igmt, direct_mmio);
+ ept_entry->igmt = igmt;
ept_entry->sp_avail = walk_level ? 1 : 0;
if ( ret == GUEST_TABLE_SUPER_PAGE )
{
split_ept_entry = split_table + i;
split_ept_entry->emt = epte_get_entry_emt(d,
- gfn-offset+i, split_mfn+i);
+ gfn-offset+i, split_mfn+i,
+ &igmt, direct_mmio);
+ split_ept_entry->igmt = igmt;
+
split_ept_entry->sp_avail = 0;
split_ept_entry->mfn = split_mfn+i;
/* Set the destinated 4k page as normal */
split_ept_entry = split_table + offset;
- split_ept_entry->emt = epte_get_entry_emt(d, gfn, mfn_x(mfn));
+ split_ept_entry->emt = epte_get_entry_emt(d, gfn, mfn_x(mfn),
+ &igmt, direct_mmio);
+ split_ept_entry->igmt = igmt;
+
split_ept_entry->mfn = mfn_x(mfn);
split_ept_entry->avail1 = p2mt;
ept_p2m_type_to_flags(split_ept_entry, p2mt);
/* Now the p2m table is not shared with vt-d page table */
- if ( iommu_enabled && is_hvm_domain(d) )
+ if ( iommu_enabled && is_hvm_domain(d)
+ && need_modify_vtd_table )
{
if ( p2mt == p2m_ram_rw )
{
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 */
static mfn_t ept_get_entry(struct domain *d, unsigned long gfn, p2m_type_t *t,
p2m_query_t q)
* Set emt for super page.
*/
order = EPT_TABLE_ORDER;
- ept_set_entry(d, gfn, _mfn(mfn), order, p2mt);
+ /* 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);
gfn += 0x1FF;
}
else
{
- /* change emt for partial entries of the 2m area */
- ept_set_entry(d, gfn, _mfn(mfn), order, p2mt);
+ /* 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);
gfn = ((gfn >> EPT_TABLE_ORDER) << EPT_TABLE_ORDER) + 0x1FF;
}
}
- else /* gfn assigned with 4k */
- ept_set_entry(d, gfn, _mfn(mfn), order, p2mt);
+ 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);
}
}