Re: [libvirt] [RFC PATCH 01/17] qemu: setup shared memory without explicit numa configuration

2018-08-16 Thread Marc-André Lureau
Hi
On Thu, Aug 16, 2018 at 12:48 PM Daniel P. Berrangé  wrote:
>
> On Fri, Jul 13, 2018 at 03:28:08PM +0200, marcandre.lur...@redhat.com wrote:
> > From: Marc-André Lureau 
> >
> > When a domain is configured with 'shared' memory backing:
> >
> >   
> > 
> >   
> >
> > But no explicit NUMA configuration, let's configure a shared memory
> > backend associated with default -numa.
>
>
> > diff --git a/tests/qemuxml2argvdata/fd-memory-no-numa-topology.args 
> > b/tests/qemuxml2argvdata/fd-memory-no-numa-topology.args
> > index bd88daaa3b..400fb39cc6 100644
> > --- a/tests/qemuxml2argvdata/fd-memory-no-numa-topology.args
> > +++ b/tests/qemuxml2argvdata/fd-memory-no-numa-topology.args
> > @@ -11,6 +11,10 @@ QEMU_AUDIO_DRV=none \
> >  -m 14336 \
> >  -mem-prealloc \
> >  -smp 8,sockets=8,cores=1,threads=1 \
> > +-object memory-backend-file,id=ram-node,\
> > +mem-path=/var/lib/libvirt/qemu/ram/libvirt/qemu/-1-instance-0092/ram-node,\
> > +share=yes,size=15032385536 \
> > +-numa node,nodeid=0,memdev=ram-node \
>
> I'm not at all convinced it is safe todo this. We've been burnt in the
> past by adding  use of memory-backend objects causing migration to break
>
>
>   commit f309db1f4d51009bad0d32e12efc75530b66836b
>   Author: Michal Privoznik 
>   Date:   Thu Dec 18 12:36:48 2014 +0100
>
> qemu: Create memory-backend-{ram,file} iff needed
>
> Libvirt BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1175397
> QEMU BZ:https://bugzilla.redhat.com/show_bug.cgi?id=1170093
>
> This change doesn't really feel like it is required either. If the
> user wants NUMA, then the XML can just be written to request a NUMA
> topology with a single node.  Better to be explicit in the XML rather
> than silently adding things as a side effect

Ok, let's drop this patch then. I'll modify "qemu: use
memory-backend-memfd if possible" to make use of memfd differently,
with explicit NUMA.

>
> Regards,
> Daniel
> --
> |: https://berrange.com  -o-https://www.flickr.com/photos/dberrange :|
> |: https://libvirt.org -o-https://fstop138.berrange.com :|
> |: https://entangle-photo.org-o-https://www.instagram.com/dberrange :|
>
> --
> libvir-list mailing list
> libvir-list@redhat.com
> https://www.redhat.com/mailman/listinfo/libvir-list



-- 
Marc-André Lureau

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Re: [libvirt] [RFC PATCH 01/17] qemu: setup shared memory without explicit numa configuration

2018-08-16 Thread Daniel P . Berrangé
On Thu, Aug 16, 2018 at 07:32:57AM -0400, John Ferlan wrote:
> 
> 
> On 08/16/2018 06:31 AM, Marc-André Lureau wrote:
> > Hi
> > 
> > On Thu, Aug 16, 2018 at 4:35 AM, John Ferlan  wrote:
> >>
> >>
> >> On 07/13/2018 09:28 AM, marcandre.lur...@redhat.com wrote:
> >>> From: Marc-André Lureau 
> >>>
> >>> When a domain is configured with 'shared' memory backing:
> >>>
> >>>   
> >>> 
> >>>   
> >>>
> >>> But no explicit NUMA configuration, let's configure a shared memory
> >>> backend associated with default -numa.
> >>>
> >>> Signed-off-by: Marc-André Lureau 
> >>> ---
> >>>  src/qemu/qemu_command.c   | 100 --
> >>>  .../fd-memory-no-numa-topology.args   |   4 +
> >>>  2 files changed, 73 insertions(+), 31 deletions(-)
> >>>
> >>
> >> NUMA, memory backends, and hugepages - not in my wheelhouse of
> >> knowledge. Hopefully Michal and/or Pavel will take a look!
> >>
> >> Is it possible someone may not want this type of thing to happen? Is
> > 
> > I assume someone that sets 'shared' memory mode may consider this as a bug 
> > fix.
> > 
> >> there an upside or downside to this?  What happens "today" when not
> > 
> > You get non-shared memory
> > 
> 
> So today someone asks for "shared" and then end up with "non-shared"? I
> don't think that's apparent from the "access" description in:
> 
> https://libvirt.org/formatdomain.html#elementsMemoryBacking
> 
> Then again, not in my wheelhouse of knowledge, so maybe that's just one
> of those givens. Of course that perhaps goes to your first answer of
> this being a "bug fix". Not something that's apparent from the existing
> documentation or commit description though. This probably should have
> been it's own separate patch and not included in this series.

If we can't honour the "shared" request, we should make sure libvirt
reports an error and aborts startup.

Regards,
Daniel
-- 
|: https://berrange.com  -o-https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o-https://fstop138.berrange.com :|
|: https://entangle-photo.org-o-https://www.instagram.com/dberrange :|

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Re: [libvirt] [RFC PATCH 01/17] qemu: setup shared memory without explicit numa configuration

2018-08-16 Thread John Ferlan


On 08/16/2018 06:31 AM, Marc-André Lureau wrote:
> Hi
> 
> On Thu, Aug 16, 2018 at 4:35 AM, John Ferlan  wrote:
>>
>>
>> On 07/13/2018 09:28 AM, marcandre.lur...@redhat.com wrote:
>>> From: Marc-André Lureau 
>>>
>>> When a domain is configured with 'shared' memory backing:
>>>
>>>   
>>> 
>>>   
>>>
>>> But no explicit NUMA configuration, let's configure a shared memory
>>> backend associated with default -numa.
>>>
>>> Signed-off-by: Marc-André Lureau 
>>> ---
>>>  src/qemu/qemu_command.c   | 100 --
>>>  .../fd-memory-no-numa-topology.args   |   4 +
>>>  2 files changed, 73 insertions(+), 31 deletions(-)
>>>
>>
>> NUMA, memory backends, and hugepages - not in my wheelhouse of
>> knowledge. Hopefully Michal and/or Pavel will take a look!
>>
>> Is it possible someone may not want this type of thing to happen? Is
> 
> I assume someone that sets 'shared' memory mode may consider this as a bug 
> fix.
> 
>> there an upside or downside to this?  What happens "today" when not
> 
> You get non-shared memory
> 

So today someone asks for "shared" and then end up with "non-shared"? I
don't think that's apparent from the "access" description in:

https://libvirt.org/formatdomain.html#elementsMemoryBacking

Then again, not in my wheelhouse of knowledge, so maybe that's just one
of those givens. Of course that perhaps goes to your first answer of
this being a "bug fix". Not something that's apparent from the existing
documentation or commit description though. This probably should have
been it's own separate patch and not included in this series.

>> generated? And of course, what about migration concerns about
>> unconditionally doing this for some target migration?
> 
> True, this will break migration though if the target uses
> numa/memory-backend-file.
> 
> What do you suggest?
> 

This needs to be configurable as we cannot break w/ migration. I'm not
quite sure how we document this other than as Dan suggests that if
someone wants NUMA, then they'll configure things properly. If this
'shared' ends up as 'non-shared' because NUMA isn't configured, then we
should indicate that. If the adding some property to the element to
indicate desire of 'shared' via usage of some (local) backing store
which means the guest probably isn't very migrate-able, then so bit it.

>>
>>> diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
>>> index 44ae8dcef7..f1235099b2 100644
>>> --- a/src/qemu/qemu_command.c
>>> +++ b/src/qemu/qemu_command.c
>>> @@ -3254,26 +3254,21 @@ qemuBuildMemoryBackendProps(virJSONValuePtr 
>>> *backendProps,
>>>
>>>
>>>  static int
>>> -qemuBuildMemoryCellBackendStr(virDomainDefPtr def,
>>> -  virQEMUDriverConfigPtr cfg,
>>> -  size_t cell,
>>> -  qemuDomainObjPrivatePtr priv,
>>> -  virBufferPtr buf)
>>> +qemuBuildMemoryBackendStr(virDomainDefPtr def,
>>> +  virQEMUDriverConfigPtr cfg,
>>> +  const char *alias,
>>
>> So the one "concern" I'd have here is some time in the future the @mem
>> gets allocated and handled like a real device eventually calling
>> virDomainDeviceInfoClear and that'd be a problem for the passed const
>> char * string.  Some future person's problem I guess!
>>
>>> +  int targetNode,
>>> +  unsigned long long memsize,
>>> +  qemuDomainObjPrivatePtr priv,
>>> +  virBufferPtr buf)
>>
>> As much as a long name is a pain, is this more of a :
>>
>> qemuBuildMemorySharedDefaultBackendStr
> 
> Why?
> 

nm, I think when first reading for some reason I had this "separate"
from the CellBackend call.

[...]

>>> +implicit = true;
>>> +} else {
>>> +ret = 0;
>>> +goto cleanup;
>>> +}
>>> +}
>>
>> So if ncells == 0 && def->mem.access != VIR_DOMAIN_MEMORY_ACCESS_SHARED,
>> then we return 0 without doing the subsequent code? Is that expected? Is
>> there something done later that may be necessary, needed, or assumed.
> 
> No, before the patch, virDomainNumaGetNodeCount() is checked before
> calling qemuBuildNumaArgStr(). Now it is handled inside in case
> ncells==0 && def->mem.access != VIR_DOMAIN_MEMORY_ACCESS_SHARED.
> 

Ah, yes - I missed the check when looking at the changes

-if (virDomainNumaGetNodeCount(def->numa) &&
-qemuBuildNumaArgStr(cfg, def, cmd, priv) < 0)

[...]

>>> diff --git a/tests/qemuxml2argvdata/fd-memory-no-numa-topology.args 
>>> b/tests/qemuxml2argvdata/fd-memory-no-numa-topology.args
>>> index bd88daaa3b..400fb39cc6 100644
>>> --- a/tests/qemuxml2argvdata/fd-memory-no-numa-topology.args
>>> +++ b/tests/qemuxml2argvdata/fd-memory-no-numa-topology.args
>>> @@ -11,6 +11,10 @@ QEMU_AUDIO_DRV=none \
>>>  -m 14336 \
>>>  -mem-prealloc \
>>>  -smp 8,sockets=8,cores=1,threads=1 \
>>> +-object 

Re: [libvirt] [RFC PATCH 01/17] qemu: setup shared memory without explicit numa configuration

2018-08-16 Thread Daniel P . Berrangé
On Fri, Jul 13, 2018 at 03:28:08PM +0200, marcandre.lur...@redhat.com wrote:
> From: Marc-André Lureau 
> 
> When a domain is configured with 'shared' memory backing:
> 
>   
> 
>   
> 
> But no explicit NUMA configuration, let's configure a shared memory
> backend associated with default -numa.


> diff --git a/tests/qemuxml2argvdata/fd-memory-no-numa-topology.args 
> b/tests/qemuxml2argvdata/fd-memory-no-numa-topology.args
> index bd88daaa3b..400fb39cc6 100644
> --- a/tests/qemuxml2argvdata/fd-memory-no-numa-topology.args
> +++ b/tests/qemuxml2argvdata/fd-memory-no-numa-topology.args
> @@ -11,6 +11,10 @@ QEMU_AUDIO_DRV=none \
>  -m 14336 \
>  -mem-prealloc \
>  -smp 8,sockets=8,cores=1,threads=1 \
> +-object memory-backend-file,id=ram-node,\
> +mem-path=/var/lib/libvirt/qemu/ram/libvirt/qemu/-1-instance-0092/ram-node,\
> +share=yes,size=15032385536 \
> +-numa node,nodeid=0,memdev=ram-node \

I'm not at all convinced it is safe todo this. We've been burnt in the
past by adding  use of memory-backend objects causing migration to break


  commit f309db1f4d51009bad0d32e12efc75530b66836b
  Author: Michal Privoznik 
  Date:   Thu Dec 18 12:36:48 2014 +0100

qemu: Create memory-backend-{ram,file} iff needed

Libvirt BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1175397
QEMU BZ:https://bugzilla.redhat.com/show_bug.cgi?id=1170093

This change doesn't really feel like it is required either. If the
user wants NUMA, then the XML can just be written to request a NUMA
topology with a single node.  Better to be explicit in the XML rather
than silently adding things as a side effect

Regards,
Daniel
-- 
|: https://berrange.com  -o-https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o-https://fstop138.berrange.com :|
|: https://entangle-photo.org-o-https://www.instagram.com/dberrange :|

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Re: [libvirt] [RFC PATCH 01/17] qemu: setup shared memory without explicit numa configuration

2018-08-16 Thread Marc-André Lureau
Hi

On Thu, Aug 16, 2018 at 4:35 AM, John Ferlan  wrote:
>
>
> On 07/13/2018 09:28 AM, marcandre.lur...@redhat.com wrote:
>> From: Marc-André Lureau 
>>
>> When a domain is configured with 'shared' memory backing:
>>
>>   
>> 
>>   
>>
>> But no explicit NUMA configuration, let's configure a shared memory
>> backend associated with default -numa.
>>
>> Signed-off-by: Marc-André Lureau 
>> ---
>>  src/qemu/qemu_command.c   | 100 --
>>  .../fd-memory-no-numa-topology.args   |   4 +
>>  2 files changed, 73 insertions(+), 31 deletions(-)
>>
>
> NUMA, memory backends, and hugepages - not in my wheelhouse of
> knowledge. Hopefully Michal and/or Pavel will take a look!
>
> Is it possible someone may not want this type of thing to happen? Is

I assume someone that sets 'shared' memory mode may consider this as a bug fix.

> there an upside or downside to this?  What happens "today" when not

You get non-shared memory

> generated? And of course, what about migration concerns about
> unconditionally doing this for some target migration?

True, this will break migration though if the target uses
numa/memory-backend-file.

What do you suggest?

>
>> diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
>> index 44ae8dcef7..f1235099b2 100644
>> --- a/src/qemu/qemu_command.c
>> +++ b/src/qemu/qemu_command.c
>> @@ -3254,26 +3254,21 @@ qemuBuildMemoryBackendProps(virJSONValuePtr 
>> *backendProps,
>>
>>
>>  static int
>> -qemuBuildMemoryCellBackendStr(virDomainDefPtr def,
>> -  virQEMUDriverConfigPtr cfg,
>> -  size_t cell,
>> -  qemuDomainObjPrivatePtr priv,
>> -  virBufferPtr buf)
>> +qemuBuildMemoryBackendStr(virDomainDefPtr def,
>> +  virQEMUDriverConfigPtr cfg,
>> +  const char *alias,
>
> So the one "concern" I'd have here is some time in the future the @mem
> gets allocated and handled like a real device eventually calling
> virDomainDeviceInfoClear and that'd be a problem for the passed const
> char * string.  Some future person's problem I guess!
>
>> +  int targetNode,
>> +  unsigned long long memsize,
>> +  qemuDomainObjPrivatePtr priv,
>> +  virBufferPtr buf)
>
> As much as a long name is a pain, is this more of a :
>
> qemuBuildMemorySharedDefaultBackendStr

Why?

>
>>  {
>>  virJSONValuePtr props = NULL;
>> -char *alias = NULL;
>> -int ret = -1;
>> -int rc;
>>  virDomainMemoryDef mem = { 0 };
>> -unsigned long long memsize = virDomainNumaGetNodeMemorySize(def->numa,
>> -cell);
>> -
>> -if (virAsprintf(, "ram-node%zu", cell) < 0)
>> -goto cleanup;
>> +int rc, ret = -1;
>>
>>  mem.size = memsize;
>> -mem.targetNode = cell;
>> -mem.info.alias = alias;
>> +mem.targetNode = targetNode;
>> +mem.info.alias = (char *)alias;
>>
>>  if ((rc = qemuBuildMemoryBackendProps(, alias, cfg, 
>> priv->qemuCaps,
>>def, , priv->autoNodeset, 
>> false)) < 0)> @@ -3284,9 +3279,30 @@ 
>> qemuBuildMemoryCellBackendStr(virDomainDefPtr def,
>>
>>  ret = rc;
>>
>> +cleanup:
>
> Fails 'make check syntax-check' :
>
> maint.mk: Top-level labels should be indented by one space
> make: *** [cfg.mk:898: sc_require_space_before_label] Error 1

argh, fixed

>
>> +virJSONValueFree(props);
>> +return ret;
>> +}
>> +
>> +
>> +static int
>> +qemuBuildMemoryCellBackendStr(virDomainDefPtr def,
>> +  virQEMUDriverConfigPtr cfg,
>> +  size_t cell,
>> +  qemuDomainObjPrivatePtr priv,
>> +  virBufferPtr buf)
>> +{
>> +char *alias = NULL;
>> +int ret = -1;
>> +unsigned long long memsize = virDomainNumaGetNodeMemorySize(def->numa, 
>> cell);
>> +
>> +if (virAsprintf(, "ram-node%zu", cell) < 0)
>> +goto cleanup;
>> +
>> +ret = qemuBuildMemoryBackendStr(def, cfg, alias, cell, memsize, priv, 
>> buf);
>> +
>>   cleanup:
>>  VIR_FREE(alias);
>> -virJSONValueFree(props);
>>
>>  return ret;
>>  }
>> @@ -7590,6 +7606,17 @@ qemuBuildNumaArgStr(virQEMUDriverConfigPtr cfg,
>>  size_t ncells = virDomainNumaGetNodeCount(def->numa);
>>  const long system_page_size = virGetSystemPageSizeKB();
>>  bool numa_distances = false;
>> +bool implicit = false;
>> +
>> +if (ncells == 0) {
>> +if (def->mem.access == VIR_DOMAIN_MEMORY_ACCESS_SHARED) {
>> +ncells = 1;
>
> Well, that's cheating for the subsequent for loop ;-)
>
>> +implicit = true;
>> +} else {
>> +ret = 0;
>> +goto cleanup;
>> +}
>> +}
>
> So if ncells == 0 && def->mem.access 

Re: [libvirt] [RFC PATCH 01/17] qemu: setup shared memory without explicit numa configuration

2018-08-15 Thread John Ferlan


On 07/13/2018 09:28 AM, marcandre.lur...@redhat.com wrote:
> From: Marc-André Lureau 
> 
> When a domain is configured with 'shared' memory backing:
> 
>   
> 
>   
> 
> But no explicit NUMA configuration, let's configure a shared memory
> backend associated with default -numa.
> 
> Signed-off-by: Marc-André Lureau 
> ---
>  src/qemu/qemu_command.c   | 100 --
>  .../fd-memory-no-numa-topology.args   |   4 +
>  2 files changed, 73 insertions(+), 31 deletions(-)
> 

NUMA, memory backends, and hugepages - not in my wheelhouse of
knowledge. Hopefully Michal and/or Pavel will take a look!

Is it possible someone may not want this type of thing to happen? Is
there an upside or downside to this?  What happens "today" when not
generated? And of course, what about migration concerns about
unconditionally doing this for some target migration?

> diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
> index 44ae8dcef7..f1235099b2 100644
> --- a/src/qemu/qemu_command.c
> +++ b/src/qemu/qemu_command.c
> @@ -3254,26 +3254,21 @@ qemuBuildMemoryBackendProps(virJSONValuePtr 
> *backendProps,
>  
>  
>  static int
> -qemuBuildMemoryCellBackendStr(virDomainDefPtr def,
> -  virQEMUDriverConfigPtr cfg,
> -  size_t cell,
> -  qemuDomainObjPrivatePtr priv,
> -  virBufferPtr buf)
> +qemuBuildMemoryBackendStr(virDomainDefPtr def,
> +  virQEMUDriverConfigPtr cfg,
> +  const char *alias,

So the one "concern" I'd have here is some time in the future the @mem
gets allocated and handled like a real device eventually calling
virDomainDeviceInfoClear and that'd be a problem for the passed const
char * string.  Some future person's problem I guess!

> +  int targetNode,
> +  unsigned long long memsize,
> +  qemuDomainObjPrivatePtr priv,
> +  virBufferPtr buf)

As much as a long name is a pain, is this more of a :

qemuBuildMemorySharedDefaultBackendStr

>  {
>  virJSONValuePtr props = NULL;
> -char *alias = NULL;
> -int ret = -1;
> -int rc;
>  virDomainMemoryDef mem = { 0 };
> -unsigned long long memsize = virDomainNumaGetNodeMemorySize(def->numa,
> -cell);
> -
> -if (virAsprintf(, "ram-node%zu", cell) < 0)
> -goto cleanup;
> +int rc, ret = -1;
>  
>  mem.size = memsize;
> -mem.targetNode = cell;
> -mem.info.alias = alias;
> +mem.targetNode = targetNode;
> +mem.info.alias = (char *)alias;
>  
>  if ((rc = qemuBuildMemoryBackendProps(, alias, cfg, priv->qemuCaps,
>def, , priv->autoNodeset, 
> false)) < 0)> @@ -3284,9 +3279,30 @@ 
> qemuBuildMemoryCellBackendStr(virDomainDefPtr def,
>  
>  ret = rc;
>  
> +cleanup:

Fails 'make check syntax-check' :

maint.mk: Top-level labels should be indented by one space
make: *** [cfg.mk:898: sc_require_space_before_label] Error 1

> +virJSONValueFree(props);
> +return ret;
> +}
> +
> +
> +static int
> +qemuBuildMemoryCellBackendStr(virDomainDefPtr def,
> +  virQEMUDriverConfigPtr cfg,
> +  size_t cell,
> +  qemuDomainObjPrivatePtr priv,
> +  virBufferPtr buf)
> +{
> +char *alias = NULL;
> +int ret = -1;
> +unsigned long long memsize = virDomainNumaGetNodeMemorySize(def->numa, 
> cell);
> +
> +if (virAsprintf(, "ram-node%zu", cell) < 0)
> +goto cleanup;
> +
> +ret = qemuBuildMemoryBackendStr(def, cfg, alias, cell, memsize, priv, 
> buf);
> +
>   cleanup:
>  VIR_FREE(alias);
> -virJSONValueFree(props);
>  
>  return ret;
>  }
> @@ -7590,6 +7606,17 @@ qemuBuildNumaArgStr(virQEMUDriverConfigPtr cfg,
>  size_t ncells = virDomainNumaGetNodeCount(def->numa);
>  const long system_page_size = virGetSystemPageSizeKB();
>  bool numa_distances = false;
> +bool implicit = false;
> +
> +if (ncells == 0) {
> +if (def->mem.access == VIR_DOMAIN_MEMORY_ACCESS_SHARED) {
> +ncells = 1;

Well, that's cheating for the subsequent for loop ;-)

> +implicit = true;
> +} else {
> +ret = 0;
> +goto cleanup;
> +}
> +}

So if ncells == 0 && def->mem.access != VIR_DOMAIN_MEMORY_ACCESS_SHARED,
then we return 0 without doing the subsequent code? Is that expected? Is
there something done later that may be necessary, needed, or assumed.

>  
>  if (virDomainNumatuneHasPerNodeBinding(def->numa) &&
>  !(virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_MEMORY_RAM) ||
> @@ -7645,14 +7672,22 @@ qemuBuildNumaArgStr(virQEMUDriverConfigPtr cfg,
>  if (virQEMUCapsGet(qemuCaps, 

[libvirt] [RFC PATCH 01/17] qemu: setup shared memory without explicit numa configuration

2018-07-13 Thread marcandre . lureau
From: Marc-André Lureau 

When a domain is configured with 'shared' memory backing:

  

  

But no explicit NUMA configuration, let's configure a shared memory
backend associated with default -numa.

Signed-off-by: Marc-André Lureau 
---
 src/qemu/qemu_command.c   | 100 --
 .../fd-memory-no-numa-topology.args   |   4 +
 2 files changed, 73 insertions(+), 31 deletions(-)

diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 44ae8dcef7..f1235099b2 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -3254,26 +3254,21 @@ qemuBuildMemoryBackendProps(virJSONValuePtr 
*backendProps,
 
 
 static int
-qemuBuildMemoryCellBackendStr(virDomainDefPtr def,
-  virQEMUDriverConfigPtr cfg,
-  size_t cell,
-  qemuDomainObjPrivatePtr priv,
-  virBufferPtr buf)
+qemuBuildMemoryBackendStr(virDomainDefPtr def,
+  virQEMUDriverConfigPtr cfg,
+  const char *alias,
+  int targetNode,
+  unsigned long long memsize,
+  qemuDomainObjPrivatePtr priv,
+  virBufferPtr buf)
 {
 virJSONValuePtr props = NULL;
-char *alias = NULL;
-int ret = -1;
-int rc;
 virDomainMemoryDef mem = { 0 };
-unsigned long long memsize = virDomainNumaGetNodeMemorySize(def->numa,
-cell);
-
-if (virAsprintf(, "ram-node%zu", cell) < 0)
-goto cleanup;
+int rc, ret = -1;
 
 mem.size = memsize;
-mem.targetNode = cell;
-mem.info.alias = alias;
+mem.targetNode = targetNode;
+mem.info.alias = (char *)alias;
 
 if ((rc = qemuBuildMemoryBackendProps(, alias, cfg, priv->qemuCaps,
   def, , priv->autoNodeset, 
false)) < 0)
@@ -3284,9 +3279,30 @@ qemuBuildMemoryCellBackendStr(virDomainDefPtr def,
 
 ret = rc;
 
+cleanup:
+virJSONValueFree(props);
+return ret;
+}
+
+
+static int
+qemuBuildMemoryCellBackendStr(virDomainDefPtr def,
+  virQEMUDriverConfigPtr cfg,
+  size_t cell,
+  qemuDomainObjPrivatePtr priv,
+  virBufferPtr buf)
+{
+char *alias = NULL;
+int ret = -1;
+unsigned long long memsize = virDomainNumaGetNodeMemorySize(def->numa, 
cell);
+
+if (virAsprintf(, "ram-node%zu", cell) < 0)
+goto cleanup;
+
+ret = qemuBuildMemoryBackendStr(def, cfg, alias, cell, memsize, priv, buf);
+
  cleanup:
 VIR_FREE(alias);
-virJSONValueFree(props);
 
 return ret;
 }
@@ -7590,6 +7606,17 @@ qemuBuildNumaArgStr(virQEMUDriverConfigPtr cfg,
 size_t ncells = virDomainNumaGetNodeCount(def->numa);
 const long system_page_size = virGetSystemPageSizeKB();
 bool numa_distances = false;
+bool implicit = false;
+
+if (ncells == 0) {
+if (def->mem.access == VIR_DOMAIN_MEMORY_ACCESS_SHARED) {
+ncells = 1;
+implicit = true;
+} else {
+ret = 0;
+goto cleanup;
+}
+}
 
 if (virDomainNumatuneHasPerNodeBinding(def->numa) &&
 !(virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_MEMORY_RAM) ||
@@ -7645,14 +7672,22 @@ qemuBuildNumaArgStr(virQEMUDriverConfigPtr cfg,
 if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_MEMORY_RAM) ||
 virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_MEMORY_FILE)) {
 
-if ((rc = qemuBuildMemoryCellBackendStr(def, cfg, i, priv,
-[i])) < 0)
+
+if (implicit)
+rc = qemuBuildMemoryBackendStr(def, cfg, "ram-node", -1,
+   def->mem.total_memory,
+   priv, [i]);
+else
+rc = qemuBuildMemoryCellBackendStr(def, cfg, i,
+   priv, [i]);
+if (rc < 0)
 goto cleanup;
 
 if (rc == 0)
 needBackend = true;
 } else {
-if (virDomainNumaGetNodeMemoryAccessMode(def->numa, i)) {
+if (implicit ||
+virDomainNumaGetNodeMemoryAccessMode(def->numa, i)) {
 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("Shared memory mapping is not supported "
  "with this QEMU"));
@@ -7667,15 +7702,18 @@ qemuBuildNumaArgStr(virQEMUDriverConfigPtr cfg,
 
 for (i = 0; i < ncells; i++) {
 VIR_FREE(cpumask);
-if (!(cpumask = virBitmapFormat(virDomainNumaGetNodeCpumask(def->numa, 
i
-goto cleanup;
 
-if (strchr(cpumask, ',') &&
-!virQEMUCapsGet(qemuCaps, QEMU_CAPS_NUMA)) {
-