Blame SOURCES/kvm-numa-Extend-CLI-to-provide-memory-latency-and-bandwi.patch

902636
From 32341d8cf680625def040b44d70b197f2399bbdb Mon Sep 17 00:00:00 2001
902636
From: "plai@redhat.com" <plai@redhat.com>
902636
Date: Thu, 21 May 2020 23:56:48 +0100
902636
Subject: [PATCH 05/12] numa: Extend CLI to provide memory latency and
902636
 bandwidth information
902636
902636
RH-Author: plai@redhat.com
902636
Message-id: <20200521235655.27141-5-plai@redhat.com>
902636
Patchwork-id: 96731
902636
O-Subject: [RHEL8.2.1 AV qemu-kvm PATCH 04/11] numa: Extend CLI to provide memory latency and bandwidth information
902636
Bugzilla: 1600217
902636
RH-Acked-by: Michael S. Tsirkin <mst@redhat.com>
902636
RH-Acked-by: Igor Mammedov <imammedo@redhat.com>
902636
RH-Acked-by: Eduardo Habkost <ehabkost@redhat.com>
902636
902636
From: Liu Jingqi <jingqi.liu@intel.com>
902636
902636
Add -numa hmat-lb option to provide System Locality Latency and
902636
Bandwidth Information. These memory attributes help to build
902636
System Locality Latency and Bandwidth Information Structure(s)
902636
in ACPI Heterogeneous Memory Attribute Table (HMAT). Before using
902636
hmat-lb option, enable HMAT with -machine hmat=on.
902636
902636
Acked-by: Markus Armbruster <armbru@redhat.com>
902636
Signed-off-by: Liu Jingqi <jingqi.liu@intel.com>
902636
Signed-off-by: Tao Xu <tao3.xu@intel.com>
902636
Message-Id: <20191213011929.2520-3-tao3.xu@intel.com>
902636
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
902636
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
902636
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
902636
(cherry picked from commit 9b12dfa03a94d7f7a4b54eb67229a31e58193384)
902636
Signed-off-by: Paul Lai <plai@redhat.com>
902636
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
902636
---
902636
 hw/core/numa.c        | 194 ++++++++++++++++++++++++++++++++++++++++++++++++++
902636
 include/sysemu/numa.h |  53 ++++++++++++++
902636
 qapi/machine.json     |  93 +++++++++++++++++++++++-
902636
 qemu-options.hx       |  47 +++++++++++-
902636
 4 files changed, 384 insertions(+), 3 deletions(-)
902636
902636
diff --git a/hw/core/numa.c b/hw/core/numa.c
902636
index a07eef9..58fe713 100644
902636
--- a/hw/core/numa.c
902636
+++ b/hw/core/numa.c
902636
@@ -23,6 +23,7 @@
902636
  */
902636
 
902636
 #include "qemu/osdep.h"
902636
+#include "qemu/units.h"
902636
 #include "sysemu/hostmem.h"
902636
 #include "sysemu/numa.h"
902636
 #include "sysemu/sysemu.h"
902636
@@ -194,6 +195,186 @@ void parse_numa_distance(MachineState *ms, NumaDistOptions *dist, Error **errp)
902636
     ms->numa_state->have_numa_distance = true;
902636
 }
902636
 
902636
+void parse_numa_hmat_lb(NumaState *numa_state, NumaHmatLBOptions *node,
902636
+                        Error **errp)
902636
+{
902636
+    int i, first_bit, last_bit;
902636
+    uint64_t max_entry, temp_base, bitmap_copy;
902636
+    NodeInfo *numa_info = numa_state->nodes;
902636
+    HMAT_LB_Info *hmat_lb =
902636
+        numa_state->hmat_lb[node->hierarchy][node->data_type];
902636
+    HMAT_LB_Data lb_data = {};
902636
+    HMAT_LB_Data *lb_temp;
902636
+
902636
+    /* Error checking */
902636
+    if (node->initiator > numa_state->num_nodes) {
902636
+        error_setg(errp, "Invalid initiator=%d, it should be less than %d",
902636
+                   node->initiator, numa_state->num_nodes);
902636
+        return;
902636
+    }
902636
+    if (node->target > numa_state->num_nodes) {
902636
+        error_setg(errp, "Invalid target=%d, it should be less than %d",
902636
+                   node->target, numa_state->num_nodes);
902636
+        return;
902636
+    }
902636
+    if (!numa_info[node->initiator].has_cpu) {
902636
+        error_setg(errp, "Invalid initiator=%d, it isn't an "
902636
+                   "initiator proximity domain", node->initiator);
902636
+        return;
902636
+    }
902636
+    if (!numa_info[node->target].present) {
902636
+        error_setg(errp, "The target=%d should point to an existing node",
902636
+                   node->target);
902636
+        return;
902636
+    }
902636
+
902636
+    if (!hmat_lb) {
902636
+        hmat_lb = g_malloc0(sizeof(*hmat_lb));
902636
+        numa_state->hmat_lb[node->hierarchy][node->data_type] = hmat_lb;
902636
+        hmat_lb->list = g_array_new(false, true, sizeof(HMAT_LB_Data));
902636
+    }
902636
+    hmat_lb->hierarchy = node->hierarchy;
902636
+    hmat_lb->data_type = node->data_type;
902636
+    lb_data.initiator = node->initiator;
902636
+    lb_data.target = node->target;
902636
+
902636
+    if (node->data_type <= HMATLB_DATA_TYPE_WRITE_LATENCY) {
902636
+        /* Input latency data */
902636
+
902636
+        if (!node->has_latency) {
902636
+            error_setg(errp, "Missing 'latency' option");
902636
+            return;
902636
+        }
902636
+        if (node->has_bandwidth) {
902636
+            error_setg(errp, "Invalid option 'bandwidth' since "
902636
+                       "the data type is latency");
902636
+            return;
902636
+        }
902636
+
902636
+        /* Detect duplicate configuration */
902636
+        for (i = 0; i < hmat_lb->list->len; i++) {
902636
+            lb_temp = &g_array_index(hmat_lb->list, HMAT_LB_Data, i);
902636
+
902636
+            if (node->initiator == lb_temp->initiator &&
902636
+                node->target == lb_temp->target) {
902636
+                error_setg(errp, "Duplicate configuration of the latency for "
902636
+                    "initiator=%d and target=%d", node->initiator,
902636
+                    node->target);
902636
+                return;
902636
+            }
902636
+        }
902636
+
902636
+        hmat_lb->base = hmat_lb->base ? hmat_lb->base : UINT64_MAX;
902636
+
902636
+        if (node->latency) {
902636
+            /* Calculate the temporary base and compressed latency */
902636
+            max_entry = node->latency;
902636
+            temp_base = 1;
902636
+            while (QEMU_IS_ALIGNED(max_entry, 10)) {
902636
+                max_entry /= 10;
902636
+                temp_base *= 10;
902636
+            }
902636
+
902636
+            /* Calculate the max compressed latency */
902636
+            temp_base = MIN(hmat_lb->base, temp_base);
902636
+            max_entry = node->latency / hmat_lb->base;
902636
+            max_entry = MAX(hmat_lb->range_bitmap, max_entry);
902636
+
902636
+            /*
902636
+             * For latency hmat_lb->range_bitmap record the max compressed
902636
+             * latency which should be less than 0xFFFF (UINT16_MAX)
902636
+             */
902636
+            if (max_entry >= UINT16_MAX) {
902636
+                error_setg(errp, "Latency %" PRIu64 " between initiator=%d and "
902636
+                        "target=%d should not differ from previously entered "
902636
+                        "min or max values on more than %d", node->latency,
902636
+                        node->initiator, node->target, UINT16_MAX - 1);
902636
+                return;
902636
+            } else {
902636
+                hmat_lb->base = temp_base;
902636
+                hmat_lb->range_bitmap = max_entry;
902636
+            }
902636
+
902636
+            /*
902636
+             * Set lb_info_provided bit 0 as 1,
902636
+             * latency information is provided
902636
+             */
902636
+            numa_info[node->target].lb_info_provided |= BIT(0);
902636
+        }
902636
+        lb_data.data = node->latency;
902636
+    } else if (node->data_type >= HMATLB_DATA_TYPE_ACCESS_BANDWIDTH) {
902636
+        /* Input bandwidth data */
902636
+        if (!node->has_bandwidth) {
902636
+            error_setg(errp, "Missing 'bandwidth' option");
902636
+            return;
902636
+        }
902636
+        if (node->has_latency) {
902636
+            error_setg(errp, "Invalid option 'latency' since "
902636
+                       "the data type is bandwidth");
902636
+            return;
902636
+        }
902636
+        if (!QEMU_IS_ALIGNED(node->bandwidth, MiB)) {
902636
+            error_setg(errp, "Bandwidth %" PRIu64 " between initiator=%d and "
902636
+                       "target=%d should be 1MB aligned", node->bandwidth,
902636
+                       node->initiator, node->target);
902636
+            return;
902636
+        }
902636
+
902636
+        /* Detect duplicate configuration */
902636
+        for (i = 0; i < hmat_lb->list->len; i++) {
902636
+            lb_temp = &g_array_index(hmat_lb->list, HMAT_LB_Data, i);
902636
+
902636
+            if (node->initiator == lb_temp->initiator &&
902636
+                node->target == lb_temp->target) {
902636
+                error_setg(errp, "Duplicate configuration of the bandwidth for "
902636
+                    "initiator=%d and target=%d", node->initiator,
902636
+                    node->target);
902636
+                return;
902636
+            }
902636
+        }
902636
+
902636
+        hmat_lb->base = hmat_lb->base ? hmat_lb->base : 1;
902636
+
902636
+        if (node->bandwidth) {
902636
+            /* Keep bitmap unchanged when bandwidth out of range */
902636
+            bitmap_copy = hmat_lb->range_bitmap;
902636
+            bitmap_copy |= node->bandwidth;
902636
+            first_bit = ctz64(bitmap_copy);
902636
+            temp_base = UINT64_C(1) << first_bit;
902636
+            max_entry = node->bandwidth / temp_base;
902636
+            last_bit = 64 - clz64(bitmap_copy);
902636
+
902636
+            /*
902636
+             * For bandwidth, first_bit record the base unit of bandwidth bits,
902636
+             * last_bit record the last bit of the max bandwidth. The max
902636
+             * compressed bandwidth should be less than 0xFFFF (UINT16_MAX)
902636
+             */
902636
+            if ((last_bit - first_bit) > UINT16_BITS ||
902636
+                max_entry >= UINT16_MAX) {
902636
+                error_setg(errp, "Bandwidth %" PRIu64 " between initiator=%d "
902636
+                        "and target=%d should not differ from previously "
902636
+                        "entered values on more than %d", node->bandwidth,
902636
+                        node->initiator, node->target, UINT16_MAX - 1);
902636
+                return;
902636
+            } else {
902636
+                hmat_lb->base = temp_base;
902636
+                hmat_lb->range_bitmap = bitmap_copy;
902636
+            }
902636
+
902636
+            /*
902636
+             * Set lb_info_provided bit 1 as 1,
902636
+             * bandwidth information is provided
902636
+             */
902636
+            numa_info[node->target].lb_info_provided |= BIT(1);
902636
+        }
902636
+        lb_data.data = node->bandwidth;
902636
+    } else {
902636
+        assert(0);
902636
+    }
902636
+
902636
+    g_array_append_val(hmat_lb->list, lb_data);
902636
+}
902636
+
902636
 void set_numa_options(MachineState *ms, NumaOptions *object, Error **errp)
902636
 {
902636
     Error *err = NULL;
902636
@@ -231,6 +412,19 @@ void set_numa_options(MachineState *ms, NumaOptions *object, Error **errp)
902636
         machine_set_cpu_numa_node(ms, qapi_NumaCpuOptions_base(&object->u.cpu),
902636
                                   &err;;
902636
         break;
902636
+    case NUMA_OPTIONS_TYPE_HMAT_LB:
902636
+        if (!ms->numa_state->hmat_enabled) {
902636
+            error_setg(errp, "ACPI Heterogeneous Memory Attribute Table "
902636
+                       "(HMAT) is disabled, enable it with -machine hmat=on "
902636
+                       "before using any of hmat specific options");
902636
+            return;
902636
+        }
902636
+
902636
+        parse_numa_hmat_lb(ms->numa_state, &object->u.hmat_lb, &err;;
902636
+        if (err) {
902636
+            goto end;
902636
+        }
902636
+        break;
902636
     default:
902636
         abort();
902636
     }
902636
diff --git a/include/sysemu/numa.h b/include/sysemu/numa.h
902636
index 788cbec..70f93c8 100644
902636
--- a/include/sysemu/numa.h
902636
+++ b/include/sysemu/numa.h
902636
@@ -14,11 +14,34 @@ struct CPUArchId;
902636
 #define NUMA_DISTANCE_MAX         254
902636
 #define NUMA_DISTANCE_UNREACHABLE 255
902636
 
902636
+/* the value of AcpiHmatLBInfo flags */
902636
+enum {
902636
+    HMAT_LB_MEM_MEMORY           = 0,
902636
+    HMAT_LB_MEM_CACHE_1ST_LEVEL  = 1,
902636
+    HMAT_LB_MEM_CACHE_2ND_LEVEL  = 2,
902636
+    HMAT_LB_MEM_CACHE_3RD_LEVEL  = 3,
902636
+    HMAT_LB_LEVELS   /* must be the last entry */
902636
+};
902636
+
902636
+/* the value of AcpiHmatLBInfo data type */
902636
+enum {
902636
+    HMAT_LB_DATA_ACCESS_LATENCY   = 0,
902636
+    HMAT_LB_DATA_READ_LATENCY     = 1,
902636
+    HMAT_LB_DATA_WRITE_LATENCY    = 2,
902636
+    HMAT_LB_DATA_ACCESS_BANDWIDTH = 3,
902636
+    HMAT_LB_DATA_READ_BANDWIDTH   = 4,
902636
+    HMAT_LB_DATA_WRITE_BANDWIDTH  = 5,
902636
+    HMAT_LB_TYPES   /* must be the last entry */
902636
+};
902636
+
902636
+#define UINT16_BITS       16
902636
+
902636
 struct NodeInfo {
902636
     uint64_t node_mem;
902636
     struct HostMemoryBackend *node_memdev;
902636
     bool present;
902636
     bool has_cpu;
902636
+    uint8_t lb_info_provided;
902636
     uint16_t initiator;
902636
     uint8_t distance[MAX_NODES];
902636
 };
902636
@@ -28,6 +51,31 @@ struct NumaNodeMem {
902636
     uint64_t node_plugged_mem;
902636
 };
902636
 
902636
+struct HMAT_LB_Data {
902636
+    uint8_t     initiator;
902636
+    uint8_t     target;
902636
+    uint64_t    data;
902636
+};
902636
+typedef struct HMAT_LB_Data HMAT_LB_Data;
902636
+
902636
+struct HMAT_LB_Info {
902636
+    /* Indicates it's memory or the specified level memory side cache. */
902636
+    uint8_t     hierarchy;
902636
+
902636
+    /* Present the type of data, access/read/write latency or bandwidth. */
902636
+    uint8_t     data_type;
902636
+
902636
+    /* The range bitmap of bandwidth for calculating common base */
902636
+    uint64_t    range_bitmap;
902636
+
902636
+    /* The common base unit for latencies or bandwidths */
902636
+    uint64_t    base;
902636
+
902636
+    /* Array to store the latencies or bandwidths */
902636
+    GArray      *list;
902636
+};
902636
+typedef struct HMAT_LB_Info HMAT_LB_Info;
902636
+
902636
 struct NumaState {
902636
     /* Number of NUMA nodes */
902636
     int num_nodes;
902636
@@ -40,11 +88,16 @@ struct NumaState {
902636
 
902636
     /* NUMA nodes information */
902636
     NodeInfo nodes[MAX_NODES];
902636
+
902636
+    /* NUMA nodes HMAT Locality Latency and Bandwidth Information */
902636
+    HMAT_LB_Info *hmat_lb[HMAT_LB_LEVELS][HMAT_LB_TYPES];
902636
 };
902636
 typedef struct NumaState NumaState;
902636
 
902636
 void set_numa_options(MachineState *ms, NumaOptions *object, Error **errp);
902636
 void parse_numa_opts(MachineState *ms);
902636
+void parse_numa_hmat_lb(NumaState *numa_state, NumaHmatLBOptions *node,
902636
+                        Error **errp);
902636
 void numa_complete_configuration(MachineState *ms);
902636
 void query_numa_node_mem(NumaNodeMem node_mem[], MachineState *ms);
902636
 extern QemuOptsList qemu_numa_opts;
902636
diff --git a/qapi/machine.json b/qapi/machine.json
902636
index 27d0e37..cf8faf5 100644
902636
--- a/qapi/machine.json
902636
+++ b/qapi/machine.json
902636
@@ -426,10 +426,12 @@
902636
 #
902636
 # @cpu: property based CPU(s) to node mapping (Since: 2.10)
902636
 #
902636
+# @hmat-lb: memory latency and bandwidth information (Since: 5.0)
902636
+#
902636
 # Since: 2.1
902636
 ##
902636
 { 'enum': 'NumaOptionsType',
902636
-  'data': [ 'node', 'dist', 'cpu' ] }
902636
+  'data': [ 'node', 'dist', 'cpu', 'hmat-lb' ] }
902636
 
902636
 ##
902636
 # @NumaOptions:
902636
@@ -444,7 +446,8 @@
902636
   'data': {
902636
     'node': 'NumaNodeOptions',
902636
     'dist': 'NumaDistOptions',
902636
-    'cpu': 'NumaCpuOptions' }}
902636
+    'cpu': 'NumaCpuOptions',
902636
+    'hmat-lb': 'NumaHmatLBOptions' }}
902636
 
902636
 ##
902636
 # @NumaNodeOptions:
902636
@@ -558,6 +561,92 @@
902636
    'data' : {} }
902636
 
902636
 ##
902636
+# @HmatLBMemoryHierarchy:
902636
+#
902636
+# The memory hierarchy in the System Locality Latency and Bandwidth
902636
+# Information Structure of HMAT (Heterogeneous Memory Attribute Table)
902636
+#
902636
+# For more information about @HmatLBMemoryHierarchy, see chapter
902636
+# 5.2.27.4: Table 5-146: Field "Flags" of ACPI 6.3 spec.
902636
+#
902636
+# @memory: the structure represents the memory performance
902636
+#
902636
+# @first-level: first level of memory side cache
902636
+#
902636
+# @second-level: second level of memory side cache
902636
+#
902636
+# @third-level: third level of memory side cache
902636
+#
902636
+# Since: 5.0
902636
+##
902636
+{ 'enum': 'HmatLBMemoryHierarchy',
902636
+  'data': [ 'memory', 'first-level', 'second-level', 'third-level' ] }
902636
+
902636
+##
902636
+# @HmatLBDataType:
902636
+#
902636
+# Data type in the System Locality Latency and Bandwidth
902636
+# Information Structure of HMAT (Heterogeneous Memory Attribute Table)
902636
+#
902636
+# For more information about @HmatLBDataType, see chapter
902636
+# 5.2.27.4: Table 5-146:  Field "Data Type" of ACPI 6.3 spec.
902636
+#
902636
+# @access-latency: access latency (nanoseconds)
902636
+#
902636
+# @read-latency: read latency (nanoseconds)
902636
+#
902636
+# @write-latency: write latency (nanoseconds)
902636
+#
902636
+# @access-bandwidth: access bandwidth (Bytes per second)
902636
+#
902636
+# @read-bandwidth: read bandwidth (Bytes per second)
902636
+#
902636
+# @write-bandwidth: write bandwidth (Bytes per second)
902636
+#
902636
+# Since: 5.0
902636
+##
902636
+{ 'enum': 'HmatLBDataType',
902636
+  'data': [ 'access-latency', 'read-latency', 'write-latency',
902636
+            'access-bandwidth', 'read-bandwidth', 'write-bandwidth' ] }
902636
+
902636
+##
902636
+# @NumaHmatLBOptions:
902636
+#
902636
+# Set the system locality latency and bandwidth information
902636
+# between Initiator and Target proximity Domains.
902636
+#
902636
+# For more information about @NumaHmatLBOptions, see chapter
902636
+# 5.2.27.4: Table 5-146 of ACPI 6.3 spec.
902636
+#
902636
+# @initiator: the Initiator Proximity Domain.
902636
+#
902636
+# @target: the Target Proximity Domain.
902636
+#
902636
+# @hierarchy: the Memory Hierarchy. Indicates the performance
902636
+#             of memory or side cache.
902636
+#
902636
+# @data-type: presents the type of data, access/read/write
902636
+#             latency or hit latency.
902636
+#
902636
+# @latency: the value of latency from @initiator to @target
902636
+#           proximity domain, the latency unit is "ns(nanosecond)".
902636
+#
902636
+# @bandwidth: the value of bandwidth between @initiator and @target
902636
+#             proximity domain, the bandwidth unit is
902636
+#             "Bytes per second".
902636
+#
902636
+# Since: 5.0
902636
+##
902636
+{ 'struct': 'NumaHmatLBOptions',
902636
+    'data': {
902636
+    'initiator': 'uint16',
902636
+    'target': 'uint16',
902636
+    'hierarchy': 'HmatLBMemoryHierarchy',
902636
+    'data-type': 'HmatLBDataType',
902636
+    '*latency': 'uint64',
902636
+    '*bandwidth': 'size' }}
902636
+
902636
+##
902636
 # @HostMemPolicy:
902636
 #
902636
 # Host memory policy types
902636
diff --git a/qemu-options.hx b/qemu-options.hx
902636
index e2ce754..86d9d8a 100644
902636
--- a/qemu-options.hx
902636
+++ b/qemu-options.hx
902636
@@ -168,16 +168,19 @@ DEF("numa", HAS_ARG, QEMU_OPTION_numa,
902636
     "-numa node[,mem=size][,cpus=firstcpu[-lastcpu]][,nodeid=node][,initiator=node]\n"
902636
     "-numa node[,memdev=id][,cpus=firstcpu[-lastcpu]][,nodeid=node][,initiator=node]\n"
902636
     "-numa dist,src=source,dst=destination,val=distance\n"
902636
-    "-numa cpu,node-id=node[,socket-id=x][,core-id=y][,thread-id=z]\n",
902636
+    "-numa cpu,node-id=node[,socket-id=x][,core-id=y][,thread-id=z]\n"
902636
+    "-numa hmat-lb,initiator=node,target=node,hierarchy=memory|first-level|second-level|third-level,data-type=access-latency|read-latency|write-latency[,latency=lat][,bandwidth=bw]\n",
902636
     QEMU_ARCH_ALL)
902636
 STEXI
902636
 @item -numa node[,mem=@var{size}][,cpus=@var{firstcpu}[-@var{lastcpu}]][,nodeid=@var{node}][,initiator=@var{initiator}]
902636
 @itemx -numa node[,memdev=@var{id}][,cpus=@var{firstcpu}[-@var{lastcpu}]][,nodeid=@var{node}][,initiator=@var{initiator}]
902636
 @itemx -numa dist,src=@var{source},dst=@var{destination},val=@var{distance}
902636
 @itemx -numa cpu,node-id=@var{node}[,socket-id=@var{x}][,core-id=@var{y}][,thread-id=@var{z}]
902636
+@itemx -numa hmat-lb,initiator=@var{node},target=@var{node},hierarchy=@var{hierarchy},data-type=@var{tpye}[,latency=@var{lat}][,bandwidth=@var{bw}]
902636
 @findex -numa
902636
 Define a NUMA node and assign RAM and VCPUs to it.
902636
 Set the NUMA distance from a source node to a destination node.
902636
+Set the ACPI Heterogeneous Memory Attributes for the given nodes.
902636
 
902636
 Legacy VCPU assignment uses @samp{cpus} option where
902636
 @var{firstcpu} and @var{lastcpu} are CPU indexes. Each
902636
@@ -256,6 +259,48 @@ specified resources, it just assigns existing resources to NUMA
902636
 nodes. This means that one still has to use the @option{-m},
902636
 @option{-smp} options to allocate RAM and VCPUs respectively.
902636
 
902636
+Use @samp{hmat-lb} to set System Locality Latency and Bandwidth Information
902636
+between initiator and target NUMA nodes in ACPI Heterogeneous Attribute Memory Table (HMAT).
902636
+Initiator NUMA node can create memory requests, usually it has one or more processors.
902636
+Target NUMA node contains addressable memory.
902636
+
902636
+In @samp{hmat-lb} option, @var{node} are NUMA node IDs. @var{hierarchy} is the memory
902636
+hierarchy of the target NUMA node: if @var{hierarchy} is 'memory', the structure
902636
+represents the memory performance; if @var{hierarchy} is 'first-level|second-level|third-level',
902636
+this structure represents aggregated performance of memory side caches for each domain.
902636
+@var{type} of 'data-type' is type of data represented by this structure instance:
902636
+if 'hierarchy' is 'memory', 'data-type' is 'access|read|write' latency or 'access|read|write'
902636
+bandwidth of the target memory; if 'hierarchy' is 'first-level|second-level|third-level',
902636
+'data-type' is 'access|read|write' hit latency or 'access|read|write' hit bandwidth of the
902636
+target memory side cache.
902636
+
902636
+@var{lat} is latency value in nanoseconds. @var{bw} is bandwidth value,
902636
+the possible value and units are NUM[M|G|T], mean that the bandwidth value are
902636
+NUM byte per second (or MB/s, GB/s or TB/s depending on used suffix).
902636
+Note that if latency or bandwidth value is 0, means the corresponding latency or
902636
+bandwidth information is not provided.
902636
+
902636
+For example, the following options describe 2 NUMA nodes. Node 0 has 2 cpus and
902636
+a ram, node 1 has only a ram. The processors in node 0 access memory in node
902636
+0 with access-latency 5 nanoseconds, access-bandwidth is 200 MB/s;
902636
+The processors in NUMA node 0 access memory in NUMA node 1 with access-latency 10
902636
+nanoseconds, access-bandwidth is 100 MB/s.
902636
+@example
902636
+-machine hmat=on \
902636
+-m 2G \
902636
+-object memory-backend-ram,size=1G,id=m0 \
902636
+-object memory-backend-ram,size=1G,id=m1 \
902636
+-smp 2 \
902636
+-numa node,nodeid=0,memdev=m0 \
902636
+-numa node,nodeid=1,memdev=m1,initiator=0 \
902636
+-numa cpu,node-id=0,socket-id=0 \
902636
+-numa cpu,node-id=0,socket-id=1 \
902636
+-numa hmat-lb,initiator=0,target=0,hierarchy=memory,data-type=access-latency,latency=5 \
902636
+-numa hmat-lb,initiator=0,target=0,hierarchy=memory,data-type=access-bandwidth,bandwidth=200M \
902636
+-numa hmat-lb,initiator=0,target=1,hierarchy=memory,data-type=access-latency,latency=10 \
902636
+-numa hmat-lb,initiator=0,target=1,hierarchy=memory,data-type=access-bandwidth,bandwidth=100M
902636
+@end example
902636
+
902636
 ETEXI
902636
 
902636
 DEF("add-fd", HAS_ARG, QEMU_OPTION_add_fd,
902636
-- 
902636
1.8.3.1
902636