xref: /aosp_15_r20/external/ltp/lib/tst_kernel.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
1*49cdfc7eSAndroid Build Coastguard Worker /*
2*49cdfc7eSAndroid Build Coastguard Worker  * Copyright (c) 2017 Cyril Hrubis <[email protected]>
3*49cdfc7eSAndroid Build Coastguard Worker  * Copyright (c) 2020-2021 Petr Vorel <[email protected]>
4*49cdfc7eSAndroid Build Coastguard Worker  * Copyright (c) Linux Test Project, 2017-2024
5*49cdfc7eSAndroid Build Coastguard Worker  *
6*49cdfc7eSAndroid Build Coastguard Worker  * This program is free software: you can redistribute it and/or modify
7*49cdfc7eSAndroid Build Coastguard Worker  * it under the terms of the GNU General Public License as published by
8*49cdfc7eSAndroid Build Coastguard Worker  * the Free Software Foundation, either version 2 of the License, or
9*49cdfc7eSAndroid Build Coastguard Worker  * (at your option) any later version.
10*49cdfc7eSAndroid Build Coastguard Worker  *
11*49cdfc7eSAndroid Build Coastguard Worker  * This program is distributed in the hope that it will be useful,
12*49cdfc7eSAndroid Build Coastguard Worker  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13*49cdfc7eSAndroid Build Coastguard Worker  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14*49cdfc7eSAndroid Build Coastguard Worker  * GNU General Public License for more details.
15*49cdfc7eSAndroid Build Coastguard Worker  *
16*49cdfc7eSAndroid Build Coastguard Worker  * You should have received a copy of the GNU General Public License
17*49cdfc7eSAndroid Build Coastguard Worker  * along with this program. If not, see <http://www.gnu.org/licenses/>.
18*49cdfc7eSAndroid Build Coastguard Worker  */
19*49cdfc7eSAndroid Build Coastguard Worker 
20*49cdfc7eSAndroid Build Coastguard Worker #include <sys/personality.h>
21*49cdfc7eSAndroid Build Coastguard Worker #include <sys/utsname.h>
22*49cdfc7eSAndroid Build Coastguard Worker #include <stdbool.h>
23*49cdfc7eSAndroid Build Coastguard Worker #include <limits.h>
24*49cdfc7eSAndroid Build Coastguard Worker 
25*49cdfc7eSAndroid Build Coastguard Worker #include "test.h"
26*49cdfc7eSAndroid Build Coastguard Worker #include "tst_kernel.h"
27*49cdfc7eSAndroid Build Coastguard Worker #include "old_safe_stdio.h"
28*49cdfc7eSAndroid Build Coastguard Worker #include "lapi/abisize.h"
29*49cdfc7eSAndroid Build Coastguard Worker 
get_kernel_bits_from_uname(struct utsname * buf)30*49cdfc7eSAndroid Build Coastguard Worker static int get_kernel_bits_from_uname(struct utsname *buf)
31*49cdfc7eSAndroid Build Coastguard Worker {
32*49cdfc7eSAndroid Build Coastguard Worker 	if (uname(buf)) {
33*49cdfc7eSAndroid Build Coastguard Worker 		tst_brkm(TBROK | TERRNO, NULL, "uname()");
34*49cdfc7eSAndroid Build Coastguard Worker 		return -1;
35*49cdfc7eSAndroid Build Coastguard Worker 	}
36*49cdfc7eSAndroid Build Coastguard Worker 
37*49cdfc7eSAndroid Build Coastguard Worker 	return strstr(buf->machine, "64") ? 64 : 32;
38*49cdfc7eSAndroid Build Coastguard Worker }
39*49cdfc7eSAndroid Build Coastguard Worker 
tst_kernel_bits(void)40*49cdfc7eSAndroid Build Coastguard Worker int tst_kernel_bits(void)
41*49cdfc7eSAndroid Build Coastguard Worker {
42*49cdfc7eSAndroid Build Coastguard Worker 	struct utsname buf;
43*49cdfc7eSAndroid Build Coastguard Worker 	static int kernel_bits;
44*49cdfc7eSAndroid Build Coastguard Worker 
45*49cdfc7eSAndroid Build Coastguard Worker 	if (kernel_bits)
46*49cdfc7eSAndroid Build Coastguard Worker 		return kernel_bits;
47*49cdfc7eSAndroid Build Coastguard Worker 
48*49cdfc7eSAndroid Build Coastguard Worker 	kernel_bits = get_kernel_bits_from_uname(&buf);
49*49cdfc7eSAndroid Build Coastguard Worker 
50*49cdfc7eSAndroid Build Coastguard Worker 	if (kernel_bits == -1)
51*49cdfc7eSAndroid Build Coastguard Worker 		return -1;
52*49cdfc7eSAndroid Build Coastguard Worker 
53*49cdfc7eSAndroid Build Coastguard Worker 	/*
54*49cdfc7eSAndroid Build Coastguard Worker 	 * ARM64 (aarch64) defines 32-bit compatibility modes as
55*49cdfc7eSAndroid Build Coastguard Worker 	 * armv8l and armv8b (little and big endian).
56*49cdfc7eSAndroid Build Coastguard Worker 	 * s390x is 64bit but not contain 64 in the words.
57*49cdfc7eSAndroid Build Coastguard Worker 	 */
58*49cdfc7eSAndroid Build Coastguard Worker 	if (!strcmp(buf.machine, "armv8l") || !strcmp(buf.machine, "armv8b")
59*49cdfc7eSAndroid Build Coastguard Worker 			|| !strcmp(buf.machine, "s390x"))
60*49cdfc7eSAndroid Build Coastguard Worker 		kernel_bits = 64;
61*49cdfc7eSAndroid Build Coastguard Worker 
62*49cdfc7eSAndroid Build Coastguard Worker #ifdef __ANDROID__
63*49cdfc7eSAndroid Build Coastguard Worker 	/* Android's bionic libc sets the PER_LINUX32 personality for all 32-bit
64*49cdfc7eSAndroid Build Coastguard Worker 	 * programs. This will cause buf.machine to report as i686 even though
65*49cdfc7eSAndroid Build Coastguard Worker 	 * the kernel itself is 64-bit.
66*49cdfc7eSAndroid Build Coastguard Worker 	 */
67*49cdfc7eSAndroid Build Coastguard Worker 	if (!strcmp(buf.machine, "i686") &&
68*49cdfc7eSAndroid Build Coastguard Worker 			(personality(0xffffffff) & PER_MASK) == PER_LINUX32) {
69*49cdfc7eSAndroid Build Coastguard Worker 		/* Set the personality back to the default. */
70*49cdfc7eSAndroid Build Coastguard Worker 		if (personality(PER_LINUX) == -1) {
71*49cdfc7eSAndroid Build Coastguard Worker 			tst_brkm(TBROK | TERRNO, NULL, "personality()");
72*49cdfc7eSAndroid Build Coastguard Worker 			return -1;
73*49cdfc7eSAndroid Build Coastguard Worker 		}
74*49cdfc7eSAndroid Build Coastguard Worker 
75*49cdfc7eSAndroid Build Coastguard Worker 		/* Redo the uname check without the PER_LINUX32 personality to
76*49cdfc7eSAndroid Build Coastguard Worker 		 * determine the actual kernel bits value.
77*49cdfc7eSAndroid Build Coastguard Worker 		 */
78*49cdfc7eSAndroid Build Coastguard Worker 		kernel_bits = get_kernel_bits_from_uname(&buf);
79*49cdfc7eSAndroid Build Coastguard Worker 		if (kernel_bits == -1)
80*49cdfc7eSAndroid Build Coastguard Worker 			return -1;
81*49cdfc7eSAndroid Build Coastguard Worker 
82*49cdfc7eSAndroid Build Coastguard Worker 		/* Set the personality back to PER_LINUX32. */
83*49cdfc7eSAndroid Build Coastguard Worker 		if (personality(PER_LINUX32) == -1) {
84*49cdfc7eSAndroid Build Coastguard Worker 			tst_brkm(TBROK | TERRNO, NULL, "personality()");
85*49cdfc7eSAndroid Build Coastguard Worker 			return -1;
86*49cdfc7eSAndroid Build Coastguard Worker 		}
87*49cdfc7eSAndroid Build Coastguard Worker 	}
88*49cdfc7eSAndroid Build Coastguard Worker #endif  /* __ANDROID__ */
89*49cdfc7eSAndroid Build Coastguard Worker 
90*49cdfc7eSAndroid Build Coastguard Worker 	tst_resm(TINFO, "uname.machine=%s kernel is %ibit",
91*49cdfc7eSAndroid Build Coastguard Worker 		 buf.machine, kernel_bits);
92*49cdfc7eSAndroid Build Coastguard Worker 
93*49cdfc7eSAndroid Build Coastguard Worker 	return kernel_bits;
94*49cdfc7eSAndroid Build Coastguard Worker }
95*49cdfc7eSAndroid Build Coastguard Worker 
tst_is_compat_mode(void)96*49cdfc7eSAndroid Build Coastguard Worker int tst_is_compat_mode(void)
97*49cdfc7eSAndroid Build Coastguard Worker {
98*49cdfc7eSAndroid Build Coastguard Worker 	return TST_ABI != tst_kernel_bits();
99*49cdfc7eSAndroid Build Coastguard Worker }
100*49cdfc7eSAndroid Build Coastguard Worker 
tst_abi_bits(int abi)101*49cdfc7eSAndroid Build Coastguard Worker bool tst_abi_bits(int abi)
102*49cdfc7eSAndroid Build Coastguard Worker {
103*49cdfc7eSAndroid Build Coastguard Worker 	if (abi != 32 && abi != 64)
104*49cdfc7eSAndroid Build Coastguard Worker 		tst_brkm(TBROK | TERRNO, NULL, "abi parameter can be only 32 or 64");
105*49cdfc7eSAndroid Build Coastguard Worker 
106*49cdfc7eSAndroid Build Coastguard Worker 	return abi == TST_ABI;
107*49cdfc7eSAndroid Build Coastguard Worker }
108*49cdfc7eSAndroid Build Coastguard Worker 
tst_search_driver_(const char * driver,const char * file)109*49cdfc7eSAndroid Build Coastguard Worker static int tst_search_driver_(const char *driver, const char *file)
110*49cdfc7eSAndroid Build Coastguard Worker {
111*49cdfc7eSAndroid Build Coastguard Worker 	struct stat st;
112*49cdfc7eSAndroid Build Coastguard Worker 	char buf[PATH_MAX];
113*49cdfc7eSAndroid Build Coastguard Worker 	char *path = NULL, *search = NULL, *sep = NULL;
114*49cdfc7eSAndroid Build Coastguard Worker 	FILE *f;
115*49cdfc7eSAndroid Build Coastguard Worker 	int ret = -1;
116*49cdfc7eSAndroid Build Coastguard Worker 
117*49cdfc7eSAndroid Build Coastguard Worker 	struct utsname uts;
118*49cdfc7eSAndroid Build Coastguard Worker 
119*49cdfc7eSAndroid Build Coastguard Worker 	if (uname(&uts)) {
120*49cdfc7eSAndroid Build Coastguard Worker 		tst_brkm(TBROK | TERRNO, NULL, "uname() failed");
121*49cdfc7eSAndroid Build Coastguard Worker 		return -1;
122*49cdfc7eSAndroid Build Coastguard Worker 	}
123*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_ASPRINTF(NULL, &path, "/lib/modules/%s/%s", uts.release, file);
124*49cdfc7eSAndroid Build Coastguard Worker 
125*49cdfc7eSAndroid Build Coastguard Worker 	if (stat(path, &st) || !(S_ISREG(st.st_mode) || S_ISLNK(st.st_mode))) {
126*49cdfc7eSAndroid Build Coastguard Worker 		tst_resm(TWARN, "expected file %s does not exist or not a file", path);
127*49cdfc7eSAndroid Build Coastguard Worker 		return -1;
128*49cdfc7eSAndroid Build Coastguard Worker 	}
129*49cdfc7eSAndroid Build Coastguard Worker 
130*49cdfc7eSAndroid Build Coastguard Worker 	if (access(path, R_OK)) {
131*49cdfc7eSAndroid Build Coastguard Worker 		tst_resm(TWARN, "file %s cannot be read", path);
132*49cdfc7eSAndroid Build Coastguard Worker 		return -1;
133*49cdfc7eSAndroid Build Coastguard Worker 	}
134*49cdfc7eSAndroid Build Coastguard Worker 
135*49cdfc7eSAndroid Build Coastguard Worker 	/* always search for x86_64 */
136*49cdfc7eSAndroid Build Coastguard Worker 	char *fix = strstr(driver, "x86-64");
137*49cdfc7eSAndroid Build Coastguard Worker 
138*49cdfc7eSAndroid Build Coastguard Worker 	if (fix)
139*49cdfc7eSAndroid Build Coastguard Worker 		fix[3] = '_';
140*49cdfc7eSAndroid Build Coastguard Worker 
141*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_ASPRINTF(NULL, &search, "/%s.ko", driver);
142*49cdfc7eSAndroid Build Coastguard Worker 
143*49cdfc7eSAndroid Build Coastguard Worker 	f = SAFE_FOPEN(NULL, path, "r");
144*49cdfc7eSAndroid Build Coastguard Worker 
145*49cdfc7eSAndroid Build Coastguard Worker 	while (fgets(buf, sizeof(buf), f)) {
146*49cdfc7eSAndroid Build Coastguard Worker 		/* cut dependencies after : */
147*49cdfc7eSAndroid Build Coastguard Worker 		if ((sep = strchr(buf, ':')))
148*49cdfc7eSAndroid Build Coastguard Worker 			*sep = 0;
149*49cdfc7eSAndroid Build Coastguard Worker 
150*49cdfc7eSAndroid Build Coastguard Worker 		/* driver found */
151*49cdfc7eSAndroid Build Coastguard Worker 		if (strstr(buf, search) != NULL) {
152*49cdfc7eSAndroid Build Coastguard Worker 			ret = 0;
153*49cdfc7eSAndroid Build Coastguard Worker 			break;
154*49cdfc7eSAndroid Build Coastguard Worker 		}
155*49cdfc7eSAndroid Build Coastguard Worker 	}
156*49cdfc7eSAndroid Build Coastguard Worker 
157*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_FCLOSE(NULL, f);
158*49cdfc7eSAndroid Build Coastguard Worker 	free(search);
159*49cdfc7eSAndroid Build Coastguard Worker 	free(path);
160*49cdfc7eSAndroid Build Coastguard Worker 
161*49cdfc7eSAndroid Build Coastguard Worker 	return ret;
162*49cdfc7eSAndroid Build Coastguard Worker }
163*49cdfc7eSAndroid Build Coastguard Worker 
tst_search_driver(const char * driver,const char * file)164*49cdfc7eSAndroid Build Coastguard Worker static int tst_search_driver(const char *driver, const char *file)
165*49cdfc7eSAndroid Build Coastguard Worker {
166*49cdfc7eSAndroid Build Coastguard Worker #ifdef __ANDROID__
167*49cdfc7eSAndroid Build Coastguard Worker 	/*
168*49cdfc7eSAndroid Build Coastguard Worker 	 * Android may not have properly installed modules.* files. We could
169*49cdfc7eSAndroid Build Coastguard Worker 	 * search modules in /system/lib/modules, but to determine built-in
170*49cdfc7eSAndroid Build Coastguard Worker 	 * drivers we need modules.builtin. Therefore assume all drivers are
171*49cdfc7eSAndroid Build Coastguard Worker 	 * available.
172*49cdfc7eSAndroid Build Coastguard Worker 	 */
173*49cdfc7eSAndroid Build Coastguard Worker 	return 0;
174*49cdfc7eSAndroid Build Coastguard Worker #endif
175*49cdfc7eSAndroid Build Coastguard Worker 
176*49cdfc7eSAndroid Build Coastguard Worker 	if (!tst_search_driver_(driver, file))
177*49cdfc7eSAndroid Build Coastguard Worker 		return 0;
178*49cdfc7eSAndroid Build Coastguard Worker 
179*49cdfc7eSAndroid Build Coastguard Worker 	int ret = -1;
180*49cdfc7eSAndroid Build Coastguard Worker 
181*49cdfc7eSAndroid Build Coastguard Worker 	if (strrchr(driver, '-') || strrchr(driver, '_')) {
182*49cdfc7eSAndroid Build Coastguard Worker 		char *driver2 = strdup(driver);
183*49cdfc7eSAndroid Build Coastguard Worker 		char *ix = driver2;
184*49cdfc7eSAndroid Build Coastguard Worker 		char find = '-', replace = '_';
185*49cdfc7eSAndroid Build Coastguard Worker 
186*49cdfc7eSAndroid Build Coastguard Worker 		if (strrchr(driver, '_')) {
187*49cdfc7eSAndroid Build Coastguard Worker 			find = '_';
188*49cdfc7eSAndroid Build Coastguard Worker 			replace = '-';
189*49cdfc7eSAndroid Build Coastguard Worker 		}
190*49cdfc7eSAndroid Build Coastguard Worker 
191*49cdfc7eSAndroid Build Coastguard Worker 		while ((ix = strchr(ix, find)))
192*49cdfc7eSAndroid Build Coastguard Worker 			*ix++ = replace;
193*49cdfc7eSAndroid Build Coastguard Worker 
194*49cdfc7eSAndroid Build Coastguard Worker 		ret = tst_search_driver_(driver2, file);
195*49cdfc7eSAndroid Build Coastguard Worker 		free(driver2);
196*49cdfc7eSAndroid Build Coastguard Worker 	}
197*49cdfc7eSAndroid Build Coastguard Worker 
198*49cdfc7eSAndroid Build Coastguard Worker 	return ret;
199*49cdfc7eSAndroid Build Coastguard Worker }
200*49cdfc7eSAndroid Build Coastguard Worker 
tst_check_builtin_driver(const char * driver)201*49cdfc7eSAndroid Build Coastguard Worker int tst_check_builtin_driver(const char *driver)
202*49cdfc7eSAndroid Build Coastguard Worker {
203*49cdfc7eSAndroid Build Coastguard Worker 	if (!tst_search_driver(driver, "modules.builtin"))
204*49cdfc7eSAndroid Build Coastguard Worker 		return 0;
205*49cdfc7eSAndroid Build Coastguard Worker 
206*49cdfc7eSAndroid Build Coastguard Worker 	return -1;
207*49cdfc7eSAndroid Build Coastguard Worker }
208*49cdfc7eSAndroid Build Coastguard Worker 
tst_check_driver(const char * driver)209*49cdfc7eSAndroid Build Coastguard Worker int tst_check_driver(const char *driver)
210*49cdfc7eSAndroid Build Coastguard Worker {
211*49cdfc7eSAndroid Build Coastguard Worker 	if (!tst_search_driver(driver, "modules.dep") ||
212*49cdfc7eSAndroid Build Coastguard Worker 		!tst_check_builtin_driver(driver))
213*49cdfc7eSAndroid Build Coastguard Worker 		return 0;
214*49cdfc7eSAndroid Build Coastguard Worker 
215*49cdfc7eSAndroid Build Coastguard Worker 	return -1;
216*49cdfc7eSAndroid Build Coastguard Worker }
217