Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 #include <sys/types.h>
0003 #include <errno.h>
0004 #include <unistd.h>
0005 #include <stdio.h>
0006 #include <stdlib.h>
0007 #include <string.h>
0008 #include <regex.h>
0009 
0010 #include "../../../util/debug.h"
0011 #include "../../../util/header.h"
0012 #include "cpuid.h"
0013 
0014 void get_cpuid_0(char *vendor, unsigned int *lvl)
0015 {
0016     unsigned int b, c, d;
0017 
0018     cpuid(0, 0, lvl, &b, &c, &d);
0019     strncpy(&vendor[0], (char *)(&b), 4);
0020     strncpy(&vendor[4], (char *)(&d), 4);
0021     strncpy(&vendor[8], (char *)(&c), 4);
0022     vendor[12] = '\0';
0023 }
0024 
0025 static int
0026 __get_cpuid(char *buffer, size_t sz, const char *fmt)
0027 {
0028     unsigned int a, b, c, d, lvl;
0029     int family = -1, model = -1, step = -1;
0030     int nb;
0031     char vendor[16];
0032 
0033     get_cpuid_0(vendor, &lvl);
0034 
0035     if (lvl >= 1) {
0036         cpuid(1, 0, &a, &b, &c, &d);
0037 
0038         family = (a >> 8) & 0xf;  /* bits 11 - 8 */
0039         model  = (a >> 4) & 0xf;  /* Bits  7 - 4 */
0040         step   = a & 0xf;
0041 
0042         /* extended family */
0043         if (family == 0xf)
0044             family += (a >> 20) & 0xff;
0045 
0046         /* extended model */
0047         if (family >= 0x6)
0048             model += ((a >> 16) & 0xf) << 4;
0049     }
0050     nb = scnprintf(buffer, sz, fmt, vendor, family, model, step);
0051 
0052     /* look for end marker to ensure the entire data fit */
0053     if (strchr(buffer, '$')) {
0054         buffer[nb-1] = '\0';
0055         return 0;
0056     }
0057     return ENOBUFS;
0058 }
0059 
0060 int
0061 get_cpuid(char *buffer, size_t sz)
0062 {
0063     return __get_cpuid(buffer, sz, "%s,%u,%u,%u$");
0064 }
0065 
0066 char *
0067 get_cpuid_str(struct perf_pmu *pmu __maybe_unused)
0068 {
0069     char *buf = malloc(128);
0070 
0071     if (buf && __get_cpuid(buf, 128, "%s-%u-%X-%X$") < 0) {
0072         free(buf);
0073         return NULL;
0074     }
0075     return buf;
0076 }
0077 
0078 /* Full CPUID format for x86 is vendor-family-model-stepping */
0079 static bool is_full_cpuid(const char *id)
0080 {
0081     const char *tmp = id;
0082     int count = 0;
0083 
0084     while ((tmp = strchr(tmp, '-')) != NULL) {
0085         count++;
0086         tmp++;
0087     }
0088 
0089     if (count == 3)
0090         return true;
0091 
0092     return false;
0093 }
0094 
0095 int strcmp_cpuid_str(const char *mapcpuid, const char *id)
0096 {
0097     regex_t re;
0098     regmatch_t pmatch[1];
0099     int match;
0100     bool full_mapcpuid = is_full_cpuid(mapcpuid);
0101     bool full_cpuid = is_full_cpuid(id);
0102 
0103     /*
0104      * Full CPUID format is required to identify a platform.
0105      * Error out if the cpuid string is incomplete.
0106      */
0107     if (full_mapcpuid && !full_cpuid) {
0108         pr_info("Invalid CPUID %s. Full CPUID is required, "
0109             "vendor-family-model-stepping\n", id);
0110         return 1;
0111     }
0112 
0113     if (regcomp(&re, mapcpuid, REG_EXTENDED) != 0) {
0114         /* Warn unable to generate match particular string. */
0115         pr_info("Invalid regular expression %s\n", mapcpuid);
0116         return 1;
0117     }
0118 
0119     match = !regexec(&re, id, 1, pmatch, 0);
0120     regfree(&re);
0121     if (match) {
0122         size_t match_len = (pmatch[0].rm_eo - pmatch[0].rm_so);
0123         size_t cpuid_len;
0124 
0125         /* If the full CPUID format isn't required,
0126          * ignoring the stepping.
0127          */
0128         if (!full_mapcpuid && full_cpuid)
0129             cpuid_len = strrchr(id, '-') - id;
0130         else
0131             cpuid_len = strlen(id);
0132 
0133         /* Verify the entire string matched. */
0134         if (match_len == cpuid_len)
0135             return 0;
0136     }
0137 
0138     return 1;
0139 }