1 /* 2 * Copyright (c) 2017 Cyril Hrubis <chrubis (at) suse.cz> 3 * 4 * This program is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 #include <linux/personality.h> 19 #include <sys/utsname.h> 20 #include "test.h" 21 #include "tst_kernel.h" 22 23 static int get_kernel_bits_from_uname(struct utsname *buf) 24 { 25 if (uname(buf)) { 26 tst_brkm(TBROK | TERRNO, NULL, "uname()"); 27 return -1; 28 } 29 30 return strstr(buf->machine, "64") ? 64 : 32; 31 } 32 33 int tst_kernel_bits(void) 34 { 35 struct utsname buf; 36 int kernel_bits = get_kernel_bits_from_uname(&buf); 37 38 if (kernel_bits == -1) 39 return -1; 40 41 /* 42 * ARM64 (aarch64) defines 32-bit compatibility modes as 43 * armv8l and armv8b (little and big endian). 44 * s390x is 64bit but not contain 64 in the words. 45 */ 46 if (!strcmp(buf.machine, "armv8l") || !strcmp(buf.machine, "armv8b") 47 || !strcmp(buf.machine, "s390x")) 48 kernel_bits = 64; 49 50 #ifdef __ANDROID__ 51 /* Android's bionic libc sets the PER_LINUX32 personality for all 32-bit 52 * programs. This will cause buf.machine to report as i686 even though 53 * the kernel itself is 64-bit. 54 */ 55 if (!strcmp(buf.machine, "i686") && 56 (personality(0xffffffff) & PER_MASK) == PER_LINUX32) { 57 /* Set the personality back to the default. */ 58 if (personality(PER_LINUX) == -1) { 59 tst_brkm(TBROK | TERRNO, NULL, "personality()"); 60 return -1; 61 } 62 63 /* Redo the uname check without the PER_LINUX32 personality to 64 * determine the actual kernel bits value. 65 */ 66 kernel_bits = get_kernel_bits_from_uname(&buf); 67 if (kernel_bits == -1) 68 return -1; 69 70 /* Set the personality back to PER_LINUX32. */ 71 if (personality(PER_LINUX32) == -1) { 72 tst_brkm(TBROK | TERRNO, NULL, "personality()"); 73 return -1; 74 } 75 } 76 #endif /* __ANDROID__ */ 77 78 tst_resm(TINFO, "uname.machine=%s kernel is %ibit", 79 buf.machine, kernel_bits); 80 81 return kernel_bits; 82 } 83 84 int tst_check_driver(const char *name) 85 { 86 #ifndef __ANDROID__ 87 const char * const argv[] = { "modprobe", "-n", name, NULL }; 88 int res = tst_run_cmd_(NULL, argv, "/dev/null", "/dev/null", 1); 89 90 /* 255 - it looks like modprobe not available */ 91 return (res == 255) ? 0 : res; 92 #else 93 /* Android modprobe may not have '-n', or properly installed 94 * module.*.bin files to determine built-in drivers. Assume 95 * all drivers are available. 96 */ 97 return 0; 98 #endif 99 } 100