From 208c9f1eb9a06d2550b7b3cfe0172840925255d4 Mon Sep 17 00:00:00 2001
From: Xu Yandong <xuyandong2@huawei.com>
Date: Mon, 20 Apr 2020 17:29:17 +0800
Subject: cpu/arm: add virCPUarmGetHost implment

Signed-off-by: Xu Yandong <xuyandong2@huawei.com>
---
 src/cpu/cpu_arm.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 86 insertions(+)

diff --git a/src/cpu/cpu_arm.c b/src/cpu/cpu_arm.c
index eb9b1c9..78e604c 100644
--- a/src/cpu/cpu_arm.c
+++ b/src/cpu/cpu_arm.c
@@ -26,9 +26,15 @@
 #include "cpu_map.h"
 #include "virstring.h"
 #include "virxml.h"
+#include "virfile.h"
 
 #define VIR_FROM_THIS VIR_FROM_CPU
 
+static const char *sysinfoCpuinfo = "/proc/cpuinfo";
+
+#define CPUINFO sysinfoCpuinfo
+#define CPUINFO_FILE_LEN (1024*1024)   /* 1MB limit for /proc/cpuinfo file */
+
 static const virArch archs[] = {
     VIR_ARCH_ARMV6L,
     VIR_ARCH_ARMV7B,
@@ -531,6 +537,85 @@ cleanup:
     return ret;
 }
 
+static int
+armCpuDataFromCpuInfo(virCPUarmData *data)
+{
+    g_autofree char *str_vendor = NULL;
+    g_autofree char *str_pvr = NULL;
+    g_autofree char *outbuf = NULL;
+    char *eol = NULL;
+    const char *cur;
+
+    if (!data)
+        return -1;
+
+    if (virFileReadAll(CPUINFO, CPUINFO_FILE_LEN, &outbuf) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Failed to open %s"), CPUINFO);
+        return -1;
+    }
+
+    /* Account for format 'CPU implementer : XXXX' */
+    if ((cur = strstr(outbuf, "CPU implementer")) == NULL) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("there is no \"CPU implementer\" info in %s"), CPUINFO);
+        return -1;
+    }
+
+    cur = strchr(cur, ':') + 1;
+    eol = strchr(cur, '\n');
+    virSkipSpaces(&cur);
+    if (!eol || !(str_vendor = g_strndup(cur, eol - cur)) ||
+        virStrToLong_ul(str_vendor, NULL, 16, &data->vendor_id) < 0)
+        return -1;
+
+    /* Account for format 'CPU part : XXXX' */
+    if ((cur = strstr(outbuf, "CPU part")) == NULL) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("there is no \"CPU part\" info in %s"), CPUINFO);
+        return -1;
+    }
+
+    cur = strchr(cur, ':') + 1;
+    eol = strchr(cur, '\n');
+    virSkipSpaces(&cur);
+    if (!eol || !(str_pvr = g_strndup(cur, eol - cur)) ||
+        virStrToLong_ul(str_pvr, NULL, 16, &data->pvr) < 0)
+        return -1;
+
+    /* Account for format 'CPU Features : XXXX' */
+    if ((cur = strstr(outbuf, "Features")) == NULL) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("there is no \"Features\" info in %s"), CPUINFO);
+        return -1;
+    }
+    cur = strchr(cur, ':') + 1;
+    eol = strchr(cur, '\n');
+    virSkipSpaces(&cur);
+    if (eol && !(data->features = g_strndup(cur, eol - cur)))
+        return -1;
+
+    return 0;
+}
+
+static int
+virCPUarmGetHost(virCPUDefPtr cpu,
+                 virDomainCapsCPUModelsPtr models)
+{
+    g_autoptr(virCPUData) cpuData = NULL;
+
+    if (virCPUarmDriverInitialize() < 0)
+        return -1;
+
+    if (!(cpuData = virCPUDataNew(archs[0])))
+        return -1;
+
+    if (armCpuDataFromCpuInfo(&cpuData->data.arm) < 0)
+        return -1;
+
+    return virCPUarmDecodeCPUData(cpu, cpuData, models);
+}
+
 
 static virCPUDefPtr
 virCPUarmBaseline(virCPUDefPtr *cpus,
@@ -590,6 +675,7 @@ struct cpuArchDriver cpuDriverArm = {
     .decode = virCPUarmDecodeCPUData,
     .encode = NULL,
     .dataFree = virCPUarmDataFree,
+    .getHost = virCPUarmGetHost,
     .baseline = virCPUarmBaseline,
     .update = virCPUarmUpdate,
     .validateFeatures = virCPUarmValidateFeatures,
-- 
2.23.0

