diff mbox

[1/2] x86/altp2m: use __get_gfn_type_access to avoid lock conflicts

Message ID 1470700619-7521-1-git-send-email-tamas.lengyel@zentific.com (mailing list archive)
State New, archived
Headers show

Commit Message

Tamas Lengyel Aug. 8, 2016, 11:56 p.m. UTC
From: Tamas K Lengyel <tamas@tklengyel.com>

Use __get_gfn_type_access instead of get_gfn_type_access when checking
the hostp2m entries during altp2m mem_access setting and gfn remapping
to avoid a lock conflict which can make dom0 freeze.

Signed-off-by: Tamas K Lengyel <tamas.lengyel@zentific.com>
---
Cc: George Dunlap <george.dunlap@eu.citrix.com>
Cc: Jan Beulich <jbeulich@suse.com>
Cc: Andrew Cooper <andrew.cooper3@citrix.com>
Cc: Razvan Cojocaru <rcojocaru@bitdefender.com>
---
 xen/arch/x86/mm/p2m.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

Comments

Razvan Cojocaru Aug. 9, 2016, 6:16 a.m. UTC | #1
On 08/09/16 02:56, Tamas K Lengyel wrote:
> From: Tamas K Lengyel <tamas@tklengyel.com>
> 
> Use __get_gfn_type_access instead of get_gfn_type_access when checking
> the hostp2m entries during altp2m mem_access setting and gfn remapping
> to avoid a lock conflict which can make dom0 freeze.
> 
> Signed-off-by: Tamas K Lengyel <tamas.lengyel@zentific.com>
> ---
> Cc: George Dunlap <george.dunlap@eu.citrix.com>
> Cc: Jan Beulich <jbeulich@suse.com>
> Cc: Andrew Cooper <andrew.cooper3@citrix.com>
> Cc: Razvan Cojocaru <rcojocaru@bitdefender.com>
> ---
>  xen/arch/x86/mm/p2m.c | 8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)

Reviewed-by: Razvan Cojocaru <rcojocaru@bitdefender.com>


Thanks,
Razvan
Jan Beulich Aug. 9, 2016, 7:55 a.m. UTC | #2
>>> On 09.08.16 at 01:56, <tamas.lengyel@zentific.com> wrote:
> Use __get_gfn_type_access instead of get_gfn_type_access when checking
> the hostp2m entries during altp2m mem_access setting and gfn remapping
> to avoid a lock conflict which can make dom0 freeze.

You fail to mention why the resulting code is nevertheless correct:

> --- a/xen/arch/x86/mm/p2m.c
> +++ b/xen/arch/x86/mm/p2m.c
> @@ -1787,8 +1787,8 @@ int p2m_set_altp2m_mem_access(struct domain *d, struct p2m_domain *hp2m,
>      if ( !mfn_valid(mfn) )
>      {
>  
> -        mfn = get_gfn_type_access(hp2m, gfn_l, &t, &old_a,
> -                                  P2M_ALLOC | P2M_UNSHARE, &page_order);
> +        mfn = __get_gfn_type_access(hp2m, gfn_l, &t, &old_a,
> +                                    P2M_ALLOC | P2M_UNSHARE, &page_order, 0);

In this case the respective p2m lock is already being held.

> @@ -2563,8 +2563,8 @@ int p2m_change_altp2m_gfn(struct domain *d, unsigned int idx,
>      /* Check host p2m if no valid entry in alternate */
>      if ( !mfn_valid(mfn) )
>      {
> -        mfn = get_gfn_type_access(hp2m, gfn_x(old_gfn), &t, &a,
> -                                  P2M_ALLOC | P2M_UNSHARE, &page_order);
> +        mfn = __get_gfn_type_access(hp2m, gfn_x(old_gfn), &t, &a,
> +                                    P2M_ALLOC | P2M_UNSHARE, &page_order, 0);

In this case, however, only ap2m's lock is being held, yet you query
hp2m, so it's not immediately obvious whether the change is correct,
and it would seem to me that you'd want to hold the gfn lock until
after the subsequent ap2m->set_entry() (to make sure the two don't
go out of sync). Since taking hp2m's lock can't nest inside any of its
ap2m-s' ones, that'd be a slightly more intrusive adjustment.

Jan
Tamas Lengyel Aug. 9, 2016, 3:44 p.m. UTC | #3
On Tue, Aug 9, 2016 at 1:55 AM, Jan Beulich <JBeulich@suse.com> wrote:
>>>> On 09.08.16 at 01:56, <tamas.lengyel@zentific.com> wrote:
>> Use __get_gfn_type_access instead of get_gfn_type_access when checking
>> the hostp2m entries during altp2m mem_access setting and gfn remapping
>> to avoid a lock conflict which can make dom0 freeze.
>
> You fail to mention why the resulting code is nevertheless correct:
>
>> --- a/xen/arch/x86/mm/p2m.c
>> +++ b/xen/arch/x86/mm/p2m.c
>> @@ -1787,8 +1787,8 @@ int p2m_set_altp2m_mem_access(struct domain *d, struct p2m_domain *hp2m,
>>      if ( !mfn_valid(mfn) )
>>      {
>>
>> -        mfn = get_gfn_type_access(hp2m, gfn_l, &t, &old_a,
>> -                                  P2M_ALLOC | P2M_UNSHARE, &page_order);
>> +        mfn = __get_gfn_type_access(hp2m, gfn_l, &t, &old_a,
>> +                                    P2M_ALLOC | P2M_UNSHARE, &page_order, 0);
>
> In this case the respective p2m lock is already being held.
>
>> @@ -2563,8 +2563,8 @@ int p2m_change_altp2m_gfn(struct domain *d, unsigned int idx,
>>      /* Check host p2m if no valid entry in alternate */
>>      if ( !mfn_valid(mfn) )
>>      {
>> -        mfn = get_gfn_type_access(hp2m, gfn_x(old_gfn), &t, &a,
>> -                                  P2M_ALLOC | P2M_UNSHARE, &page_order);
>> +        mfn = __get_gfn_type_access(hp2m, gfn_x(old_gfn), &t, &a,
>> +                                    P2M_ALLOC | P2M_UNSHARE, &page_order, 0);
>
> In this case, however, only ap2m's lock is being held, yet you query
> hp2m, so it's not immediately obvious whether the change is correct,
> and it would seem to me that you'd want to hold the gfn lock until
> after the subsequent ap2m->set_entry() (to make sure the two don't
> go out of sync). Since taking hp2m's lock can't nest inside any of its
> ap2m-s' ones, that'd be a slightly more intrusive adjustment.
>

True, we should lock the hp2m just before we lock the ap2m here,
similar to the mem_access path, as we can't do gfn_lock after the
altp2m is already locked.

Tamas
diff mbox

Patch

diff --git a/xen/arch/x86/mm/p2m.c b/xen/arch/x86/mm/p2m.c
index 812dbf6..fb1fda4 100644
--- a/xen/arch/x86/mm/p2m.c
+++ b/xen/arch/x86/mm/p2m.c
@@ -1787,8 +1787,8 @@  int p2m_set_altp2m_mem_access(struct domain *d, struct p2m_domain *hp2m,
     if ( !mfn_valid(mfn) )
     {
 
-        mfn = get_gfn_type_access(hp2m, gfn_l, &t, &old_a,
-                                  P2M_ALLOC | P2M_UNSHARE, &page_order);
+        mfn = __get_gfn_type_access(hp2m, gfn_l, &t, &old_a,
+                                    P2M_ALLOC | P2M_UNSHARE, &page_order, 0);
 
         rc = -ESRCH;
         if ( !mfn_valid(mfn) || t != p2m_ram_rw )
@@ -2563,8 +2563,8 @@  int p2m_change_altp2m_gfn(struct domain *d, unsigned int idx,
     /* Check host p2m if no valid entry in alternate */
     if ( !mfn_valid(mfn) )
     {
-        mfn = get_gfn_type_access(hp2m, gfn_x(old_gfn), &t, &a,
-                                  P2M_ALLOC | P2M_UNSHARE, &page_order);
+        mfn = __get_gfn_type_access(hp2m, gfn_x(old_gfn), &t, &a,
+                                    P2M_ALLOC | P2M_UNSHARE, &page_order, 0);
 
         if ( !mfn_valid(mfn) || t != p2m_ram_rw )
             goto out;