Skip to content

Commit 89a3f03

Browse files
authored
Add FreeBSD Arm64 support (#295)
* Add FreeBSD Arm64 detection Getting all the features is handled by reading /var/run/dmesg.boot. Feature detections were taken from the freebsd kernel code sys/arm64/arm64/identcpu.c * Add FreeBSD Arm64 tests * Add flagm, flagm2 and rng detection * Add HWCAP FreeBSD AArch64 * Update include to use linux hwcaps for powerpc * Add FreeBSD aarch64 impl * Separate Hwacps to freebsd and linux implementation * Add aarch64 midr_el1 implementation * Add detection hwcap cpuid to hwcaps.h * Add MIDR_EL1 tests
1 parent 494d965 commit 89a3f03

File tree

11 files changed

+424
-155
lines changed

11 files changed

+424
-155
lines changed

BUILD.bazel

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
load("@bazel_skylib//lib:selects.bzl", "selects")
44
load("//:bazel/platforms.bzl", "PLATFORM_CPU_ARM", "PLATFORM_CPU_ARM64", "PLATFORM_CPU_MIPS", "PLATFORM_CPU_PPC", "PLATFORM_CPU_RISCV32", "PLATFORM_CPU_RISCV64", "PLATFORM_CPU_X86_64")
5-
load("//:bazel/platforms.bzl", "PLATFORM_OS_MACOS")
5+
load("//:bazel/platforms.bzl", "PLATFORM_OS_MACOS", "PLATFORM_OS_LINUX", "PLATFORM_OS_FREEBSD", "PLATFORM_OS_ANDROID")
66

77
package(
88
default_visibility = ["//visibility:public"],
@@ -169,11 +169,18 @@ cc_library(
169169

170170
cc_library(
171171
name = "hwcaps",
172-
srcs = ["src/hwcaps.c"],
172+
srcs = [
173+
"src/hwcaps.c",
174+
"src/hwcaps_freebsd.c",
175+
"src/hwcaps_linux_or_android.c",
176+
],
173177
copts = C99_FLAGS,
174178
defines = selects.with_or({
175179
PLATFORM_OS_MACOS: ["HAVE_DLFCN_H"],
176-
"//conditions:default": ["HAVE_STRONG_GETAUXVAL"],
180+
PLATFORM_OS_FREEBSD: ["HAVE_STRONG_ELF_AUX_INFO"],
181+
PLATFORM_OS_LINUX: ["HAVE_STRONG_GETAUXVAL"],
182+
PLATFORM_OS_ANDROID: ["HAVE_STRONG_GETAUXVAL"],
183+
"//conditions:default": [],
177184
}),
178185
includes = INCLUDES,
179186
textual_hdrs = ["include/internal/hwcaps.h"],
@@ -189,6 +196,8 @@ cc_library(
189196
testonly = 1,
190197
srcs = [
191198
"src/hwcaps.c",
199+
"src/hwcaps_freebsd.c",
200+
"src/hwcaps_linux_or_android.c",
192201
"test/hwcaps_for_testing.cc",
193202
],
194203
hdrs = [
@@ -218,9 +227,11 @@ cc_library(
218227
],
219228
PLATFORM_CPU_ARM: ["src/impl_arm_linux_or_android.c"],
220229
PLATFORM_CPU_ARM64: [
230+
"src/impl_aarch64_cpuid.c",
221231
"src/impl_aarch64_linux_or_android.c",
222232
"src/impl_aarch64_macos_or_iphone.c",
223233
"src/impl_aarch64_windows.c",
234+
"src/impl_aarch64_freebsd.c",
224235
],
225236
PLATFORM_CPU_MIPS: ["src/impl_mips_linux_or_android.c"],
226237
PLATFORM_CPU_PPC: ["src/impl_ppc_linux.c"],
@@ -234,7 +245,10 @@ cc_library(
234245
"include/internal/windows_utils.h",
235246
],
236247
PLATFORM_CPU_ARM: ["include/cpuinfo_arm.h"],
237-
PLATFORM_CPU_ARM64: ["include/cpuinfo_aarch64.h"],
248+
PLATFORM_CPU_ARM64: [
249+
"include/cpuinfo_aarch64.h",
250+
"include/internal/cpuid_aarch64.h",
251+
],
238252
PLATFORM_CPU_MIPS: ["include/cpuinfo_mips.h"],
239253
PLATFORM_CPU_PPC: ["include/cpuinfo_ppc.h"],
240254
PLATFORM_CPU_RISCV32: ["include/cpuinfo_riscv.h"],
@@ -278,9 +292,11 @@ cc_library(
278292
],
279293
PLATFORM_CPU_ARM: ["src/impl_arm_linux_or_android.c"],
280294
PLATFORM_CPU_ARM64: [
295+
"src/impl_aarch64_cpuid.c",
281296
"src/impl_aarch64_linux_or_android.c",
282297
"src/impl_aarch64_macos_or_iphone.c",
283298
"src/impl_aarch64_windows.c",
299+
"src/impl_aarch64_freebsd.c",
284300
],
285301
PLATFORM_CPU_MIPS: ["src/impl_mips_linux_or_android.c"],
286302
PLATFORM_CPU_PPC: ["src/impl_ppc_linux.c"],
@@ -294,7 +310,10 @@ cc_library(
294310
"include/internal/windows_utils.h",
295311
],
296312
PLATFORM_CPU_ARM: ["include/cpuinfo_arm.h"],
297-
PLATFORM_CPU_ARM64: ["include/cpuinfo_aarch64.h"],
313+
PLATFORM_CPU_ARM64: [
314+
"include/cpuinfo_aarch64.h",
315+
"include/internal/cpuid_aarch64.h"
316+
],
298317
PLATFORM_CPU_MIPS: ["include/cpuinfo_mips.h"],
299318
PLATFORM_CPU_PPC: ["include/cpuinfo_ppc.h"],
300319
PLATFORM_CPU_RISCV32: ["include/cpuinfo_riscv.h"],

CMakeLists.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ macro(add_cpu_features_headers_and_sources HDRS_LIST_NAME SRCS_LIST_NAME)
106106
list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_arm.h)
107107
elseif(PROCESSOR_IS_AARCH64)
108108
list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_aarch64.h)
109+
list(APPEND ${SRCS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/internal/cpuid_aarch64.h)
109110
list(APPEND ${SRCS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/internal/windows_utils.h)
110111
elseif(PROCESSOR_IS_X86)
111112
list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_x86.h)
@@ -146,6 +147,8 @@ setup_include_and_definitions(utils)
146147
if(UNIX)
147148
add_library(unix_based_hardware_detection OBJECT
148149
${PROJECT_SOURCE_DIR}/include/internal/hwcaps.h
150+
${PROJECT_SOURCE_DIR}/src/hwcaps_linux_or_android.c
151+
${PROJECT_SOURCE_DIR}/src/hwcaps_freebsd.c
149152
${PROJECT_SOURCE_DIR}/src/hwcaps.c
150153
)
151154
setup_include_and_definitions(unix_based_hardware_detection)
@@ -154,9 +157,13 @@ if(UNIX)
154157
target_compile_definitions(unix_based_hardware_detection PRIVATE HAVE_DLFCN_H)
155158
endif()
156159
check_symbol_exists(getauxval "sys/auxv.h" HAVE_STRONG_GETAUXVAL)
160+
check_symbol_exists(elf_aux_info "sys/auxv.h" HAVE_STRONG_ELF_AUX_INFO)
157161
if(HAVE_STRONG_GETAUXVAL)
158162
target_compile_definitions(unix_based_hardware_detection PRIVATE HAVE_STRONG_GETAUXVAL)
159163
endif()
164+
if(HAVE_STRONG_ELF_AUX_INFO)
165+
target_compile_definitions(unix_based_hardware_detection PUBLIC HAVE_STRONG_ELF_AUX_INFO)
166+
endif()
160167
endif()
161168

162169
#

bazel/platforms.bzl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,9 @@ PLATFORM_CPU_RISCV64 = ("@platforms//cpu:riscv64")
1616

1717

1818
PLATFORM_OS_MACOS = ("@platforms//os:macos")
19+
20+
PLATFORM_OS_LINUX = ("@platforms//os:linux")
21+
22+
PLATFORM_OS_ANDROID = ("@platforms//os:android")
23+
24+
PLATFORM_OS_FREEBSD = ("@platforms//os:freebsd")

include/internal/cpuid_aarch64.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright 2023 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#ifndef CPU_FEATURES_INCLUDE_CPUID_AARCH64_H_
16+
#define CPU_FEATURES_INCLUDE_CPUID_AARCH64_H_
17+
18+
#include <stdint.h>
19+
20+
#include "cpu_features_macros.h"
21+
22+
CPU_FEATURES_START_CPP_NAMESPACE
23+
24+
uint64_t GetMidrEl1(void);
25+
26+
CPU_FEATURES_END_CPP_NAMESPACE
27+
28+
#endif // CPU_FEATURES_INCLUDE_CPUID_AARCH64_H_

src/hwcaps.c

Lines changed: 1 addition & 142 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,7 @@
1414

1515
#include "internal/hwcaps.h"
1616

17-
#include <stdlib.h>
18-
#include <string.h>
19-
20-
#include "cpu_features_macros.h"
21-
#include "internal/filesystem.h"
22-
#include "internal/string_view.h"
17+
#include <stdbool.h>
2318

2419
static bool IsSet(const uint32_t mask, const uint32_t value) {
2520
if (mask == 0) return false;
@@ -31,139 +26,3 @@ bool CpuFeatures_IsHwCapsSet(const HardwareCapabilities hwcaps_mask,
3126
return IsSet(hwcaps_mask.hwcaps, hwcaps.hwcaps) ||
3227
IsSet(hwcaps_mask.hwcaps2, hwcaps.hwcaps2);
3328
}
34-
35-
#ifdef CPU_FEATURES_TEST
36-
// In test mode, hwcaps_for_testing will define the following functions.
37-
HardwareCapabilities CpuFeatures_GetHardwareCapabilities(void);
38-
const char* CpuFeatures_GetPlatformPointer(void);
39-
const char* CpuFeatures_GetBasePlatformPointer(void);
40-
#else
41-
42-
// Debug facilities
43-
#if defined(NDEBUG)
44-
#define D(...)
45-
#else
46-
#include <stdio.h>
47-
#define D(...) \
48-
do { \
49-
printf(__VA_ARGS__); \
50-
fflush(stdout); \
51-
} while (0)
52-
#endif
53-
54-
////////////////////////////////////////////////////////////////////////////////
55-
// Implementation of GetElfHwcapFromGetauxval
56-
////////////////////////////////////////////////////////////////////////////////
57-
58-
#define AT_HWCAP 16
59-
#define AT_HWCAP2 26
60-
#define AT_PLATFORM 15
61-
#define AT_BASE_PLATFORM 24
62-
63-
#if defined(HAVE_STRONG_GETAUXVAL)
64-
#include <sys/auxv.h>
65-
static unsigned long GetElfHwcapFromGetauxval(uint32_t hwcap_type) {
66-
return getauxval(hwcap_type);
67-
}
68-
#elif defined(HAVE_DLFCN_H)
69-
// On Android we probe the system's C library for a 'getauxval' function and
70-
// call it if it exits, or return 0 for failure. This function is available
71-
// since API level 18.
72-
//
73-
// Note that getauxval() can't really be re-implemented here, because its
74-
// implementation does not parse /proc/self/auxv. Instead it depends on values
75-
// that are passed by the kernel at process-init time to the C runtime
76-
// initialization layer.
77-
78-
#include <dlfcn.h>
79-
80-
typedef unsigned long getauxval_func_t(unsigned long);
81-
82-
static uint32_t GetElfHwcapFromGetauxval(uint32_t hwcap_type) {
83-
uint32_t ret = 0;
84-
void *libc_handle = NULL;
85-
getauxval_func_t *func = NULL;
86-
87-
dlerror(); // Cleaning error state before calling dlopen.
88-
libc_handle = dlopen("libc.so", RTLD_NOW);
89-
if (!libc_handle) {
90-
D("Could not dlopen() C library: %s\n", dlerror());
91-
return 0;
92-
}
93-
func = (getauxval_func_t *)dlsym(libc_handle, "getauxval");
94-
if (!func) {
95-
D("Could not find getauxval() in C library\n");
96-
} else {
97-
// Note: getauxval() returns 0 on failure. Doesn't touch errno.
98-
ret = (uint32_t)(*func)(hwcap_type);
99-
}
100-
dlclose(libc_handle);
101-
return ret;
102-
}
103-
#else
104-
#error "This platform does not provide hardware capabilities."
105-
#endif
106-
107-
// Implementation of GetHardwareCapabilities for OS that provide
108-
// GetElfHwcapFromGetauxval().
109-
110-
// Fallback when getauxval is not available, retrieves hwcaps from
111-
// "/proc/self/auxv".
112-
static uint32_t GetElfHwcapFromProcSelfAuxv(uint32_t hwcap_type) {
113-
struct {
114-
uint32_t tag;
115-
uint32_t value;
116-
} entry;
117-
uint32_t result = 0;
118-
const char filepath[] = "/proc/self/auxv";
119-
const int fd = CpuFeatures_OpenFile(filepath);
120-
if (fd < 0) {
121-
D("Could not open %s\n", filepath);
122-
return 0;
123-
}
124-
for (;;) {
125-
const int ret = CpuFeatures_ReadFile(fd, (char *)&entry, sizeof entry);
126-
if (ret < 0) {
127-
D("Error while reading %s\n", filepath);
128-
break;
129-
}
130-
// Detect end of list.
131-
if (ret == 0 || (entry.tag == 0 && entry.value == 0)) {
132-
break;
133-
}
134-
if (entry.tag == hwcap_type) {
135-
result = entry.value;
136-
break;
137-
}
138-
}
139-
CpuFeatures_CloseFile(fd);
140-
return result;
141-
}
142-
143-
// Retrieves hardware capabilities by first trying to call getauxval, if not
144-
// available falls back to reading "/proc/self/auxv".
145-
static unsigned long GetHardwareCapabilitiesFor(uint32_t type) {
146-
unsigned long hwcaps = GetElfHwcapFromGetauxval(type);
147-
if (!hwcaps) {
148-
D("Parsing /proc/self/auxv to extract ELF hwcaps!\n");
149-
hwcaps = GetElfHwcapFromProcSelfAuxv(type);
150-
}
151-
return hwcaps;
152-
}
153-
154-
HardwareCapabilities CpuFeatures_GetHardwareCapabilities(void) {
155-
HardwareCapabilities capabilities;
156-
capabilities.hwcaps = GetHardwareCapabilitiesFor(AT_HWCAP);
157-
capabilities.hwcaps2 = GetHardwareCapabilitiesFor(AT_HWCAP2);
158-
return capabilities;
159-
}
160-
161-
const char *CpuFeatures_GetPlatformPointer(void) {
162-
return (const char *)GetHardwareCapabilitiesFor(AT_PLATFORM);
163-
}
164-
165-
const char *CpuFeatures_GetBasePlatformPointer(void) {
166-
return (const char *)GetHardwareCapabilitiesFor(AT_BASE_PLATFORM);
167-
}
168-
169-
#endif // CPU_FEATURES_TEST

src/hwcaps_freebsd.c

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// Copyright 2023 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include "cpu_features_macros.h"
16+
17+
#ifdef CPU_FEATURES_OS_FREEBSD
18+
19+
#include "internal/hwcaps.h"
20+
21+
#ifdef CPU_FEATURES_TEST
22+
// In test mode, hwcaps_for_testing will define the following functions.
23+
HardwareCapabilities CpuFeatures_GetHardwareCapabilities(void);
24+
const char* CpuFeatures_GetPlatformPointer(void);
25+
const char* CpuFeatures_GetBasePlatformPointer(void);
26+
#else
27+
28+
#ifdef HAVE_STRONG_ELF_AUX_INFO
29+
#include <stddef.h>
30+
#include <sys/auxv.h>
31+
32+
static unsigned long GetElfHwcapFromElfAuxInfo(int hwcap_type) {
33+
unsigned long hwcap;
34+
elf_aux_info(hwcap_type, &hwcap, sizeof(hwcap));
35+
return hwcap;
36+
}
37+
38+
HardwareCapabilities CpuFeatures_GetHardwareCapabilities(void) {
39+
HardwareCapabilities capabilities;
40+
capabilities.hwcaps = GetElfHwcapFromElfAuxInfo(AT_HWCAP);
41+
capabilities.hwcaps2 = GetElfHwcapFromElfAuxInfo(AT_HWCAP2);
42+
return capabilities;
43+
}
44+
45+
const char *CpuFeatures_GetPlatformPointer(void) { return NULL; }
46+
47+
const char *CpuFeatures_GetBasePlatformPointer(void) { return NULL; }
48+
49+
#else
50+
#error "FreeBSD needs support for elf_aux_info"
51+
#endif // HAVE_STRONG_ELF_AUX_INFO
52+
53+
#endif // CPU_FEATURES_TEST
54+
#endif // CPU_FEATURES_OS_FREEBSD

0 commit comments

Comments
 (0)