[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH] x86/shadow: adjust minimum allocation calculations



On Wed, Feb 06, 2019 at 03:56:49AM -0700, Jan Beulich wrote:
> A previously bad situation has become worse with the early setting of
> ->max_vcpus: The value returned by shadow_min_acceptable_pages() has
> further grown, and hence now holds back even more memory from use for
> the p2m.
> 
> Make sh_min_allocation() account for all p2m memory needed for
> shadow_enable() to succeed during domain creation (at which point the
> domain has no memory at all allocated to it yet, and hence use of
> d->tot_pages is meaningless).
> 
> Also make shadow_min_acceptable_pages() no longer needlessly add 1 to
> the vCPU count.
> 
> Finally make the debugging printk() in shadow_alloc_p2m_page() a little
> more useful by logging some of the relevant domain settings.
> 
> Reported-by: Roger Pau Monné <roger.pau@xxxxxxxxxx>
> Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
> ---
> TBD: The question of course is whether such an "exact" calculation isn't
>      a little risky going forward, the more that the regression here
>      wasn't found by osstest, because domains with sufficiently few
>      vCPU-s weren't affected, due to the 4Mb minimum allocation enforced
>      by shadow_enable()'s call to shadow_set_allocation(). I would,
>      however, question this enforcement of a static minimum as well -
>      shadow_one_bit_enable() doesn't do so, for example.

I wondered the same while doing my fix, whether it was best to account
for the exact amount of pages needed for shadow_enable to succeed, or
whether to add a fixed amount of slack that was greater than the
actual requirements of shadow_enable.

Since you have done the accounting, and I expect shadow_enable to not
change it's memory requirements very often I guess we can go with the
exact amount for now.

> 
> --- a/xen/arch/x86/mm/shadow/common.c
> +++ b/xen/arch/x86/mm/shadow/common.c
> @@ -966,7 +966,8 @@ const u8 sh_type_to_size[] = {
>      1  /* SH_type_oos_snapshot   */
>  };
>  
> -/* Figure out the least acceptable quantity of shadow memory.
> +/*
> + * Figure out the least acceptable quantity of shadow memory.
>   * The minimum memory requirement for always being able to free up a
>   * chunk of memory is very small -- only three max-order chunks per
>   * vcpu to hold the top level shadows and pages with Xen mappings in them.
> @@ -975,11 +976,11 @@ const u8 sh_type_to_size[] = {
>   * instruction, we must be able to map a large number (about thirty) VAs
>   * at the same time, which means that to guarantee progress, we must
>   * allow for more than ninety allocated pages per vcpu.  We round that
> - * up to 128 pages, or half a megabyte per vcpu, and add 1 more vcpu's
> - * worth to make sure we never return zero. */
> + * up to 128 pages, or half a megabyte per vcpu.
> + */
>  static unsigned int shadow_min_acceptable_pages(const struct domain *d)
>  {
> -    return (d->max_vcpus + 1) * 128;
> +    return d->max_vcpus * 128;
>  }
>  
>  /* Dispatcher function: call the per-mode function that will unhook the
> @@ -1322,8 +1323,11 @@ shadow_alloc_p2m_page(struct domain *d)
>          if ( !d->arch.paging.p2m_alloc_failed )
>          {
>              d->arch.paging.p2m_alloc_failed = 1;
> -            dprintk(XENLOG_ERR, "d%i failed to allocate from shadow pool\n",
> -                    d->domain_id);
> +            dprintk(XENLOG_ERR,
> +                    "d%d failed to allocate from shadow pool (tot=%u p2m=%u 
> min=%u)\n",
> +                    d->domain_id, d->arch.paging.shadow.total_pages,
> +                    d->arch.paging.shadow.p2m_pages,
> +                    shadow_min_acceptable_pages(d));
>          }
>          paging_unlock(d);
>          return NULL;
> @@ -1373,9 +1377,15 @@ static unsigned int sh_min_allocation(co
>  {
>      /*
>       * Don't allocate less than the minimum acceptable, plus one page per
> -     * megabyte of RAM (for the p2m table).
> +     * megabyte of RAM (for the p2m table, minimally enough for HVM's setting
> +     * up of slot zero and VMX's setting up of the LAPIC page), plus one for
> +     * HVM's 1-to-1 pagetable.
>       */
> -    return shadow_min_acceptable_pages(d) + (d->tot_pages / 256);
> +    return shadow_min_acceptable_pages(d) +
> +           max(d->tot_pages / 256,
> +               is_hvm_domain(d) ? CONFIG_PAGING_LEVELS + !!cpu_has_vmx * 2
> +                                : 0U) +
> +           is_hvm_domain(d);

Should the call to shadow_set_allocation be changed so it attempts to
allocate sh_min_allocation(d) + d->arch.paging.shadow.p2m_pages?

It seems a little misleading to check whether there's a certain amount
of pages in the pool (sh_min_allocation(d) +
d->arch.paging.shadow.p2m_pages) and then set the allocation to 4M
unconditionally.

Thanks, Roger.

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.