提交 b4e8a49f 编写于 作者: M Michal Privoznik

Introduce NVDIMM memory model

NVDIMM is new type of memory introduced into QEMU 2.6. The idea
is that we have a Non-Volatile memory module that keeps the data
persistent across domain reboots.

At the domain XML level, we already have some representation of
'dimm' modules. Long story short, NVDIMM will utilize the
existing <memory/> element that lives under <devices/> by adding
a new attribute 'nvdimm' to the existing @model and introduce a
new <path/> element for <source/> while reusing other fields. The
resulting XML would appear as:

    <memory model='nvdimm'>
      <source>
        <path>/tmp/nvdimm</path>
      </source>
      <target>
        <size unit='KiB'>523264</size>
        <node>0</node>
      </target>
      <address type='dimm' slot='0'/>
    </memory>

So far, this is just a XML parser/formatter extension. QEMU
driver implementation is in the next commit.

For more info on NVDIMM visit the following web page:

    http://pmem.io/Signed-off-by: NMichal Privoznik <mprivozn@redhat.com>
上级 8cbdd2ca
......@@ -7092,7 +7092,6 @@ qemu-kvm -net nic,model=? /dev/null
guests' memory resource needs.
Some hypervisors may require NUMA configured for the guest.
<span class="since">Since 1.2.14</span>
</p>
<p>
......@@ -7117,6 +7116,15 @@ qemu-kvm -net nic,model=? /dev/null
&lt;node&gt;1&lt;/node&gt;
&lt;/target&gt;
&lt;/memory&gt;
&lt;memory model='nvdimm'&gt;
&lt;source&gt;
&lt;path&gt;/tmp/nvdimm&lt;/path&gt;
&lt;/source&gt;
&lt;target&gt;
&lt;size unit='KiB'&gt;524288&lt;/size&gt;
&lt;node&gt;1&lt;/node&gt;
&lt;/target&gt;
&lt;/memory&gt;
&lt;/devices&gt;
...
</pre>
......@@ -7124,28 +7132,48 @@ qemu-kvm -net nic,model=? /dev/null
<dt><code>model</code></dt>
<dd>
<p>
Currently only the <code>dimm</code> model is supported in order to
add a virtual DIMM module to the guest.
Provide <code>dimm</code> to add a virtual DIMM module to the guest.
<span class="since">Since 1.2.14</span>
Provide <code>nvdimm</code> model adds a Non-Volatile DIMM
module. <span class="since">Since 3.2.0</span>
</p>
</dd>
<dt><code>source</code></dt>
<dd>
<p>
The optional source element allows to fine tune the source of the
memory used for the given memory device. If the element is not
provided defaults configured via <code>numatune</code> are used.
For model <code>dimm</code> this element is optional and allows to
fine tune the source of the memory used for the given memory device.
If the element is not provided defaults configured via
<code>numatune</code> are used. If <code>dimm</code> is provided,
then the following optional elements can be provided as well:
</p>
<dl>
<dt><code>pagesize</code></dt>
<dd>
<p>
<code>pagesize</code> can optionally be used to override the default
This element can be used to override the default
host page size used for backing the memory device.
The configured value must correspond to a page size
supported by the host.
</p>
</dd>
The configured value must correspond to a page size supported by the
host.
<dt><code>nodemask</code></dt>
<dd>
<p>
This element can be used to override the default
set of NUMA nodes where the memory would be
allocated.
</p>
</dd>
</dl>
<p>
<code>nodemask</code> can optionally be used to override the default
set of NUMA nodes where the memory would be allocated.
For model <code>nvdimm</code> this element is mandatory and has a
single child element <code>path</code> that represents a path
in the host that backs the nvdimm module in the guest.
</p>
</dd>
......
......@@ -4747,6 +4747,7 @@
<attribute name="model">
<choice>
<value>dimm</value>
<value>nvdimm</value>
</choice>
</attribute>
<interleave>
......@@ -4766,6 +4767,8 @@
<define name="memorydev-source">
<element name="source">
<choice>
<group>
<interleave>
<optional>
<element name="pagesize">
......@@ -4778,6 +4781,13 @@
</element>
</optional>
</interleave>
</group>
<group>
<element name="path">
<ref name="absFilePath"/>
</element>
</group>
</choice>
</element>
</define>
......
......@@ -859,8 +859,11 @@ VIR_ENUM_DECL(virDomainBlockJob)
VIR_ENUM_IMPL(virDomainBlockJob, VIR_DOMAIN_BLOCK_JOB_TYPE_LAST,
"", "", "copy", "", "active-commit")
VIR_ENUM_IMPL(virDomainMemoryModel, VIR_DOMAIN_MEMORY_MODEL_LAST,
"", "dimm")
VIR_ENUM_IMPL(virDomainMemoryModel,
VIR_DOMAIN_MEMORY_MODEL_LAST,
"",
"dimm",
"nvdimm")
VIR_ENUM_IMPL(virDomainShmemModel, VIR_DOMAIN_SHMEM_MODEL_LAST,
"ivshmem",
......@@ -2419,6 +2422,7 @@ void virDomainMemoryDefFree(virDomainMemoryDefPtr def)
if (!def)
return;
VIR_FREE(def->nvdimmPath);
virBitmapFree(def->sourceNodes);
virDomainDeviceInfoClear(&def->info);
VIR_FREE(def);
......@@ -13716,6 +13720,8 @@ virDomainMemorySourceDefParseXML(xmlNodePtr node,
xmlNodePtr save = ctxt->node;
ctxt->node = node;
switch ((virDomainMemoryModel) def->model) {
case VIR_DOMAIN_MEMORY_MODEL_DIMM:
if (virDomainParseMemory("./pagesize", "./pagesize/@unit", ctxt,
&def->pagesize, false, false) < 0)
goto cleanup;
......@@ -13731,6 +13737,20 @@ virDomainMemorySourceDefParseXML(xmlNodePtr node,
goto cleanup;
}
}
break;
case VIR_DOMAIN_MEMORY_MODEL_NVDIMM:
if (!(def->nvdimmPath = virXPathString("string(./path)", ctxt))) {
virReportError(VIR_ERR_XML_DETAIL, "%s",
_("path is required for model nvdimm'"));
goto cleanup;
}
break;
case VIR_DOMAIN_MEMORY_MODEL_NONE:
case VIR_DOMAIN_MEMORY_MODEL_LAST:
break;
}
ret = 0;
......@@ -15134,12 +15154,25 @@ virDomainMemoryFindByDefInternal(virDomainDefPtr def,
tmp->size != mem->size)
continue;
switch ((virDomainMemoryModel) mem->model) {
case VIR_DOMAIN_MEMORY_MODEL_DIMM:
/* source stuff -> match with device */
if (tmp->pagesize != mem->pagesize)
continue;
if (!virBitmapEqual(tmp->sourceNodes, mem->sourceNodes))
continue;
break;
case VIR_DOMAIN_MEMORY_MODEL_NVDIMM:
if (STRNEQ(tmp->nvdimmPath, mem->nvdimmPath))
continue;
break;
case VIR_DOMAIN_MEMORY_MODEL_NONE:
case VIR_DOMAIN_MEMORY_MODEL_LAST:
break;
}
break;
}
......@@ -22532,12 +22565,14 @@ virDomainMemorySourceDefFormat(virBufferPtr buf,
char *bitmap = NULL;
int ret = -1;
if (!def->pagesize && !def->sourceNodes)
if (!def->pagesize && !def->sourceNodes && !def->nvdimmPath)
return 0;
virBufferAddLit(buf, "<source>\n");
virBufferAdjustIndent(buf, 2);
switch ((virDomainMemoryModel) def->model) {
case VIR_DOMAIN_MEMORY_MODEL_DIMM:
if (def->sourceNodes) {
if (!(bitmap = virBitmapFormat(def->sourceNodes)))
goto cleanup;
......@@ -22548,6 +22583,16 @@ virDomainMemorySourceDefFormat(virBufferPtr buf,
if (def->pagesize)
virBufferAsprintf(buf, "<pagesize unit='KiB'>%llu</pagesize>\n",
def->pagesize);
break;
case VIR_DOMAIN_MEMORY_MODEL_NVDIMM:
virBufferEscapeString(buf, "<path>%s</path>\n", def->nvdimmPath);
break;
case VIR_DOMAIN_MEMORY_MODEL_NONE:
case VIR_DOMAIN_MEMORY_MODEL_LAST:
break;
}
virBufferAdjustIndent(buf, -2);
virBufferAddLit(buf, "</source>\n");
......
......@@ -1997,6 +1997,7 @@ struct _virDomainRNGDef {
typedef enum {
VIR_DOMAIN_MEMORY_MODEL_NONE,
VIR_DOMAIN_MEMORY_MODEL_DIMM, /* dimm hotpluggable memory device */
VIR_DOMAIN_MEMORY_MODEL_NVDIMM, /* nvdimm memory device */
VIR_DOMAIN_MEMORY_MODEL_LAST
} virDomainMemoryModel;
......@@ -2005,6 +2006,7 @@ struct _virDomainMemoryDef {
/* source */
virBitmapPtr sourceNodes;
unsigned long long pagesize; /* kibibytes */
char *nvdimmPath;
/* target */
int model; /* virDomainMemoryModel */
......
......@@ -3515,6 +3515,12 @@ qemuBuildMemoryDeviceStr(virDomainMemoryDefPtr mem)
break;
case VIR_DOMAIN_MEMORY_MODEL_NVDIMM:
virReportError(VIR_ERR_NO_SUPPORT, "%s",
_("nvdimm not supported yet"));
return NULL;
break;
case VIR_DOMAIN_MEMORY_MODEL_NONE:
case VIR_DOMAIN_MEMORY_MODEL_LAST:
break;
......
......@@ -5967,6 +5967,11 @@ qemuDomainDefValidateMemoryHotplugDevice(const virDomainMemoryDef *mem,
}
break;
case VIR_DOMAIN_MEMORY_MODEL_NVDIMM:
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("nvdimm hotplug not supported yet"));
return -1;
case VIR_DOMAIN_MEMORY_MODEL_NONE:
case VIR_DOMAIN_MEMORY_MODEL_LAST:
return -1;
......
<domain type='qemu'>
<name>QEMUGuest1</name>
<uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
<maxMemory slots='16' unit='KiB'>1099511627776</maxMemory>
<memory unit='KiB'>1267710</memory>
<currentMemory unit='KiB'>1267710</currentMemory>
<vcpu placement='static' cpuset='0-1'>2</vcpu>
<os>
<type arch='i686' machine='pc'>hvm</type>
<boot dev='hd'/>
</os>
<idmap>
<uid start='0' target='1000' count='10'/>
<gid start='0' target='1000' count='10'/>
</idmap>
<cpu>
<topology sockets='2' cores='1' threads='1'/>
<numa>
<cell id='0' cpus='0-1' memory='1048576' unit='KiB'/>
</numa>
</cpu>
<clock offset='utc'/>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>destroy</on_crash>
<devices>
<emulator>/usr/bin/qemu</emulator>
<disk type='block' device='disk'>
<source dev='/dev/HostVG/QEMUGuest1'/>
<target dev='hda' bus='ide'/>
<address type='drive' controller='0' bus='0' target='0' unit='0'/>
</disk>
<controller type='ide' index='0'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
</controller>
<controller type='usb' index='0'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
</controller>
<controller type='pci' index='0' model='pci-root'/>
<input type='mouse' bus='ps2'/>
<input type='keyboard' bus='ps2'/>
<memballoon model='virtio'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
</memballoon>
<memory model='nvdimm'>
<source>
<path>/tmp/nvdimm</path>
</source>
<target>
<size unit='KiB'>523264</size>
<node>0</node>
</target>
<address type='dimm' slot='0'/>
</memory>
</devices>
</domain>
../qemuxml2argvdata/qemuxml2argv-memory-hotplug-nvdimm.xml
\ No newline at end of file
......@@ -1078,6 +1078,7 @@ mymain(void)
DO_TEST("memory-hotplug", NONE);
DO_TEST("memory-hotplug-nonuma", NONE);
DO_TEST("memory-hotplug-dimm", NONE);
DO_TEST("memory-hotplug-nvdimm", NONE);
DO_TEST("net-udp", NONE);
DO_TEST("video-virtio-gpu-device", NONE);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册