From: Olaf Hering <olaf@aepfle.de>
To: Tim Deegan <tim@xen.org>
Cc: andres@gridcentric.ca, xen-devel@lists.xensource.com,
adin@gridcentric.ca
Subject: Re: [PATCH 5 of 6] [RFC] x86/mm: use wait queues for mem_paging
Date: Fri, 24 Feb 2012 14:45:44 +0100 [thread overview]
Message-ID: <20120224134544.GA13134@aepfle.de> (raw)
In-Reply-To: <510d80343793227bd39b.1330014867@whitby.uk.xensource.com>
On Thu, Feb 23, Tim Deegan wrote:
> This is based on an earlier RFC patch by Olaf Hering, but heavily
> simplified (removing a per-gfn queue of waiting vcpus in favour of
> a scan of all vcpus on page-in).
Tim, thanks for that work. From just reading the change it looks ok.
A few comments below:
> +++ b/xen/arch/x86/mm/p2m.c Thu Feb 23 16:18:09 2012 +0000
> @@ -160,13 +160,49 @@ mfn_t __get_gfn_type_access(struct p2m_d
> }
>
> /* For now only perform locking on hap domains */
> - if ( locked && (hap_enabled(p2m->domain)) )
> + locked = locked && hap_enabled(p2m->domain);
> +
> +#ifdef __x86_64__
> +again:
> +#endif
> + if ( locked )
> /* 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);
>
> #ifdef __x86_64__
> + if ( p2m_is_paging(*t) && (q & P2M_ALLOC)
> + && p2m->domain == current->domain )
> + {
> + if ( locked )
> + gfn_unlock(p2m, gfn, 0);
> +
> + /* Ping the pager */
> + if ( *t == p2m_ram_paging_out || *t == p2m_ram_paged )
> + p2m_mem_paging_populate(p2m->domain, gfn);
> +
> + /* Wait until the pager finishes paging it in */
> + current->arch.mem_paging_gfn = gfn;
> + wait_event(current->arch.mem_paging_wq, ({
> + int done;
> + mfn = p2m->get_entry(p2m, gfn, t, a, 0, page_order);
> + done = (*t != p2m_ram_paging_in);
I assume p2m_mem_paging_populate() will not return until the state is
forwarded to p2m_ram_paging_in. Maybe p2m_is_paging(*t) would make it
more obvious what this check is supposed to do.
> + /* Safety catch: it _should_ be safe to wait here
> + * but if it's not, crash the VM, not the host */
> + if ( in_atomic() )
> + {
> + WARN();
> + domain_crash(p2m->domain);
> + done = 1;
> + }
> + done;
> + }));
> + goto again;
> + }
> +#endif
> +
> +#ifdef __x86_64__
> if ( (q & P2M_UNSHARE) && p2m_is_shared(*t) )
> {
> ASSERT(!p2m_is_nestedp2m(p2m));
> @@ -946,17 +982,17 @@ void p2m_mem_paging_drop_page(struct dom
> * 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.
> + * 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. 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.
> + * If the gfn is not in the paging-out path 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;
> @@ -965,6 +1001,7 @@ void p2m_mem_paging_populate(struct doma
> p2m_access_t a;
> mfn_t mfn;
> struct p2m_domain *p2m = p2m_get_hostp2m(d);
> + int send_request = 0;
Is that variable supposed to be used?
Perhaps the feature to fast-forward (or rollback) from
p2m_ram_paging_out to p2m_ram_rw could be a separate patch. My initial
version of this patch did not have a strict requirement for this
feature, if I remember correctly.
> /* We're paging. There should be a ring */
> int rc = mem_event_claim_slot(d, &d->mem_event->paging);
> @@ -987,19 +1024,22 @@ void p2m_mem_paging_populate(struct doma
> /* Evict will fail now, tag this request for pager */
> if ( p2mt == p2m_ram_paging_out )
> req.flags |= MEM_EVENT_FLAG_EVICT_FAIL;
> -
> - set_p2m_entry(p2m, gfn, mfn, PAGE_ORDER_4K, p2m_ram_paging_in, a);
> + if ( p2mt == p2m_ram_paging_out && mfn_valid(mfn) && v->domain == d )
> + /* Short-cut back to paged-in state (but not for foreign
> + * mappings, or the pager couldn't map it to page it out) */
> + set_p2m_entry(p2m, gfn, mfn, PAGE_ORDER_4K,
> + paging_mode_log_dirty(d)
> + ? p2m_ram_logdirty : p2m_ram_rw, a);
> + else
> + {
> + set_p2m_entry(p2m, gfn, mfn, PAGE_ORDER_4K, p2m_ram_paging_in, a);
> + send_request = 1;
> + }
> }
> gfn_unlock(p2m, gfn, 0);
>
> - /* Pause domain if request came from guest and gfn has paging type */
> - if ( p2m_is_paging(p2mt) && v->domain == d )
> - {
> - vcpu_pause_nosync(v);
> - req.flags |= MEM_EVENT_FLAG_VCPU_PAUSED;
> - }
> /* No need to inform pager if the gfn is not in the page-out path */
> - else if ( p2mt != p2m_ram_paging_out && p2mt != p2m_ram_paged )
> + if ( p2mt != p2m_ram_paging_out && p2mt != p2m_ram_paged )
> {
> /* gfn is already on its way back and vcpu is not paused */
> mem_event_cancel_slot(d, &d->mem_event->paging);
next prev parent reply other threads:[~2012-02-24 13:45 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-02-23 16:34 [PATCH 0 of 6] [RFC] Use wait queues for paging, v2 Tim Deegan
2012-02-23 16:34 ` [PATCH 1 of 6] mm: guest_remove_page() should not populate or unshare Tim Deegan
2012-02-23 16:34 ` [PATCH 2 of 6] x86/mm: remove 'p2m_guest' lookup type Tim Deegan
2012-02-23 16:34 ` [PATCH 3 of 6] x86/mm: make 'query type' argument to get_gfn into a set of flags Tim Deegan
2012-02-23 16:45 ` Andres Lagar-Cavilla
2012-02-23 16:34 ` [PATCH 4 of 6] x86/mm: tidy up get_two_gfns() a little Tim Deegan
2012-02-23 16:34 ` [PATCH 5 of 6] [RFC] x86/mm: use wait queues for mem_paging Tim Deegan
2012-02-24 13:45 ` Olaf Hering [this message]
2012-02-27 19:26 ` Tim Deegan
2012-02-27 20:18 ` Olaf Hering
2012-02-23 16:34 ` [PATCH 6 of 6] x86/mm: Don't claim a slot on the paging ring if we might not need it Tim Deegan
2012-02-23 16:48 ` Andres Lagar-Cavilla
2012-02-23 16:43 ` [PATCH 0 of 6] [RFC] Use wait queues for paging, v2 Tim Deegan
2012-02-23 16:49 ` Andres Lagar-Cavilla
2012-02-26 22:14 ` Olaf Hering
2012-02-27 16:51 ` Olaf Hering
[not found] ` <EC947F02-8448-45B0-A240-8BBD41C3F9B7@gridcentric.ca>
2012-02-28 21:11 ` Andres Lagar-Cavilla
2012-02-29 16:18 ` Olaf Hering
2012-02-29 19:56 ` Olaf Hering
2012-03-15 15:27 ` Tim Deegan
2012-03-15 15:37 ` Olaf Hering
2012-03-15 15:40 ` Tim Deegan
2012-03-15 15:56 ` Andres Lagar-Cavilla
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20120224134544.GA13134@aepfle.de \
--to=olaf@aepfle.de \
--cc=adin@gridcentric.ca \
--cc=andres@gridcentric.ca \
--cc=tim@xen.org \
--cc=xen-devel@lists.xensource.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.