[PATCH 1/1] Signed-off-by: Jiadong Zeng <zengjiadong at phytium.com.cn>

2860939690 at qq.com 2860939690 at qq.com
Fri Apr 9 04:14:11 UTC 2021


From: Jiadong Zeng <zengjiadong at 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 <zengjiadong at 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





More information about the libvir-list mailing list