From: Jiadong Zeng <zengjiad...@phytium.com.cn>

Reasons:
1.The Libvirt source code does not add information about Phytium's
machine,which is reflected in the fact that the Phytium's information
cannot be obtained when running the command "virsh capabilities".

2.Phytium identifies CPU chip information based on dmi information.This
is because Phytium's MIDR register cannot uniquely identify the CPU
chip.

Change:
For Phytium,obtain the information of CPU vendor and CPU model by
reading DMI.

Signed-off-by: Jiadong Zeng <zengjiad...@phytium.com.cn>
---
 src/cpu/cpu_arm.c | 145 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 145 insertions(+)

diff --git a/src/cpu/cpu_arm.c b/src/cpu/cpu_arm.c
index 65d69c0..c0d09f0 100644
--- a/src/cpu/cpu_arm.c
+++ b/src/cpu/cpu_arm.c
@@ -21,6 +21,14 @@
 
 #include <config.h>
 
+#if defined(__aarch64__)
+#include <asm/hwcap.h>
+#include <sys/auxv.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#endif
+
 #include "viralloc.h"
 #include "cpu.h"
 #include "virstring.h"
@@ -98,11 +106,148 @@ virCPUarmCompare(virCPUDefPtr host ATTRIBUTE_UNUSED,
     return VIR_CPU_COMPARE_IDENTICAL;
 }
 
+#if defined(__aarch64__)
+#define MAX_CPU_FLAGS                  32
+#define BIT_SHIFTS(n)                  (1UL << (n))
+
+/* Generate human readable flag list according to the order of AT_HWCAP bit 
map */
+const char *aarch64_cpu_flags[MAX_CPU_FLAGS] = {
+       "fp", "asimd", "evtstrm", "aes", "pmull", "sha1", "sha2",
+       "crc32", "atomics", "fphp", "asimdhp", "cpuid", "asimdrdm",
+       "jscvt", "fcma", "lrcpc", "dcpop", "sha3", "sm3", "sm4",
+       "asimddp", "sha512", "sve", "asimdfhm", "dit", "uscat",
+       "ilrcpc", "flagm", "ssbs", "sb", "paca", "pacg"
+};
+
+static inline int dmi_read_data(int fd, char *buf, int count)
+{
+       int len = 0;
+
+       do {
+               len = read(fd, buf, count);
+       } while (len == -1 && errno == EINTR);
+
+       if (len < 0)
+               return -1;
+
+       return len;
+}
+
+static char *dmi_get_string(char *buf, uint8_t skip, int *len)
+{
+       char *bp = buf;
+
+       if (skip == 0)
+               return NULL;
+
+       while (skip > 1 && *bp) {
+               bp += strlen(bp);
+               bp++;
+               skip--;
+       }
+
+       if (!*bp)
+               return NULL;
+
+       *len = (int)strlen(bp);
+
+       return bp;
+}
+
+static int dmi_get_model_and_vendor(char **model, char **vendor)
+{
+       int fd;
+       int ret = 0, len = 0;
+       char buf[128], *bp = buf, *str = NULL;
+#define DMI_MFR_OFFSET                 0x07
+#define DMI_VERSION_OFFSET             0x10
+
+       fd = open("/sys/firmware/dmi/entries/4-0/raw", O_RDONLY);
+       if (fd < 0)
+               return -1;
+
+       ret = dmi_read_data(fd, buf, 128);
+       if (ret < 0)
+               return -1;
+
+       close(fd);
+
+       /* skip dmi header and pointer to data */
+       bp += buf[1];
+
+       /* model info */
+       str = dmi_get_string(bp, buf[DMI_MFR_OFFSET], &len);
+       if (str)
+               *vendor = strndup(str, len);
+
+       /* vendor info */
+       str = dmi_get_string(bp, buf[DMI_VERSION_OFFSET], &len);
+       if (str)
+               *model = strndup(str, len);
+
+       if (*model == NULL || *vendor == NULL)
+               return -1;
+
+#undef DMI_MFR_OFFSET
+#undef DMI_VERSION_OFFSET
+
+       return 0;
+}
+
+static int virCPUarmGetHost(virCPUDefPtr cpu, virDomainCapsCPUModelsPtr models)
+{
+       unsigned long hwcaps;
+       int i, idx = 0;
+
+       /* unused */
+       (void)models;
+
+       if (dmi_get_model_and_vendor(&cpu->model, &cpu->vendor) < 0) {
+               virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("DMI info 
failed"));
+               return -1;
+       }
+
+       if (!(getauxval(AT_HWCAP) & HWCAP_CPUID)) {
+               virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("CPUID registers 
unavailable"));
+               return -1;
+       }
+
+       hwcaps = getauxval(AT_HWCAP);
+       if (!hwcaps) {
+               virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("AT_HWCAP is not 
found"));
+               return -1;
+       }
+
+       /* count total supported-features. */
+       for (i = 0; i < MAX_CPU_FLAGS; i++) {
+               if (hwcaps & BIT_SHIFTS(i))
+                       cpu->nfeatures++;
+       }
+
+       if (VIR_ALLOC_N(cpu->features, cpu->nfeatures) < 0)
+               return -1;
+
+       /* match cpu feature */
+       for (i = 0; i < MAX_CPU_FLAGS; i++) {
+               if (hwcaps & BIT_SHIFTS(i)) {
+                       cpu->features[idx].policy = VIR_CPU_FEATURE_REQUIRE;
+                       cpu->features[idx].name = strdup(aarch64_cpu_flags[i]);
+                       idx++;
+               }
+       }
+
+       return 0;
+}
+#endif
+
 struct cpuArchDriver cpuDriverArm = {
     .name = "arm",
     .arch = archs,
     .narch = ARRAY_CARDINALITY(archs),
     .compare = virCPUarmCompare,
+#if defined(__aarch64__)
+       .getHost = virCPUarmGetHost,
+#endif
     .decode = NULL,
     .encode = NULL,
     .baseline = virCPUarmBaseline,
-- 
1.8.3.1


Reply via email to