mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-22 04:25:18 +00:00
qemu: Build HMAT command line
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1786303 Signed-off-by: Michal Privoznik <mprivozn@redhat.com> Reviewed-by: Daniel Henrique Barboza <danielhb413@gmail.com>
This commit is contained in:
parent
c2f15f1b18
commit
aeecbc87b7
@ -1904,6 +1904,13 @@ virDomainNumaGetNodeInitiator(const virDomainNuma *numa,
|
|||||||
if (!numa || node >= numa->nmem_nodes)
|
if (!numa || node >= numa->nmem_nodes)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
/* A NUMA node which has at least one vCPU is initiator to itself by
|
||||||
|
* definition. */
|
||||||
|
if (numa->mem_nodes[node].cpumask)
|
||||||
|
return node;
|
||||||
|
|
||||||
|
/* For the rest, "NUMA node that has best performance (the lowest
|
||||||
|
* latency or largest bandwidth) to this NUMA node." */
|
||||||
for (i = 0; i < numa->ninterconnects; i++) {
|
for (i = 0; i < numa->ninterconnects; i++) {
|
||||||
const virDomainNumaInterconnect *l = &numa->interconnects[i];
|
const virDomainNumaInterconnect *l = &numa->interconnects[i];
|
||||||
|
|
||||||
|
@ -6933,6 +6933,9 @@ qemuBuildMachineCommandLine(virCommandPtr cmd,
|
|||||||
virBufferAsprintf(&buf, ",pflash1=%s", priv->pflash1->nodeformat);
|
virBufferAsprintf(&buf, ",pflash1=%s", priv->pflash1->nodeformat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (virDomainNumaHasHMAT(def->numa))
|
||||||
|
virBufferAddLit(&buf, ",hmat=on");
|
||||||
|
|
||||||
virCommandAddArgBuffer(cmd, &buf);
|
virCommandAddArgBuffer(cmd, &buf);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -7115,6 +7118,134 @@ qemuBuildIOThreadCommandLine(virCommandPtr cmd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
qemuBuilNumaCellCache(virCommandPtr cmd,
|
||||||
|
const virDomainDef *def,
|
||||||
|
size_t cell)
|
||||||
|
{
|
||||||
|
size_t ncaches = virDomainNumaGetNodeCacheCount(def->numa, cell);
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
if (ncaches == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (i = 0; i < ncaches; i++) {
|
||||||
|
g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
|
||||||
|
unsigned int level;
|
||||||
|
unsigned int size;
|
||||||
|
unsigned int line;
|
||||||
|
virDomainCacheAssociativity associativity;
|
||||||
|
virDomainCachePolicy policy;
|
||||||
|
|
||||||
|
if (virDomainNumaGetNodeCache(def->numa, cell, i,
|
||||||
|
&level, &size, &line,
|
||||||
|
&associativity, &policy) < 0) {
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
|
_("Unable to format NUMA node cache"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
virBufferAsprintf(&buf,
|
||||||
|
"hmat-cache,node-id=%zu,size=%uK,level=%u",
|
||||||
|
cell, size, level);
|
||||||
|
|
||||||
|
switch (associativity) {
|
||||||
|
case VIR_DOMAIN_CACHE_ASSOCIATIVITY_NONE:
|
||||||
|
virBufferAddLit(&buf, ",associativity=none");
|
||||||
|
break;
|
||||||
|
case VIR_DOMAIN_CACHE_ASSOCIATIVITY_DIRECT:
|
||||||
|
virBufferAddLit(&buf, ",associativity=direct");
|
||||||
|
break;
|
||||||
|
case VIR_DOMAIN_CACHE_ASSOCIATIVITY_FULL:
|
||||||
|
virBufferAddLit(&buf, ",associativity=complex");
|
||||||
|
break;
|
||||||
|
case VIR_DOMAIN_CACHE_ASSOCIATIVITY_LAST:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (policy) {
|
||||||
|
case VIR_DOMAIN_CACHE_POLICY_NONE:
|
||||||
|
virBufferAddLit(&buf, ",policy=none");
|
||||||
|
break;
|
||||||
|
case VIR_DOMAIN_CACHE_POLICY_WRITEBACK:
|
||||||
|
virBufferAddLit(&buf, ",policy=write-back");
|
||||||
|
break;
|
||||||
|
case VIR_DOMAIN_CACHE_POLICY_WRITETHROUGH:
|
||||||
|
virBufferAddLit(&buf, ",policy=write-through");
|
||||||
|
break;
|
||||||
|
case VIR_DOMAIN_CACHE_POLICY_LAST:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (line > 0)
|
||||||
|
virBufferAsprintf(&buf, ",line=%u", line);
|
||||||
|
|
||||||
|
virCommandAddArg(cmd, "-numa");
|
||||||
|
virCommandAddArgBuffer(cmd, &buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VIR_ENUM_DECL(qemuDomainMemoryHierarchy);
|
||||||
|
VIR_ENUM_IMPL(qemuDomainMemoryHierarchy,
|
||||||
|
4, /* Maximum level of cache */
|
||||||
|
"memory", /* Special case, whole memory not specific cache */
|
||||||
|
"first-level",
|
||||||
|
"second-level",
|
||||||
|
"third-level");
|
||||||
|
|
||||||
|
static int
|
||||||
|
qemuBuildNumaHMATCommandLine(virCommandPtr cmd,
|
||||||
|
const virDomainDef *def)
|
||||||
|
{
|
||||||
|
size_t nlatencies;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
if (!def->numa)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
nlatencies = virDomainNumaGetInterconnectsCount(def->numa);
|
||||||
|
for (i = 0; i < nlatencies; i++) {
|
||||||
|
g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
|
||||||
|
virDomainNumaInterconnectType type;
|
||||||
|
unsigned int initiator;
|
||||||
|
unsigned int target;
|
||||||
|
unsigned int cache;
|
||||||
|
virDomainMemoryLatency accessType;
|
||||||
|
unsigned long value;
|
||||||
|
const char *hierarchyStr;
|
||||||
|
const char *accessStr;
|
||||||
|
|
||||||
|
if (virDomainNumaGetInterconnect(def->numa, i,
|
||||||
|
&type, &initiator, &target,
|
||||||
|
&cache, &accessType, &value) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
hierarchyStr = qemuDomainMemoryHierarchyTypeToString(cache);
|
||||||
|
accessStr = virDomainMemoryLatencyTypeToString(accessType);
|
||||||
|
virBufferAsprintf(&buf,
|
||||||
|
"hmat-lb,initiator=%u,target=%u,hierarchy=%s,data-type=%s-",
|
||||||
|
initiator, target, hierarchyStr, accessStr);
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case VIR_DOMAIN_NUMA_INTERCONNECT_TYPE_LATENCY:
|
||||||
|
virBufferAsprintf(&buf, "latency,latency=%lu", value);
|
||||||
|
break;
|
||||||
|
case VIR_DOMAIN_NUMA_INTERCONNECT_TYPE_BANDWIDTH:
|
||||||
|
virBufferAsprintf(&buf, "bandwidth,bandwidth=%luK", value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
virCommandAddArg(cmd, "-numa");
|
||||||
|
virCommandAddArgBuffer(cmd, &buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
qemuBuildNumaCommandLine(virQEMUDriverConfigPtr cfg,
|
qemuBuildNumaCommandLine(virQEMUDriverConfigPtr cfg,
|
||||||
virDomainDefPtr def,
|
virDomainDefPtr def,
|
||||||
@ -7127,9 +7258,11 @@ qemuBuildNumaCommandLine(virQEMUDriverConfigPtr cfg,
|
|||||||
char *next = NULL;
|
char *next = NULL;
|
||||||
virBufferPtr nodeBackends = NULL;
|
virBufferPtr nodeBackends = NULL;
|
||||||
bool needBackend = false;
|
bool needBackend = false;
|
||||||
|
bool hmat = false;
|
||||||
int rc;
|
int rc;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
size_t ncells = virDomainNumaGetNodeCount(def->numa);
|
size_t ncells = virDomainNumaGetNodeCount(def->numa);
|
||||||
|
ssize_t masterInitiator = -1;
|
||||||
|
|
||||||
if (!virDomainNumatuneNodesetIsAvailable(def->numa, priv->autoNodeset))
|
if (!virDomainNumatuneNodesetIsAvailable(def->numa, priv->autoNodeset))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
@ -7139,6 +7272,11 @@ qemuBuildNumaCommandLine(virQEMUDriverConfigPtr cfg,
|
|||||||
def->os.machine))
|
def->os.machine))
|
||||||
needBackend = true;
|
needBackend = true;
|
||||||
|
|
||||||
|
if (virDomainNumaHasHMAT(def->numa)) {
|
||||||
|
needBackend = true;
|
||||||
|
hmat = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (VIR_ALLOC_N(nodeBackends, ncells) < 0)
|
if (VIR_ALLOC_N(nodeBackends, ncells) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
@ -7167,8 +7305,22 @@ qemuBuildNumaCommandLine(virQEMUDriverConfigPtr cfg,
|
|||||||
qemuBuildMemPathStr(def, cmd, priv) < 0)
|
qemuBuildMemPathStr(def, cmd, priv) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
|
for (i = 0; i < ncells; i++) {
|
||||||
|
if (virDomainNumaGetNodeCpumask(def->numa, i)) {
|
||||||
|
masterInitiator = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (masterInitiator) {
|
||||||
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||||
|
_("At least one NUMA node has to have CPUs"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < ncells; i++) {
|
for (i = 0; i < ncells; i++) {
|
||||||
virBitmapPtr cpumask = virDomainNumaGetNodeCpumask(def->numa, i);
|
virBitmapPtr cpumask = virDomainNumaGetNodeCpumask(def->numa, i);
|
||||||
|
ssize_t initiator = virDomainNumaGetNodeInitiator(def->numa, i);
|
||||||
|
|
||||||
if (needBackend) {
|
if (needBackend) {
|
||||||
virCommandAddArg(cmd, "-object");
|
virCommandAddArg(cmd, "-object");
|
||||||
@ -7193,6 +7345,13 @@ qemuBuildNumaCommandLine(virQEMUDriverConfigPtr cfg,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hmat) {
|
||||||
|
if (initiator < 0)
|
||||||
|
initiator = masterInitiator;
|
||||||
|
|
||||||
|
virBufferAsprintf(&buf, ",initiator=%zd", initiator);
|
||||||
|
}
|
||||||
|
|
||||||
if (needBackend)
|
if (needBackend)
|
||||||
virBufferAsprintf(&buf, ",memdev=ram-node%zu", i);
|
virBufferAsprintf(&buf, ",memdev=ram-node%zu", i);
|
||||||
else
|
else
|
||||||
@ -7218,6 +7377,18 @@ qemuBuildNumaCommandLine(virQEMUDriverConfigPtr cfg,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hmat) {
|
||||||
|
if (qemuBuildNumaHMATCommandLine(cmd, def) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
/* This can't be moved into any of the loops above,
|
||||||
|
* because hmat-cache can be specified only after hmat-lb. */
|
||||||
|
for (i = 0; i < ncells; i++) {
|
||||||
|
if (qemuBuilNumaCellCache(cmd, def, i) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
|
@ -888,6 +888,13 @@ qemuValidateDomainDef(const virDomainDef *def,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (virDomainNumaHasHMAT(def->numa) &&
|
||||||
|
!virQEMUCapsGet(qemuCaps, QEMU_CAPS_NUMA_HMAT)) {
|
||||||
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||||
|
_("HMAT is not supported with this QEMU"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (def->genidRequested &&
|
if (def->genidRequested &&
|
||||||
!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VMGENID)) {
|
!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VMGENID)) {
|
||||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||||
|
53
tests/qemuxml2argvdata/numatune-hmat.x86_64-latest.args
Normal file
53
tests/qemuxml2argvdata/numatune-hmat.x86_64-latest.args
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
LC_ALL=C \
|
||||||
|
PATH=/bin \
|
||||||
|
HOME=/tmp/lib/domain--1-QEMUGuest \
|
||||||
|
USER=test \
|
||||||
|
LOGNAME=test \
|
||||||
|
XDG_DATA_HOME=/tmp/lib/domain--1-QEMUGuest/.local/share \
|
||||||
|
XDG_CACHE_HOME=/tmp/lib/domain--1-QEMUGuest/.cache \
|
||||||
|
XDG_CONFIG_HOME=/tmp/lib/domain--1-QEMUGuest/.config \
|
||||||
|
QEMU_AUDIO_DRV=none \
|
||||||
|
/usr/bin/qemu-system-x86_64 \
|
||||||
|
-name guest=QEMUGuest,debug-threads=on \
|
||||||
|
-S \
|
||||||
|
-object secret,id=masterKey0,format=raw,\
|
||||||
|
file=/tmp/lib/domain--1-QEMUGuest/master-key.aes \
|
||||||
|
-machine pc,accel=tcg,usb=off,dump-guest-core=off,hmat=on \
|
||||||
|
-cpu qemu64 \
|
||||||
|
-m 12288 \
|
||||||
|
-overcommit mem-lock=off \
|
||||||
|
-smp 12,sockets=12,cores=1,threads=1 \
|
||||||
|
-object memory-backend-ram,id=ram-node0,size=2147483648 \
|
||||||
|
-numa node,nodeid=0,cpus=0-3,initiator=0,memdev=ram-node0 \
|
||||||
|
-object memory-backend-ram,id=ram-node1,size=2147483648 \
|
||||||
|
-numa node,nodeid=1,cpus=4-7,initiator=1,memdev=ram-node1 \
|
||||||
|
-object memory-backend-ram,id=ram-node2,size=2147483648 \
|
||||||
|
-numa node,nodeid=2,cpus=8-11,initiator=2,memdev=ram-node2 \
|
||||||
|
-object memory-backend-ram,id=ram-node3,size=2147483648 \
|
||||||
|
-numa node,nodeid=3,initiator=0,memdev=ram-node3 \
|
||||||
|
-object memory-backend-ram,id=ram-node4,size=2147483648 \
|
||||||
|
-numa node,nodeid=4,initiator=0,memdev=ram-node4 \
|
||||||
|
-object memory-backend-ram,id=ram-node5,size=2147483648 \
|
||||||
|
-numa node,nodeid=5,initiator=0,memdev=ram-node5 \
|
||||||
|
-numa hmat-lb,initiator=0,target=0,hierarchy=memory,data-type=access-latency,\
|
||||||
|
latency=5 \
|
||||||
|
-numa hmat-lb,initiator=0,target=0,hierarchy=first-level,\
|
||||||
|
data-type=access-latency,latency=10 \
|
||||||
|
-numa hmat-lb,initiator=0,target=0,hierarchy=memory,data-type=access-bandwidth,\
|
||||||
|
bandwidth=204800K \
|
||||||
|
-numa hmat-cache,node-id=0,size=10K,level=1,associativity=direct,\
|
||||||
|
policy=write-back,line=8 \
|
||||||
|
-uuid c7a5fdb2-cdaf-9455-926a-d65c16db1809 \
|
||||||
|
-display none \
|
||||||
|
-no-user-config \
|
||||||
|
-nodefaults \
|
||||||
|
-chardev socket,id=charmonitor,fd=1729,server,nowait \
|
||||||
|
-mon chardev=charmonitor,id=monitor,mode=control \
|
||||||
|
-rtc base=utc \
|
||||||
|
-no-shutdown \
|
||||||
|
-boot strict=on \
|
||||||
|
-device piix3-usb-uhci,id=usb,bus=pci.0,addr=0x1.0x2 \
|
||||||
|
-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3 \
|
||||||
|
-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,\
|
||||||
|
resourcecontrol=deny \
|
||||||
|
-msg timestamp=on
|
@ -1946,6 +1946,7 @@ mymain(void)
|
|||||||
|
|
||||||
DO_TEST("numatune-distances", QEMU_CAPS_NUMA, QEMU_CAPS_NUMA_DIST);
|
DO_TEST("numatune-distances", QEMU_CAPS_NUMA, QEMU_CAPS_NUMA_DIST);
|
||||||
DO_TEST("numatune-no-vcpu", NONE);
|
DO_TEST("numatune-no-vcpu", NONE);
|
||||||
|
DO_TEST_CAPS_LATEST("numatune-hmat");
|
||||||
|
|
||||||
DO_TEST("numatune-auto-nodeset-invalid", NONE);
|
DO_TEST("numatune-auto-nodeset-invalid", NONE);
|
||||||
DO_TEST("numatune-auto-prefer", QEMU_CAPS_OBJECT_MEMORY_RAM,
|
DO_TEST("numatune-auto-prefer", QEMU_CAPS_OBJECT_MEMORY_RAM,
|
||||||
|
@ -1127,7 +1127,7 @@ mymain(void)
|
|||||||
DO_TEST("numatune-memnode-no-memory", QEMU_CAPS_OBJECT_MEMORY_FILE);
|
DO_TEST("numatune-memnode-no-memory", QEMU_CAPS_OBJECT_MEMORY_FILE);
|
||||||
DO_TEST("numatune-distances", QEMU_CAPS_NUMA, QEMU_CAPS_NUMA_DIST);
|
DO_TEST("numatune-distances", QEMU_CAPS_NUMA, QEMU_CAPS_NUMA_DIST);
|
||||||
DO_TEST("numatune-no-vcpu", QEMU_CAPS_NUMA);
|
DO_TEST("numatune-no-vcpu", QEMU_CAPS_NUMA);
|
||||||
DO_TEST("numatune-hmat", NONE);
|
DO_TEST("numatune-hmat", QEMU_CAPS_NUMA_HMAT);
|
||||||
|
|
||||||
DO_TEST("bios-nvram", NONE);
|
DO_TEST("bios-nvram", NONE);
|
||||||
DO_TEST("bios-nvram-os-interleave", NONE);
|
DO_TEST("bios-nvram-os-interleave", NONE);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user