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