From: George Dunlap <george.dunlap@citrix.com>
To: Jan Beulich <JBeulich@suse.com>,
xen-devel <xen-devel@lists.xenproject.org>
Cc: George Dunlap <George.Dunlap@eu.citrix.com>,
Andrew Cooper <andrew.cooper3@citrix.com>,
Keir Fraser <keir@xen.org>
Subject: Re: [PATCH v2] x86/PoD: shorten certain operations on higher order ranges
Date: Tue, 29 Sep 2015 13:58:33 +0100 [thread overview]
Message-ID: <560A8AF9.4000804@citrix.com> (raw)
In-Reply-To: <56096B3902000078000A63BE@prv-mh.provo.novell.com>
On 28/09/15 15:30, Jan Beulich wrote:
> Now that p2m->get_entry() always returns a valid order, utilize this
> to accelerate some of the operations in PoD code. (There are two uses
> of p2m->get_entry() left which don't easily lend themselves to this
> optimization.)
>
> Also adjust a few types as needed and remove stale comments from
> p2m_pod_cache_add() (to avoid duplicating them yet another time).
>
> Signed-off-by: Jan Beulich <jbeulich@suse.com>
> ---
> v2: Add a code comment in p2m_pod_decrease_reservation().
>
> --- a/xen/arch/x86/mm/p2m-pod.c
> +++ b/xen/arch/x86/mm/p2m-pod.c
> @@ -119,20 +119,23 @@ p2m_pod_cache_add(struct p2m_domain *p2m
>
> unlock_page_alloc(p2m);
>
> - /* Then add the first one to the appropriate populate-on-demand list */
> - switch(order)
> + /* Then add to the appropriate populate-on-demand list. */
> + switch ( order )
> {
> + case PAGE_ORDER_1G:
> + for ( i = 0; i < (1UL << PAGE_ORDER_1G); i += 1UL << PAGE_ORDER_2M )
> + page_list_add_tail(page + i, &p2m->pod.super);
> + break;
> case PAGE_ORDER_2M:
> - page_list_add_tail(page, &p2m->pod.super); /* lock: page_alloc */
> - p2m->pod.count += 1 << order;
> + page_list_add_tail(page, &p2m->pod.super);
> break;
> case PAGE_ORDER_4K:
> - page_list_add_tail(page, &p2m->pod.single); /* lock: page_alloc */
> - p2m->pod.count += 1;
> + page_list_add_tail(page, &p2m->pod.single);
> break;
> default:
> BUG();
> }
> + p2m->pod.count += 1 << order;
>
> return 0;
> }
> @@ -502,11 +505,10 @@ p2m_pod_decrease_reservation(struct doma
> unsigned int order)
> {
> int ret=0;
> - int i;
> + unsigned long i, n;
> struct p2m_domain *p2m = p2m_get_hostp2m(d);
> -
> - int steal_for_cache;
> - int pod, nonpod, ram;
> + bool_t steal_for_cache;
> + long pod, nonpod, ram;
>
> gfn_lock(p2m, gpfn, order);
> pod_lock(p2m);
> @@ -525,21 +527,21 @@ recount:
> /* Figure out if we need to steal some freed memory for our cache */
> steal_for_cache = ( p2m->pod.entry_count > p2m->pod.count );
>
> - /* FIXME: Add contiguous; query for PSE entries? */
> - for ( i=0; i<(1<<order); i++)
> + for ( i = 0; i < (1UL << order); i += n )
> {
> p2m_access_t a;
> p2m_type_t t;
> + unsigned int cur_order;
>
> - (void)p2m->get_entry(p2m, gpfn + i, &t, &a, 0, NULL, NULL);
> -
> + p2m->get_entry(p2m, gpfn + i, &t, &a, 0, &cur_order, NULL);
> + n = 1UL << min(order, cur_order);
> if ( t == p2m_populate_on_demand )
> - pod++;
> + pod += n;
> else
> {
> - nonpod++;
> + nonpod += n;
> if ( p2m_is_ram(t) )
> - ram++;
> + ram += n;
> }
> }
>
> @@ -574,41 +576,53 @@ recount:
> * + There are PoD entries to handle, or
> * + There is ram left, and we want to steal it
> */
> - for ( i=0;
> - i<(1<<order) && (pod>0 || (steal_for_cache && ram > 0));
> - i++)
> + for ( i = 0;
> + i < (1UL << order) && (pod > 0 || (steal_for_cache && ram > 0));
> + i += n )
> {
> mfn_t mfn;
> p2m_type_t t;
> p2m_access_t a;
> + unsigned int cur_order;
>
> - mfn = p2m->get_entry(p2m, gpfn + i, &t, &a, 0, NULL, NULL);
> + mfn = p2m->get_entry(p2m, gpfn + i, &t, &a, 0, &cur_order, NULL);
> + if ( order < cur_order )
> + cur_order = order;
> + n = 1UL << cur_order;
> if ( t == p2m_populate_on_demand )
> {
> - p2m_set_entry(p2m, gpfn + i, _mfn(INVALID_MFN), 0, p2m_invalid,
> - p2m->default_access);
> - p2m->pod.entry_count--;
> + p2m_set_entry(p2m, gpfn + i, _mfn(INVALID_MFN), cur_order,
> + p2m_invalid, p2m->default_access);
> + p2m->pod.entry_count -= n;
> BUG_ON(p2m->pod.entry_count < 0);
> - pod--;
> + pod -= n;
> }
> else if ( steal_for_cache && p2m_is_ram(t) )
> {
> + /*
> + * If we need less than 1 << cur_order, we may end up stealing
> + * more memory here than we actually need. This will be rectified
> + * below, however; and stealing too much and then freeing what we
> + * need may allow us to free smaller pages from the cache, and
> + * avoid breaking up superpages.
> + */
> struct page_info *page;
> + unsigned int j;
>
> ASSERT(mfn_valid(mfn));
>
> page = mfn_to_page(mfn);
>
> - p2m_set_entry(p2m, gpfn + i, _mfn(INVALID_MFN), 0, p2m_invalid,
> - p2m->default_access);
> - set_gpfn_from_mfn(mfn_x(mfn), INVALID_M2P_ENTRY);
> -
> - p2m_pod_cache_add(p2m, page, 0);
> + p2m_set_entry(p2m, gpfn + i, _mfn(INVALID_MFN), cur_order,
> + p2m_invalid, p2m->default_access);
> + for ( j = 0; j < n; ++j )
> + set_gpfn_from_mfn(mfn_x(mfn), INVALID_M2P_ENTRY);
> + p2m_pod_cache_add(p2m, page, cur_order);
>
> steal_for_cache = ( p2m->pod.entry_count > p2m->pod.count );
>
> - nonpod--;
> - ram--;
> + nonpod -= n;
> + ram -= n;
> }
> }
>
> @@ -649,7 +656,8 @@ p2m_pod_zero_check_superpage(struct p2m_
> p2m_type_t type, type0 = 0;
> unsigned long * map = NULL;
> int ret=0, reset = 0;
> - int i, j;
> + unsigned long i, n;
> + unsigned int j;
> int max_ref = 1;
> struct domain *d = p2m->domain;
>
> @@ -668,10 +676,13 @@ p2m_pod_zero_check_superpage(struct p2m_
>
> /* Look up the mfns, checking to make sure they're the same mfn
> * and aligned, and mapping them. */
> - for ( i=0; i<SUPERPAGE_PAGES; i++ )
> + for ( i = 0; i < SUPERPAGE_PAGES; i += n )
> {
> p2m_access_t a;
> - mfn = p2m->get_entry(p2m, gfn + i, &type, &a, 0, NULL, NULL);
> + unsigned int cur_order;
> +
> + mfn = p2m->get_entry(p2m, gfn + i, &type, &a, 0, &cur_order, NULL);
> + n = 1UL << min(cur_order, SUPERPAGE_ORDER + 0U);
Again just thinking out loud a bit here -- I wonder how often it will be
the case that we manage to find a contiguous superpage that is not
actually set as a superpage in the p2m. The only reason this loop is
here in the first place is because when I wrote it there was as yet no
way to get the order of a p2m entry. I'm now thinking it might be
better to just read the entry and bail if the order is SUPERPAGE_ORDER.
But in any case, this code is correct and doesn't change the end-to-end
functionality AFAICT, so:
Reviewed-by: George Dunlap <george.dunlap@citrix.com>
next prev parent reply other threads:[~2015-09-29 12:58 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-09-28 14:30 [PATCH v2] x86/PoD: shorten certain operations on higher order ranges Jan Beulich
2015-09-29 12:20 ` Andrew Cooper
2015-09-29 12:57 ` Jan Beulich
2015-09-29 13:03 ` Andrew Cooper
2015-09-29 12:58 ` George Dunlap [this message]
2015-09-29 16:45 ` George Dunlap
2015-09-30 12:12 ` Jan Beulich
2015-09-30 14:23 ` George Dunlap
2015-09-30 15:40 ` Jan Beulich
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=560A8AF9.4000804@citrix.com \
--to=george.dunlap@citrix.com \
--cc=George.Dunlap@eu.citrix.com \
--cc=JBeulich@suse.com \
--cc=andrew.cooper3@citrix.com \
--cc=keir@xen.org \
--cc=xen-devel@lists.xenproject.org \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).