Re: [PATCH RESEND v20 2/8] numa: Extend CLI to provide memory latency and bandwidth information

2019-12-13 Thread Igor Mammedov
On Fri, 13 Dec 2019 09:19:23 +0800
Tao Xu  wrote:

> From: Liu Jingqi 
> 
> Add -numa hmat-lb option to provide System Locality Latency and
> Bandwidth Information. These memory attributes help to build
> System Locality Latency and Bandwidth Information Structure(s)
> in ACPI Heterogeneous Memory Attribute Table (HMAT). Before using
> hmat-lb option, enable HMAT with -machine hmat=on.
> 
> Acked-by: Markus Armbruster 
> Signed-off-by: Liu Jingqi 
> Signed-off-by: Tao Xu 

Reviewed-by: Igor Mammedov 

> ---
> 
> Changes in v20:
> - Update the QAPI description (Markus)
> - Keep base and bitmap unchanged when latency or bandwidth
>   out of range
> 
> Changes in v19:
> - Add description about the machine property 'hmat' in commit
>   message (Markus)
> 
> Changes in v18:
> - Use qapi type uint64 and only nanosecond for latency (Markus)
> 
> Changes in v17:
> - Add check when user input latency or bandwidth 0, the
>   lb_info_provided should also be 0. Because in ACPI 6.3 5.2.27.4,
>   0 means the corresponding latency or bandwidth information is
>   not provided.
> - Fix the infinite loop when node->latency is 0.
> ---
>  hw/core/numa.c| 194 ++
>  include/sysemu/numa.h |  53 
>  qapi/machine.json |  93 +++-
>  qemu-options.hx   |  47 +-
>  4 files changed, 384 insertions(+), 3 deletions(-)
> 
> diff --git a/hw/core/numa.c b/hw/core/numa.c
> index e60da99293..34eb413f5d 100644
> --- a/hw/core/numa.c
> +++ b/hw/core/numa.c
> @@ -23,6 +23,7 @@
>   */
>  
>  #include "qemu/osdep.h"
> +#include "qemu/units.h"
>  #include "sysemu/hostmem.h"
>  #include "sysemu/numa.h"
>  #include "sysemu/sysemu.h"
> @@ -198,6 +199,186 @@ void parse_numa_distance(MachineState *ms, 
> NumaDistOptions *dist, Error **errp)
>  ms->numa_state->have_numa_distance = true;
>  }
>  
> +void parse_numa_hmat_lb(NumaState *numa_state, NumaHmatLBOptions *node,
> +Error **errp)
> +{
> +int i, first_bit, last_bit;
> +uint64_t max_entry, temp_base, bitmap_copy;
> +NodeInfo *numa_info = numa_state->nodes;
> +HMAT_LB_Info *hmat_lb =
> +numa_state->hmat_lb[node->hierarchy][node->data_type];
> +HMAT_LB_Data lb_data = {};
> +HMAT_LB_Data *lb_temp;
> +
> +/* Error checking */
> +if (node->initiator > numa_state->num_nodes) {
> +error_setg(errp, "Invalid initiator=%d, it should be less than %d",
> +   node->initiator, numa_state->num_nodes);
> +return;
> +}
> +if (node->target > numa_state->num_nodes) {
> +error_setg(errp, "Invalid target=%d, it should be less than %d",
> +   node->target, numa_state->num_nodes);
> +return;
> +}
> +if (!numa_info[node->initiator].has_cpu) {
> +error_setg(errp, "Invalid initiator=%d, it isn't an "
> +   "initiator proximity domain", node->initiator);
> +return;
> +}
> +if (!numa_info[node->target].present) {
> +error_setg(errp, "The target=%d should point to an existing node",
> +   node->target);
> +return;
> +}
> +
> +if (!hmat_lb) {
> +hmat_lb = g_malloc0(sizeof(*hmat_lb));
> +numa_state->hmat_lb[node->hierarchy][node->data_type] = hmat_lb;
> +hmat_lb->list = g_array_new(false, true, sizeof(HMAT_LB_Data));
> +}
> +hmat_lb->hierarchy = node->hierarchy;
> +hmat_lb->data_type = node->data_type;
> +lb_data.initiator = node->initiator;
> +lb_data.target = node->target;
> +
> +if (node->data_type <= HMATLB_DATA_TYPE_WRITE_LATENCY) {
> +/* Input latency data */
> +
> +if (!node->has_latency) {
> +error_setg(errp, "Missing 'latency' option");
> +return;
> +}
> +if (node->has_bandwidth) {
> +error_setg(errp, "Invalid option 'bandwidth' since "
> +   "the data type is latency");
> +return;
> +}
> +
> +/* Detect duplicate configuration */
> +for (i = 0; i < hmat_lb->list->len; i++) {
> +lb_temp = _array_index(hmat_lb->list, HMAT_LB_Data, i);
> +
> +if (node->initiator == lb_temp->initiator &&
> +node->target == lb_temp->target) {
> +error_setg(errp, "Duplicate configuration of the latency for 
> "
> +"initiator=%d and target=%d", node->initiator,
> +node->target);
> +return;
> +}
> +}
> +
> +hmat_lb->base = hmat_lb->base ? hmat_lb->base : UINT64_MAX;
> +
> +if (node->latency) {
> +/* Calculate the temporary base and compressed latency */
> +max_entry = node->latency;
> +temp_base = 1;
> +while (QEMU_IS_ALIGNED(max_entry, 10)) {
> +max_entry /= 10;
> +temp_base *= 10;
> +  

[PATCH RESEND v20 2/8] numa: Extend CLI to provide memory latency and bandwidth information

2019-12-12 Thread Tao Xu
From: Liu Jingqi 

Add -numa hmat-lb option to provide System Locality Latency and
Bandwidth Information. These memory attributes help to build
System Locality Latency and Bandwidth Information Structure(s)
in ACPI Heterogeneous Memory Attribute Table (HMAT). Before using
hmat-lb option, enable HMAT with -machine hmat=on.

Acked-by: Markus Armbruster 
Signed-off-by: Liu Jingqi 
Signed-off-by: Tao Xu 
---

Changes in v20:
- Update the QAPI description (Markus)
- Keep base and bitmap unchanged when latency or bandwidth
  out of range

Changes in v19:
- Add description about the machine property 'hmat' in commit
  message (Markus)

Changes in v18:
- Use qapi type uint64 and only nanosecond for latency (Markus)

Changes in v17:
- Add check when user input latency or bandwidth 0, the
  lb_info_provided should also be 0. Because in ACPI 6.3 5.2.27.4,
  0 means the corresponding latency or bandwidth information is
  not provided.
- Fix the infinite loop when node->latency is 0.
---
 hw/core/numa.c| 194 ++
 include/sysemu/numa.h |  53 
 qapi/machine.json |  93 +++-
 qemu-options.hx   |  47 +-
 4 files changed, 384 insertions(+), 3 deletions(-)

diff --git a/hw/core/numa.c b/hw/core/numa.c
index e60da99293..34eb413f5d 100644
--- a/hw/core/numa.c
+++ b/hw/core/numa.c
@@ -23,6 +23,7 @@
  */
 
 #include "qemu/osdep.h"
+#include "qemu/units.h"
 #include "sysemu/hostmem.h"
 #include "sysemu/numa.h"
 #include "sysemu/sysemu.h"
@@ -198,6 +199,186 @@ void parse_numa_distance(MachineState *ms, 
NumaDistOptions *dist, Error **errp)
 ms->numa_state->have_numa_distance = true;
 }
 
+void parse_numa_hmat_lb(NumaState *numa_state, NumaHmatLBOptions *node,
+Error **errp)
+{
+int i, first_bit, last_bit;
+uint64_t max_entry, temp_base, bitmap_copy;
+NodeInfo *numa_info = numa_state->nodes;
+HMAT_LB_Info *hmat_lb =
+numa_state->hmat_lb[node->hierarchy][node->data_type];
+HMAT_LB_Data lb_data = {};
+HMAT_LB_Data *lb_temp;
+
+/* Error checking */
+if (node->initiator > numa_state->num_nodes) {
+error_setg(errp, "Invalid initiator=%d, it should be less than %d",
+   node->initiator, numa_state->num_nodes);
+return;
+}
+if (node->target > numa_state->num_nodes) {
+error_setg(errp, "Invalid target=%d, it should be less than %d",
+   node->target, numa_state->num_nodes);
+return;
+}
+if (!numa_info[node->initiator].has_cpu) {
+error_setg(errp, "Invalid initiator=%d, it isn't an "
+   "initiator proximity domain", node->initiator);
+return;
+}
+if (!numa_info[node->target].present) {
+error_setg(errp, "The target=%d should point to an existing node",
+   node->target);
+return;
+}
+
+if (!hmat_lb) {
+hmat_lb = g_malloc0(sizeof(*hmat_lb));
+numa_state->hmat_lb[node->hierarchy][node->data_type] = hmat_lb;
+hmat_lb->list = g_array_new(false, true, sizeof(HMAT_LB_Data));
+}
+hmat_lb->hierarchy = node->hierarchy;
+hmat_lb->data_type = node->data_type;
+lb_data.initiator = node->initiator;
+lb_data.target = node->target;
+
+if (node->data_type <= HMATLB_DATA_TYPE_WRITE_LATENCY) {
+/* Input latency data */
+
+if (!node->has_latency) {
+error_setg(errp, "Missing 'latency' option");
+return;
+}
+if (node->has_bandwidth) {
+error_setg(errp, "Invalid option 'bandwidth' since "
+   "the data type is latency");
+return;
+}
+
+/* Detect duplicate configuration */
+for (i = 0; i < hmat_lb->list->len; i++) {
+lb_temp = _array_index(hmat_lb->list, HMAT_LB_Data, i);
+
+if (node->initiator == lb_temp->initiator &&
+node->target == lb_temp->target) {
+error_setg(errp, "Duplicate configuration of the latency for "
+"initiator=%d and target=%d", node->initiator,
+node->target);
+return;
+}
+}
+
+hmat_lb->base = hmat_lb->base ? hmat_lb->base : UINT64_MAX;
+
+if (node->latency) {
+/* Calculate the temporary base and compressed latency */
+max_entry = node->latency;
+temp_base = 1;
+while (QEMU_IS_ALIGNED(max_entry, 10)) {
+max_entry /= 10;
+temp_base *= 10;
+}
+
+/* Calculate the max compressed latency */
+temp_base = MIN(hmat_lb->base, temp_base);
+max_entry = node->latency / hmat_lb->base;
+max_entry = MAX(hmat_lb->range_bitmap, max_entry);
+
+/*
+ * For latency hmat_lb->range_bitmap record the max compressed
+ *