From mboxrd@z Thu Jan 1 00:00:00 1970 From: Aravindh Puthiyaparambil Subject: [PATCH 1 of 2] x86/mm: Split ept_set_entry() Date: Thu, 26 Apr 2012 11:33:30 -0700 Message-ID: References: Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: In-Reply-To: List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org To: xen-devel@lists.xen.org Cc: tim@xen.org List-Id: xen-devel@lists.xenproject.org xen/arch/x86/mm/p2m-ept.c | 60 ++++++++++++++++++++++++++++------------------ 1 files changed, 37 insertions(+), 23 deletions(-) Split ept_set_entry() such that mapping and unmapping of the page tables and ept_sync occurrs outside of it. Signed-off-by: Aravindh Puthiyaparambil diff -r 63eb1343cbdb -r f12cf785738f xen/arch/x86/mm/p2m-ept.c --- a/xen/arch/x86/mm/p2m-ept.c Wed Apr 25 19:29:53 2012 -0700 +++ b/xen/arch/x86/mm/p2m-ept.c Wed Apr 25 19:29:54 2012 -0700 @@ -272,14 +272,15 @@ static int ept_next_level(struct p2m_dom } /* - * 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 p2m_domain *p2m, unsigned long gfn, mfn_t mfn, - unsigned int order, p2m_type_t p2mt, p2m_access_t p2ma) +__ept_set_entry(struct p2m_domain *p2m, unsigned long gfn, mfn_t mfn, + unsigned int order, p2m_type_t p2mt, p2m_access_t p2ma, + ept_entry_t *table, ept_entry_t *old_entry, bool_t *needs_sync) { - ept_entry_t *table, *ept_entry = NULL; + ept_entry_t *ept_entry = NULL; unsigned long gfn_remainder = gfn; unsigned long offset = 0; u32 index; @@ -288,11 +289,9 @@ ept_set_entry(struct p2m_domain *p2m, un int ret = 0; bool_t direct_mmio = (p2mt == p2m_mmio_direct); uint8_t ipat = 0; - int need_modify_vtd_table = 1; - int vtd_pte_present = 0; - int needs_sync = 1; + bool_t need_modify_vtd_table = 1; + bool_t vtd_pte_present = 0; struct domain *d = p2m->domain; - ept_entry_t old_entry = { .epte = 0 }; /* * the caller must make sure: @@ -305,12 +304,6 @@ ept_set_entry(struct p2m_domain *p2m, un (order % EPT_TABLE_ORDER) ) return 0; - ASSERT((target == 2 && hvm_hap_has_1gb(d)) || - (target == 1 && hvm_hap_has_2mb(d)) || - (target == 0)); - - table = map_domain_page(ept_get_asr(d)); - for ( i = ept_get_wl(d); i > target; i-- ) { ret = ept_next_level(p2m, 0, &table, &gfn_remainder, i); @@ -327,7 +320,7 @@ ept_set_entry(struct p2m_domain *p2m, un ept_entry = table + index; - /* In case VT-d uses same page table, this flag is needed by VT-d */ + /* In case VT-d uses same page table, this flag is needed by VT-d */ vtd_pte_present = is_epte_present(ept_entry) ? 1 : 0; /* @@ -352,7 +345,7 @@ ept_set_entry(struct p2m_domain *p2m, un * the intermediate tables will be freed below after the ept flush * * Read-then-write is OK because we hold the p2m lock. */ - old_entry = *ept_entry; + old_entry->epte = ept_entry->epte; if ( mfn_valid(mfn_x(mfn)) || direct_mmio || p2m_is_paged(p2mt) || (p2mt == p2m_ram_paging_in) ) @@ -369,7 +362,7 @@ ept_set_entry(struct p2m_domain *p2m, un new_entry.mfn = mfn_x(mfn); - if ( old_entry.mfn == new_entry.mfn ) + if ( old_entry->mfn == new_entry.mfn ) need_modify_vtd_table = 0; ept_p2m_type_to_flags(&new_entry, p2mt, p2ma); @@ -435,12 +428,7 @@ ept_set_entry(struct p2m_domain *p2m, un /* Success */ rv = 1; -out: - unmap_domain_page(table); - - if ( needs_sync ) - ept_sync_domain(p2m->domain); - + out: if ( rv && iommu_enabled && need_iommu(p2m->domain) && need_modify_vtd_table ) { if ( iommu_hap_pt_share ) @@ -473,6 +461,32 @@ out: } } + return rv; +} + +static int +ept_set_entry(struct p2m_domain *p2m, unsigned long gfn, mfn_t mfn, + unsigned int order, p2m_type_t p2mt, p2m_access_t p2ma) +{ + ept_entry_t *table; + int target = order / EPT_TABLE_ORDER; + int rv = 0; + bool_t needs_sync = 1; + struct domain *d = p2m->domain; + ept_entry_t old_entry = { .epte = 0 }; + + ASSERT((target == 2 && hvm_hap_has_1gb(d)) || + (target == 1 && hvm_hap_has_2mb(d)) || + (target == 0)); + + table = map_domain_page(ept_get_asr(d)); + rv = __ept_set_entry(p2m, gfn, mfn, order, p2mt, p2ma, table, &old_entry, + &needs_sync); + unmap_domain_page(table); + + if ( needs_sync ) + ept_sync_domain(p2m->domain); + /* Release the old intermediate tables, if any. This has to be the last thing we do, after the ept_sync_domain() and removal from the iommu tables, so as to avoid a potential