All of lore.kernel.org
 help / color / mirror / Atom feed
From: Razvan Cojocaru <rcojocaru@bitdefender.com>
To: George Dunlap <george.dunlap@citrix.com>, xen-devel@lists.xenproject.org
Cc: George Dunlap <george.dunlap@eu.citrix.com>,
	Andrew Cooper <andrew.cooper3@citrix.com>,
	Wei Liu <wei.liu2@citrix.com>, Jan Beulich <jbeulich@suse.com>
Subject: Re: [PATCH V5 2/3] x86/mm: allocate logdirty_ranges for altp2ms
Date: Tue, 13 Nov 2018 20:43:10 +0200	[thread overview]
Message-ID: <7b71af9a-29ca-6f7e-13a3-27d02e0392f6@bitdefender.com> (raw)
In-Reply-To: <2c1b78c1-e526-4481-f36d-791e11bdd06e@citrix.com>

On 11/13/18 7:57 PM, George Dunlap wrote:
> On 11/11/18 2:07 PM, Razvan Cojocaru wrote:
>> This patch is a pre-requisite for the one fixing VGA logdirty
>> freezes when using altp2m. It only concerns itself with the
>> ranges allocation / deallocation / initialization part. While
>> touching the code, I've switched global_logdirty from bool_t
>> to bool.
>>
>> Signed-off-by: Razvan Cojocaru <rcojocaru@bitdefender.com>
> 
> I've convinced myself that this patch is probably correct now, and as a
> result I've had a chance to look a bit at the resulting code.  Which
> means, unfortunately, that I'm going to be a bit annoying and ask more
> questions that I didn't ask last time.

Thanks for the review, and please ask away. :)

>> ---
>> CC: George Dunlap <george.dunlap@eu.citrix.com>
>> CC: Jan Beulich <jbeulich@suse.com>
>> CC: Andrew Cooper <andrew.cooper3@citrix.com>
>> CC: Wei Liu <wei.liu2@citrix.com>
>>
>> ---
>> Changes since V4:
>>  - Always call p2m_free_logdirty() in p2m_free_one() (previously
>>    the call was gated on hap_enabled(p2m->domain) && cpu_has_vmx).
>> ---
>>  xen/arch/x86/mm/p2m.c     | 74 ++++++++++++++++++++++++++++++++++++-----------
>>  xen/include/asm-x86/p2m.h |  2 +-
>>  2 files changed, 58 insertions(+), 18 deletions(-)
>>
>> diff --git a/xen/arch/x86/mm/p2m.c b/xen/arch/x86/mm/p2m.c
>> index 42b9ef4..69536c1 100644
>> --- a/xen/arch/x86/mm/p2m.c
>> +++ b/xen/arch/x86/mm/p2m.c
>> @@ -59,6 +59,28 @@ static void p2m_nestedp2m_init(struct p2m_domain *p2m)
>>  #endif
>>  }
>>  
>> +static int p2m_init_logdirty(struct p2m_domain *p2m)
>> +{
>> +    if ( p2m->logdirty_ranges )
>> +        return 0;
>> +
>> +    p2m->logdirty_ranges = rangeset_new(p2m->domain, "log-dirty",
>> +                                        RANGESETF_prettyprint_hex);
>> +    if ( !p2m->logdirty_ranges )
>> +        return -ENOMEM;
>> +
>> +    return 0;
>> +}
>> +
>> +static void p2m_free_logdirty(struct p2m_domain *p2m)
>> +{
>> +    if ( !p2m->logdirty_ranges )
>> +        return;
>> +
>> +    rangeset_destroy(p2m->logdirty_ranges);
>> +    p2m->logdirty_ranges = NULL;
>> +}
>> +
>>  /* Init the datastructures for later use by the p2m code */
>>  static int p2m_initialise(struct domain *d, struct p2m_domain *p2m)
>>  {
>> @@ -107,6 +129,7 @@ free_p2m:
>>  
>>  static void p2m_free_one(struct p2m_domain *p2m)
>>  {
>> +    p2m_free_logdirty(p2m);
>>      if ( hap_enabled(p2m->domain) && cpu_has_vmx )
>>          ept_p2m_uninit(p2m);
>>      free_cpumask_var(p2m->dirty_cpumask);
>> @@ -116,19 +139,19 @@ static void p2m_free_one(struct p2m_domain *p2m)
>>  static int p2m_init_hostp2m(struct domain *d)
>>  {
>>      struct p2m_domain *p2m = p2m_init_one(d);
>> +    int rc;
>>  
>> -    if ( p2m )
>> -    {
>> -        p2m->logdirty_ranges = rangeset_new(d, "log-dirty",
>> -                                            RANGESETF_prettyprint_hex);
>> -        if ( p2m->logdirty_ranges )
>> -        {
>> -            d->arch.p2m = p2m;
>> -            return 0;
>> -        }
>> +    if ( !p2m )
>> +        return -ENOMEM;
>> +
>> +    rc = p2m_init_logdirty(p2m);
>> +
>> +    if ( !rc )
>> +        d->arch.p2m = p2m;
>> +    else
>>          p2m_free_one(p2m);
>> -    }
>> -    return -ENOMEM;
>> +
>> +    return rc;
>>  }
>>  
>>  static void p2m_teardown_hostp2m(struct domain *d)
>> @@ -138,7 +161,6 @@ static void p2m_teardown_hostp2m(struct domain *d)
>>  
>>      if ( p2m )
>>      {
>> -        rangeset_destroy(p2m->logdirty_ranges);
>>          p2m_free_one(p2m);
>>          d->arch.p2m = NULL;
>>      }
>> @@ -2279,6 +2301,18 @@ void p2m_flush_altp2m(struct domain *d)
>>      altp2m_list_unlock(d);
>>  }
> 
> I think everything above here could usefully be in its own patch; it
> would make it easier to verify that there were no functional changes in
> the refactoring.

Right, I'll split this patch then.

>> +static int p2m_init_altp2m_logdirty(struct p2m_domain *p2m)
>> +{
>> +    struct p2m_domain *hostp2m = p2m_get_hostp2m(p2m->domain);
>> +    int rc = p2m_init_logdirty(p2m);
>> +
>> +    if ( rc )
>> +        return rc;
>> +
>> +    /* The following is really just a rangeset copy. */
>> +    return rangeset_merge(p2m->logdirty_ranges, hostp2m->logdirty_ranges);
>> +}
>> +
>>  int p2m_init_altp2m_by_id(struct domain *d, unsigned int idx)
>>  {
>>      int rc = -EINVAL;
>> @@ -2290,8 +2324,9 @@ int p2m_init_altp2m_by_id(struct domain *d, unsigned int idx)
>>  
>>      if ( d->arch.altp2m_eptp[idx] == mfn_x(INVALID_MFN) )
>>      {
>> -        p2m_init_altp2m_ept(d, idx);
>> -        rc = 0;
>> +        rc = p2m_init_altp2m_logdirty(d->arch.altp2m_p2m[idx]);
>> +        if ( !rc )
>> +            p2m_init_altp2m_ept(d, idx);
>>      }
>>  
>>      altp2m_list_unlock(d);
>> @@ -2310,9 +2345,13 @@ int p2m_init_next_altp2m(struct domain *d, uint16_t *idx)
>>          if ( d->arch.altp2m_eptp[i] != mfn_x(INVALID_MFN) )
>>              continue;
>>  
>> -        p2m_init_altp2m_ept(d, i);
>> -        *idx = i;
>> -        rc = 0;
>> +        rc = p2m_init_altp2m_logdirty(d->arch.altp2m_p2m[i]);
>> +
>> +        if ( !rc )
>> +        {
>> +            p2m_init_altp2m_ept(d, i);
>> +            *idx = i;
>> +        }
> 
> It looks like there's a 1-1 correspondence between
> p2m_init_altp2m_logdirty() succeeding and calling p2m_inti_altp2m_ept().
>  Would it make sense to combine them into the same function, maybe named
> "p2m_activate_altp2m()" or something (to distinguish it from
> p2m_init_altp2m())?

Of course, that'll cut back on some redundancy. Always a good thing.

>> @@ -2341,6 +2380,7 @@ int p2m_destroy_altp2m_by_id(struct domain *d, unsigned int idx)
>>          {
>>              p2m_flush_table(d->arch.altp2m_p2m[idx]);
>>              /* Uninit and reinit ept to force TLB shootdown */
>> +            p2m_free_logdirty(d->arch.altp2m_p2m[idx]);
>>              ept_p2m_uninit(d->arch.altp2m_p2m[idx]);
>>              ept_p2m_init(d->arch.altp2m_p2m[idx]);
>>              d->arch.altp2m_eptp[idx] = mfn_x(INVALID_MFN);
> 
> (In case I forget: Also, this is called without holding the appropriate
> p2m lock. )

Could you please provide more details? I have assumed that at the point
of calling a function called p2m_destroy_altp2m_by_id() it should be
safe to tear the altp2m down without further precaution.

I think you're saying that I should p2m_lock(d->arch.altp2m_p2m[idx])
just for the duration of the p2m_free_logdirty() call?

> I'm a bit suspicious of long strings of these sorts of functions in the
> middle of another function.  It turns out that there are three copies of
> this sequence of function calls (p2m_flush_table -> ept_p2m_uninit ->
> ept_p2m_init):
> 
> * Here (p2m_destroy_altp2m_id), when the user asks for the alt2m index
> to be destroyed
> 
> * In p2m_flush_altp2m(), which is called when altp2m is disabled for a
> domain
> 
> * In p2m_reset_altp2m(), which is called when an entry in the hostp2m is
> set to INVALID_MFN.
> 
> Presumably in p2m_reset_altp2m() we don't want to call
> p2m_free_logdirty(), as the altp2m is still active and we want to keep
> the logdirty ranges around.  But in p2m_flush_altp2m(), I'm pretty sure
> we do want to discard them: when altp2m is enabled again,
> p2m_init_logdirty() will return early, leaving the old rangesets in
> place; if the hostp2m rangesets have changed between the time altp2m was
> disabled and enabled again, the rangeset_merge() may have incorrect results.

I'll call p2m_free_logdirty() in p2m_flush_altp2m() as well.

> At the moment we essentially have two "init" states:
> * After domain creation; altp2m structures allocated, but no rangesets, & c
> * After being enabled for the first time: rangesets mirroring hostp2m,
> p2m_init_altp2m_ept() initialization done
> 
> Is there any particular reason we allocate the p2m structures on domain
> creation, but not logdirty range structures?  It seems like allocating
> altp2m structures on-demand, rather than at domain creation time, might
> make a lot of the reasoning here simpler.

I assume that this question is not addressed to me, since I'm not able
to answer it - I can only assume that having less heap used has been
preferred.


Thanks,
Razvan

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

  reply	other threads:[~2018-11-13 18:43 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-11-11 14:07 [PATCH V5 0/3] Fix VGA logdirty related display freezes with altp2m Razvan Cojocaru
2018-11-11 14:07 ` [PATCH V5 1/3] x86/altp2m: propagate ept.ad changes to all active altp2ms Razvan Cojocaru
2018-11-14  5:44   ` Tian, Kevin
2018-11-14  7:14     ` Razvan Cojocaru
2018-11-11 14:07 ` [PATCH V5 2/3] x86/mm: allocate logdirty_ranges for altp2ms Razvan Cojocaru
2018-11-13 17:57   ` George Dunlap
2018-11-13 18:43     ` Razvan Cojocaru [this message]
2018-11-13 18:57       ` Razvan Cojocaru
2018-11-14  8:11         ` Jan Beulich
2018-11-14 11:58       ` George Dunlap
2018-11-14 12:50         ` Razvan Cojocaru
2018-11-14 14:00           ` Jan Beulich
2018-11-14 14:05             ` Razvan Cojocaru
2018-11-14 15:05               ` Jan Beulich
2018-11-11 14:07 ` [PATCH V5 3/3] x86/altp2m: fix display frozen when switching to a new view early Razvan Cojocaru
2018-11-14  5:55   ` Tian, Kevin
2018-11-14  7:33     ` Razvan Cojocaru
2018-11-14  7:35       ` Tian, Kevin
2018-11-14  7:43         ` Razvan Cojocaru

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=7b71af9a-29ca-6f7e-13a3-27d02e0392f6@bitdefender.com \
    --to=rcojocaru@bitdefender.com \
    --cc=andrew.cooper3@citrix.com \
    --cc=george.dunlap@citrix.com \
    --cc=george.dunlap@eu.citrix.com \
    --cc=jbeulich@suse.com \
    --cc=wei.liu2@citrix.com \
    --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 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.