1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Implementation of get_cpuid().
4 *
5 * Author: Nikita Shubin <n.shubin@yadro.com>
6 * Bibo Mao <maobibo@loongson.cn>
7 * Huacai Chen <chenhuacai@loongson.cn>
8 */
9
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <api/fs/fs.h>
13 #include <errno.h>
14 #include "util/debug.h"
15 #include "util/header.h"
16
17 /*
18 * Output example from /proc/cpuinfo
19 * CPU Family : Loongson-64bit
20 * Model Name : Loongson-3C5000
21 * CPU Revision : 0x10
22 * FPU Revision : 0x01
23 */
24 #define CPUINFO_MODEL "Model Name"
25 #define CPUINFO "/proc/cpuinfo"
26
_get_field(const char * line)27 static char *_get_field(const char *line)
28 {
29 char *line2, *nl;
30
31 line2 = strrchr(line, ' ');
32 if (!line2)
33 return NULL;
34
35 line2++;
36 nl = strrchr(line, '\n');
37 if (!nl)
38 return NULL;
39
40 return strndup(line2, nl - line2);
41 }
42
_get_cpuid(void)43 static char *_get_cpuid(void)
44 {
45 unsigned long line_sz;
46 char *line, *model, *cpuid;
47 FILE *file;
48
49 file = fopen(CPUINFO, "r");
50 if (file == NULL)
51 return NULL;
52
53 line = model = cpuid = NULL;
54 while (getline(&line, &line_sz, file) != -1) {
55 if (strncmp(line, CPUINFO_MODEL, strlen(CPUINFO_MODEL)))
56 continue;
57
58 model = _get_field(line);
59 if (!model)
60 goto out_free;
61 break;
62 }
63
64 if (model && (asprintf(&cpuid, "%s", model) < 0))
65 cpuid = NULL;
66
67 out_free:
68 fclose(file);
69 free(model);
70 return cpuid;
71 }
72
get_cpuid(char * buffer,size_t sz)73 int get_cpuid(char *buffer, size_t sz)
74 {
75 int ret = 0;
76 char *cpuid = _get_cpuid();
77
78 if (!cpuid)
79 return EINVAL;
80
81 if (sz < strlen(cpuid)) {
82 ret = ENOBUFS;
83 goto out_free;
84 }
85
86 scnprintf(buffer, sz, "%s", cpuid);
87
88 out_free:
89 free(cpuid);
90 return ret;
91 }
92
get_cpuid_str(struct perf_pmu * pmu __maybe_unused)93 char *get_cpuid_str(struct perf_pmu *pmu __maybe_unused)
94 {
95 return _get_cpuid();
96 }
97