CMake: Detect cache line size dynamically on AArch64 Linux

This commit is contained in:
Stenzek 2024-05-14 23:50:26 +10:00
parent d9003b10c3
commit 88ace6e4ae
No known key found for this signature in database
4 changed files with 62 additions and 1 deletions

View file

@ -29,6 +29,7 @@ detect_operating_system()
detect_compiler()
detect_architecture()
detect_page_size()
detect_cache_line_size()
# Build options. Depends on system attributes.
include(DuckStationBuildOptions)

View file

@ -139,3 +139,58 @@ int main() {
set(HOST_PAGE_SIZE ${detect_page_size_output} CACHE STRING "Reported host page size")
endif()
endfunction()
function(detect_cache_line_size)
# This is only needed for ARM64, or if the user hasn't overridden it explicitly.
if(NOT CPU_ARCH_ARM64 OR HOST_CACHE_LINE_SIZE)
return()
endif()
if(NOT LINUX)
# For universal Apple builds, we use preprocessor macros to determine page size.
# Similar for Windows, except it's always 64 bytes.
return()
endif()
if(CMAKE_CROSSCOMPILING)
message(WARNING "Cross-compiling and can't determine page size, assuming default.")
return()
endif()
message(STATUS "Determining host cache line size")
set(detect_cache_line_size_file ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.c)
file(WRITE ${detect_cache_line_size_file} "
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main() {
int l1i = sysconf(_SC_LEVEL1_DCACHE_LINESIZE);
int l1d = sysconf(_SC_LEVEL1_ICACHE_LINESIZE);
int res = (l1i > l1d) ? l1i : l1d;
for (int index = 0; index < 16; index++) {
char buf[128];
snprintf(buf, sizeof(buf), \"/sys/devices/system/cpu/cpu0/cache/index%d/coherency_line_size\", index);
FILE* fp = fopen(buf, \"rb\");
if (!fp)
break;
fread(buf, sizeof(buf), 1, fp);
fclose(fp);
int val = atoi(buf);
res = (val > res) ? val : res;
}
printf(\"%d\", res);
return (res > 0) ? EXIT_SUCCESS : EXIT_FAILURE;
}")
try_run(
detect_cache_line_size_run_result
detect_cache_line_size_compile_result
${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}
${detect_cache_line_size_file}
RUN_OUTPUT_VARIABLE detect_cache_line_size_output)
if(NOT detect_cache_line_size_compile_result OR NOT detect_cache_line_size_run_result EQUAL 0)
message(FATAL_ERROR "Could not determine host cache line size.")
else()
message(STATUS "Host cache line size: ${detect_cache_line_size_output}")
set(HOST_CACHE_LINE_SIZE ${detect_cache_line_size_output} CACHE STRING "Reported host cache line size")
endif()
endfunction()

View file

@ -111,3 +111,6 @@ endif()
if(HOST_PAGE_SIZE)
target_compile_definitions(common PUBLIC "-DOVERRIDE_HOST_PAGE_SIZE=${HOST_PAGE_SIZE}")
endif()
if(HOST_CACHE_LINE_SIZE)
target_compile_definitions(common PUBLIC "-DOVERRIDE_HOST_CACHE_LINE_SIZE=${HOST_CACHE_LINE_SIZE}")
endif()

View file

@ -192,7 +192,9 @@ static constexpr u32 HOST_PAGE_SHIFT = 12;
#endif
// Host cache line sizes.
#if defined(__APPLE__) && defined(__aarch64__)
#if defined(OVERRIDE_HOST_CACHE_LINE_SIZE)
static constexpr u32 HOST_CACHE_LINE_SIZE = OVERRIDE_HOST_CACHE_LINE_SIZE;
#elif defined(__APPLE__) && defined(__aarch64__)
static constexpr u32 HOST_CACHE_LINE_SIZE = 128; // Apple Silicon uses 128b cache lines.
#else
static constexpr u32 HOST_CACHE_LINE_SIZE = 64; // Everything else is 64b.