WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

Re: [Xen-devel] [PATCH 2 of 3] Make p2m lookups fully synchronized wrt m

To: "Tim Deegan" <tim@xxxxxxx>
Subject: Re: [Xen-devel] [PATCH 2 of 3] Make p2m lookups fully synchronized wrt modifications
From: "Andres Lagar-Cavilla" <andres@xxxxxxxxxxxxxxxx>
Date: Mon, 14 Nov 2011 10:03:08 -0800
Cc: olaf@xxxxxxxxx, xen-devel@xxxxxxxxxxxxxxxxxxx, george.dunlap@xxxxxxxxxxxxx, andres@xxxxxxxxxxxxxx, keir.xen@xxxxxxxxx, adin@xxxxxxxxxxxxxx
Delivery-date: Mon, 14 Nov 2011 11:47:54 -0800
Dkim-signature: v=1; a=rsa-sha1; c=relaxed; d=lagarcavilla.org; h= message-id:in-reply-to:references:date:subject:from:to:cc :reply-to:mime-version:content-type:content-transfer-encoding; s=lagarcavilla.org; bh=efjUAuAhKRhkous4qB6vPdUPzps=; b=M4kxeECm U7BReDre/C8f07eJ141DjjVHaMXPPDmv/uycGo455xVJEa1YZeJMJWiG+d5/pjEw iWghZA+7DhupNjq2cWZJUfsWu8kwpCBKeEUeP8zg5A4MHu/pdqowuAVlfVpEUCR4 uHEq4GcnGYtD8aNJ2vAwBQFCRcT+Kr6oAWY=
Domainkey-signature: a=rsa-sha1; c=nofws; d=lagarcavilla.org; h=message-id :in-reply-to:references:date:subject:from:to:cc:reply-to :mime-version:content-type:content-transfer-encoding; q=dns; s= lagarcavilla.org; b=GzvkFcjT2eGywbnwcABFvic/lhNQxHV3cTtGGdCR+xlH oocx9q4r0o3RvoxJ6OWZlZsYHaT5e5ry2DgpXorsT5uGHqivh5lFZ+TDj3UwxMmc Y8XI65/m8LYKsCF6jhHbXfQcD1S5r0nZoGKxRj+dqteKwERCusvUb21jlkkNelw=
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
In-reply-to: <20111110125342.GG62117@xxxxxxxxxxxxxxxxxxxxx>
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
References: <patchbomb.1320788543@xxxxxxxxxxxxxxxxxxx> <6203a0549d8a1a21753b.1320788545@xxxxxxxxxxxxxxxxxxx> <20111110125342.GG62117@xxxxxxxxxxxxxxxxxxxxx>
Reply-to: andres@xxxxxxxxxxxxxxxx
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: SquirrelMail/1.4.21
Hi there,
> At 16:42 -0500 on 08 Nov (1320770545), Andres Lagar-Cavilla wrote:
>>  xen/arch/x86/mm/mm-locks.h |  13 +++++++------
>>  xen/arch/x86/mm/p2m.c      |  18 +++++++++++++++++-
>>  xen/include/asm-x86/p2m.h  |  39
>> ++++++++++++++++++++++++---------------
>>  3 files changed, 48 insertions(+), 22 deletions(-)
>>
>>
>> We achieve this by locking/unlocking the global p2m_lock in get/put_gfn.
>> This brings about a few consequences for the p2m_lock:
>>
>>  - not ordered anymore in mm-locks.h: unshare does get_gfn -> shr_lock,
>>    there are code paths that do paging_lock -> get_gfn. All of these
>>    would cause mm-locks.h to panic.
>
> In that case there's a potential deadlock in the sharing code, and
> turning off the safety catches is not an acceptable response to that. :)
>
> ISTR you had a plan to get rid of the shr_lock entirely, or am
> I misremembering?
Sharing is actually fine, I can reorder those safely until I get rid of
the shr_lock. Except for sharing audits, which basically lock the whole
hypervisor, and _no one is using at all_.

I have a more fundamental problem with the paging lock. sh_update_cr3 can
be called from a variety of situations. It will walk the four top level
PAE mappings, acquiring the p2m entry for each, with the paging lock held.
This is an inversion & deadlock, if I try to synchronize p2m lookups with
the p2m lock.

Any suggestions here? Other than disabling ordering of the p2m lock?

Thanks
Andres

>
> Tim.
>
>>  - the lock is always taken recursively, as there are many paths that
>>    do get_gfn -> p2m_lock
>>
>> Signed-off-by: Andres Lagar-Cavilla <andres@xxxxxxxxxxxxxxxx>
>>
>> diff -r a0c55cc5d696 -r 6203a0549d8a xen/arch/x86/mm/mm-locks.h
>> --- a/xen/arch/x86/mm/mm-locks.h
>> +++ b/xen/arch/x86/mm/mm-locks.h
>> @@ -165,14 +165,15 @@ declare_mm_lock(nestedp2m)
>>
>>  /* P2M lock (per-p2m-table)
>>   *
>> - * This protects all updates to the p2m table.  Updates are expected to
>> - * be safe against concurrent reads, which do *not* require the lock.
>> */
>> + * This protects all queries and updates to the p2m table. Because
>> queries
>> + * can happen interleaved with other locks in here, we do not enforce
>> + * ordering, and make all locking recursive. */
>>
>> -declare_mm_lock(p2m)
>> -#define p2m_lock(p)           mm_lock(p2m, &(p)->lock)
>> -#define p2m_lock_recursive(p) mm_lock_recursive(p2m, &(p)->lock)
>> -#define p2m_unlock(p)         mm_unlock(&(p)->lock)
>> +#define p2m_lock(p)           spin_lock_recursive(&(p)->lock.lock)
>> +#define p2m_lock_recursive(p) spin_lock_recursive(&(p)->lock.lock)
>> +#define p2m_unlock(p)         spin_unlock_recursive(&(p)->lock.lock)
>>  #define p2m_locked_by_me(p)   mm_locked_by_me(&(p)->lock)
>> +#define gfn_locked_by_me(p,g) mm_locked_by_me(&(p)->lock)
>>
>>  /* Page alloc lock (per-domain)
>>   *
>> diff -r a0c55cc5d696 -r 6203a0549d8a xen/arch/x86/mm/p2m.c
>> --- a/xen/arch/x86/mm/p2m.c
>> +++ b/xen/arch/x86/mm/p2m.c
>> @@ -158,6 +158,9 @@ mfn_t gfn_to_mfn_type_p2m(struct p2m_dom
>>          return _mfn(gfn);
>>      }
>>
>> +    /* Grab the lock here, don't release until put_gfn */
>> +    p2m_lock(p2m);
>> +
>>      mfn = p2m->get_entry(p2m, gfn, t, a, q, page_order);
>>
>>  #ifdef __x86_64__
>> @@ -182,6 +185,19 @@ mfn_t gfn_to_mfn_type_p2m(struct p2m_dom
>>      return mfn;
>>  }
>>
>> +void put_gfn(struct domain *d, unsigned long gfn)
>> +{
>> +    struct p2m_domain *p2m = p2m_get_hostp2m(d);
>> +
>> +    if ( !p2m || !paging_mode_translate(d) )
>> +        /* Nothing to do in this case */
>> +        return;
>> +
>> +    ASSERT(p2m_locked_by_me(p2m));
>> +
>> +    p2m_unlock(p2m);
>> +}
>> +
>>  int set_p2m_entry(struct p2m_domain *p2m, unsigned long gfn, mfn_t mfn,
>>                    unsigned int page_order, p2m_type_t p2mt,
>> p2m_access_t p2ma)
>>  {
>> @@ -190,7 +206,7 @@ int set_p2m_entry(struct p2m_domain *p2m
>>      unsigned int order;
>>      int rc = 1;
>>
>> -    ASSERT(p2m_locked_by_me(p2m));
>> +    ASSERT(gfn_locked_by_me(p2m, gfn));
>>
>>      while ( todo )
>>      {
>> diff -r a0c55cc5d696 -r 6203a0549d8a xen/include/asm-x86/p2m.h
>> --- a/xen/include/asm-x86/p2m.h
>> +++ b/xen/include/asm-x86/p2m.h
>> @@ -305,9 +305,10 @@ struct p2m_domain *p2m_get_p2m(struct vc
>>
>>  #define p2m_get_pagetable(p2m)  ((p2m)->phys_table)
>>
>> -/**** p2m query accessors. After calling any of the variants below, you
>> - * need to call put_gfn(domain, gfn). If you don't, you'll lock the
>> - * hypervisor. ****/
>> +/**** p2m query accessors. They lock p2m_lock, and thus serialize
>> + * lookups wrt modifications. They _do not_ release the lock on exit.
>> + * After calling any of the variants below, caller needs to use
>> + * put_gfn. ****/
>>
>>  /* Read a particular P2M table, mapping pages as we go.  Most callers
>>   * should _not_ call this directly; use the other get_gfn* functions
>> @@ -349,19 +350,27 @@ static inline unsigned long get_gfn_unty
>>      return INVALID_MFN;
>>  }
>>
>> -/* This is a noop for now. */
>> -static inline void put_gfn(struct domain *d, unsigned long gfn)
>> -{
>> -}
>> +/* Will release the p2m_lock and put the page behind this mapping. */
>> +void put_gfn(struct domain *d, unsigned long gfn);
>>
>> -/* These are identical for now. The intent is to have the caller not
>> worry
>> - * about put_gfn. To only be used in printk's, crash situations, or to
>> - * peek at a type. You're not holding the p2m entry exclsively after
>> calling
>> - * this. */
>> -#define get_gfn_unlocked(d, g, t)         get_gfn_type((d), (g), (t),
>> p2m_alloc)
>> -#define get_gfn_query_unlocked(d, g, t)   get_gfn_type((d), (g), (t),
>> p2m_query)
>> -#define get_gfn_guest_unlocked(d, g, t)   get_gfn_type((d), (g), (t),
>> p2m_guest)
>> -#define get_gfn_unshare_unlocked(d, g, t) get_gfn_type((d), (g), (t),
>> p2m_unshare)
>> +/* The intent is to have the caller not worry about put_gfn. They apply
>> to
>> + * very specific situations: debug printk's, dumps during a domain
>> crash,
>> + * or to peek at a p2m entry/type. Caller is not holding the p2m entry
>> + * exclusively after calling this. */
>> +#define build_unlocked_accessor(name)
>> \
>> +    static inline mfn_t get_gfn ## name ## _unlocked(struct domain *d,
>> \
>> +                                                unsigned long gfn,
>> \
>> +                                                p2m_type_t *t)
>> \
>> +    {
>> \
>> +        mfn_t mfn = get_gfn ##name (d, gfn, t);
>> \
>> +        put_gfn(d, gfn);
>> \
>> +        return mfn;
>> \
>> +    }
>> +
>> +build_unlocked_accessor()
>> +build_unlocked_accessor(_query)
>> +build_unlocked_accessor(_guest)
>> +build_unlocked_accessor(_unshare)
>>
>>  /* General conversion function from mfn to gfn */
>>  static inline unsigned long mfn_to_gfn(struct domain *d, mfn_t mfn)
>>
>> _______________________________________________
>> Xen-devel mailing list
>> Xen-devel@xxxxxxxxxxxxxxxxxxx
>> http://lists.xensource.com/xen-devel
>



_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel