Olaf Hering
2011-Oct-19 14:23 UTC
[Xen-devel] [PATCH 0 of 3] xenpaging fixes for xen-unstable
The following changes for xenpaging add checking for the p2mt in the page-in path to make the functions more robust, add some documentation to each p2m_mem_paging function, and disable paging in a PoD guest. Please review and apply. Olaf tools/xenpaging/xenpaging.c | 3 + xen/arch/x86/mm/mem_event.c | 6 ++ xen/arch/x86/mm/p2m.c | 111 ++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 116 insertions(+), 4 deletions(-) _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Olaf Hering
2011-Oct-19 14:23 UTC
[Xen-devel] [PATCH 1 of 3] xenpaging: check p2mt in p2m_mem_paging functions
# HG changeset patch # User Olaf Hering <olaf@aepfle.de> # Date 1319034159 -7200 # Node ID f835012a0c062e70495aa341d41e3970a121bf6a # Parent 6880bfc48504db31e2680de01bfadf4db3b0b7a0 xenpaging: check p2mt in p2m_mem_paging functions Add checks to forward the p2m_ram_paging* state properly during page-in. Resume can be called several times if several vcpus called populate for the gfn. Finish resume only once. v2: - remove debug output for non-p2m_ram_rw case Signed-off-by: Olaf Hering <olaf@aepfle.de> diff -r 6880bfc48504 -r f835012a0c06 xen/arch/x86/mm/p2m.c --- a/xen/arch/x86/mm/p2m.c +++ b/xen/arch/x86/mm/p2m.c @@ -851,16 +851,22 @@ int p2m_mem_paging_prep(struct domain *d p2m_access_t a; mfn_t mfn; struct p2m_domain *p2m = p2m_get_hostp2m(d); - int ret = -ENOMEM; + int ret; p2m_lock(p2m); mfn = p2m->get_entry(p2m, gfn, &p2mt, &a, p2m_query, NULL); + ret = -ENOENT; + /* Allow only missing pages */ + if ( p2mt != p2m_ram_paging_in_start ) + goto out; + /* Allocate a page if the gfn does not have one yet */ if ( !mfn_valid(mfn) ) { /* Get a free page */ + ret = -ENOMEM; page = alloc_domheap_page(p2m->domain, 0); if ( unlikely(page == NULL) ) goto out; @@ -896,9 +902,13 @@ void p2m_mem_paging_resume(struct domain { p2m_lock(p2m); mfn = p2m->get_entry(p2m, rsp.gfn, &p2mt, &a, p2m_query, NULL); - set_p2m_entry(p2m, rsp.gfn, mfn, 0, p2m_ram_rw, a); - set_gpfn_from_mfn(mfn_x(mfn), rsp.gfn); - audit_p2m(p2m, 1); + /* Allow only pages which were prepared properly, or pages which were nominated but not evicted */ + if ( mfn_valid(mfn) && ( p2mt == p2m_ram_paging_in || p2mt == p2m_ram_paging_in_start ) ) + { + set_p2m_entry(p2m, rsp.gfn, mfn, 0, p2m_ram_rw, a); + set_gpfn_from_mfn(mfn_x(mfn), rsp.gfn); + audit_p2m(p2m, 1); + } p2m_unlock(p2m); } _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Olaf Hering
2011-Oct-19 14:23 UTC
[Xen-devel] [PATCH 2 of 3] xenpaging: document p2m_mem_paging functions
# HG changeset patch # User Olaf Hering <olaf@aepfle.de> # Date 1319034159 -7200 # Node ID cc6184fcd784f94165417073935c5fd0c4b4a76e # Parent f835012a0c062e70495aa341d41e3970a121bf6a xenpaging: document p2m_mem_paging functions Add some documentation for each of the p2m_mem_paging functions to describe what they ought to do. Signed-off-by: Olaf Hering <olaf@aepfle.de> diff -r f835012a0c06 -r cc6184fcd784 xen/arch/x86/mm/p2m.c --- a/xen/arch/x86/mm/p2m.c +++ b/xen/arch/x86/mm/p2m.c @@ -668,6 +668,24 @@ set_shared_p2m_entry(struct domain *d, u } #ifdef __x86_64__ +/** + * p2m_mem_paging_nominate - Mark a guest page as to-be-paged-out + * @d: guest domain + * @gfn: guest page to nominate + * + * Returns 0 for success or negative errno values if gfn is not pageable. + * + * p2m_mem_paging_nominate() is called by the pager and checks if a guest page + * can be paged out. If the following conditions are met the p2mt will be + * changed: + * - the gfn is backed by a mfn + * - the p2mt of the gfn is pageable + * - the mfn is not used for IO + * - the mfn has exactly one user and has no special meaning + * + * Once the p2mt is changed the page is readonly for the guest. On success the + * pager can write the page contents to disk and later evict the page. + */ int p2m_mem_paging_nominate(struct domain *d, unsigned long gfn) { struct page_info *page; @@ -714,6 +732,25 @@ int p2m_mem_paging_nominate(struct domai return ret; } +/** + * p2m_mem_paging_evict - Mark a guest page as paged-out + * @d: guest domain + * @gfn: guest page to evict + * + * Returns 0 for success or negative errno values if eviction is not possible. + * + * p2m_mem_paging_evict() is called by the pager and will free a guest page and + * release it back to Xen. If the following conditions are met the page can be + * freed: + * - the gfn is backed by a mfn + * - the gfn was nominated + * - the mfn has still exactly one user and has no special meaning + * + * After successful nomination some other process could have mapped the page. In + * this case eviction can not be done. If the gfn was populated before the pager + * could evict it, eviction can not be done either. In this case the gfn is + * still backed by a mfn. + */ int p2m_mem_paging_evict(struct domain *d, unsigned long gfn) { struct page_info *page; @@ -773,6 +810,15 @@ int p2m_mem_paging_evict(struct domain * return ret; } +/** + * p2m_mem_paging_drop_page - Tell pager to drop its reference to a paged page + * @d: guest domain + * @gfn: guest page to drop + * + * p2m_mem_paging_drop_page() will notify the pager that a paged-out gfn was + * released by the guest. The pager is supposed to drop its reference of the + * gfn. + */ void p2m_mem_paging_drop_page(struct domain *d, unsigned long gfn) { struct vcpu *v = current; @@ -791,6 +837,27 @@ void p2m_mem_paging_drop_page(struct dom } } +/** + * p2m_mem_paging_populate - Tell pager to populete a paged page + * @d: guest domain + * @gfn: guest page in paging state + * + * p2m_mem_paging_populate() will notify the pager that a page in any of the + * paging states needs to be written back into the guest. + * This function needs to be called whenever gfn_to_mfn() returns any of the p2m + * paging types because the gfn may not be backed by a mfn. + * + * The gfn can be in any of the paging states, but the pager needs only be + * notified when the gfn is in the paging-out path (paging_out or paged). This + * function may be called more than once from several vcpus. If the vcpu belongs + * to the guest, the vcpu must be stopped and the pager notified that the vcpu + * was stopped. The pager needs to handle several requests for the same gfn. + * + * If the gfn is not in the paging-out path and the vcpu does not belong to the + * guest, nothing needs to be done and the function assumes that a request was + * already sent to the pager. In this case the caller has to try again until the + * gfn is fully paged in again. + */ void p2m_mem_paging_populate(struct domain *d, unsigned long gfn) { struct vcpu *v = current; @@ -844,6 +911,17 @@ void p2m_mem_paging_populate(struct doma mem_event_put_request(d, &d->mem_paging, &req); } +/** + * p2m_mem_paging_prep - Allocate a new page for the guest + * @d: guest domain + * @gfn: guest page in paging state + * + * p2m_mem_paging_prep() will allocate a new page for the guest if the gfn is + * not backed by a mfn. It is called by the pager. + * It is required that the gfn was already populated. The gfn may already have a + * mfn if populate was called for gfn which was nominated but not evicted. In + * this case only the p2mt needs to be forwarded. + */ int p2m_mem_paging_prep(struct domain *d, unsigned long gfn) { struct page_info *page; @@ -886,6 +964,21 @@ int p2m_mem_paging_prep(struct domain *d return ret; } +/** + * p2m_mem_paging_resume - Resume guest gfn and vcpus + * @d: guest domain + * @gfn: guest page in paging state + * + * p2m_mem_paging_resume() will forward the p2mt of a gfn to ram_rw and all + * waiting vcpus will be unpaused again. It is called by the pager. + * + * The gfn was previously either evicted and populated, or nominated and + * populated. If the page was evicted the p2mt will be p2m_ram_paging_in. If + * the page was just nominated the p2mt will be p2m_ram_paging_in_start because + * the pager did not call p2m_mem_paging_prep(). + * + * If the gfn was dropped the vcpu needs to be unpaused. + */ void p2m_mem_paging_resume(struct domain *d) { struct p2m_domain *p2m = p2m_get_hostp2m(d); _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Olaf Hering
2011-Oct-19 14:23 UTC
[Xen-devel] [PATCH 3 of 3] xenpaging: disallow paging in a PoD guest
# HG changeset patch # User Olaf Hering <olaf@aepfle.de> # Date 1319034160 -7200 # Node ID d56219addb9e921a02bce5fa8a97c43eba9bc914 # Parent cc6184fcd784f94165417073935c5fd0c4b4a76e xenpaging: disallow paging in a PoD guest Disallow xenpaging in a PoD guest until coexistance between the two features is properly implemented. Signed-off-by: Olaf Hering <olaf@aepfle.de> diff -r cc6184fcd784 -r d56219addb9e tools/xenpaging/xenpaging.c --- a/tools/xenpaging/xenpaging.c +++ b/tools/xenpaging/xenpaging.c @@ -246,6 +246,9 @@ static xenpaging_t *xenpaging_init(domid case ENODEV: ERROR("EPT not supported for this guest"); break; + case EXDEV: + ERROR("xenpaging not supported in a PoD guest"); + break; default: ERROR("Error initialising shared page: %s", strerror(errno)); break; diff -r cc6184fcd784 -r d56219addb9e xen/arch/x86/mm/mem_event.c --- a/xen/arch/x86/mm/mem_event.c +++ b/xen/arch/x86/mm/mem_event.c @@ -253,6 +253,7 @@ int mem_event_domctl(struct domain *d, x case XEN_DOMCTL_MEM_EVENT_OP_PAGING: { struct mem_event_domain *med = &d->mem_paging; + struct p2m_domain *p2m = p2m_get_hostp2m(d); rc = -ENODEV; /* Only HAP is supported */ if ( !hap_enabled(d) ) @@ -262,6 +263,11 @@ int mem_event_domctl(struct domain *d, x if ( boot_cpu_data.x86_vendor != X86_VENDOR_INTEL ) break; + rc = -EXDEV; + /* Disallow paging in a PoD guest */ + if ( p2m->pod.entry_count ) + break; + switch( mec->op ) { case XEN_DOMCTL_MEM_EVENT_OP_PAGING_ENABLE: _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Tim Deegan
2011-Oct-20 10:32 UTC
Re: [Xen-devel] [PATCH 0 of 3] xenpaging fixes for xen-unstable
At 16:23 +0200 on 19 Oct (1319041400), Olaf Hering wrote:> > The following changes for xenpaging add checking for the p2mt in the page-in > path to make the functions more robust, add some documentation to each > p2m_mem_paging function, and disable paging in a PoD guest. > > Please review and apply.Applied, thanks. Double thanks for adding documentation! Tim. _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel