[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v6 08/15] x86/altp2m: add control of suppress_ve.
From: George Dunlap <george.dunlap@xxxxxxxxxxxxx> The existing ept_set_entry() and ept_get_entry() routines are extended to optionally set/get suppress_ve. Passing -1 will set suppress_ve on new p2m entries, or retain suppress_ve flag on existing entries. Signed-off-by: George Dunlap <george.dunlap@xxxxxxxxxxxxx> Signed-off-by: Ravi Sahita <ravi.sahita@xxxxxxxxx> Reviewed-by: Jan Beulich <jbeulich@xxxxxxxx> Reviewed-by: George Dunlap <george.dunlap@xxxxxxxxxxxxx> --- xen/arch/x86/mm/mem_sharing.c | 4 ++-- xen/arch/x86/mm/p2m-ept.c | 18 ++++++++++++---- xen/arch/x86/mm/p2m-pod.c | 12 +++++------ xen/arch/x86/mm/p2m-pt.c | 10 +++++++-- xen/arch/x86/mm/p2m.c | 48 +++++++++++++++++++++---------------------- xen/include/asm-x86/p2m.h | 24 ++++++++++++---------- 6 files changed, 67 insertions(+), 49 deletions(-) diff --git a/xen/arch/x86/mm/mem_sharing.c b/xen/arch/x86/mm/mem_sharing.c index 1a01e45..d2e3786 100644 --- a/xen/arch/x86/mm/mem_sharing.c +++ b/xen/arch/x86/mm/mem_sharing.c @@ -1260,7 +1260,7 @@ int relinquish_shared_pages(struct domain *d) if ( atomic_read(&d->shr_pages) == 0 ) break; - mfn = p2m->get_entry(p2m, gfn, &t, &a, 0, NULL); + mfn = p2m->get_entry(p2m, gfn, &t, &a, 0, NULL, NULL); if ( mfn_valid(mfn) && (t == p2m_ram_shared) ) { /* Does not fail with ENOMEM given the DESTROY flag */ @@ -1270,7 +1270,7 @@ int relinquish_shared_pages(struct domain *d) * unshare. Must succeed: we just read the old entry and * we hold the p2m lock. */ set_rc = p2m->set_entry(p2m, gfn, _mfn(0), PAGE_ORDER_4K, - p2m_invalid, p2m_access_rwx); + p2m_invalid, p2m_access_rwx, -1); ASSERT(set_rc == 0); count += 0x10; } diff --git a/xen/arch/x86/mm/p2m-ept.c b/xen/arch/x86/mm/p2m-ept.c index b532811..3652996 100644 --- a/xen/arch/x86/mm/p2m-ept.c +++ b/xen/arch/x86/mm/p2m-ept.c @@ -658,7 +658,8 @@ bool_t ept_handle_misconfig(uint64_t gpa) */ 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) + unsigned int order, p2m_type_t p2mt, p2m_access_t p2ma, + int sve) { ept_entry_t *table, *ept_entry = NULL; unsigned long gfn_remainder = gfn; @@ -804,7 +805,11 @@ ept_set_entry(struct p2m_domain *p2m, unsigned long gfn, mfn_t mfn, ept_p2m_type_to_flags(p2m, &new_entry, p2mt, p2ma); } - new_entry.suppress_ve = 1; + if ( sve != -1 ) + new_entry.suppress_ve = !!sve; + else + new_entry.suppress_ve = is_epte_valid(&old_entry) ? + old_entry.suppress_ve : 1; rc = atomic_write_ept_entry(ept_entry, new_entry, target); if ( unlikely(rc) ) @@ -851,8 +856,9 @@ out: /* Read ept p2m entries */ 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) + unsigned long gfn, p2m_type_t *t, p2m_access_t* a, + p2m_query_t q, unsigned int *page_order, + bool_t *sve) { ept_entry_t *table = map_domain_page(_mfn(pagetable_get_pfn(p2m_get_pagetable(p2m)))); unsigned long gfn_remainder = gfn; @@ -866,6 +872,8 @@ static mfn_t ept_get_entry(struct p2m_domain *p2m, *t = p2m_mmio_dm; *a = p2m_access_n; + if ( sve ) + *sve = 1; /* This pfn is higher than the highest the p2m map currently holds */ if ( gfn > p2m->max_mapped_pfn ) @@ -931,6 +939,8 @@ static mfn_t ept_get_entry(struct p2m_domain *p2m, else *t = ept_entry->sa_p2mt; *a = ept_entry->access; + if ( sve ) + *sve = ept_entry->suppress_ve; mfn = _mfn(ept_entry->mfn); if ( i ) diff --git a/xen/arch/x86/mm/p2m-pod.c b/xen/arch/x86/mm/p2m-pod.c index 6e27bcd..6aee85a 100644 --- a/xen/arch/x86/mm/p2m-pod.c +++ b/xen/arch/x86/mm/p2m-pod.c @@ -536,7 +536,7 @@ recount: p2m_access_t a; p2m_type_t t; - (void)p2m->get_entry(p2m, gpfn + i, &t, &a, 0, NULL); + (void)p2m->get_entry(p2m, gpfn + i, &t, &a, 0, NULL, NULL); if ( t == p2m_populate_on_demand ) pod++; @@ -587,7 +587,7 @@ recount: p2m_type_t t; p2m_access_t a; - mfn = p2m->get_entry(p2m, gpfn + i, &t, &a, 0, NULL); + mfn = p2m->get_entry(p2m, gpfn + i, &t, &a, 0, NULL, NULL); if ( t == p2m_populate_on_demand ) { p2m_set_entry(p2m, gpfn + i, _mfn(INVALID_MFN), 0, p2m_invalid, @@ -676,7 +676,7 @@ p2m_pod_zero_check_superpage(struct p2m_domain *p2m, unsigned long gfn) for ( i=0; i<SUPERPAGE_PAGES; i++ ) { p2m_access_t a; - mfn = p2m->get_entry(p2m, gfn + i, &type, &a, 0, NULL); + mfn = p2m->get_entry(p2m, gfn + i, &type, &a, 0, NULL, NULL); if ( i == 0 ) { @@ -808,7 +808,7 @@ p2m_pod_zero_check(struct p2m_domain *p2m, unsigned long *gfns, int count) for ( i=0; i<count; i++ ) { p2m_access_t a; - mfns[i] = p2m->get_entry(p2m, gfns[i], types + i, &a, 0, NULL); + mfns[i] = p2m->get_entry(p2m, gfns[i], types + i, &a, 0, NULL, NULL); /* If this is ram, and not a pagetable or from the xen heap, and probably not mapped elsewhere, map it; otherwise, skip. */ if ( p2m_is_ram(types[i]) @@ -947,7 +947,7 @@ p2m_pod_emergency_sweep(struct p2m_domain *p2m) for ( i=p2m->pod.reclaim_single; i > 0 ; i-- ) { p2m_access_t a; - (void)p2m->get_entry(p2m, i, &t, &a, 0, NULL); + (void)p2m->get_entry(p2m, i, &t, &a, 0, NULL, NULL); if ( p2m_is_ram(t) ) { gfns[j] = i; @@ -1135,7 +1135,7 @@ guest_physmap_mark_populate_on_demand(struct domain *d, unsigned long gfn, for ( i = 0; i < (1UL << order); i++ ) { p2m_access_t a; - omfn = p2m->get_entry(p2m, gfn + i, &ot, &a, 0, NULL); + omfn = p2m->get_entry(p2m, gfn + i, &ot, &a, 0, NULL, NULL); if ( p2m_is_ram(ot) ) { P2M_DEBUG("gfn_to_mfn returned type %d!\n", ot); diff --git a/xen/arch/x86/mm/p2m-pt.c b/xen/arch/x86/mm/p2m-pt.c index a6dd464..926de0b 100644 --- a/xen/arch/x86/mm/p2m-pt.c +++ b/xen/arch/x86/mm/p2m-pt.c @@ -482,7 +482,8 @@ int p2m_pt_handle_deferred_changes(uint64_t gpa) /* Returns: 0 for success, -errno for failure */ static int p2m_pt_set_entry(struct p2m_domain *p2m, unsigned long gfn, mfn_t mfn, - unsigned int page_order, p2m_type_t p2mt, p2m_access_t p2ma) + unsigned int page_order, p2m_type_t p2mt, p2m_access_t p2ma, + int sve) { /* XXX -- this might be able to be faster iff current->domain == d */ void *table; @@ -495,6 +496,8 @@ p2m_pt_set_entry(struct p2m_domain *p2m, unsigned long gfn, mfn_t mfn, unsigned int iommu_pte_flags = p2m_get_iommu_flags(p2mt); unsigned long old_mfn = 0; + ASSERT(sve != 0); + if ( tb_init_done ) { struct { @@ -689,7 +692,7 @@ static inline p2m_type_t recalc_type(bool_t recalc, p2m_type_t t, static mfn_t p2m_pt_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) + unsigned int *page_order, bool_t *sve) { mfn_t mfn; paddr_t addr = ((paddr_t)gfn) << PAGE_SHIFT; @@ -701,6 +704,9 @@ p2m_pt_get_entry(struct p2m_domain *p2m, unsigned long gfn, ASSERT(paging_mode_translate(p2m->domain)); + if ( sve ) + *sve = 1; + /* XXX This is for compatibility with the old model, where anything not * XXX marked as RAM was considered to be emulated MMIO space. * XXX Once we start explicitly registering MMIO regions in the p2m diff --git a/xen/arch/x86/mm/p2m.c b/xen/arch/x86/mm/p2m.c index 0fb3209..93ecd87 100644 --- a/xen/arch/x86/mm/p2m.c +++ b/xen/arch/x86/mm/p2m.c @@ -346,7 +346,7 @@ mfn_t __get_gfn_type_access(struct p2m_domain *p2m, unsigned long gfn, /* Grab the lock here, don't release until put_gfn */ gfn_lock(p2m, gfn, 0); - mfn = p2m->get_entry(p2m, gfn, t, a, q, page_order); + mfn = p2m->get_entry(p2m, gfn, t, a, q, page_order, NULL); if ( (q & P2M_UNSHARE) && p2m_is_shared(*t) ) { @@ -355,7 +355,7 @@ mfn_t __get_gfn_type_access(struct p2m_domain *p2m, unsigned long gfn, * sleeping. */ if ( mem_sharing_unshare_page(p2m->domain, gfn, 0) < 0 ) (void)mem_sharing_notify_enomem(p2m->domain, gfn, 0); - mfn = p2m->get_entry(p2m, gfn, t, a, q, page_order); + mfn = p2m->get_entry(p2m, gfn, t, a, q, page_order, NULL); } if (unlikely((p2m_is_broken(*t)))) @@ -459,7 +459,7 @@ int p2m_set_entry(struct p2m_domain *p2m, unsigned long gfn, mfn_t mfn, else order = 0; - set_rc = p2m->set_entry(p2m, gfn, mfn, order, p2mt, p2ma); + set_rc = p2m->set_entry(p2m, gfn, mfn, order, p2mt, p2ma, -1); if ( set_rc ) rc = set_rc; @@ -623,7 +623,7 @@ p2m_remove_page(struct p2m_domain *p2m, unsigned long gfn, unsigned long mfn, { for ( i = 0; i < (1UL << page_order); i++ ) { - mfn_return = p2m->get_entry(p2m, gfn + i, &t, &a, 0, NULL); + mfn_return = p2m->get_entry(p2m, gfn + i, &t, &a, 0, NULL, NULL); if ( !p2m_is_grant(t) && !p2m_is_shared(t) && !p2m_is_foreign(t) ) set_gpfn_from_mfn(mfn+i, INVALID_M2P_ENTRY); ASSERT( !p2m_is_valid(t) || mfn + i == mfn_x(mfn_return) ); @@ -686,7 +686,7 @@ guest_physmap_add_entry(struct domain *d, unsigned long gfn, /* First, remove m->p mappings for existing p->m mappings */ for ( i = 0; i < (1UL << page_order); i++ ) { - omfn = p2m->get_entry(p2m, gfn + i, &ot, &a, 0, NULL); + omfn = p2m->get_entry(p2m, gfn + i, &ot, &a, 0, NULL, NULL); if ( p2m_is_shared(ot) ) { /* Do an unshare to cleanly take care of all corner @@ -710,7 +710,7 @@ guest_physmap_add_entry(struct domain *d, unsigned long gfn, (void)mem_sharing_notify_enomem(p2m->domain, gfn + i, 0); return rc; } - omfn = p2m->get_entry(p2m, gfn + i, &ot, &a, 0, NULL); + omfn = p2m->get_entry(p2m, gfn + i, &ot, &a, 0, NULL, NULL); ASSERT(!p2m_is_shared(ot)); } if ( p2m_is_grant(ot) || p2m_is_foreign(ot) ) @@ -758,7 +758,7 @@ guest_physmap_add_entry(struct domain *d, unsigned long gfn, * address */ P2M_DEBUG("aliased! mfn=%#lx, old gfn=%#lx, new gfn=%#lx\n", mfn + i, ogfn, gfn + i); - omfn = p2m->get_entry(p2m, ogfn, &ot, &a, 0, NULL); + omfn = p2m->get_entry(p2m, ogfn, &ot, &a, 0, NULL, NULL); if ( p2m_is_ram(ot) && !p2m_is_paged(ot) ) { ASSERT(mfn_valid(omfn)); @@ -825,7 +825,7 @@ int p2m_change_type_one(struct domain *d, unsigned long gfn, gfn_lock(p2m, gfn, 0); - mfn = p2m->get_entry(p2m, gfn, &pt, &a, 0, NULL); + mfn = p2m->get_entry(p2m, gfn, &pt, &a, 0, NULL, NULL); rc = likely(pt == ot) ? p2m_set_entry(p2m, gfn, mfn, PAGE_ORDER_4K, nt, p2m->default_access) @@ -909,7 +909,7 @@ static int set_typed_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn, return -EIO; gfn_lock(p2m, gfn, 0); - omfn = p2m->get_entry(p2m, gfn, &ot, &a, 0, NULL); + omfn = p2m->get_entry(p2m, gfn, &ot, &a, 0, NULL, NULL); if ( p2m_is_grant(ot) || p2m_is_foreign(ot) ) { p2m_unlock(p2m); @@ -960,7 +960,7 @@ int clear_mmio_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn) return -EIO; gfn_lock(p2m, gfn, 0); - actual_mfn = p2m->get_entry(p2m, gfn, &t, &a, 0, NULL); + actual_mfn = p2m->get_entry(p2m, gfn, &t, &a, 0, NULL, NULL); /* Do not use mfn_valid() here as it will usually fail for MMIO pages. */ if ( (INVALID_MFN == mfn_x(actual_mfn)) || (t != p2m_mmio_direct) ) @@ -996,7 +996,7 @@ int set_shared_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn) return -EIO; gfn_lock(p2m, gfn, 0); - omfn = p2m->get_entry(p2m, gfn, &ot, &a, 0, NULL); + omfn = p2m->get_entry(p2m, gfn, &ot, &a, 0, NULL, NULL); /* At the moment we only allow p2m change if gfn has already been made * sharable first */ ASSERT(p2m_is_shared(ot)); @@ -1048,7 +1048,7 @@ int p2m_mem_paging_nominate(struct domain *d, unsigned long gfn) gfn_lock(p2m, gfn, 0); - mfn = p2m->get_entry(p2m, gfn, &p2mt, &a, 0, NULL); + mfn = p2m->get_entry(p2m, gfn, &p2mt, &a, 0, NULL, NULL); /* Check if mfn is valid */ if ( !mfn_valid(mfn) ) @@ -1110,7 +1110,7 @@ int p2m_mem_paging_evict(struct domain *d, unsigned long gfn) gfn_lock(p2m, gfn, 0); /* Get mfn */ - mfn = p2m->get_entry(p2m, gfn, &p2mt, &a, 0, NULL); + mfn = p2m->get_entry(p2m, gfn, &p2mt, &a, 0, NULL, NULL); if ( unlikely(!mfn_valid(mfn)) ) goto out; @@ -1242,7 +1242,7 @@ void p2m_mem_paging_populate(struct domain *d, unsigned long gfn) /* Fix p2m mapping */ gfn_lock(p2m, gfn, 0); - mfn = p2m->get_entry(p2m, gfn, &p2mt, &a, 0, NULL); + mfn = p2m->get_entry(p2m, gfn, &p2mt, &a, 0, NULL, NULL); /* Allow only nominated or evicted pages to enter page-in path */ if ( p2mt == p2m_ram_paging_out || p2mt == p2m_ram_paged ) { @@ -1304,7 +1304,7 @@ int p2m_mem_paging_prep(struct domain *d, unsigned long gfn, uint64_t buffer) gfn_lock(p2m, gfn, 0); - mfn = p2m->get_entry(p2m, gfn, &p2mt, &a, 0, NULL); + mfn = p2m->get_entry(p2m, gfn, &p2mt, &a, 0, NULL, NULL); ret = -ENOENT; /* Allow missing pages */ @@ -1392,7 +1392,7 @@ void p2m_mem_paging_resume(struct domain *d, vm_event_response_t *rsp) unsigned long gfn = rsp->u.mem_access.gfn; gfn_lock(p2m, gfn, 0); - mfn = p2m->get_entry(p2m, gfn, &p2mt, &a, 0, NULL); + mfn = p2m->get_entry(p2m, gfn, &p2mt, &a, 0, NULL, NULL); /* * Allow only pages which were prepared properly, or pages which * were nominated but not evicted. @@ -1541,11 +1541,11 @@ bool_t p2m_mem_access_check(paddr_t gpa, unsigned long gla, * These calls to p2m->set_entry() must succeed: we have the gfn * locked and just did a successful get_entry(). */ gfn_lock(p2m, gfn, 0); - mfn = p2m->get_entry(p2m, gfn, &p2mt, &p2ma, 0, NULL); + mfn = p2m->get_entry(p2m, gfn, &p2mt, &p2ma, 0, NULL, NULL); if ( npfec.write_access && p2ma == p2m_access_rx2rw ) { - rc = p2m->set_entry(p2m, gfn, mfn, PAGE_ORDER_4K, p2mt, p2m_access_rw); + rc = p2m->set_entry(p2m, gfn, mfn, PAGE_ORDER_4K, p2mt, p2m_access_rw, -1); ASSERT(rc == 0); gfn_unlock(p2m, gfn, 0); return 1; @@ -1554,7 +1554,7 @@ bool_t p2m_mem_access_check(paddr_t gpa, unsigned long gla, { ASSERT(npfec.write_access || npfec.read_access || npfec.insn_fetch); rc = p2m->set_entry(p2m, gfn, mfn, PAGE_ORDER_4K, - p2mt, p2m_access_rwx); + p2mt, p2m_access_rwx, -1); ASSERT(rc == 0); } gfn_unlock(p2m, gfn, 0); @@ -1574,14 +1574,14 @@ bool_t p2m_mem_access_check(paddr_t gpa, unsigned long gla, else { gfn_lock(p2m, gfn, 0); - mfn = p2m->get_entry(p2m, gfn, &p2mt, &p2ma, 0, NULL); + mfn = p2m->get_entry(p2m, gfn, &p2mt, &p2ma, 0, NULL, NULL); if ( p2ma != p2m_access_n2rwx ) { /* A listener is not required, so clear the access * restrictions. This set must succeed: we have the * gfn locked and just did a successful get_entry(). */ rc = p2m->set_entry(p2m, gfn, mfn, PAGE_ORDER_4K, - p2mt, p2m_access_rwx); + p2mt, p2m_access_rwx, -1); ASSERT(rc == 0); } gfn_unlock(p2m, gfn, 0); @@ -1712,8 +1712,8 @@ long p2m_set_mem_access(struct domain *d, gfn_t gfn, uint32_t nr, p2m_lock(p2m); for ( gfn_l = gfn_x(gfn) + start; nr > start; ++gfn_l ) { - mfn = p2m->get_entry(p2m, gfn_l, &t, &_a, 0, NULL); - rc = p2m->set_entry(p2m, gfn_l, mfn, PAGE_ORDER_4K, t, a); + mfn = p2m->get_entry(p2m, gfn_l, &t, &_a, 0, NULL, NULL); + rc = p2m->set_entry(p2m, gfn_l, mfn, PAGE_ORDER_4K, t, a, -1); if ( rc ) break; @@ -1762,7 +1762,7 @@ int p2m_get_mem_access(struct domain *d, gfn_t gfn, xenmem_access_t *access) } gfn_lock(p2m, gfn, 0); - mfn = p2m->get_entry(p2m, gfn_x(gfn), &t, &a, 0, NULL); + mfn = p2m->get_entry(p2m, gfn_x(gfn), &t, &a, 0, NULL, NULL); gfn_unlock(p2m, gfn, 0); if ( mfn_x(mfn) == INVALID_MFN ) diff --git a/xen/include/asm-x86/p2m.h b/xen/include/asm-x86/p2m.h index 079a298..0a172e0 100644 --- a/xen/include/asm-x86/p2m.h +++ b/xen/include/asm-x86/p2m.h @@ -226,17 +226,19 @@ struct p2m_domain { /* Pages used to construct the p2m */ struct page_list_head pages; - int (*set_entry )(struct p2m_domain *p2m, - unsigned long gfn, - mfn_t mfn, unsigned int page_order, - p2m_type_t p2mt, - p2m_access_t p2ma); - mfn_t (*get_entry )(struct p2m_domain *p2m, - unsigned long gfn, - p2m_type_t *p2mt, - p2m_access_t *p2ma, - p2m_query_t q, - unsigned int *page_order); + int (*set_entry)(struct p2m_domain *p2m, + unsigned long gfn, + mfn_t mfn, unsigned int page_order, + p2m_type_t p2mt, + p2m_access_t p2ma, + int sve); + mfn_t (*get_entry)(struct p2m_domain *p2m, + unsigned long gfn, + p2m_type_t *p2mt, + p2m_access_t *p2ma, + p2m_query_t q, + unsigned int *page_order, + bool_t *sve); void (*enable_hardware_log_dirty)(struct p2m_domain *p2m); void (*disable_hardware_log_dirty)(struct p2m_domain *p2m); void (*flush_hardware_cached_dirty)(struct p2m_domain *p2m); -- 1.9.1 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |