diff mbox series

[v6,1/9] x86/p2m: Allow p2m_get_page_from_gfn to return shared entries

Message ID 8f7138e4d6a11975ef85458c000a337a60a4e13e.1580148227.git.tamas.lengyel@intel.com (mailing list archive)
State New, archived
Headers show
Series [v6,1/9] x86/p2m: Allow p2m_get_page_from_gfn to return shared entries | expand

Commit Message

Tamas K Lengyel Jan. 27, 2020, 6:06 p.m. UTC
The owner domain of shared pages is dom_cow, use that for get_page
otherwise the function fails to return the correct page. Fixing the
error now and simplifying the checks since we can't have any shared
entries with dom_cow being NULL.

Signed-off-by: Tamas K Lengyel <tamas.lengyel@intel.com>
---
v6: use simplified check for dom_cow in both slow and fast path
---
 xen/arch/x86/mm/p2m.c | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

Comments

Jan Beulich Jan. 28, 2020, 4:37 p.m. UTC | #1
On 27.01.2020 19:06, Tamas K Lengyel wrote:
> --- a/xen/arch/x86/mm/p2m.c
> +++ b/xen/arch/x86/mm/p2m.c
> @@ -574,11 +574,12 @@ struct page_info *p2m_get_page_from_gfn(
>                  if ( fdom == NULL )
>                      page = NULL;
>              }
> -            else if ( !get_page(page, p2m->domain) &&
> -                      /* Page could be shared */
> -                      (!dom_cow || !p2m_is_shared(*t) ||
> -                       !get_page(page, dom_cow)) )
> -                page = NULL;
> +            else
> +            {
> +                struct domain *d = !p2m_is_shared(*t) ? p2m->domain : dom_cow;
> +                if ( !get_page(page, d) )
> +                    page = NULL;
> +            }
>          }
>          p2m_read_unlock(p2m);
>  
> @@ -594,8 +595,9 @@ struct page_info *p2m_get_page_from_gfn(
>      mfn = get_gfn_type_access(p2m, gfn_x(gfn), t, a, q, NULL);
>      if ( p2m_is_ram(*t) && mfn_valid(mfn) )
>      {
> +        struct domain *d = !p2m_is_shared(*t) ? p2m->domain : dom_cow;
>          page = mfn_to_page(mfn);
> -        if ( !get_page(page, p2m->domain) )
> +        if ( !get_page(page, d) )
>              page = NULL;
>      }
>      put_gfn(p2m->domain, gfn_x(gfn));

Personally I would have preferred to go without new local variables
here, but I'm not the maintainer of this code. However, at the very
least blank lines would need inserting between declaration and
statements. With at least this done (which could be done while
committing)

Reviewed-by: Jan Beulich <jbeulich@suse.com>

As an aside, I don't think the title accurately describes the
change, since there's just one out of two cases which shared
entries weren't taken care of. Similarly the description doesn't
reflect this at all.

Jan
Tamas K Lengyel Jan. 28, 2020, 4:42 p.m. UTC | #2
On Tue, Jan 28, 2020 at 9:38 AM Jan Beulich <jbeulich@suse.com> wrote:
>
> On 27.01.2020 19:06, Tamas K Lengyel wrote:
> > --- a/xen/arch/x86/mm/p2m.c
> > +++ b/xen/arch/x86/mm/p2m.c
> > @@ -574,11 +574,12 @@ struct page_info *p2m_get_page_from_gfn(
> >                  if ( fdom == NULL )
> >                      page = NULL;
> >              }
> > -            else if ( !get_page(page, p2m->domain) &&
> > -                      /* Page could be shared */
> > -                      (!dom_cow || !p2m_is_shared(*t) ||
> > -                       !get_page(page, dom_cow)) )
> > -                page = NULL;
> > +            else
> > +            {
> > +                struct domain *d = !p2m_is_shared(*t) ? p2m->domain : dom_cow;
> > +                if ( !get_page(page, d) )
> > +                    page = NULL;
> > +            }
> >          }
> >          p2m_read_unlock(p2m);
> >
> > @@ -594,8 +595,9 @@ struct page_info *p2m_get_page_from_gfn(
> >      mfn = get_gfn_type_access(p2m, gfn_x(gfn), t, a, q, NULL);
> >      if ( p2m_is_ram(*t) && mfn_valid(mfn) )
> >      {
> > +        struct domain *d = !p2m_is_shared(*t) ? p2m->domain : dom_cow;
> >          page = mfn_to_page(mfn);
> > -        if ( !get_page(page, p2m->domain) )
> > +        if ( !get_page(page, d) )
> >              page = NULL;
> >      }
> >      put_gfn(p2m->domain, gfn_x(gfn));
>
> Personally I would have preferred to go without new local variables
> here, but I'm not the maintainer of this code. However, at the very
> least blank lines would need inserting between declaration and
> statements. With at least this done (which could be done while
> committing)
>
> Reviewed-by: Jan Beulich <jbeulich@suse.com>
>
> As an aside, I don't think the title accurately describes the
> change, since there's just one out of two cases which shared
> entries weren't taken care of. Similarly the description doesn't
> reflect this at all.

Well, for our use-case it is broken right now. So just because it's
not broken in another doesn't make the title/description incorrect.

Tamas
diff mbox series

Patch

diff --git a/xen/arch/x86/mm/p2m.c b/xen/arch/x86/mm/p2m.c
index 49cc138362..f54360b43d 100644
--- a/xen/arch/x86/mm/p2m.c
+++ b/xen/arch/x86/mm/p2m.c
@@ -574,11 +574,12 @@  struct page_info *p2m_get_page_from_gfn(
                 if ( fdom == NULL )
                     page = NULL;
             }
-            else if ( !get_page(page, p2m->domain) &&
-                      /* Page could be shared */
-                      (!dom_cow || !p2m_is_shared(*t) ||
-                       !get_page(page, dom_cow)) )
-                page = NULL;
+            else
+            {
+                struct domain *d = !p2m_is_shared(*t) ? p2m->domain : dom_cow;
+                if ( !get_page(page, d) )
+                    page = NULL;
+            }
         }
         p2m_read_unlock(p2m);
 
@@ -594,8 +595,9 @@  struct page_info *p2m_get_page_from_gfn(
     mfn = get_gfn_type_access(p2m, gfn_x(gfn), t, a, q, NULL);
     if ( p2m_is_ram(*t) && mfn_valid(mfn) )
     {
+        struct domain *d = !p2m_is_shared(*t) ? p2m->domain : dom_cow;
         page = mfn_to_page(mfn);
-        if ( !get_page(page, p2m->domain) )
+        if ( !get_page(page, d) )
             page = NULL;
     }
     put_gfn(p2m->domain, gfn_x(gfn));