diff mbox series

[v2] x86/mm: switch to new APIs in arch_init_memory

Message ID e8ba0fb1451ef89c36b21a2063590baed2432031.1582799255.git.hongyxia@amazon.com (mailing list archive)
State New, archived
Headers show
Series [v2] x86/mm: switch to new APIs in arch_init_memory | expand

Commit Message

Xia, Hongyan Feb. 27, 2020, 10:27 a.m. UTC
From: Wei Liu <wei.liu2@citrix.com>

The function will map and unmap pages on demand.

Since we now map and unmap Xen PTE pages, we would like to track the
lifetime of mappings so that 1) we do not dereference memory through a
variable after it is unmapped, 2) we do not unmap more than once.
Therefore, we introduce the UNMAP_DOMAIN_PAGE macro to nullify the
variable after unmapping, and ignore NULL.

Signed-off-by: Wei Liu <wei.liu2@citrix.com>
Signed-off-by: Hongyan Xia <hongyxia@amazon.com>

---
Changed in v2:
- let UNMAP_DOMAIN_PAGE itself check whether the input is NULL to avoid
  adding the check in unmap_domain_page.
- reword the commit message.
---
 xen/arch/x86/mm.c             | 14 ++++++++------
 xen/include/xen/domain_page.h |  7 +++++++
 2 files changed, 15 insertions(+), 6 deletions(-)

Comments

Wei Liu Feb. 27, 2020, 11:44 a.m. UTC | #1
On Thu, Feb 27, 2020 at 10:27:39AM +0000, Hongyan Xia wrote:
> From: Wei Liu <wei.liu2@citrix.com>
> 
> The function will map and unmap pages on demand.
> 
> Since we now map and unmap Xen PTE pages, we would like to track the
> lifetime of mappings so that 1) we do not dereference memory through a
> variable after it is unmapped, 2) we do not unmap more than once.
> Therefore, we introduce the UNMAP_DOMAIN_PAGE macro to nullify the
> variable after unmapping, and ignore NULL.
> 
> Signed-off-by: Wei Liu <wei.liu2@citrix.com>
> Signed-off-by: Hongyan Xia <hongyxia@amazon.com>
> 
> ---
> Changed in v2:
> - let UNMAP_DOMAIN_PAGE itself check whether the input is NULL to avoid
>   adding the check in unmap_domain_page.
> - reword the commit message.
> ---
>  xen/arch/x86/mm.c             | 14 ++++++++------
>  xen/include/xen/domain_page.h |  7 +++++++
>  2 files changed, 15 insertions(+), 6 deletions(-)
> 
> diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
> index 70b87c4830..9fcdcde5b7 100644
> --- a/xen/arch/x86/mm.c
> +++ b/xen/arch/x86/mm.c
> @@ -356,19 +356,21 @@ void __init arch_init_memory(void)
>              ASSERT(root_pgt_pv_xen_slots < ROOT_PAGETABLE_PV_XEN_SLOTS);
>              if ( l4_table_offset(split_va) == l4_table_offset(split_va - 1) )
>              {
> -                l3_pgentry_t *l3tab = alloc_xen_pagetable();
> +                mfn_t l3mfn = alloc_xen_pagetable_new();
>  
> -                if ( l3tab )
> +                if ( !mfn_eq(l3mfn, INVALID_MFN) )
>                  {
> -                    const l3_pgentry_t *l3idle =
> -                        l4e_to_l3e(idle_pg_table[l4_table_offset(split_va)]);
> +                    l3_pgentry_t *l3idle = map_l3t_from_l4e(
> +                            idle_pg_table[l4_table_offset(split_va)]);
> +                    l3_pgentry_t *l3tab = map_domain_page(l3mfn);
>  
>                      for ( i = 0; i < l3_table_offset(split_va); ++i )
>                          l3tab[i] = l3idle[i];
>                      for ( ; i < L3_PAGETABLE_ENTRIES; ++i )
>                          l3tab[i] = l3e_empty();
> -                    split_l4e = l4e_from_mfn(virt_to_mfn(l3tab),
> -                                             __PAGE_HYPERVISOR_RW);
> +                    split_l4e = l4e_from_mfn(l3mfn, __PAGE_HYPERVISOR_RW);
> +                    UNMAP_DOMAIN_PAGE(l3idle);
> +                    UNMAP_DOMAIN_PAGE(l3tab);
>                  }
>                  else
>                      ++root_pgt_pv_xen_slots;
> diff --git a/xen/include/xen/domain_page.h b/xen/include/xen/domain_page.h
> index 32669a3339..bfc3bf6aeb 100644
> --- a/xen/include/xen/domain_page.h
> +++ b/xen/include/xen/domain_page.h
> @@ -72,4 +72,11 @@ static inline void unmap_domain_page_global(const void *va) {};
>  
>  #endif /* !CONFIG_DOMAIN_PAGE */
>  
> +#define UNMAP_DOMAIN_PAGE(p) do {   \
> +    if ( p ) {                      \

Coding style mandates { should be placed in the next line.

Other than this, the code looks correct to me.

Wei.

> +        unmap_domain_page(p);       \
> +        (p) = NULL;                 \
> +    }                               \
> +} while ( false )
> +
>  #endif /* __XEN_DOMAIN_PAGE_H__ */
> -- 
> 2.17.1
>
Julien Grall Feb. 27, 2020, 11:51 a.m. UTC | #2
Hi Hongyan,

On 27/02/2020 10:27, Hongyan Xia wrote:
> From: Wei Liu <wei.liu2@citrix.com>
> 
> The function will map and unmap pages on demand.
> 
> Since we now map and unmap Xen PTE pages, we would like to track the
> lifetime of mappings so that 1) we do not dereference memory through a
> variable after it is unmapped, 2) we do not unmap more than once.
> Therefore, we introduce the UNMAP_DOMAIN_PAGE macro to nullify the
> variable after unmapping, and ignore NULL.
> 
> Signed-off-by: Wei Liu <wei.liu2@citrix.com>
> Signed-off-by: Hongyan Xia <hongyxia@amazon.com>
> 
> ---
> Changed in v2:
> - let UNMAP_DOMAIN_PAGE itself check whether the input is NULL to avoid
>    adding the check in unmap_domain_page.
> - reword the commit message.
> ---
>   xen/arch/x86/mm.c             | 14 ++++++++------
>   xen/include/xen/domain_page.h |  7 +++++++
>   2 files changed, 15 insertions(+), 6 deletions(-)
> 
> diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
> index 70b87c4830..9fcdcde5b7 100644
> --- a/xen/arch/x86/mm.c
> +++ b/xen/arch/x86/mm.c
> @@ -356,19 +356,21 @@ void __init arch_init_memory(void)
>               ASSERT(root_pgt_pv_xen_slots < ROOT_PAGETABLE_PV_XEN_SLOTS);
>               if ( l4_table_offset(split_va) == l4_table_offset(split_va - 1) )
>               {
> -                l3_pgentry_t *l3tab = alloc_xen_pagetable();
> +                mfn_t l3mfn = alloc_xen_pagetable_new();
>   
> -                if ( l3tab )
> +                if ( !mfn_eq(l3mfn, INVALID_MFN) )
>                   {
> -                    const l3_pgentry_t *l3idle =
> -                        l4e_to_l3e(idle_pg_table[l4_table_offset(split_va)]);
> +                    l3_pgentry_t *l3idle = map_l3t_from_l4e(
> +                            idle_pg_table[l4_table_offset(split_va)]);
> +                    l3_pgentry_t *l3tab = map_domain_page(l3mfn);
>   
>                       for ( i = 0; i < l3_table_offset(split_va); ++i )
>                           l3tab[i] = l3idle[i];
>                       for ( ; i < L3_PAGETABLE_ENTRIES; ++i )
>                           l3tab[i] = l3e_empty();
> -                    split_l4e = l4e_from_mfn(virt_to_mfn(l3tab),
> -                                             __PAGE_HYPERVISOR_RW);
> +                    split_l4e = l4e_from_mfn(l3mfn, __PAGE_HYPERVISOR_RW);
> +                    UNMAP_DOMAIN_PAGE(l3idle);
> +                    UNMAP_DOMAIN_PAGE(l3tab);
>                   }
>                   else
>                       ++root_pgt_pv_xen_slots;
> diff --git a/xen/include/xen/domain_page.h b/xen/include/xen/domain_page.h
> index 32669a3339..bfc3bf6aeb 100644
> --- a/xen/include/xen/domain_page.h
> +++ b/xen/include/xen/domain_page.h
> @@ -72,4 +72,11 @@ static inline void unmap_domain_page_global(const void *va) {};
>   
>   #endif /* !CONFIG_DOMAIN_PAGE */
>   
> +#define UNMAP_DOMAIN_PAGE(p) do {   \
> +    if ( p ) {                      \
> +        unmap_domain_page(p);       \
> +        (p) = NULL;                 \
> +    }                               \
> +} while ( false )

Do we need to keep the do {} while ()?

Cheers,
Xia, Hongyan Feb. 27, 2020, 11:59 a.m. UTC | #3
On Thu, 2020-02-27 at 11:51 +0000, Julien Grall wrote:
> Hi Hongyan,
> 
> On 27/02/2020 10:27, Hongyan Xia wrote:
> > ...
> > diff --git a/xen/include/xen/domain_page.h
> > b/xen/include/xen/domain_page.h
> > index 32669a3339..bfc3bf6aeb 100644
> > --- a/xen/include/xen/domain_page.h
> > +++ b/xen/include/xen/domain_page.h
> > @@ -72,4 +72,11 @@ static inline void
> > unmap_domain_page_global(const void *va) {};
> >   
> >   #endif /* !CONFIG_DOMAIN_PAGE */
> >   
> > +#define UNMAP_DOMAIN_PAGE(p) do {   \
> > +    if ( p ) {                      \
> > +        unmap_domain_page(p);       \
> > +        (p) = NULL;                 \
> > +    }                               \
> > +} while ( false )
> 
> Do we need to keep the do {} while ()?

I think we do. For example:

if ( cond )
    UNMAP_DOMAIN_PAGE(p);
else
    blah_blah_blah();

If we remove the do-while, the else clause will be paired with the if
in UNMAP_DOMAIN_PAGE();

Hongyan
Julien Grall Feb. 27, 2020, 12:03 p.m. UTC | #4
Hi Hongyan,

On 27/02/2020 11:59, Xia, Hongyan wrote:
> On Thu, 2020-02-27 at 11:51 +0000, Julien Grall wrote:
>> Hi Hongyan,
>>
>> On 27/02/2020 10:27, Hongyan Xia wrote:
>>> ...
>>> diff --git a/xen/include/xen/domain_page.h
>>> b/xen/include/xen/domain_page.h
>>> index 32669a3339..bfc3bf6aeb 100644
>>> --- a/xen/include/xen/domain_page.h
>>> +++ b/xen/include/xen/domain_page.h
>>> @@ -72,4 +72,11 @@ static inline void
>>> unmap_domain_page_global(const void *va) {};
>>>    
>>>    #endif /* !CONFIG_DOMAIN_PAGE */
>>>    
>>> +#define UNMAP_DOMAIN_PAGE(p) do {   \
>>> +    if ( p ) {                      \
>>> +        unmap_domain_page(p);       \
>>> +        (p) = NULL;                 \
>>> +    }                               \
>>> +} while ( false )
>>
>> Do we need to keep the do {} while ()?
> 
> I think we do. For example:
> 
> if ( cond )
>      UNMAP_DOMAIN_PAGE(p);
> else
>      blah_blah_blah();
> 
> If we remove the do-while, the else clause will be paired with the if
> in UNMAP_DOMAIN_PAGE();

GCC will actually throw a compiler error:

test.c: In function ‘f’:
test.c:13:5: error: ‘else’ without a previous ‘if’
      else
      ^~~~

Anyway, yes we do need to keep do while {} to catch any use without the 
semicolon. Sorry for the noise.

Cheers,
Jan Beulich March 3, 2020, 9:21 a.m. UTC | #5
On 27.02.2020 11:27, Hongyan Xia wrote:
> From: Wei Liu <wei.liu2@citrix.com>
> 
> The function will map and unmap pages on demand.
> 
> Since we now map and unmap Xen PTE pages, we would like to track the
> lifetime of mappings so that 1) we do not dereference memory through a
> variable after it is unmapped, 2) we do not unmap more than once.
> Therefore, we introduce the UNMAP_DOMAIN_PAGE macro to nullify the
> variable after unmapping, and ignore NULL.
> 
> Signed-off-by: Wei Liu <wei.liu2@citrix.com>
> Signed-off-by: Hongyan Xia <hongyxia@amazon.com>
> 
> ---
> Changed in v2:
> - let UNMAP_DOMAIN_PAGE itself check whether the input is NULL to avoid
>   adding the check in unmap_domain_page.
> - reword the commit message.
> ---
>  xen/arch/x86/mm.c             | 14 ++++++++------
>  xen/include/xen/domain_page.h |  7 +++++++
>  2 files changed, 15 insertions(+), 6 deletions(-)
> 
> diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
> index 70b87c4830..9fcdcde5b7 100644
> --- a/xen/arch/x86/mm.c
> +++ b/xen/arch/x86/mm.c
> @@ -356,19 +356,21 @@ void __init arch_init_memory(void)
>              ASSERT(root_pgt_pv_xen_slots < ROOT_PAGETABLE_PV_XEN_SLOTS);
>              if ( l4_table_offset(split_va) == l4_table_offset(split_va - 1) )
>              {
> -                l3_pgentry_t *l3tab = alloc_xen_pagetable();
> +                mfn_t l3mfn = alloc_xen_pagetable_new();
>  
> -                if ( l3tab )
> +                if ( !mfn_eq(l3mfn, INVALID_MFN) )
>                  {
> -                    const l3_pgentry_t *l3idle =
> -                        l4e_to_l3e(idle_pg_table[l4_table_offset(split_va)]);
> +                    l3_pgentry_t *l3idle = map_l3t_from_l4e(
> +                            idle_pg_table[l4_table_offset(split_va)]);

Somehow you've lost the const. I think both this and ...

> --- a/xen/include/xen/domain_page.h
> +++ b/xen/include/xen/domain_page.h
> @@ -72,4 +72,11 @@ static inline void unmap_domain_page_global(const void *va) {};
>  
>  #endif /* !CONFIG_DOMAIN_PAGE */
>  
> +#define UNMAP_DOMAIN_PAGE(p) do {   \
> +    if ( p ) {                      \

... the brace placement here can be dealt with while committing.
With both of them in place
Reviewed-by: Jan Beulich <jbeulich@suse.com>

Jan
diff mbox series

Patch

diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
index 70b87c4830..9fcdcde5b7 100644
--- a/xen/arch/x86/mm.c
+++ b/xen/arch/x86/mm.c
@@ -356,19 +356,21 @@  void __init arch_init_memory(void)
             ASSERT(root_pgt_pv_xen_slots < ROOT_PAGETABLE_PV_XEN_SLOTS);
             if ( l4_table_offset(split_va) == l4_table_offset(split_va - 1) )
             {
-                l3_pgentry_t *l3tab = alloc_xen_pagetable();
+                mfn_t l3mfn = alloc_xen_pagetable_new();
 
-                if ( l3tab )
+                if ( !mfn_eq(l3mfn, INVALID_MFN) )
                 {
-                    const l3_pgentry_t *l3idle =
-                        l4e_to_l3e(idle_pg_table[l4_table_offset(split_va)]);
+                    l3_pgentry_t *l3idle = map_l3t_from_l4e(
+                            idle_pg_table[l4_table_offset(split_va)]);
+                    l3_pgentry_t *l3tab = map_domain_page(l3mfn);
 
                     for ( i = 0; i < l3_table_offset(split_va); ++i )
                         l3tab[i] = l3idle[i];
                     for ( ; i < L3_PAGETABLE_ENTRIES; ++i )
                         l3tab[i] = l3e_empty();
-                    split_l4e = l4e_from_mfn(virt_to_mfn(l3tab),
-                                             __PAGE_HYPERVISOR_RW);
+                    split_l4e = l4e_from_mfn(l3mfn, __PAGE_HYPERVISOR_RW);
+                    UNMAP_DOMAIN_PAGE(l3idle);
+                    UNMAP_DOMAIN_PAGE(l3tab);
                 }
                 else
                     ++root_pgt_pv_xen_slots;
diff --git a/xen/include/xen/domain_page.h b/xen/include/xen/domain_page.h
index 32669a3339..bfc3bf6aeb 100644
--- a/xen/include/xen/domain_page.h
+++ b/xen/include/xen/domain_page.h
@@ -72,4 +72,11 @@  static inline void unmap_domain_page_global(const void *va) {};
 
 #endif /* !CONFIG_DOMAIN_PAGE */
 
+#define UNMAP_DOMAIN_PAGE(p) do {   \
+    if ( p ) {                      \
+        unmap_domain_page(p);       \
+        (p) = NULL;                 \
+    }                               \
+} while ( false )
+
 #endif /* __XEN_DOMAIN_PAGE_H__ */