From e57db36600d0954adc4c69bf37cde688d31625b4 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Sat, 24 Feb 2024 21:40:56 +1000 Subject: [PATCH] CMake: Determine host page size at build time Needed for running on Asahi Linux. --- CMakeLists.txt | 23 +++++++++------- CMakeModules/DuckStationUtils.cmake | 42 +++++++++++++++++++++++++++++ src/common/CMakeLists.txt | 7 ++++- src/common/types.h | 9 +++++-- src/core/cpu_code_cache.cpp | 5 ++-- 5 files changed, 70 insertions(+), 16 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 647f09ffd..40b1dc7b2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,9 +5,9 @@ project(duckstation C CXX) cmake_policy(SET CMP0069 NEW) set(CMAKE_POLICY_DEFAULT_CMP0069 NEW) -message("CMake Version: ${CMAKE_VERSION}") -message("CMake System Name: ${CMAKE_SYSTEM_NAME}") -message("Build Type: ${CMAKE_BUILD_TYPE}") +message(STATUS "CMake Version: ${CMAKE_VERSION}") +message(STATUS "CMake System Name: ${CMAKE_SYSTEM_NAME}") +message(STATUS "Build Type: ${CMAKE_BUILD_TYPE}") # Pull in modules. set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/CMakeModules/") @@ -118,17 +118,17 @@ if(APPLE AND NOT "${CMAKE_OSX_ARCHITECTURES}" STREQUAL "") # Universal binaries. if("x86_64" IN_LIST CMAKE_OSX_ARCHITECTURES) set(CPU_ARCH_X64 TRUE) - message("Building x86_64 MacOS binaries.") + message(STATUS "Building x86_64 MacOS binaries.") endif() if("arm64" IN_LIST CMAKE_OSX_ARCHITECTURES) set(CPU_ARCH_ARM64 TRUE) - message("Building ARM64 MacOS binaries.") + message(STATUS "Building ARM64 MacOS binaries.") endif() elseif("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "x86_64" OR "${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "amd64" OR "${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "AMD64" OR "${CMAKE_OSX_ARCHITECTURES}" STREQUAL "x86_64") if(CMAKE_SIZEOF_VOID_P EQUAL 8) set(CPU_ARCH_X64 TRUE) - message("Building x86_64 binaries.") + message(STATUS "Building x86_64 binaries.") else() # Cross-compiling 32-bit build. 32-bit hosts are not supported. set(CPU_ARCH_X86 TRUE) @@ -141,17 +141,17 @@ elseif("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "x86" OR "${CMAKE_SYSTEM_PROCESSOR}" elseif("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "aarch64" OR "${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "arm64") if(CMAKE_SIZEOF_VOID_P EQUAL 8) # Might have an A64 kernel, e.g. Raspbian. set(CPU_ARCH_ARM64 TRUE) - message("Building ARM64 binaries.") + message(STATUS "Building ARM64 binaries.") else() set(CPU_ARCH_ARM32 TRUE) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -marm -march=armv7-a") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -marm -march=armv7-a") - message("Building ARM32 binaries on ARM64.") + message(STATUS "Building ARM32 binaries on ARM64.") endif() elseif("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "arm" OR "${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "armv7-a" OR "${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "armv7l") set(CPU_ARCH_ARM32 TRUE) - message("Building ARM32 binaries.") + message(STATUS "Building ARM32 binaries.") if(ANDROID) # Force ARM mode, since apparently ANDROID_ARM_MODE isn't working.. set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -marm") @@ -163,7 +163,7 @@ elseif("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "arm" OR "${CMAKE_SYSTEM_PROCESSOR}" endif() elseif("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "riscv64") set(CPU_ARCH_RISCV64 TRUE) - message("Building RISC-V 64 binaries.") + message(STATUS "Building RISC-V 64 binaries.") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -finline-atomics") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -finline-atomics") @@ -179,6 +179,9 @@ else() message(FATAL_ERROR "Unknown system processor: ${CMAKE_SYSTEM_PROCESSOR}") endif() +# Detect page size if needed. +detect_page_size() + # We don't need exceptions, disable them to save a bit of code size. if(MSVC) diff --git a/CMakeModules/DuckStationUtils.cmake b/CMakeModules/DuckStationUtils.cmake index 265fe4f2e..1f12bac57 100644 --- a/CMakeModules/DuckStationUtils.cmake +++ b/CMakeModules/DuckStationUtils.cmake @@ -5,3 +5,45 @@ function(disable_compiler_warnings_for_target target) target_compile_options(${target} PRIVATE "-w") endif() endfunction() + +function(detect_page_size) + # This is only needed for ARM64, or if the user hasn't overridden it explicitly. + if(NOT CPU_ARCH_ARM64 OR HOST_PAGE_SIZE) + return() + endif() + + if(NOT LINUX OR ANDROID) + # For universal Apple builds, we use preprocessor macros to determine page size. + # Similar for Windows, except it's always 4KB. + return() + endif() + + if(CMAKE_CROSSCOMPILING) + message(WARNING "Cross-compiling and can't determine page size, assuming default.") + return() + endif() + + message(STATUS "Determining host page size") + set(detect_page_size_file ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.c) + file(WRITE ${detect_page_size_file} " +#include +#include +#include +int main() { + int res = sysconf(_SC_PAGESIZE); + printf(\"%d\", res); + return (res > 0) ? EXIT_SUCCESS : EXIT_FAILURE; +}") + try_run( + detect_page_size_run_result + detect_page_size_compile_result + ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY} + ${detect_page_size_file} + RUN_OUTPUT_VARIABLE detect_page_size_output) + if(NOT detect_page_size_compile_result OR NOT detect_page_size_run_result EQUAL 0) + message(FATAL_ERROR "Could not determine host page size.") + else() + message(STATUS "Host page size: ${detect_page_size_output}") + set(HOST_PAGE_SIZE ${detect_page_size_output} CACHE STRING "Reported host page size") + endif() +endfunction() diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index f69f9e687..07249e650 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -105,7 +105,12 @@ if(ANDROID) target_link_libraries(common PRIVATE log) endif() -if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux") +if(LINUX) # We need -lrt for shm_unlink target_link_libraries(common PRIVATE rt) endif() + +# If the host size was detected, we need to set it as a macro. +if(HOST_PAGE_SIZE) + target_compile_definitions(common PUBLIC "-DOVERRIDE_HOST_PAGE_SIZE=${HOST_PAGE_SIZE}") +endif() diff --git a/src/common/types.h b/src/common/types.h index 540a1b608..6295006b4 100644 --- a/src/common/types.h +++ b/src/common/types.h @@ -1,7 +1,8 @@ -// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin +// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) #pragma once +#include #include #include #include @@ -170,7 +171,11 @@ struct dependent_int_false : std::false_type #endif // Host page sizes. -#if defined(__APPLE__) && defined(__aarch64__) +#if defined(OVERRIDE_HOST_PAGE_SIZE) +static constexpr u32 HOST_PAGE_SIZE = OVERRIDE_HOST_PAGE_SIZE; +static constexpr u32 HOST_PAGE_MASK = HOST_PAGE_SIZE - 1; +static constexpr u32 HOST_PAGE_SHIFT = std::bit_width(HOST_PAGE_MASK); +#elif defined(__APPLE__) && defined(__aarch64__) static constexpr u32 HOST_PAGE_SIZE = 0x4000; static constexpr u32 HOST_PAGE_MASK = HOST_PAGE_SIZE - 1; static constexpr u32 HOST_PAGE_SHIFT = 14; diff --git a/src/core/cpu_code_cache.cpp b/src/core/cpu_code_cache.cpp index e3686bc65..d0e05a934 100644 --- a/src/core/cpu_code_cache.cpp +++ b/src/core/cpu_code_cache.cpp @@ -135,7 +135,6 @@ static constexpr u32 RECOMPILER_FAR_CODE_CACHE_SIZE = 16 * 1024 * 1024; #endif #ifdef USE_STATIC_CODE_BUFFER -static constexpr u32 RECOMPILER_GUARD_SIZE = 4096; alignas(HOST_PAGE_SIZE) static u8 s_code_storage[RECOMPILER_CODE_CACHE_SIZE + RECOMPILER_FAR_CODE_CACHE_SIZE]; #endif @@ -170,8 +169,8 @@ bool CPU::CodeCache::ProcessStartup() #ifdef ENABLE_RECOMPILER_SUPPORT #ifdef USE_STATIC_CODE_BUFFER - const bool has_buffer = s_code_buffer.Initialize(s_code_storage, sizeof(s_code_storage), - RECOMPILER_FAR_CODE_CACHE_SIZE, RECOMPILER_GUARD_SIZE); + const bool has_buffer = + s_code_buffer.Initialize(s_code_storage, sizeof(s_code_storage), RECOMPILER_FAR_CODE_CACHE_SIZE, HOST_PAGE_SIZE); #else const bool has_buffer = false; #endif