diff mbox

[v2] xen/x86: add a way to obtain the needed number of memory map entries

Message ID 20161206134743.2813-1-jgross@suse.com (mailing list archive)
State New, archived
Headers show

Commit Message

Juergen Gross Dec. 6, 2016, 1:47 p.m. UTC
Today there is no way for a domain to obtain the number of entries of
the machine memory map returned by XENMEM_machine_memory_map hypercall.

Modify the interface to return just the needed number of map entries
in case the buffer was specified as NULL.

Signed-off-by: Juergen Gross <jgross@suse.com>
---
 xen/arch/x86/mm.c           | 40 +++++++++++++++++++++++++---------------
 xen/include/public/memory.h |  2 ++
 2 files changed, 27 insertions(+), 15 deletions(-)

Comments

Jan Beulich Dec. 6, 2016, 2:19 p.m. UTC | #1
>>> On 06.12.16 at 14:47, <JGross@suse.com> wrote:
> Today there is no way for a domain to obtain the number of entries of
> the machine memory map returned by XENMEM_machine_memory_map hypercall.
> 
> Modify the interface to return just the needed number of map entries
> in case the buffer was specified as NULL.
> 
> Signed-off-by: Juergen Gross <jgross@suse.com>

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

albeit I'd like to have at least one more REST maintainer's agreement
that ...

> --- a/xen/include/public/memory.h
> +++ b/xen/include/public/memory.h
> @@ -339,6 +339,8 @@ DEFINE_XEN_GUEST_HANDLE(xen_memory_map_t);
>  /*
>   * Returns the real physical memory map. Passes the same structure as
>   * XENMEM_memory_map.
> + * Specifying buffer as NULL will return the number of entries required
> + * to store the complete memory map.
>   * arg == addr of xen_memory_map_t.
>   */
>  #define XENMEM_machine_memory_map   10

... this slight behavioral change is fine to make.

Jan
Konrad Rzeszutek Wilk Dec. 6, 2016, 2:23 p.m. UTC | #2
On Tue, Dec 06, 2016 at 07:19:13AM -0700, Jan Beulich wrote:
> >>> On 06.12.16 at 14:47, <JGross@suse.com> wrote:
> > Today there is no way for a domain to obtain the number of entries of
> > the machine memory map returned by XENMEM_machine_memory_map hypercall.
> > 
> > Modify the interface to return just the needed number of map entries
> > in case the buffer was specified as NULL.
> > 
> > Signed-off-by: Juergen Gross <jgross@suse.com>
> 
> Reviewed-by: Jan Beulich <jbeulich@suse.com>
> 
> albeit I'd like to have at least one more REST maintainer's agreement
> that ...
> 
> > --- a/xen/include/public/memory.h
> > +++ b/xen/include/public/memory.h
> > @@ -339,6 +339,8 @@ DEFINE_XEN_GUEST_HANDLE(xen_memory_map_t);
> >  /*
> >   * Returns the real physical memory map. Passes the same structure as
> >   * XENMEM_memory_map.
> > + * Specifying buffer as NULL will return the number of entries required
> > + * to store the complete memory map.
> >   * arg == addr of xen_memory_map_t.
> >   */
> >  #define XENMEM_machine_memory_map   10
> 
> ... this slight behavioral change is fine to make.

I think it is fine. It won't break the existing guests. And it is inline
with what we are doing when retroffiting other hypercalls.

Thanks.

> 
> Jan
>
Jan Beulich Dec. 7, 2016, 1:05 p.m. UTC | #3
>>> On 06.12.16 at 14:47, <JGross@suse.com> wrote:
> Today there is no way for a domain to obtain the number of entries of
> the machine memory map returned by XENMEM_machine_memory_map hypercall.
> 
> Modify the interface to return just the needed number of map entries
> in case the buffer was specified as NULL.
> 
> Signed-off-by: Juergen Gross <jgross@suse.com>

I've committed this, but whether to add it to my list of backports
depends on whether you intend to make use of this in Linux.
Please let me know.

Jan
Juergen Gross Dec. 7, 2016, 2:13 p.m. UTC | #4
On 07/12/16 14:05, Jan Beulich wrote:
>>>> On 06.12.16 at 14:47, <JGross@suse.com> wrote:
>> Today there is no way for a domain to obtain the number of entries of
>> the machine memory map returned by XENMEM_machine_memory_map hypercall.
>>
>> Modify the interface to return just the needed number of map entries
>> in case the buffer was specified as NULL.
>>
>> Signed-off-by: Juergen Gross <jgross@suse.com>
> 
> I've committed this, but whether to add it to my list of backports
> depends on whether you intend to make use of this in Linux.
> Please let me know.

I've no such plans in the moment.


Juergen
diff mbox

Patch

diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
index 14552a1..3ff0e97 100644
--- a/xen/arch/x86/mm.c
+++ b/xen/arch/x86/mm.c
@@ -4736,15 +4736,18 @@  static int _handle_iomem_range(unsigned long s, unsigned long e,
         XEN_GUEST_HANDLE_PARAM(e820entry_t) buffer_param;
         XEN_GUEST_HANDLE(e820entry_t) buffer;
 
-        if ( ctxt->n + 1 >= ctxt->map.nr_entries )
-            return -EINVAL;
-        ent.addr = (uint64_t)ctxt->s << PAGE_SHIFT;
-        ent.size = (uint64_t)(s - ctxt->s) << PAGE_SHIFT;
-        ent.type = E820_RESERVED;
-        buffer_param = guest_handle_cast(ctxt->map.buffer, e820entry_t);
-        buffer = guest_handle_from_param(buffer_param, e820entry_t);
-        if ( __copy_to_guest_offset(buffer, ctxt->n, &ent, 1) )
-            return -EFAULT;
+        if ( !guest_handle_is_null(ctxt->map.buffer) )
+        {
+            if ( ctxt->n + 1 >= ctxt->map.nr_entries )
+                return -EINVAL;
+            ent.addr = (uint64_t)ctxt->s << PAGE_SHIFT;
+            ent.size = (uint64_t)(s - ctxt->s) << PAGE_SHIFT;
+            ent.type = E820_RESERVED;
+            buffer_param = guest_handle_cast(ctxt->map.buffer, e820entry_t);
+            buffer = guest_handle_from_param(buffer_param, e820entry_t);
+            if ( __copy_to_guest_offset(buffer, ctxt->n, &ent, 1) )
+                return -EFAULT;
+        }
         ctxt->n++;
     }
     ctxt->s = e + 1;
@@ -4978,6 +4981,7 @@  long arch_memory_op(unsigned long cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
         XEN_GUEST_HANDLE(e820entry_t) buffer;
         XEN_GUEST_HANDLE_PARAM(e820entry_t) buffer_param;
         unsigned int i;
+        bool store;
 
         rc = xsm_machine_memory_map(XSM_PRIV);
         if ( rc )
@@ -4985,12 +4989,15 @@  long arch_memory_op(unsigned long cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
 
         if ( copy_from_guest(&ctxt.map, arg, 1) )
             return -EFAULT;
-        if ( ctxt.map.nr_entries < e820.nr_map + 1 )
+
+        store = !guest_handle_is_null(ctxt.map.buffer);
+
+        if ( store && ctxt.map.nr_entries < e820.nr_map + 1 )
             return -EINVAL;
 
         buffer_param = guest_handle_cast(ctxt.map.buffer, e820entry_t);
         buffer = guest_handle_from_param(buffer_param, e820entry_t);
-        if ( !guest_handle_okay(buffer, ctxt.map.nr_entries) )
+        if ( store && !guest_handle_okay(buffer, ctxt.map.nr_entries) )
             return -EFAULT;
 
         for ( i = 0, ctxt.n = 0, ctxt.s = 0; i < e820.nr_map; ++i, ++ctxt.n )
@@ -5007,10 +5014,13 @@  long arch_memory_op(unsigned long cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
                 if ( rc )
                     return rc;
             }
-            if ( ctxt.map.nr_entries <= ctxt.n + (e820.nr_map - i) )
-                return -EINVAL;
-            if ( __copy_to_guest_offset(buffer, ctxt.n, e820.map + i, 1) )
-                return -EFAULT;
+            if ( store )
+            {
+                if ( ctxt.map.nr_entries <= ctxt.n + (e820.nr_map - i) )
+                    return -EINVAL;
+                if ( __copy_to_guest_offset(buffer, ctxt.n, e820.map + i, 1) )
+                    return -EFAULT;
+            }
             ctxt.s = PFN_UP(e820.map[i].addr + e820.map[i].size);
         }
 
diff --git a/xen/include/public/memory.h b/xen/include/public/memory.h
index 5bf840f..e633047 100644
--- a/xen/include/public/memory.h
+++ b/xen/include/public/memory.h
@@ -339,6 +339,8 @@  DEFINE_XEN_GUEST_HANDLE(xen_memory_map_t);
 /*
  * Returns the real physical memory map. Passes the same structure as
  * XENMEM_memory_map.
+ * Specifying buffer as NULL will return the number of entries required
+ * to store the complete memory map.
  * arg == addr of xen_memory_map_t.
  */
 #define XENMEM_machine_memory_map   10