Move Linux version calculation to common code

This commit is contained in:
Ryan Houdek committed 2026-07-14 20:06:37 -07:00
1 parent 30f2a7b23b
commit 50c75d1f43
10 files changed
+69 -53

No files matched your search

+2 -1
View File
@@ -14,7 +14,8 @@ if (NOT MINGW)
list(APPEND SRCS
FEXServerClient.cpp
FileFormatCheck.cpp
Linux/SBRKAllocations.cpp)
Linux/SBRKAllocations.cpp
Linux/LinuxVersion.cpp)
endif()
add_library(${NAME} STATIC ${SRCS})
+25
View File
@@ -0,0 +1,25 @@
// SPDX-License-Identifier: MIT
#include <cstdint>
#include <charconv>
#include <sys/utsname.h>
namespace FEX::LinuxVersion {
uint32_t CalculateHostKernelVersion() {
struct utsname buf {};
if (uname(&buf) == -1) {
return 0;
}
uint32_t Major {};
uint32_t Minor {};
uint32_t Patch {};
// Parse kernel version in the form of `<Major>.<Minor>.<Patch>[Optional Data]`
const auto End = buf.release + sizeof(buf.release);
auto Results = std::from_chars(buf.release, End, Major, 10);
Results = std::from_chars(Results.ptr + 1, End, Minor, 10);
Results = std::from_chars(Results.ptr + 1, End, Patch, 10);
return (Major << 24) | (Minor << 16) | Patch;
}
} // namespace FEX::LinuxVersion
+22
View File
@@ -0,0 +1,22 @@
// SPDX-License-Identifier: MIT
#pragma once
#include <cstdint>
namespace FEX::LinuxVersion {
inline uint32_t KernelVersion(uint32_t Major, uint32_t Minor = 0, uint32_t Patch = 0) {
return (Major << 24) | (Minor << 16) | Patch;
}
inline uint32_t KernelMajor(uint32_t Version) {
return Version >> 24;
}
inline uint32_t KernelMinor(uint32_t Version) {
return (Version >> 16) & 0xFF;
}
inline uint32_t KernelPatch(uint32_t Version) {
return Version & 0xFFFF;
}
uint32_t CalculateHostKernelVersion();
} // namespace FEX::LinuxVersion
+2 -2
View File
@@ -297,8 +297,8 @@ public:
#ifndef AT_FLAGS_PRESERVE_ARGV0
#define AT_FLAGS_PRESERVE_ARGV0 1
#endif
uint32_t HostKernel = FEX::HLE::SyscallHandler::CalculateHostKernelVersion();
if ((HostKernel >= FEX::HLE::SyscallHandler::KernelVersion(5, 12, 0) && (AtFlags & AT_FLAGS_PRESERVE_ARGV0)) || LoadedWithFD) {
uint32_t HostKernel = FEX::LinuxVersion::CalculateHostKernelVersion();
if ((HostKernel >= FEX::LinuxVersion::KernelVersion(5, 12, 0) && (AtFlags & AT_FLAGS_PRESERVE_ARGV0)) || LoadedWithFD) {
// Erase the initial argument from the list in this case
ApplicationArgs.erase(ApplicationArgs.begin());
@@ -10,6 +10,7 @@ $end_info$
#include "Common/FEXServerClient.h"
#include "Common/Config.h"
#include "Common/HostFeatures.h"
#include "Common/Linux/LinuxVersion.h"
#include "Common/Linux/SBRKAllocations.h"
#include "PortabilityInfo.h"
#include "ELFCodeLoader.h"
@@ -463,8 +464,8 @@ int main(int argc, char** argv, char** const envp) {
return -ENOEXEC;
}
uint32_t KernelVersion = FEX::HLE::SyscallHandler::CalculateHostKernelVersion();
if (KernelVersion < FEX::HLE::SyscallHandler::KernelVersion(5, 15)) {
uint32_t KernelVersion = FEX::LinuxVersion::CalculateHostKernelVersion();
if (KernelVersion < FEX::LinuxVersion::KernelVersion(5, 15)) {
LogMan::Msg::EFmt("FEX requires kernel 5.15 minimum. Expect problems.");
}
@@ -532,8 +532,8 @@ EmulatedFDManager::EmulatedFDManager(FEXCore::Context::Context* ctx)
int FD = GenTmpFD(pathname, flags);
uint32_t GuestVersion = FEX::HLE::_SyscallHandler->GetGuestKernelVersion();
char Tmp[64] {};
snprintf(Tmp, sizeof(Tmp), "%d.%d.%d\n", FEX::HLE::SyscallHandler::KernelMajor(GuestVersion),
FEX::HLE::SyscallHandler::KernelMinor(GuestVersion), FEX::HLE::SyscallHandler::KernelPatch(GuestVersion));
snprintf(Tmp, sizeof(Tmp), "%d.%d.%d\n", FEX::LinuxVersion::KernelMajor(GuestVersion), FEX::LinuxVersion::KernelMinor(GuestVersion),
FEX::LinuxVersion::KernelPatch(GuestVersion));
// + 1 to ensure null at the end
write(FD, Tmp, strlen(Tmp) + 1);
lseek(FD, 0, SEEK_SET);
@@ -548,8 +548,8 @@ EmulatedFDManager::EmulatedFDManager(FEXCore::Context::Context* ctx)
const char kernel_version[] = "Linux version %d.%d.%d (FEX@FEX) (clang) #" GIT_DESCRIBE_STRING " SMP " __DATE__ " " __TIME__ "\n";
uint32_t GuestVersion = FEX::HLE::_SyscallHandler->GetGuestKernelVersion();
char Tmp[sizeof(kernel_version) + 64] {};
snprintf(Tmp, sizeof(Tmp), kernel_version, FEX::HLE::SyscallHandler::KernelMajor(GuestVersion),
FEX::HLE::SyscallHandler::KernelMinor(GuestVersion), FEX::HLE::SyscallHandler::KernelPatch(GuestVersion));
snprintf(Tmp, sizeof(Tmp), kernel_version, FEX::LinuxVersion::KernelMajor(GuestVersion), FEX::LinuxVersion::KernelMinor(GuestVersion),
FEX::LinuxVersion::KernelPatch(GuestVersion));
// + 1 to ensure null at the end
write(FD, Tmp, strlen(Tmp) + 1);
lseek(FD, 0, SEEK_SET);
@@ -790,7 +790,7 @@ SyscallHandler::SyscallHandler(FEXCore::Context::Context* _CTX, FEX::HLE::Signal
, SignalDelegation {_SignalDelegation}
, ThunkHandler {ThunkHandler} {
FEX::HLE::_SyscallHandler = this;
HostKernelVersion = CalculateHostKernelVersion();
HostKernelVersion = LinuxVersion::CalculateHostKernelVersion();
GuestKernelVersion = CalculateGuestKernelVersion();
Alloc32Handler = FEX::HLE::Create32BitAllocator();
@@ -803,28 +803,9 @@ SyscallHandler::~SyscallHandler() {
FEXCore::Allocator::munmap(reinterpret_cast<void*>(DataSpace), DataSpaceMappedSize);
}
uint32_t SyscallHandler::CalculateHostKernelVersion() {
struct utsname buf {};
if (uname(&buf) == -1) {
return 0;
}
uint32_t Major {};
uint32_t Minor {};
uint32_t Patch {};
// Parse kernel version in the form of `<Major>.<Minor>.<Patch>[Optional Data]`
const auto End = buf.release + sizeof(buf.release);
auto Results = std::from_chars(buf.release, End, Major, 10);
Results = std::from_chars(Results.ptr + 1, End, Minor, 10);
Results = std::from_chars(Results.ptr + 1, End, Patch, 10);
return (Major << 24) | (Minor << 16) | Patch;
}
uint32_t SyscallHandler::CalculateGuestKernelVersion() {
// We currently only emulate a kernel between the ranges of Kernel 5.15.0 and 6.11.0
return std::max(KernelVersion(5, 15), std::min(KernelVersion(6, 11), GetHostKernelVersion()));
return std::max(LinuxVersion::KernelVersion(5, 15), std::min(LinuxVersion::KernelVersion(6, 11), GetHostKernelVersion()));
}
uint64_t SyscallHandler::HandleSyscall(FEXCore::Core::CpuStateFrame* Frame, FEXCore::HLE::SyscallArguments* Args) {
@@ -8,6 +8,7 @@ $end_info$
#pragma once
#include "Common/Linux/LinuxVersion.h"
#include "Common/VolatileMetadata.h"
#include "LinuxSyscalls/FileManagement.h"
#include "LinuxSyscalls/LinuxAllocator.h"
@@ -210,26 +211,11 @@ public:
}
bool IsHostKernelVersionAtLeast(uint32_t Major, uint32_t Minor = 0, uint32_t Patch = 0) const {
return GetHostKernelVersion() >= KernelVersion(Major, Minor, Patch);
return GetHostKernelVersion() >= LinuxVersion::KernelVersion(Major, Minor, Patch);
}
static uint32_t CalculateHostKernelVersion();
uint32_t CalculateGuestKernelVersion();
static uint32_t KernelVersion(uint32_t Major, uint32_t Minor = 0, uint32_t Patch = 0) {
return (Major << 24) | (Minor << 16) | Patch;
}
static uint32_t KernelMajor(uint32_t Version) {
return Version >> 24;
}
static uint32_t KernelMinor(uint32_t Version) {
return (Version >> 16) & 0xFF;
}
static uint32_t KernelPatch(uint32_t Version) {
return Version & 0xFFFF;
}
virtual FEX::HLE::MemAllocator* Get32BitAllocator() {
return Alloc32Handler.get();
}
@@ -51,10 +51,10 @@ void RegisterInfo(FEX::HLE::SyscallHandler* Handler) {
uint32_t GuestVersion = FEX::HLE::_SyscallHandler->GetGuestKernelVersion();
if (Thread->persona & UNAME26) {
// Kernel version converts from 6.x.y to 2.6.60+x.
GuestVersion = FEX::HLE::SyscallHandler::KernelVersion(2, 6, 60 + FEX::HLE::SyscallHandler::KernelMinor(GuestVersion));
GuestVersion = FEX::LinuxVersion::KernelVersion(2, 6, 60 + FEX::LinuxVersion::KernelMinor(GuestVersion));
}
snprintf(buf->release, sizeof(buf->release), "%d.%d.%d", FEX::HLE::SyscallHandler::KernelMajor(GuestVersion),
FEX::HLE::SyscallHandler::KernelMinor(GuestVersion), FEX::HLE::SyscallHandler::KernelPatch(GuestVersion));
snprintf(buf->release, sizeof(buf->release), "%d.%d.%d", FEX::LinuxVersion::KernelMajor(GuestVersion),
FEX::LinuxVersion::KernelMinor(GuestVersion), FEX::LinuxVersion::KernelPatch(GuestVersion));
const char version[] = "#" GIT_DESCRIBE_STRING " SMP " __DATE__ " " __TIME__;
strcpy(buf->version, version);
@@ -61,8 +61,8 @@ void RegisterInfo(FEX::HLE::SyscallHandler* Handler) {
}
strncpy(buf->sysname, "Linux", __OLD_UTS_LEN);
uint32_t GuestVersion = FEX::HLE::_SyscallHandler->GetGuestKernelVersion();
snprintf(buf->release, __OLD_UTS_LEN, "%d.%d.%d", FEX::HLE::SyscallHandler::KernelMajor(GuestVersion),
FEX::HLE::SyscallHandler::KernelMinor(GuestVersion), FEX::HLE::SyscallHandler::KernelPatch(GuestVersion));
snprintf(buf->release, __OLD_UTS_LEN, "%d.%d.%d", FEX::LinuxVersion::KernelMajor(GuestVersion),
FEX::LinuxVersion::KernelMinor(GuestVersion), FEX::LinuxVersion::KernelPatch(GuestVersion));
const char version[] = "#" GIT_DESCRIBE_STRING " SMP " __DATE__ " " __TIME__;
strncpy(buf->version, version, __OLD_UTS_LEN);
@@ -85,8 +85,8 @@ void RegisterInfo(FEX::HLE::SyscallHandler* Handler) {
}
strncpy(buf->sysname, "Linux", __NEW_UTS_LEN);
uint32_t GuestVersion = FEX::HLE::_SyscallHandler->GetGuestKernelVersion();
snprintf(buf->release, __NEW_UTS_LEN, "%d.%d.%d", FEX::HLE::SyscallHandler::KernelMajor(GuestVersion),
FEX::HLE::SyscallHandler::KernelMinor(GuestVersion), FEX::HLE::SyscallHandler::KernelPatch(GuestVersion));
snprintf(buf->release, __NEW_UTS_LEN, "%d.%d.%d", FEX::LinuxVersion::KernelMajor(GuestVersion),
FEX::LinuxVersion::KernelMinor(GuestVersion), FEX::LinuxVersion::KernelPatch(GuestVersion));
const char version[] = "#" GIT_DESCRIBE_STRING " SMP " __DATE__ " " __TIME__;
strncpy(buf->version, version, __NEW_UTS_LEN);