xref: /linux/tools/perf/arch/riscv/util/header.c (revision cbdb1f163af2bb90d01be1f0263df1d8d5c9d9d3)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Implementation of get_cpuid().
4  *
5  * Author: Nikita Shubin <n.shubin@yadro.com>
6  */
7 
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <api/fs/fs.h>
11 #include <errno.h>
12 #include "../../util/debug.h"
13 #include "../../util/header.h"
14 
15 #define CPUINFO_MVEN	"mvendorid"
16 #define CPUINFO_MARCH	"marchid"
17 #define CPUINFO_MIMP	"mimpid"
18 #define CPUINFO		"/proc/cpuinfo"
19 
20 static char *_get_field(const char *line)
21 {
22 	char *line2, *nl;
23 
24 	line2 = strrchr(line, ' ');
25 	if (!line2)
26 		return NULL;
27 
28 	line2++;
29 	nl = strrchr(line, '\n');
30 	if (!nl)
31 		return NULL;
32 
33 	return strndup(line2, nl - line2);
34 }
35 
36 static char *_get_cpuid(void)
37 {
38 	char *line = NULL;
39 	char *mvendorid = NULL;
40 	char *marchid = NULL;
41 	char *mimpid = NULL;
42 	char *cpuid = NULL;
43 	int read;
44 	unsigned long line_sz;
45 	FILE *cpuinfo;
46 
47 	cpuinfo = fopen(CPUINFO, "r");
48 	if (cpuinfo == NULL)
49 		return cpuid;
50 
51 	while ((read = getline(&line, &line_sz, cpuinfo)) != -1) {
52 		if (!strncmp(line, CPUINFO_MVEN, strlen(CPUINFO_MVEN))) {
53 			mvendorid = _get_field(line);
54 			if (!mvendorid)
55 				goto free;
56 		} else if (!strncmp(line, CPUINFO_MARCH, strlen(CPUINFO_MARCH))) {
57 			marchid = _get_field(line);
58 			if (!marchid)
59 				goto free;
60 		} else if (!strncmp(line, CPUINFO_MIMP, strlen(CPUINFO_MIMP))) {
61 			mimpid = _get_field(line);
62 			if (!mimpid)
63 				goto free;
64 
65 			break;
66 		}
67 	}
68 
69 	if (!mvendorid || !marchid || !mimpid)
70 		goto free;
71 
72 	if (asprintf(&cpuid, "%s-%s-%s", mvendorid, marchid, mimpid) < 0)
73 		cpuid = NULL;
74 
75 free:
76 	fclose(cpuinfo);
77 	free(mvendorid);
78 	free(marchid);
79 	free(mimpid);
80 
81 	return cpuid;
82 }
83 
84 int get_cpuid(char *buffer, size_t sz)
85 {
86 	char *cpuid = _get_cpuid();
87 	int ret = 0;
88 
89 	if (sz < strlen(cpuid)) {
90 		ret = -EINVAL;
91 		goto free;
92 	}
93 
94 	scnprintf(buffer, sz, "%s", cpuid);
95 free:
96 	free(cpuid);
97 	return ret;
98 }
99 
100 char *
101 get_cpuid_str(struct perf_pmu *pmu __maybe_unused)
102 {
103 	return _get_cpuid();
104 }
105