diff mbox series

[3/5] x86_64/mm: map and unmap page tables in share_hotadd_m2p_table

Message ID 2fa83ef5818805c179757caac99ccf7ab4f7ba3a.1584955616.git.hongyxia@amazon.com (mailing list archive)
State Superseded
Headers show
Series use new API for Xen page tables | expand

Commit Message

Hongyan Xia March 23, 2020, 9:41 a.m. UTC
From: Wei Liu <wei.liu2@citrix.com>

Fetch lYe by mapping and unmapping lXe instead of using the direct map,
which is now done via the new lYe_from_lXe() helpers.

Signed-off-by: Wei Liu <wei.liu2@citrix.com>
Signed-off-by: Hongyan Xia <hongyxia@amazon.com>
---
 xen/arch/x86/x86_64/mm.c   | 12 ++++++------
 xen/include/asm-x86/page.h | 18 ++++++++++++++++++
 2 files changed, 24 insertions(+), 6 deletions(-)

Comments

Jan Beulich April 1, 2020, 12:29 p.m. UTC | #1
On 23.03.2020 10:41, Hongyan Xia wrote:
> --- a/xen/include/asm-x86/page.h
> +++ b/xen/include/asm-x86/page.h
> @@ -196,6 +196,24 @@ static inline l4_pgentry_t l4e_from_paddr(paddr_t pa, unsigned int flags)
>  #define map_l2t_from_l3e(x)        (l2_pgentry_t *)map_domain_page(l3e_get_mfn(x))
>  #define map_l3t_from_l4e(x)        (l3_pgentry_t *)map_domain_page(l4e_get_mfn(x))
>  
> +#define l1e_from_l2e(l2e, off) ({                   \
> +        l1_pgentry_t *l1t = map_l1t_from_l2e(l2e);  \
> +        l1_pgentry_t l1e = l1t[off];                \
> +        UNMAP_DOMAIN_PAGE(l1t);                     \
> +        l1e; })
> +
> +#define l2e_from_l3e(l3e, off) ({                   \
> +        l2_pgentry_t *l2t = map_l2t_from_l3e(l3e);  \
> +        l2_pgentry_t l2e = l2t[off];                \
> +        UNMAP_DOMAIN_PAGE(l2t);                     \
> +        l2e; })
> +
> +#define l3e_from_l4e(l4e, off) ({                   \
> +        l3_pgentry_t *l3t = map_l3t_from_l4e(l4e);  \
> +        l3_pgentry_t l3e = l3t[off];                \
> +        UNMAP_DOMAIN_PAGE(l3t);                     \
> +        l3e; })

There's a reason these are macros rather than inline functions,
I assume? (This reason would be nice to be stated in the
description.)

I don't see why you use UNMAP_DOMAIN_PAGE() rather than
unmap_domain_page() here - the variables in question go out of
scope right afterwards, so the storing of NULL into them is
pointless (and very likely to be eliminated by the compiler
anyway).

Finally the pointers should each be "to const", as you're
only reading through them.

Jan
Hongyan Xia April 7, 2020, 3:11 p.m. UTC | #2
On Wed, 2020-04-01 at 14:29 +0200, Jan Beulich wrote:
> On 23.03.2020 10:41, Hongyan Xia wrote:
> > --- a/xen/include/asm-x86/page.h
> > +++ b/xen/include/asm-x86/page.h
> > @@ -196,6 +196,24 @@ static inline l4_pgentry_t
> > l4e_from_paddr(paddr_t pa, unsigned int flags)
> >  #define map_l2t_from_l3e(x)        (l2_pgentry_t
> > *)map_domain_page(l3e_get_mfn(x))
> >  #define map_l3t_from_l4e(x)        (l3_pgentry_t
> > *)map_domain_page(l4e_get_mfn(x))
> >  
> > +#define l1e_from_l2e(l2e, off) ({                   \
> > +        l1_pgentry_t *l1t = map_l1t_from_l2e(l2e);  \
> > +        l1_pgentry_t l1e = l1t[off];                \
> > +        UNMAP_DOMAIN_PAGE(l1t);                     \
> > +        l1e; })
> > +
> > +#define l2e_from_l3e(l3e, off) ({                   \
> > +        l2_pgentry_t *l2t = map_l2t_from_l3e(l3e);  \
> > +        l2_pgentry_t l2e = l2t[off];                \
> > +        UNMAP_DOMAIN_PAGE(l2t);                     \
> > +        l2e; })
> > +
> > +#define l3e_from_l4e(l4e, off) ({                   \
> > +        l3_pgentry_t *l3t = map_l3t_from_l4e(l4e);  \
> > +        l3_pgentry_t l3e = l3t[off];                \
> > +        UNMAP_DOMAIN_PAGE(l3t);                     \
> > +        l3e; })
> 
> There's a reason these are macros rather than inline functions,
> I assume? (This reason would be nice to be stated in the
> description.)

Actually no specific reasons, just to keep them as macros to be
consistent with other helpers above. Fairly trivial to convert them
into inline functions if this is desired.

> I don't see why you use UNMAP_DOMAIN_PAGE() rather than
> unmap_domain_page() here - the variables in question go out of
> scope right afterwards, so the storing of NULL into them is
> pointless (and very likely to be eliminated by the compiler
> anyway).

My intention is to just avoid using the lower case one altogether, so
that one day when we need to expand any function or macros we do not
need to look back at the code and worry about whether any lower case
ones need to be converted to upper case (sometimes for large functions
this may not be trivial), and the compiler can deal with the extra
nullification anyway.

> Finally the pointers should each be "to const", as you're
> only reading through them.

Good point. Will const qualify in next revision.

Thanks,
Hongyan
Jan Beulich April 7, 2020, 3:14 p.m. UTC | #3
On 07.04.2020 17:11, Hongyan Xia wrote:
> On Wed, 2020-04-01 at 14:29 +0200, Jan Beulich wrote:
>> On 23.03.2020 10:41, Hongyan Xia wrote:
>>> --- a/xen/include/asm-x86/page.h
>>> +++ b/xen/include/asm-x86/page.h
>>> @@ -196,6 +196,24 @@ static inline l4_pgentry_t
>>> l4e_from_paddr(paddr_t pa, unsigned int flags)
>>>  #define map_l2t_from_l3e(x)        (l2_pgentry_t
>>> *)map_domain_page(l3e_get_mfn(x))
>>>  #define map_l3t_from_l4e(x)        (l3_pgentry_t
>>> *)map_domain_page(l4e_get_mfn(x))
>>>  
>>> +#define l1e_from_l2e(l2e, off) ({                   \
>>> +        l1_pgentry_t *l1t = map_l1t_from_l2e(l2e);  \
>>> +        l1_pgentry_t l1e = l1t[off];                \
>>> +        UNMAP_DOMAIN_PAGE(l1t);                     \
>>> +        l1e; })
>>> +
>>> +#define l2e_from_l3e(l3e, off) ({                   \
>>> +        l2_pgentry_t *l2t = map_l2t_from_l3e(l3e);  \
>>> +        l2_pgentry_t l2e = l2t[off];                \
>>> +        UNMAP_DOMAIN_PAGE(l2t);                     \
>>> +        l2e; })
>>> +
>>> +#define l3e_from_l4e(l4e, off) ({                   \
>>> +        l3_pgentry_t *l3t = map_l3t_from_l4e(l4e);  \
>>> +        l3_pgentry_t l3e = l3t[off];                \
>>> +        UNMAP_DOMAIN_PAGE(l3t);                     \
>>> +        l3e; })
>>
>> There's a reason these are macros rather than inline functions,
>> I assume? (This reason would be nice to be stated in the
>> description.)
> 
> Actually no specific reasons, just to keep them as macros to be
> consistent with other helpers above. Fairly trivial to convert them
> into inline functions if this is desired.

Where possible this would be the preferred route for new helpers.

>> I don't see why you use UNMAP_DOMAIN_PAGE() rather than
>> unmap_domain_page() here - the variables in question go out of
>> scope right afterwards, so the storing of NULL into them is
>> pointless (and very likely to be eliminated by the compiler
>> anyway).
> 
> My intention is to just avoid using the lower case one altogether, so
> that one day when we need to expand any function or macros we do not
> need to look back at the code and worry about whether any lower case
> ones need to be converted to upper case (sometimes for large functions
> this may not be trivial), and the compiler can deal with the extra
> nullification anyway.

I don't agree with this goal; perhaps others on Cc have an opinion?

Jan
Hongyan Xia April 8, 2020, 9:32 a.m. UTC | #4
On Wed, 2020-04-01 at 14:29 +0200, Jan Beulich wrote:
> On 23.03.2020 10:41, Hongyan Xia wrote:
> > --- a/xen/include/asm-x86/page.h
> > +++ b/xen/include/asm-x86/page.h
> > @@ -196,6 +196,24 @@ static inline l4_pgentry_t
> > l4e_from_paddr(paddr_t pa, unsigned int flags)
> >  #define map_l2t_from_l3e(x)        (l2_pgentry_t
> > *)map_domain_page(l3e_get_mfn(x))
> >  #define map_l3t_from_l4e(x)        (l3_pgentry_t
> > *)map_domain_page(l4e_get_mfn(x))
> >  
> > +#define l1e_from_l2e(l2e, off) ({                   \
> > +        l1_pgentry_t *l1t = map_l1t_from_l2e(l2e);  \
> > +        l1_pgentry_t l1e = l1t[off];                \
> > +        UNMAP_DOMAIN_PAGE(l1t);                     \
> > +        l1e; })
> > +
> > +#define l2e_from_l3e(l3e, off) ({                   \
> > +        l2_pgentry_t *l2t = map_l2t_from_l3e(l3e);  \
> > +        l2_pgentry_t l2e = l2t[off];                \
> > +        UNMAP_DOMAIN_PAGE(l2t);                     \
> > +        l2e; })
> > +
> > +#define l3e_from_l4e(l4e, off) ({                   \
> > +        l3_pgentry_t *l3t = map_l3t_from_l4e(l4e);  \
> > +        l3_pgentry_t l3e = l3t[off];                \
> > +        UNMAP_DOMAIN_PAGE(l3t);                     \
> > +        l3e; })
> 
> There's a reason these are macros rather than inline functions,
> I assume? (This reason would be nice to be stated in the
> description.)

While converting them into inline functions, I realised I cannot do
that due to the header mess. Converting into inline functions needs the
domain_page.h header, which opens a can of worms if I include it here
(page.h). Keeping them as macros works around this issue.

I will add this in the description.

Hongyan
diff mbox series

Patch

diff --git a/xen/arch/x86/x86_64/mm.c b/xen/arch/x86/x86_64/mm.c
index a440dac25e..2680173fab 100644
--- a/xen/arch/x86/x86_64/mm.c
+++ b/xen/arch/x86/x86_64/mm.c
@@ -173,14 +173,14 @@  static int share_hotadd_m2p_table(struct mem_hotadd_info *info)
           v += n << PAGE_SHIFT )
     {
         n = L2_PAGETABLE_ENTRIES * L1_PAGETABLE_ENTRIES;
-        l3e = l4e_to_l3e(idle_pg_table[l4_table_offset(v)])[
-            l3_table_offset(v)];
+        l3e = l3e_from_l4e(idle_pg_table[l4_table_offset(v)],
+                           l3_table_offset(v));
         if ( !(l3e_get_flags(l3e) & _PAGE_PRESENT) )
             continue;
         if ( !(l3e_get_flags(l3e) & _PAGE_PSE) )
         {
             n = L1_PAGETABLE_ENTRIES;
-            l2e = l3e_to_l2e(l3e)[l2_table_offset(v)];
+            l2e = l2e_from_l3e(l3e, l2_table_offset(v));
             if ( !(l2e_get_flags(l2e) & _PAGE_PRESENT) )
                 continue;
             m2p_start_mfn = l2e_get_mfn(l2e);
@@ -201,11 +201,11 @@  static int share_hotadd_m2p_table(struct mem_hotadd_info *info)
           v != RDWR_COMPAT_MPT_VIRT_END;
           v += 1 << L2_PAGETABLE_SHIFT )
     {
-        l3e = l4e_to_l3e(idle_pg_table[l4_table_offset(v)])[
-            l3_table_offset(v)];
+        l3e = l3e_from_l4e(idle_pg_table[l4_table_offset(v)],
+                           l3_table_offset(v));
         if ( !(l3e_get_flags(l3e) & _PAGE_PRESENT) )
             continue;
-        l2e = l3e_to_l2e(l3e)[l2_table_offset(v)];
+        l2e = l2e_from_l3e(l3e, l2_table_offset(v));
         if ( !(l2e_get_flags(l2e) & _PAGE_PRESENT) )
             continue;
         m2p_start_mfn = l2e_get_mfn(l2e);
diff --git a/xen/include/asm-x86/page.h b/xen/include/asm-x86/page.h
index c98d8f5ede..d4752a5925 100644
--- a/xen/include/asm-x86/page.h
+++ b/xen/include/asm-x86/page.h
@@ -196,6 +196,24 @@  static inline l4_pgentry_t l4e_from_paddr(paddr_t pa, unsigned int flags)
 #define map_l2t_from_l3e(x)        (l2_pgentry_t *)map_domain_page(l3e_get_mfn(x))
 #define map_l3t_from_l4e(x)        (l3_pgentry_t *)map_domain_page(l4e_get_mfn(x))
 
+#define l1e_from_l2e(l2e, off) ({                   \
+        l1_pgentry_t *l1t = map_l1t_from_l2e(l2e);  \
+        l1_pgentry_t l1e = l1t[off];                \
+        UNMAP_DOMAIN_PAGE(l1t);                     \
+        l1e; })
+
+#define l2e_from_l3e(l3e, off) ({                   \
+        l2_pgentry_t *l2t = map_l2t_from_l3e(l3e);  \
+        l2_pgentry_t l2e = l2t[off];                \
+        UNMAP_DOMAIN_PAGE(l2t);                     \
+        l2e; })
+
+#define l3e_from_l4e(l4e, off) ({                   \
+        l3_pgentry_t *l3t = map_l3t_from_l4e(l4e);  \
+        l3_pgentry_t l3e = l3t[off];                \
+        UNMAP_DOMAIN_PAGE(l3t);                     \
+        l3e; })
+
 /* Given a virtual address, get an entry offset into a page table. */
 #define l1_table_offset(a)         \
     (((a) >> L1_PAGETABLE_SHIFT) & (L1_PAGETABLE_ENTRIES - 1))