[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v6 10/15] x86/altp2m: add remaining support routines.
On 07/21/2015 12:58 AM, Ed White wrote: > Add the remaining routines required to support enabling the alternate > p2m functionality. > > Signed-off-by: Ed White <edmund.h.white@xxxxxxxxx> > > Reviewed-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> > --- > xen/arch/x86/hvm/hvm.c | 58 +++++- > xen/arch/x86/mm/hap/Makefile | 1 + > xen/arch/x86/mm/hap/altp2m_hap.c | 98 ++++++++++ > xen/arch/x86/mm/p2m-ept.c | 3 + > xen/arch/x86/mm/p2m.c | 385 > +++++++++++++++++++++++++++++++++++++++ > xen/include/asm-x86/hvm/altp2m.h | 4 + > xen/include/asm-x86/p2m.h | 33 ++++ > 7 files changed, 576 insertions(+), 6 deletions(-) > create mode 100644 xen/arch/x86/mm/hap/altp2m_hap.c > > diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c > index f0ab4d4..38cf0c6 100644 > --- a/xen/arch/x86/hvm/hvm.c > +++ b/xen/arch/x86/hvm/hvm.c > @@ -2856,10 +2856,11 @@ int hvm_hap_nested_page_fault(paddr_t gpa, unsigned > long gla, > mfn_t mfn; > struct vcpu *curr = current; > struct domain *currd = curr->domain; > - struct p2m_domain *p2m; > + struct p2m_domain *p2m, *hostp2m; > int rc, fall_through = 0, paged = 0; > int sharing_enomem = 0; > vm_event_request_t *req_ptr = NULL; > + bool_t ap2m_active = 0; > > /* On Nested Virtualization, walk the guest page table. > * If this succeeds, all is fine. > @@ -2919,11 +2920,31 @@ int hvm_hap_nested_page_fault(paddr_t gpa, unsigned > long gla, > goto out; > } > > - p2m = p2m_get_hostp2m(currd); > - mfn = get_gfn_type_access(p2m, gfn, &p2mt, &p2ma, > + ap2m_active = altp2m_active(currd); > + > + /* Take a lock on the host p2m speculatively, to avoid potential > + * locking order problems later and to handle unshare etc. > + */ > + hostp2m = p2m_get_hostp2m(currd); > + mfn = get_gfn_type_access(hostp2m, gfn, &p2mt, &p2ma, > P2M_ALLOC | (npfec.write_access ? P2M_UNSHARE > : 0), > NULL); > > + if ( ap2m_active ) > + { > + if ( altp2m_hap_nested_page_fault(curr, gpa, gla, npfec, &p2m) == 1 ) > + { > + /* entry was lazily copied from host -- retry */ > + __put_gfn(hostp2m, gfn); > + rc = 1; > + goto out; > + } > + > + mfn = get_gfn_type_access(p2m, gfn, &p2mt, &p2ma, 0, NULL); > + } > + else > + p2m = hostp2m; > + > /* Check access permissions first, then handle faults */ > if ( mfn_x(mfn) != INVALID_MFN ) > { > @@ -2963,6 +2984,20 @@ int hvm_hap_nested_page_fault(paddr_t gpa, unsigned > long gla, > > if ( violation ) > { > + /* Should #VE be emulated for this fault? */ > + if ( p2m_is_altp2m(p2m) && !cpu_has_vmx_virt_exceptions ) > + { > + bool_t sve; > + > + p2m->get_entry(p2m, gfn, &p2mt, &p2ma, 0, NULL, &sve); > + > + if ( !sve && altp2m_vcpu_emulate_ve(curr) ) > + { > + rc = 1; > + goto out_put_gfn; > + } > + } > + > if ( p2m_mem_access_check(gpa, gla, npfec, &req_ptr) ) > { > fall_through = 1; > @@ -2982,7 +3017,9 @@ int hvm_hap_nested_page_fault(paddr_t gpa, unsigned > long gla, > (npfec.write_access && > (p2m_is_discard_write(p2mt) || (p2mt == p2m_mmio_write_dm))) ) > { > - put_gfn(currd, gfn); > + __put_gfn(p2m, gfn); > + if ( ap2m_active ) > + __put_gfn(hostp2m, gfn); > > rc = 0; > if ( unlikely(is_pvh_domain(currd)) ) > @@ -3011,6 +3048,7 @@ int hvm_hap_nested_page_fault(paddr_t gpa, unsigned > long gla, > /* Spurious fault? PoD and log-dirty also take this path. */ > if ( p2m_is_ram(p2mt) ) > { > + rc = 1; > /* > * Page log dirty is always done with order 0. If this mfn resides in > * a large page, we do not change other pages type within that large > @@ -3019,9 +3057,15 @@ int hvm_hap_nested_page_fault(paddr_t gpa, unsigned > long gla, > if ( npfec.write_access ) > { > paging_mark_dirty(currd, mfn_x(mfn)); > + /* If p2m is really an altp2m, unlock here to avoid lock ordering > + * violation when the change below is propagated from host p2m */ > + if ( ap2m_active ) > + __put_gfn(p2m, gfn); > p2m_change_type_one(currd, gfn, p2m_ram_logdirty, p2m_ram_rw); > + __put_gfn(ap2m_active ? hostp2m : p2m, gfn); > + > + goto out; > } > - rc = 1; > goto out_put_gfn; > } > > @@ -3031,7 +3075,9 @@ int hvm_hap_nested_page_fault(paddr_t gpa, unsigned > long gla, > rc = fall_through; > > out_put_gfn: > - put_gfn(currd, gfn); > + __put_gfn(p2m, gfn); > + if ( ap2m_active ) > + __put_gfn(hostp2m, gfn); > out: > /* All of these are delayed until we exit, since we might > * sleep on event ring wait queues, and we must not hold > diff --git a/xen/arch/x86/mm/hap/Makefile b/xen/arch/x86/mm/hap/Makefile > index 68f2bb5..216cd90 100644 > --- a/xen/arch/x86/mm/hap/Makefile > +++ b/xen/arch/x86/mm/hap/Makefile > @@ -4,6 +4,7 @@ obj-y += guest_walk_3level.o > obj-$(x86_64) += guest_walk_4level.o > obj-y += nested_hap.o > obj-y += nested_ept.o > +obj-y += altp2m_hap.o > > guest_walk_%level.o: guest_walk.c Makefile > $(CC) $(CFLAGS) -DGUEST_PAGING_LEVELS=$* -c $< -o $@ > diff --git a/xen/arch/x86/mm/hap/altp2m_hap.c > b/xen/arch/x86/mm/hap/altp2m_hap.c > new file mode 100644 > index 0000000..52c7877 > --- /dev/null > +++ b/xen/arch/x86/mm/hap/altp2m_hap.c > @@ -0,0 +1,98 @@ > +/****************************************************************************** > + * arch/x86/mm/hap/altp2m_hap.c > + * > + * Copyright (c) 2014 Intel Corporation. > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation; either version 2 of the License, or > + * (at your option) any later version. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program; if not, write to the Free Software > + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA > + */ > + > +#include <asm/domain.h> > +#include <asm/page.h> > +#include <asm/paging.h> > +#include <asm/p2m.h> > +#include <asm/hap.h> > +#include <asm/hvm/altp2m.h> > + > +#include "private.h" > + > +/* > + * If the fault is for a not present entry: > + * if the entry in the host p2m has a valid mfn, copy it and retry > + * else indicate that outer handler should handle fault > + * > + * If the fault is for a present entry: > + * indicate that outer handler should handle fault > + */ > + > +int > +altp2m_hap_nested_page_fault(struct vcpu *v, paddr_t gpa, > + unsigned long gla, struct npfec npfec, > + struct p2m_domain **ap2m) > +{ > + struct p2m_domain *hp2m = p2m_get_hostp2m(v->domain); > + p2m_type_t p2mt; > + p2m_access_t p2ma; > + unsigned int page_order; > + gfn_t gfn = _gfn(paddr_to_pfn(gpa)); > + unsigned long mask; > + mfn_t mfn; > + int rv; > + > + *ap2m = p2m_get_altp2m(v); > + > + mfn = get_gfn_type_access(*ap2m, gfn_x(gfn), &p2mt, &p2ma, > + 0, &page_order); > + __put_gfn(*ap2m, gfn_x(gfn)); > + > + if ( mfn_x(mfn) != INVALID_MFN ) > + return 0; > + > + mfn = get_gfn_type_access(hp2m, gfn_x(gfn), &p2mt, &p2ma, > + P2M_ALLOC | P2M_UNSHARE, &page_order); > + put_gfn(hp2m->domain, gfn_x(gfn)); To quote myself: --- Please do at least give this function a name that reflects what it does (i.e., try to propagate changes from the host p2m to the altp2m), and change this put_gfn() to match the __put_gfn() above. I'd prefer it if you moved this into mm/p2m.c as well. --- -George _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |