|
|
397dc2 |
From 17e9b949ec3876e74bcaa217810afbd46f297a65 Mon Sep 17 00:00:00 2001
|
|
|
397dc2 |
Message-Id: <17e9b949ec3876e74bcaa217810afbd46f297a65@dist-git>
|
|
|
397dc2 |
From: Michal Privoznik <mprivozn@redhat.com>
|
|
|
397dc2 |
Date: Wed, 7 Oct 2020 18:45:39 +0200
|
|
|
397dc2 |
Subject: [PATCH] conf: Parse and format HMAT
|
|
|
397dc2 |
MIME-Version: 1.0
|
|
|
397dc2 |
Content-Type: text/plain; charset=UTF-8
|
|
|
397dc2 |
Content-Transfer-Encoding: 8bit
|
|
|
397dc2 |
|
|
|
397dc2 |
To cite ACPI specification:
|
|
|
397dc2 |
|
|
|
397dc2 |
Heterogeneous Memory Attribute Table describes the memory
|
|
|
397dc2 |
attributes, such as memory side cache attributes and bandwidth
|
|
|
397dc2 |
and latency details, related to the System Physical Address
|
|
|
397dc2 |
(SPA) Memory Ranges. The software is expected to use this
|
|
|
397dc2 |
information as hint for optimization.
|
|
|
397dc2 |
|
|
|
397dc2 |
According to our upstream discussion [1] this is exposed under
|
|
|
397dc2 |
<numa/> as <cache/> under NUMA <cell/> and <latency> or
|
|
|
397dc2 |
<bandwidth/> under numa/latencies.
|
|
|
397dc2 |
|
|
|
397dc2 |
1: https://www.redhat.com/archives/libvir-list/2020-January/msg00422.html
|
|
|
397dc2 |
|
|
|
397dc2 |
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
|
|
|
397dc2 |
Reviewed-by: Daniel Henrique Barboza <danielhb413@gmail.com>
|
|
|
397dc2 |
(cherry picked from commit a89bbbac86383a10be0cec5a93feb7ed820871eb)
|
|
|
397dc2 |
|
|
|
397dc2 |
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1749518
|
|
|
397dc2 |
|
|
|
397dc2 |
Conflicts:
|
|
|
397dc2 |
- src/conf/numa_conf.c: Context, because we're not using
|
|
|
397dc2 |
VIR_XPATH_NODE_AUTORESTORE() everywhere in the old code.
|
|
|
397dc2 |
|
|
|
397dc2 |
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
|
|
|
397dc2 |
Message-Id: <f5d9028ca8eff876c2bd471460629d0ef3b20630.1602087923.git.mprivozn@redhat.com>
|
|
|
397dc2 |
Reviewed-by: Ján Tomko <jtomko@redhat.com>
|
|
|
397dc2 |
---
|
|
|
397dc2 |
docs/formatdomain.html.in | 107 +++++++
|
|
|
397dc2 |
docs/schemas/cputypes.rng | 110 ++++++-
|
|
|
397dc2 |
src/conf/numa_conf.c | 349 ++++++++++++++++++++-
|
|
|
397dc2 |
src/conf/numa_conf.h | 33 ++
|
|
|
397dc2 |
src/libvirt_private.syms | 6 +
|
|
|
397dc2 |
tests/qemuxml2argvdata/numatune-hmat.xml | 52 +++
|
|
|
397dc2 |
tests/qemuxml2xmloutdata/numatune-hmat.xml | 1 +
|
|
|
397dc2 |
tests/qemuxml2xmltest.c | 1 +
|
|
|
397dc2 |
8 files changed, 644 insertions(+), 15 deletions(-)
|
|
|
397dc2 |
create mode 100644 tests/qemuxml2argvdata/numatune-hmat.xml
|
|
|
397dc2 |
create mode 120000 tests/qemuxml2xmloutdata/numatune-hmat.xml
|
|
|
397dc2 |
|
|
|
397dc2 |
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
|
|
|
397dc2 |
index 4b8d312596..bec753e37f 100644
|
|
|
397dc2 |
--- a/docs/formatdomain.html.in
|
|
|
397dc2 |
+++ b/docs/formatdomain.html.in
|
|
|
397dc2 |
@@ -1874,6 +1874,113 @@
|
|
|
397dc2 |
using 10 for local and 20 for remote distances.
|
|
|
397dc2 |
|
|
|
397dc2 |
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+...
|
|
|
397dc2 |
+<cpu>
|
|
|
397dc2 |
+ ...
|
|
|
397dc2 |
+ <numa>
|
|
|
397dc2 |
+ <cell id='0' cpus='0-3' memory='512000' unit='KiB' discard='yes'/>
|
|
|
397dc2 |
+ <cell id='1' cpus='4-7' memory='512000' unit='KiB' memAccess='shared'/>
|
|
|
397dc2 |
+ <cell id='3' cpus='0-3' memory='2097152' unit='KiB'>
|
|
|
397dc2 |
+ <cache level='1' associativity='direct' policy='writeback'>
|
|
|
397dc2 |
+ <size value='10' unit='KiB'/>
|
|
|
397dc2 |
+ <line value='8' unit='B'/>
|
|
|
397dc2 |
+ </cache>
|
|
|
397dc2 |
+ </cell>
|
|
|
397dc2 |
+ <interconnects>
|
|
|
397dc2 |
+ <latency initiator='0' target='0' type='access' value='5'/>
|
|
|
397dc2 |
+ <latency initiator='0' target='0' cache='1' type='access' value='10'/>
|
|
|
397dc2 |
+ <bandwidth initiator='0' target='0' type='access' value='204800' unit='KiB'/>
|
|
|
397dc2 |
+ </interconnects>
|
|
|
397dc2 |
+ </numa>
|
|
|
397dc2 |
+ ...
|
|
|
397dc2 |
+</cpu>
|
|
|
397dc2 |
+...
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ Since 6.6.0 the cell element can
|
|
|
397dc2 |
+ have a cache child element which describes memory side cache
|
|
|
397dc2 |
+ for memory proximity domains. The cache element has a
|
|
|
397dc2 |
+ level attribute describing the cache level and thus the
|
|
|
397dc2 |
+ element can be repeated multiple times to describe different levels of
|
|
|
397dc2 |
+ the cache.
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ The cache element then has following mandatory attributes:
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ level
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ Level of the cache this description refers to.
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ associativity
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ Describes cache associativity (accepted values are none ,
|
|
|
397dc2 |
+ direct and full ).
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ policy
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ Describes cache write associativity (accepted values are
|
|
|
397dc2 |
+ none , writeback and
|
|
|
397dc2 |
+ writethrough ).
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ The cache element has two mandatory child elements then:
|
|
|
397dc2 |
+ size and line which describe cache size and
|
|
|
397dc2 |
+ cache line size. Both elements accept two attributes: value
|
|
|
397dc2 |
+ and unit which set the value of corresponding cache
|
|
|
397dc2 |
+ attribute.
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ The NUMA description has an optional interconnects element that
|
|
|
397dc2 |
+ describes the normalized memory read/write latency, read/write bandwidth
|
|
|
397dc2 |
+ between Initiator Proximity Domains (Processor or I/O) and Target
|
|
|
397dc2 |
+ Proximity Domains (Memory).
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ The interconnects element can have zero or more
|
|
|
397dc2 |
+ latency child elements to describe latency between two
|
|
|
397dc2 |
+ memory nodes and zero or more bandwidth child elements to
|
|
|
397dc2 |
+ describe bandwidth between two memory nodes. Both these have the
|
|
|
397dc2 |
+ following mandatory attributes:
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ initiator
|
|
|
397dc2 |
+ Refers to the source NUMA node
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ target
|
|
|
397dc2 |
+ Refers to the target NUMA node
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ type
|
|
|
397dc2 |
+ The type of the access. Accepted values: access ,
|
|
|
397dc2 |
+ read , write
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ value
|
|
|
397dc2 |
+ The actual value. For latency this is delay in nanoseconds, for
|
|
|
397dc2 |
+ bandwidth this value is in kibibytes per second. Use additional
|
|
|
397dc2 |
+ unit attribute to change the units.
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ To describe latency from one NUMA node to a cache of another NUMA node
|
|
|
397dc2 |
+ the latency element has optional cache
|
|
|
397dc2 |
+ attribute which in combination with target attribute creates
|
|
|
397dc2 |
+ full reference to distant NUMA node's cache level. For instance,
|
|
|
397dc2 |
+ target='0' cache='1' refers to the first level cache of NUMA
|
|
|
397dc2 |
+ node 0.
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+
|
|
|
397dc2 |
|
|
|
397dc2 |
|
|
|
397dc2 |
|
|
|
397dc2 |
diff --git a/docs/schemas/cputypes.rng b/docs/schemas/cputypes.rng
|
|
|
397dc2 |
index a1682a1003..ba30dbf9ff 100644
|
|
|
397dc2 |
--- a/docs/schemas/cputypes.rng
|
|
|
397dc2 |
+++ b/docs/schemas/cputypes.rng
|
|
|
397dc2 |
@@ -102,9 +102,14 @@
|
|
|
397dc2 |
|
|
|
397dc2 |
<define name="cpuNuma">
|
|
|
397dc2 |
<element name="numa">
|
|
|
397dc2 |
- <oneOrMore>
|
|
|
397dc2 |
- <ref name="numaCell"/>
|
|
|
397dc2 |
- </oneOrMore>
|
|
|
397dc2 |
+ <interleave>
|
|
|
397dc2 |
+ <oneOrMore>
|
|
|
397dc2 |
+ <ref name="numaCell"/>
|
|
|
397dc2 |
+ </oneOrMore>
|
|
|
397dc2 |
+ <optional>
|
|
|
397dc2 |
+ <ref name="numaInterconnects"/>
|
|
|
397dc2 |
+ </optional>
|
|
|
397dc2 |
+ </interleave>
|
|
|
397dc2 |
</element>
|
|
|
397dc2 |
</define>
|
|
|
397dc2 |
|
|
|
397dc2 |
@@ -148,6 +153,9 @@
|
|
|
397dc2 |
</oneOrMore>
|
|
|
397dc2 |
</element>
|
|
|
397dc2 |
</optional>
|
|
|
397dc2 |
+ <zeroOrMore>
|
|
|
397dc2 |
+ <ref name="numaCache"/>
|
|
|
397dc2 |
+ </zeroOrMore>
|
|
|
397dc2 |
</element>
|
|
|
397dc2 |
</define>
|
|
|
397dc2 |
|
|
|
397dc2 |
@@ -162,6 +170,102 @@
|
|
|
397dc2 |
</element>
|
|
|
397dc2 |
</define>
|
|
|
397dc2 |
|
|
|
397dc2 |
+ <define name="numaCache">
|
|
|
397dc2 |
+ <element name="cache">
|
|
|
397dc2 |
+ <attribute name="level">
|
|
|
397dc2 |
+ <ref name="unsignedInt"/>
|
|
|
397dc2 |
+ </attribute>
|
|
|
397dc2 |
+ <attribute name="associativity">
|
|
|
397dc2 |
+ <choice>
|
|
|
397dc2 |
+ <value>none</value>
|
|
|
397dc2 |
+ <value>direct</value>
|
|
|
397dc2 |
+ <value>full</value>
|
|
|
397dc2 |
+ </choice>
|
|
|
397dc2 |
+ </attribute>
|
|
|
397dc2 |
+ <attribute name="policy">
|
|
|
397dc2 |
+ <choice>
|
|
|
397dc2 |
+ <value>none</value>
|
|
|
397dc2 |
+ <value>writeback</value>
|
|
|
397dc2 |
+ <value>writethrough</value>
|
|
|
397dc2 |
+ </choice>
|
|
|
397dc2 |
+ </attribute>
|
|
|
397dc2 |
+ <interleave>
|
|
|
397dc2 |
+ <element name="size">
|
|
|
397dc2 |
+ <attribute name="value">
|
|
|
397dc2 |
+ <ref name="unsignedInt"/>
|
|
|
397dc2 |
+ </attribute>
|
|
|
397dc2 |
+ <attribute name="unit">
|
|
|
397dc2 |
+ <ref name="unit"/>
|
|
|
397dc2 |
+ </attribute>
|
|
|
397dc2 |
+ </element>
|
|
|
397dc2 |
+ <element name="line">
|
|
|
397dc2 |
+ <attribute name="value">
|
|
|
397dc2 |
+ <ref name="unsignedInt"/>
|
|
|
397dc2 |
+ </attribute>
|
|
|
397dc2 |
+ <attribute name="unit">
|
|
|
397dc2 |
+ <ref name="unit"/>
|
|
|
397dc2 |
+ </attribute>
|
|
|
397dc2 |
+ </element>
|
|
|
397dc2 |
+ </interleave>
|
|
|
397dc2 |
+ </element>
|
|
|
397dc2 |
+ </define>
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ <define name="numaInterconnects">
|
|
|
397dc2 |
+ <element name="interconnects">
|
|
|
397dc2 |
+ <interleave>
|
|
|
397dc2 |
+ <zeroOrMore>
|
|
|
397dc2 |
+ <element name="latency">
|
|
|
397dc2 |
+ <attribute name="initiator">
|
|
|
397dc2 |
+ <ref name="unsignedInt"/>
|
|
|
397dc2 |
+ </attribute>
|
|
|
397dc2 |
+ <attribute name="target">
|
|
|
397dc2 |
+ <ref name="unsignedInt"/>
|
|
|
397dc2 |
+ </attribute>
|
|
|
397dc2 |
+ <optional>
|
|
|
397dc2 |
+ <attribute name="cache">
|
|
|
397dc2 |
+ <ref name="unsignedInt"/>
|
|
|
397dc2 |
+ </attribute>
|
|
|
397dc2 |
+ </optional>
|
|
|
397dc2 |
+ <attribute name="type">
|
|
|
397dc2 |
+ <choice>
|
|
|
397dc2 |
+ <value>access</value>
|
|
|
397dc2 |
+ <value>read</value>
|
|
|
397dc2 |
+ <value>write</value>
|
|
|
397dc2 |
+ </choice>
|
|
|
397dc2 |
+ </attribute>
|
|
|
397dc2 |
+ <attribute name="value">
|
|
|
397dc2 |
+ <ref name="unsignedInt"/>
|
|
|
397dc2 |
+ </attribute>
|
|
|
397dc2 |
+ <empty/>
|
|
|
397dc2 |
+ </element>
|
|
|
397dc2 |
+ </zeroOrMore>
|
|
|
397dc2 |
+ <zeroOrMore>
|
|
|
397dc2 |
+ <element name="bandwidth">
|
|
|
397dc2 |
+ <attribute name="initiator">
|
|
|
397dc2 |
+ <ref name="unsignedInt"/>
|
|
|
397dc2 |
+ </attribute>
|
|
|
397dc2 |
+ <attribute name="target">
|
|
|
397dc2 |
+ <ref name="unsignedInt"/>
|
|
|
397dc2 |
+ </attribute>
|
|
|
397dc2 |
+ <attribute name="type">
|
|
|
397dc2 |
+ <choice>
|
|
|
397dc2 |
+ <value>access</value>
|
|
|
397dc2 |
+ <value>read</value>
|
|
|
397dc2 |
+ <value>write</value>
|
|
|
397dc2 |
+ </choice>
|
|
|
397dc2 |
+ </attribute>
|
|
|
397dc2 |
+ <attribute name="value">
|
|
|
397dc2 |
+ <ref name="unsignedInt"/>
|
|
|
397dc2 |
+ </attribute>
|
|
|
397dc2 |
+ <attribute name="unit">
|
|
|
397dc2 |
+ <ref name="unit"/>
|
|
|
397dc2 |
+ </attribute>
|
|
|
397dc2 |
+ </element>
|
|
|
397dc2 |
+ </zeroOrMore>
|
|
|
397dc2 |
+ </interleave>
|
|
|
397dc2 |
+ </element>
|
|
|
397dc2 |
+ </define>
|
|
|
397dc2 |
+
|
|
|
397dc2 |
|
|
|
397dc2 |
<define name="memoryKB">
|
|
|
397dc2 |
<data type="unsignedLong"/>
|
|
|
397dc2 |
diff --git a/src/conf/numa_conf.c b/src/conf/numa_conf.c
|
|
|
397dc2 |
index a805336d16..5c764190c3 100644
|
|
|
397dc2 |
--- a/src/conf/numa_conf.c
|
|
|
397dc2 |
+++ b/src/conf/numa_conf.c
|
|
|
397dc2 |
@@ -59,9 +59,37 @@ VIR_ENUM_IMPL(virDomainMemoryAccess,
|
|
|
397dc2 |
"private",
|
|
|
397dc2 |
);
|
|
|
397dc2 |
|
|
|
397dc2 |
+VIR_ENUM_IMPL(virDomainCacheAssociativity,
|
|
|
397dc2 |
+ VIR_DOMAIN_CACHE_ASSOCIATIVITY_LAST,
|
|
|
397dc2 |
+ "none",
|
|
|
397dc2 |
+ "direct",
|
|
|
397dc2 |
+ "full",
|
|
|
397dc2 |
+);
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+VIR_ENUM_IMPL(virDomainCachePolicy,
|
|
|
397dc2 |
+ VIR_DOMAIN_CACHE_POLICY_LAST,
|
|
|
397dc2 |
+ "none",
|
|
|
397dc2 |
+ "writeback",
|
|
|
397dc2 |
+ "writethrough",
|
|
|
397dc2 |
+);
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+VIR_ENUM_IMPL(virDomainMemoryLatency,
|
|
|
397dc2 |
+ VIR_DOMAIN_MEMORY_LATENCY_LAST,
|
|
|
397dc2 |
+ "none",
|
|
|
397dc2 |
+ "access",
|
|
|
397dc2 |
+ "read",
|
|
|
397dc2 |
+ "write"
|
|
|
397dc2 |
+);
|
|
|
397dc2 |
+
|
|
|
397dc2 |
typedef struct _virDomainNumaDistance virDomainNumaDistance;
|
|
|
397dc2 |
typedef virDomainNumaDistance *virDomainNumaDistancePtr;
|
|
|
397dc2 |
|
|
|
397dc2 |
+typedef struct _virDomainNumaCache virDomainNumaCache;
|
|
|
397dc2 |
+typedef virDomainNumaCache *virDomainNumaCachePtr;
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+typedef struct _virDomainNumaInterconnect virDomainNumaInterconnect;
|
|
|
397dc2 |
+typedef virDomainNumaInterconnect *virDomainNumaInterconnectPtr;
|
|
|
397dc2 |
+
|
|
|
397dc2 |
typedef struct _virDomainNumaNode virDomainNumaNode;
|
|
|
397dc2 |
typedef virDomainNumaNode *virDomainNumaNodePtr;
|
|
|
397dc2 |
|
|
|
397dc2 |
@@ -86,9 +114,30 @@ struct _virDomainNuma {
|
|
|
397dc2 |
unsigned int cellid;
|
|
|
397dc2 |
} *distances; /* remote node distances */
|
|
|
397dc2 |
size_t ndistances;
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ struct _virDomainNumaCache {
|
|
|
397dc2 |
+ unsigned int level; /* cache level */
|
|
|
397dc2 |
+ unsigned int size; /* cache size */
|
|
|
397dc2 |
+ unsigned int line; /* line size, !!! in bytes !!! */
|
|
|
397dc2 |
+ virDomainCacheAssociativity associativity; /* cache associativity */
|
|
|
397dc2 |
+ virDomainCachePolicy policy; /* cache policy */
|
|
|
397dc2 |
+ } *caches;
|
|
|
397dc2 |
+ size_t ncaches;
|
|
|
397dc2 |
} *mem_nodes; /* guest node configuration */
|
|
|
397dc2 |
size_t nmem_nodes;
|
|
|
397dc2 |
|
|
|
397dc2 |
+ struct _virDomainNumaInterconnect {
|
|
|
397dc2 |
+ virDomainNumaInterconnectType type; /* whether structure describes latency
|
|
|
397dc2 |
+ or bandwidth */
|
|
|
397dc2 |
+ unsigned int initiator; /* the initiator NUMA node */
|
|
|
397dc2 |
+ unsigned int target; /* the target NUMA node */
|
|
|
397dc2 |
+ unsigned int cache; /* the target cache on @target; if 0 then the
|
|
|
397dc2 |
+ memory on @target */
|
|
|
397dc2 |
+ virDomainMemoryLatency accessType; /* what type of access is defined */
|
|
|
397dc2 |
+ unsigned long value; /* value itself */
|
|
|
397dc2 |
+ } *interconnects;
|
|
|
397dc2 |
+ size_t ninterconnects;
|
|
|
397dc2 |
+
|
|
|
397dc2 |
/* Future NUMA tuning related stuff should go here. */
|
|
|
397dc2 |
};
|
|
|
397dc2 |
|
|
|
397dc2 |
@@ -368,9 +417,13 @@ virDomainNumaFree(virDomainNumaPtr numa)
|
|
|
397dc2 |
|
|
|
397dc2 |
if (numa->mem_nodes[i].ndistances > 0)
|
|
|
397dc2 |
VIR_FREE(numa->mem_nodes[i].distances);
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ VIR_FREE(numa->mem_nodes[i].caches);
|
|
|
397dc2 |
}
|
|
|
397dc2 |
VIR_FREE(numa->mem_nodes);
|
|
|
397dc2 |
|
|
|
397dc2 |
+ VIR_FREE(numa->interconnects);
|
|
|
397dc2 |
+
|
|
|
397dc2 |
VIR_FREE(numa);
|
|
|
397dc2 |
}
|
|
|
397dc2 |
|
|
|
397dc2 |
@@ -841,6 +894,97 @@ virDomainNumaDefNodeDistanceParseXML(virDomainNumaPtr def,
|
|
|
397dc2 |
return ret;
|
|
|
397dc2 |
}
|
|
|
397dc2 |
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+static int
|
|
|
397dc2 |
+virDomainNumaDefNodeCacheParseXML(virDomainNumaPtr def,
|
|
|
397dc2 |
+ xmlXPathContextPtr ctxt,
|
|
|
397dc2 |
+ unsigned int cur_cell)
|
|
|
397dc2 |
+{
|
|
|
397dc2 |
+ g_autofree xmlNodePtr *nodes = NULL;
|
|
|
397dc2 |
+ int n;
|
|
|
397dc2 |
+ size_t i;
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ if ((n = virXPathNodeSet("./cache", ctxt, &nodes)) < 0)
|
|
|
397dc2 |
+ return -1;
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ def->mem_nodes[cur_cell].caches = g_new0(virDomainNumaCache, n);
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ for (i = 0; i < n; i++) {
|
|
|
397dc2 |
+ VIR_XPATH_NODE_AUTORESTORE(ctxt);
|
|
|
397dc2 |
+ virDomainNumaCachePtr cache = &def->mem_nodes[cur_cell].caches[i];
|
|
|
397dc2 |
+ g_autofree char *tmp = NULL;
|
|
|
397dc2 |
+ unsigned int level;
|
|
|
397dc2 |
+ int associativity;
|
|
|
397dc2 |
+ int policy;
|
|
|
397dc2 |
+ unsigned long long size;
|
|
|
397dc2 |
+ unsigned long long line;
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ if (!(tmp = virXMLPropString(nodes[i], "level"))) {
|
|
|
397dc2 |
+ virReportError(VIR_ERR_XML_ERROR,
|
|
|
397dc2 |
+ _("Missing 'level' attribute in cache "
|
|
|
397dc2 |
+ "element for NUMA node %d"),
|
|
|
397dc2 |
+ cur_cell);
|
|
|
397dc2 |
+ return -1;
|
|
|
397dc2 |
+ }
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ if (virStrToLong_uip(tmp, NULL, 10, &level) < 0 ||
|
|
|
397dc2 |
+ level == 0) {
|
|
|
397dc2 |
+ virReportError(VIR_ERR_XML_ERROR,
|
|
|
397dc2 |
+ _("Invalid 'level' attribute in cache "
|
|
|
397dc2 |
+ "element for NUMA node %d"),
|
|
|
397dc2 |
+ cur_cell);
|
|
|
397dc2 |
+ return -1;
|
|
|
397dc2 |
+ }
|
|
|
397dc2 |
+ VIR_FREE(tmp);
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ if (!(tmp = virXMLPropString(nodes[i], "associativity"))) {
|
|
|
397dc2 |
+ virReportError(VIR_ERR_XML_ERROR,
|
|
|
397dc2 |
+ _("Missing 'associativity' attribute in cache "
|
|
|
397dc2 |
+ "element for NUMA node %d"),
|
|
|
397dc2 |
+ cur_cell);
|
|
|
397dc2 |
+ return -1;
|
|
|
397dc2 |
+ }
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ if ((associativity = virDomainCacheAssociativityTypeFromString(tmp)) < 0) {
|
|
|
397dc2 |
+ virReportError(VIR_ERR_XML_ERROR,
|
|
|
397dc2 |
+ _("Invalid cache associativity '%s'"),
|
|
|
397dc2 |
+ tmp);
|
|
|
397dc2 |
+ return -1;
|
|
|
397dc2 |
+ }
|
|
|
397dc2 |
+ VIR_FREE(tmp);
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ if (!(tmp = virXMLPropString(nodes[i], "policy"))) {
|
|
|
397dc2 |
+ virReportError(VIR_ERR_XML_ERROR,
|
|
|
397dc2 |
+ _("Missing 'policy' attribute in cache "
|
|
|
397dc2 |
+ "element for NUMA node %d"),
|
|
|
397dc2 |
+ cur_cell);
|
|
|
397dc2 |
+ }
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ if ((policy = virDomainCachePolicyTypeFromString(tmp)) < 0) {
|
|
|
397dc2 |
+ virReportError(VIR_ERR_XML_ERROR,
|
|
|
397dc2 |
+ _("Invalid cache policy '%s'"),
|
|
|
397dc2 |
+ tmp);
|
|
|
397dc2 |
+ return -1;
|
|
|
397dc2 |
+ }
|
|
|
397dc2 |
+ VIR_FREE(tmp);
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ ctxt->node = nodes[i];
|
|
|
397dc2 |
+ if (virDomainParseMemory("./size/@value", "./size/unit",
|
|
|
397dc2 |
+ ctxt, &size, true, false) < 0)
|
|
|
397dc2 |
+ return -1;
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ if (virParseScaledValue("./line/@value", "./line/unit",
|
|
|
397dc2 |
+ ctxt, &line, 1, ULLONG_MAX, true) < 0)
|
|
|
397dc2 |
+ return -1;
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ *cache = (virDomainNumaCache){level, size, line, associativity, policy};
|
|
|
397dc2 |
+ def->mem_nodes[cur_cell].ncaches++;
|
|
|
397dc2 |
+ }
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ return 0;
|
|
|
397dc2 |
+}
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+
|
|
|
397dc2 |
int
|
|
|
397dc2 |
virDomainNumaDefParseXML(virDomainNumaPtr def,
|
|
|
397dc2 |
xmlXPathContextPtr ctxt)
|
|
|
397dc2 |
@@ -867,6 +1011,7 @@ virDomainNumaDefParseXML(virDomainNumaPtr def,
|
|
|
397dc2 |
def->nmem_nodes = n;
|
|
|
397dc2 |
|
|
|
397dc2 |
for (i = 0; i < n; i++) {
|
|
|
397dc2 |
+ VIR_XPATH_NODE_AUTORESTORE(ctxt);
|
|
|
397dc2 |
int rc;
|
|
|
397dc2 |
unsigned int cur_cell = i;
|
|
|
397dc2 |
|
|
|
397dc2 |
@@ -953,7 +1098,109 @@ virDomainNumaDefParseXML(virDomainNumaPtr def,
|
|
|
397dc2 |
|
|
|
397dc2 |
/* Parse NUMA distances info */
|
|
|
397dc2 |
if (virDomainNumaDefNodeDistanceParseXML(def, ctxt, cur_cell) < 0)
|
|
|
397dc2 |
+ goto cleanup;
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ /* Parse cache info */
|
|
|
397dc2 |
+ if (virDomainNumaDefNodeCacheParseXML(def, ctxt, cur_cell) < 0)
|
|
|
397dc2 |
+ goto cleanup;
|
|
|
397dc2 |
+ }
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ VIR_FREE(nodes);
|
|
|
397dc2 |
+ if ((n = virXPathNodeSet("./cpu/numa[1]/interconnects[1]/latency|"
|
|
|
397dc2 |
+ "./cpu/numa[1]/interconnects[1]/bandwidth", ctxt, &nodes)) < 0)
|
|
|
397dc2 |
+ goto cleanup;
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ def->interconnects = g_new0(virDomainNumaInterconnect, n);
|
|
|
397dc2 |
+ for (i = 0; i < n; i++) {
|
|
|
397dc2 |
+ virDomainNumaInterconnectType type;
|
|
|
397dc2 |
+ unsigned int initiator;
|
|
|
397dc2 |
+ unsigned int target;
|
|
|
397dc2 |
+ unsigned int cache = 0;
|
|
|
397dc2 |
+ int accessType;
|
|
|
397dc2 |
+ unsigned long long value;
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ if (virXMLNodeNameEqual(nodes[i], "latency")) {
|
|
|
397dc2 |
+ type = VIR_DOMAIN_NUMA_INTERCONNECT_TYPE_LATENCY;
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ if (!(tmp = virXMLPropString(nodes[i], "value"))) {
|
|
|
397dc2 |
+ virReportError(VIR_ERR_XML_ERROR, "%s",
|
|
|
397dc2 |
+ _("Missing 'value' attribute in NUMA interconnects"));
|
|
|
397dc2 |
goto cleanup;
|
|
|
397dc2 |
+ }
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ if (virStrToLong_ullp(tmp, NULL, 10, &value) < 0) {
|
|
|
397dc2 |
+ virReportError(VIR_ERR_XML_ERROR, "%s",
|
|
|
397dc2 |
+ _("Invalid 'value' attribute in NUMA interconnects"));
|
|
|
397dc2 |
+ goto cleanup;
|
|
|
397dc2 |
+ }
|
|
|
397dc2 |
+ VIR_FREE(tmp);
|
|
|
397dc2 |
+ } else if (virXMLNodeNameEqual(nodes[i], "bandwidth")) {
|
|
|
397dc2 |
+ VIR_XPATH_NODE_AUTORESTORE(ctxt);
|
|
|
397dc2 |
+ type = VIR_DOMAIN_NUMA_INTERCONNECT_TYPE_BANDWIDTH;
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ ctxt->node = nodes[i];
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ if (virDomainParseMemory("./@value", "./@unit", ctxt, &value, true, false) < 0)
|
|
|
397dc2 |
+ goto cleanup;
|
|
|
397dc2 |
+ } else {
|
|
|
397dc2 |
+ /* Ignore yet unknown child elements. */
|
|
|
397dc2 |
+ continue;
|
|
|
397dc2 |
+ }
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ if (!(tmp = virXMLPropString(nodes[i], "initiator"))) {
|
|
|
397dc2 |
+ virReportError(VIR_ERR_XML_ERROR, "%s",
|
|
|
397dc2 |
+ _("Missing 'initiator' attribute in NUMA interconnects"));
|
|
|
397dc2 |
+ goto cleanup;
|
|
|
397dc2 |
+ }
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ if (virStrToLong_uip(tmp, NULL, 10, &initiator) < 0) {
|
|
|
397dc2 |
+ virReportError(VIR_ERR_XML_ERROR, "%s",
|
|
|
397dc2 |
+ _("Invalid 'initiator' attribute in NUMA interconnects"));
|
|
|
397dc2 |
+ goto cleanup;
|
|
|
397dc2 |
+ }
|
|
|
397dc2 |
+ VIR_FREE(tmp);
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ if (!(tmp = virXMLPropString(nodes[i], "target"))) {
|
|
|
397dc2 |
+ virReportError(VIR_ERR_XML_ERROR, "%s",
|
|
|
397dc2 |
+ _("Missing 'target' attribute in NUMA interconnects"));
|
|
|
397dc2 |
+ goto cleanup;
|
|
|
397dc2 |
+ }
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ if (virStrToLong_uip(tmp, NULL, 10, &target) < 0) {
|
|
|
397dc2 |
+ virReportError(VIR_ERR_XML_ERROR, "%s",
|
|
|
397dc2 |
+ _("Invalid 'target' attribute in NUMA interconnects"));
|
|
|
397dc2 |
+ goto cleanup;
|
|
|
397dc2 |
+ }
|
|
|
397dc2 |
+ VIR_FREE(tmp);
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ /* cache attribute is optional */
|
|
|
397dc2 |
+ if ((tmp = virXMLPropString(nodes[i], "cache"))) {
|
|
|
397dc2 |
+ if (virStrToLong_uip(tmp, NULL, 10, &cache) < 0 ||
|
|
|
397dc2 |
+ cache == 0) {
|
|
|
397dc2 |
+ virReportError(VIR_ERR_XML_ERROR, "%s",
|
|
|
397dc2 |
+ _("Invalid 'cache' attribute in NUMA interconnects"));
|
|
|
397dc2 |
+ goto cleanup;
|
|
|
397dc2 |
+ }
|
|
|
397dc2 |
+ }
|
|
|
397dc2 |
+ VIR_FREE(tmp);
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ if (!(tmp = virXMLPropString(nodes[i], "type"))) {
|
|
|
397dc2 |
+ virReportError(VIR_ERR_XML_ERROR, "%s",
|
|
|
397dc2 |
+ _("Missing 'type' attribute in NUMA interconnects"));
|
|
|
397dc2 |
+ goto cleanup;
|
|
|
397dc2 |
+ }
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ if ((accessType = virDomainMemoryLatencyTypeFromString(tmp)) <= 0) {
|
|
|
397dc2 |
+ virReportError(VIR_ERR_XML_ERROR, "%s",
|
|
|
397dc2 |
+ _("Invalid 'type' attribute in NUMA interconnects"));
|
|
|
397dc2 |
+ goto cleanup;
|
|
|
397dc2 |
+ }
|
|
|
397dc2 |
+ VIR_FREE(tmp);
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ def->interconnects[i] = (virDomainNumaInterconnect) {type, initiator, target,
|
|
|
397dc2 |
+ cache, accessType, value};
|
|
|
397dc2 |
+ def->ninterconnects++;
|
|
|
397dc2 |
}
|
|
|
397dc2 |
|
|
|
397dc2 |
ret = 0;
|
|
|
397dc2 |
@@ -983,6 +1230,7 @@ virDomainNumaDefFormatXML(virBufferPtr buf,
|
|
|
397dc2 |
for (i = 0; i < ncells; i++) {
|
|
|
397dc2 |
virBitmapPtr cpumask = virDomainNumaGetNodeCpumask(def, i);
|
|
|
397dc2 |
int ndistances;
|
|
|
397dc2 |
+ size_t ncaches;
|
|
|
397dc2 |
|
|
|
397dc2 |
memAccess = virDomainNumaGetNodeMemoryAccessMode(def, i);
|
|
|
397dc2 |
discard = virDomainNumaGetNodeDiscard(def, i);
|
|
|
397dc2 |
@@ -1009,30 +1257,107 @@ virDomainNumaDefFormatXML(virBufferPtr buf,
|
|
|
397dc2 |
virTristateBoolTypeToString(discard));
|
|
|
397dc2 |
|
|
|
397dc2 |
ndistances = def->mem_nodes[i].ndistances;
|
|
|
397dc2 |
- if (ndistances == 0) {
|
|
|
397dc2 |
+ ncaches = def->mem_nodes[i].ncaches;
|
|
|
397dc2 |
+ if (ndistances == 0 && ncaches == 0) {
|
|
|
397dc2 |
virBufferAddLit(buf, "/>\n");
|
|
|
397dc2 |
} else {
|
|
|
397dc2 |
size_t j;
|
|
|
397dc2 |
- virDomainNumaDistancePtr distances = def->mem_nodes[i].distances;
|
|
|
397dc2 |
|
|
|
397dc2 |
virBufferAddLit(buf, ">\n");
|
|
|
397dc2 |
virBufferAdjustIndent(buf, 2);
|
|
|
397dc2 |
- virBufferAddLit(buf, "<distances>\n");
|
|
|
397dc2 |
- virBufferAdjustIndent(buf, 2);
|
|
|
397dc2 |
- for (j = 0; j < ndistances; j++) {
|
|
|
397dc2 |
- if (distances[j].value) {
|
|
|
397dc2 |
- virBufferAddLit(buf, "
|
|
|
397dc2 |
- virBufferAsprintf(buf, " id='%d'", distances[j].cellid);
|
|
|
397dc2 |
- virBufferAsprintf(buf, " value='%d'", distances[j].value);
|
|
|
397dc2 |
- virBufferAddLit(buf, "/>\n");
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ if (ndistances) {
|
|
|
397dc2 |
+ virDomainNumaDistancePtr distances = def->mem_nodes[i].distances;
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ virBufferAddLit(buf, "<distances>\n");
|
|
|
397dc2 |
+ virBufferAdjustIndent(buf, 2);
|
|
|
397dc2 |
+ for (j = 0; j < ndistances; j++) {
|
|
|
397dc2 |
+ if (distances[j].value) {
|
|
|
397dc2 |
+ virBufferAddLit(buf, "
|
|
|
397dc2 |
+ virBufferAsprintf(buf, " id='%d'", distances[j].cellid);
|
|
|
397dc2 |
+ virBufferAsprintf(buf, " value='%d'", distances[j].value);
|
|
|
397dc2 |
+ virBufferAddLit(buf, "/>\n");
|
|
|
397dc2 |
+ }
|
|
|
397dc2 |
}
|
|
|
397dc2 |
+ virBufferAdjustIndent(buf, -2);
|
|
|
397dc2 |
+ virBufferAddLit(buf, "</distances>\n");
|
|
|
397dc2 |
+ }
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ for (j = 0; j < ncaches; j++) {
|
|
|
397dc2 |
+ virDomainNumaCachePtr cache = &def->mem_nodes[i].caches[j];
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ virBufferAsprintf(buf, "<cache level='%u'", cache->level);
|
|
|
397dc2 |
+ if (cache->associativity) {
|
|
|
397dc2 |
+ virBufferAsprintf(buf, " associativity='%s'",
|
|
|
397dc2 |
+ virDomainCacheAssociativityTypeToString(cache->associativity));
|
|
|
397dc2 |
+ }
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ if (cache->policy) {
|
|
|
397dc2 |
+ virBufferAsprintf(buf, " policy='%s'",
|
|
|
397dc2 |
+ virDomainCachePolicyTypeToString(cache->policy));
|
|
|
397dc2 |
+ }
|
|
|
397dc2 |
+ virBufferAddLit(buf, ">\n");
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ virBufferAdjustIndent(buf, 2);
|
|
|
397dc2 |
+ virBufferAsprintf(buf,
|
|
|
397dc2 |
+ "<size value='%u' unit='KiB'/>\n",
|
|
|
397dc2 |
+ cache->size);
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ if (cache->line) {
|
|
|
397dc2 |
+ virBufferAsprintf(buf,
|
|
|
397dc2 |
+ "<line value='%u' unit='B'/>\n",
|
|
|
397dc2 |
+ cache->line);
|
|
|
397dc2 |
+ }
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ virBufferAdjustIndent(buf, -2);
|
|
|
397dc2 |
+ virBufferAddLit(buf, "</cache>\n");
|
|
|
397dc2 |
}
|
|
|
397dc2 |
- virBufferAdjustIndent(buf, -2);
|
|
|
397dc2 |
- virBufferAddLit(buf, "</distances>\n");
|
|
|
397dc2 |
virBufferAdjustIndent(buf, -2);
|
|
|
397dc2 |
virBufferAddLit(buf, "</cell>\n");
|
|
|
397dc2 |
}
|
|
|
397dc2 |
}
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ if (def->ninterconnects) {
|
|
|
397dc2 |
+ virBufferAddLit(buf, "<interconnects>\n");
|
|
|
397dc2 |
+ virBufferAdjustIndent(buf, 2);
|
|
|
397dc2 |
+ }
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ for (i = 0; i < def->ninterconnects; i++) {
|
|
|
397dc2 |
+ virDomainNumaInterconnectPtr l = &def->interconnects[i];
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ switch (l->type) {
|
|
|
397dc2 |
+ case VIR_DOMAIN_NUMA_INTERCONNECT_TYPE_LATENCY:
|
|
|
397dc2 |
+ virBufferAddLit(buf, "
|
|
|
397dc2 |
+ break;
|
|
|
397dc2 |
+ case VIR_DOMAIN_NUMA_INTERCONNECT_TYPE_BANDWIDTH:
|
|
|
397dc2 |
+ virBufferAddLit(buf, "
|
|
|
397dc2 |
+ }
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ virBufferAsprintf(buf,
|
|
|
397dc2 |
+ " initiator='%u' target='%u'",
|
|
|
397dc2 |
+ l->initiator, l->target);
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ if (l->cache > 0) {
|
|
|
397dc2 |
+ virBufferAsprintf(buf,
|
|
|
397dc2 |
+ " cache='%u'",
|
|
|
397dc2 |
+ l->cache);
|
|
|
397dc2 |
+ }
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ virBufferAsprintf(buf,
|
|
|
397dc2 |
+ " type='%s' value='%lu'",
|
|
|
397dc2 |
+ virDomainMemoryLatencyTypeToString(l->accessType),
|
|
|
397dc2 |
+ l->value);
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ if (l->type == VIR_DOMAIN_NUMA_INTERCONNECT_TYPE_BANDWIDTH)
|
|
|
397dc2 |
+ virBufferAddLit(buf, " unit='KiB'");
|
|
|
397dc2 |
+ virBufferAddLit(buf, "/>\n");
|
|
|
397dc2 |
+ }
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ if (def->ninterconnects) {
|
|
|
397dc2 |
+ virBufferAdjustIndent(buf, -2);
|
|
|
397dc2 |
+ virBufferAddLit(buf, "</interconnects>\n");
|
|
|
397dc2 |
+ }
|
|
|
397dc2 |
+
|
|
|
397dc2 |
virBufferAdjustIndent(buf, -2);
|
|
|
397dc2 |
virBufferAddLit(buf, "</numa>\n");
|
|
|
397dc2 |
|
|
|
397dc2 |
diff --git a/src/conf/numa_conf.h b/src/conf/numa_conf.h
|
|
|
397dc2 |
index 6808439a7c..5043c5a6d4 100644
|
|
|
397dc2 |
--- a/src/conf/numa_conf.h
|
|
|
397dc2 |
+++ b/src/conf/numa_conf.h
|
|
|
397dc2 |
@@ -52,6 +52,39 @@ typedef enum {
|
|
|
397dc2 |
} virDomainMemoryAccess;
|
|
|
397dc2 |
VIR_ENUM_DECL(virDomainMemoryAccess);
|
|
|
397dc2 |
|
|
|
397dc2 |
+typedef enum {
|
|
|
397dc2 |
+ VIR_DOMAIN_CACHE_ASSOCIATIVITY_NONE, /* No associativity */
|
|
|
397dc2 |
+ VIR_DOMAIN_CACHE_ASSOCIATIVITY_DIRECT, /* Direct mapped cache */
|
|
|
397dc2 |
+ VIR_DOMAIN_CACHE_ASSOCIATIVITY_FULL, /* Fully associative cache */
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ VIR_DOMAIN_CACHE_ASSOCIATIVITY_LAST
|
|
|
397dc2 |
+} virDomainCacheAssociativity;
|
|
|
397dc2 |
+VIR_ENUM_DECL(virDomainCacheAssociativity);
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+typedef enum {
|
|
|
397dc2 |
+ VIR_DOMAIN_CACHE_POLICY_NONE, /* No policy */
|
|
|
397dc2 |
+ VIR_DOMAIN_CACHE_POLICY_WRITEBACK, /* Write-back policy */
|
|
|
397dc2 |
+ VIR_DOMAIN_CACHE_POLICY_WRITETHROUGH, /* Write-through policy */
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ VIR_DOMAIN_CACHE_POLICY_LAST
|
|
|
397dc2 |
+} virDomainCachePolicy;
|
|
|
397dc2 |
+VIR_ENUM_DECL(virDomainCachePolicy);
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+typedef enum {
|
|
|
397dc2 |
+ VIR_DOMAIN_NUMA_INTERCONNECT_TYPE_LATENCY,
|
|
|
397dc2 |
+ VIR_DOMAIN_NUMA_INTERCONNECT_TYPE_BANDWIDTH,
|
|
|
397dc2 |
+} virDomainNumaInterconnectType;
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+typedef enum {
|
|
|
397dc2 |
+ VIR_DOMAIN_MEMORY_LATENCY_NONE = 0, /* No memory latency defined */
|
|
|
397dc2 |
+ VIR_DOMAIN_MEMORY_LATENCY_ACCESS, /* Access latency */
|
|
|
397dc2 |
+ VIR_DOMAIN_MEMORY_LATENCY_READ, /* Read latency */
|
|
|
397dc2 |
+ VIR_DOMAIN_MEMORY_LATENCY_WRITE, /* Write latency */
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ VIR_DOMAIN_MEMORY_LATENCY_LAST
|
|
|
397dc2 |
+} virDomainMemoryLatency;
|
|
|
397dc2 |
+VIR_ENUM_DECL(virDomainMemoryLatency);
|
|
|
397dc2 |
+
|
|
|
397dc2 |
|
|
|
397dc2 |
virDomainNumaPtr virDomainNumaNew(void);
|
|
|
397dc2 |
void virDomainNumaFree(virDomainNumaPtr numa);
|
|
|
397dc2 |
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
|
|
|
397dc2 |
index acb25eb8c8..de95e3b116 100644
|
|
|
397dc2 |
--- a/src/libvirt_private.syms
|
|
|
397dc2 |
+++ b/src/libvirt_private.syms
|
|
|
397dc2 |
@@ -808,8 +808,14 @@ virNodeDeviceDeleteVport;
|
|
|
397dc2 |
virNodeDeviceGetParentName;
|
|
|
397dc2 |
|
|
|
397dc2 |
# conf/numa_conf.h
|
|
|
397dc2 |
+virDomainCacheAssociativityTypeFromString;
|
|
|
397dc2 |
+virDomainCacheAssociativityTypeToString;
|
|
|
397dc2 |
+virDomainCachePolicyTypeFromString;
|
|
|
397dc2 |
+virDomainCachePolicyTypeToString;
|
|
|
397dc2 |
virDomainMemoryAccessTypeFromString;
|
|
|
397dc2 |
virDomainMemoryAccessTypeToString;
|
|
|
397dc2 |
+virDomainMemoryLatencyTypeFromString;
|
|
|
397dc2 |
+virDomainMemoryLatencyTypeToString;
|
|
|
397dc2 |
virDomainNumaCheckABIStability;
|
|
|
397dc2 |
virDomainNumaEquals;
|
|
|
397dc2 |
virDomainNumaFree;
|
|
|
397dc2 |
diff --git a/tests/qemuxml2argvdata/numatune-hmat.xml b/tests/qemuxml2argvdata/numatune-hmat.xml
|
|
|
397dc2 |
new file mode 100644
|
|
|
397dc2 |
index 0000000000..83f0b56c9b
|
|
|
397dc2 |
--- /dev/null
|
|
|
397dc2 |
+++ b/tests/qemuxml2argvdata/numatune-hmat.xml
|
|
|
397dc2 |
@@ -0,0 +1,52 @@
|
|
|
397dc2 |
+<domain type='qemu'>
|
|
|
397dc2 |
+ <name>QEMUGuest</name>
|
|
|
397dc2 |
+ <uuid>c7a5fdb2-cdaf-9455-926a-d65c16db1809</uuid>
|
|
|
397dc2 |
+ <memory unit='KiB'>8388608</memory>
|
|
|
397dc2 |
+ <currentMemory unit='KiB'>8388608</currentMemory>
|
|
|
397dc2 |
+ <vcpu placement='static'>12</vcpu>
|
|
|
397dc2 |
+ <os>
|
|
|
397dc2 |
+ <type arch='x86_64' machine='pc'>hvm</type>
|
|
|
397dc2 |
+ <boot dev='hd'/>
|
|
|
397dc2 |
+ </os>
|
|
|
397dc2 |
+ <features>
|
|
|
397dc2 |
+ <acpi/>
|
|
|
397dc2 |
+ <apic/>
|
|
|
397dc2 |
+ <pae/>
|
|
|
397dc2 |
+ </features>
|
|
|
397dc2 |
+ <cpu>
|
|
|
397dc2 |
+ <numa>
|
|
|
397dc2 |
+ <cell id='0' cpus='0-3' memory='2097152' unit='KiB'>
|
|
|
397dc2 |
+ <cache level='1' associativity='direct' policy='writeback'>
|
|
|
397dc2 |
+ <size value='10' unit='KiB'/>
|
|
|
397dc2 |
+ <line value='8' unit='B'/>
|
|
|
397dc2 |
+ </cache>
|
|
|
397dc2 |
+ </cell>
|
|
|
397dc2 |
+ <cell id='1' cpus='4-7' memory='2097152' unit='KiB'/>
|
|
|
397dc2 |
+ <cell id='2' cpus='8-11' memory='2097152' unit='KiB'/>
|
|
|
397dc2 |
+ <cell id='3' memory='2097152' unit='KiB'/>
|
|
|
397dc2 |
+ <cell id='4' memory='2097152' unit='KiB'/>
|
|
|
397dc2 |
+ <cell id='5' memory='2097152' unit='KiB'/>
|
|
|
397dc2 |
+ <interconnects>
|
|
|
397dc2 |
+ <latency initiator='0' target='0' type='access' value='5'/>
|
|
|
397dc2 |
+ <latency initiator='0' target='0' cache='1' type='access' value='10'/>
|
|
|
397dc2 |
+ <bandwidth initiator='0' target='0' type='access' value='204800' unit='KiB'/>
|
|
|
397dc2 |
+ </interconnects>
|
|
|
397dc2 |
+ </numa>
|
|
|
397dc2 |
+ </cpu>
|
|
|
397dc2 |
+ <clock offset='utc'/>
|
|
|
397dc2 |
+ <on_poweroff>destroy</on_poweroff>
|
|
|
397dc2 |
+ <on_reboot>restart</on_reboot>
|
|
|
397dc2 |
+ <on_crash>restart</on_crash>
|
|
|
397dc2 |
+ <devices>
|
|
|
397dc2 |
+ <emulator>/usr/bin/qemu-system-x86_64</emulator>
|
|
|
397dc2 |
+ <controller type='usb' index='0'>
|
|
|
397dc2 |
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
|
|
|
397dc2 |
+ </controller>
|
|
|
397dc2 |
+ <controller type='pci' index='0' model='pci-root'/>
|
|
|
397dc2 |
+ <input type='mouse' bus='ps2'/>
|
|
|
397dc2 |
+ <input type='keyboard' bus='ps2'/>
|
|
|
397dc2 |
+ <memballoon model='virtio'>
|
|
|
397dc2 |
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
|
|
|
397dc2 |
+ </memballoon>
|
|
|
397dc2 |
+ </devices>
|
|
|
397dc2 |
+</domain>
|
|
|
397dc2 |
diff --git a/tests/qemuxml2xmloutdata/numatune-hmat.xml b/tests/qemuxml2xmloutdata/numatune-hmat.xml
|
|
|
397dc2 |
new file mode 120000
|
|
|
397dc2 |
index 0000000000..6903a80ab1
|
|
|
397dc2 |
--- /dev/null
|
|
|
397dc2 |
+++ b/tests/qemuxml2xmloutdata/numatune-hmat.xml
|
|
|
397dc2 |
@@ -0,0 +1 @@
|
|
|
397dc2 |
+../qemuxml2argvdata/numatune-hmat.xml
|
|
|
397dc2 |
\ No newline at end of file
|
|
|
397dc2 |
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
|
|
|
397dc2 |
index 1ddeba30f0..de1d720e1d 100644
|
|
|
397dc2 |
--- a/tests/qemuxml2xmltest.c
|
|
|
397dc2 |
+++ b/tests/qemuxml2xmltest.c
|
|
|
397dc2 |
@@ -1106,6 +1106,7 @@ mymain(void)
|
|
|
397dc2 |
DO_TEST("numatune-memnode-no-memory", QEMU_CAPS_OBJECT_MEMORY_FILE);
|
|
|
397dc2 |
DO_TEST("numatune-distances", QEMU_CAPS_NUMA, QEMU_CAPS_NUMA_DIST);
|
|
|
397dc2 |
DO_TEST("numatune-no-vcpu", QEMU_CAPS_NUMA);
|
|
|
397dc2 |
+ DO_TEST("numatune-hmat", NONE);
|
|
|
397dc2 |
|
|
|
397dc2 |
DO_TEST("bios-nvram", NONE);
|
|
|
397dc2 |
DO_TEST("bios-nvram-os-interleave", NONE);
|
|
|
397dc2 |
--
|
|
|
397dc2 |
2.29.2
|
|
|
397dc2 |
|