xref: /linux/tools/perf/arch/loongarch/util/header.c (revision a1ff5a7d78a036d6c2178ee5acd6ba4946243800)
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