Skip to content

Commit

Permalink
Merge pull request #4245 from Sonicadvance1/update_kernel_minspec
Browse files Browse the repository at this point in the history
FEXLoader: Increase minimum kernel requirement from 5.0 to 5.15
  • Loading branch information
lioncash authored Jan 2, 2025
2 parents e55b5d0 + 4cfb811 commit 6bc7a83
Show file tree
Hide file tree
Showing 10 changed files with 119 additions and 206 deletions.
2 changes: 1 addition & 1 deletion Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# FEX - Fast x86 emulation frontend
FEX allows you to run x86 and x86-64 binaries on an AArch64 host, similar to qemu-user and box86.
It has native support for a rootfs overlay, so you don't need to chroot, as well as some thunklibs so it can forward things like GL to the host.
FEX presents a Linux 5.0+ interface to the guest, and supports only AArch64 as a host.
FEX presents a Linux 5.15+ interface to the guest, and supports only AArch64 as a host.
FEX is very much work in progress, so expect things to change.


Expand Down
5 changes: 2 additions & 3 deletions Source/Tools/FEXLoader/FEXLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -439,9 +439,8 @@ int main(int argc, char** argv, char** const envp) {
}

uint32_t KernelVersion = FEX::HLE::SyscallHandler::CalculateHostKernelVersion();
if (KernelVersion < FEX::HLE::SyscallHandler::KernelVersion(4, 17)) {
// We require 4.17 minimum for MAP_FIXED_NOREPLACE
LogMan::Msg::EFmt("FEXLoader requires kernel 4.17 minimum. Expect problems.");
if (KernelVersion < FEX::HLE::SyscallHandler::KernelVersion(5, 15)) {
LogMan::Msg::EFmt("FEXLoader requires kernel 5.15 minimum. Expect problems.");
}

// Before we go any further, set all of our host environment variables that the config has provided
Expand Down
19 changes: 7 additions & 12 deletions Source/Tools/LinuxEmulation/LinuxSyscalls/FileManagement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -333,8 +333,6 @@ FileManager::FileManager(FEXCore::Context::Context* ctx)
ProcFSDev = Buffer.st_dev;
}

uint32_t KernelVersion = FEX::HLE::SyscallHandler::CalculateHostKernelVersion();
HasOpenat2 = KernelVersion >= FEX::HLE::SyscallHandler::KernelVersion(5, 8, 0);
UpdatePID(::getpid());
}

Expand Down Expand Up @@ -648,17 +646,16 @@ uint64_t FileManager::Open(const char* pathname, int flags, uint32_t mode) {

if (!ShouldSkipOpenInEmu(flags)) {
FDPathTmpData TmpFilename;
auto Path = GetEmulatedFDPath(AT_FDCWD, SelfPath, !HasOpenat2, TmpFilename);
auto Path = GetEmulatedFDPath(AT_FDCWD, SelfPath, false, TmpFilename);
if (Path.first != -1) {
FEX::HLE::open_how how = {
.flags = (uint64_t)flags,
.mode = (flags & (O_CREAT | O_TMPFILE)) ? mode & 07777 : 0, // openat2() is stricter about this
.resolve = (Path.first == AT_FDCWD) ? 0u : RESOLVE_IN_ROOT, // AT_FDCWD means it's a thunk and not via RootFS
};
if (HasOpenat2) {
fd = ::syscall(SYSCALL_DEF(openat2), Path.first, Path.second, &how, sizeof(how));
}
if (fd == -1 && (!HasOpenat2 || errno == EXDEV)) {
fd = ::syscall(SYSCALL_DEF(openat2), Path.first, Path.second, &how, sizeof(how));

if (fd == -1 && errno == EXDEV) {
// This means a magic symlink (/proc/foo) was involved. In this case we
// just punt and do the access without RESOLVE_IN_ROOT.
fd = ::syscall(SYSCALL_DEF(openat), Path.first, Path.second, flags, mode);
Expand Down Expand Up @@ -903,17 +900,15 @@ uint64_t FileManager::Openat([[maybe_unused]] int dirfs, const char* pathname, i

if (!ShouldSkipOpenInEmu(flags)) {
FDPathTmpData TmpFilename;
auto Path = GetEmulatedFDPath(dirfs, SelfPath, !HasOpenat2, TmpFilename);
auto Path = GetEmulatedFDPath(dirfs, SelfPath, false, TmpFilename);
if (Path.first != -1) {
FEX::HLE::open_how how = {
.flags = (uint64_t)flags,
.mode = (flags & (O_CREAT | O_TMPFILE)) ? mode & 07777 : 0, // openat2() is stricter about this,
.resolve = (Path.first == AT_FDCWD) ? 0u : RESOLVE_IN_ROOT, // AT_FDCWD means it's a thunk and not via RootFS
};
if (HasOpenat2) {
fd = ::syscall(SYSCALL_DEF(openat2), Path.first, Path.second, &how, sizeof(how));
}
if (fd == -1 && (!HasOpenat2 || errno == EXDEV)) {
fd = ::syscall(SYSCALL_DEF(openat2), Path.first, Path.second, &how, sizeof(how));
if (fd == -1 && errno == EXDEV) {
// This means a magic symlink (/proc/foo) was involved. In this case we
// just punt and do the access without RESOLVE_IN_ROOT.
fd = ::syscall(SYSCALL_DEF(openat), Path.first, Path.second, flags, mode);
Expand Down
1 change: 0 additions & 1 deletion Source/Tools/LinuxEmulation/LinuxSyscalls/FileManagement.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,5 @@ class FileManager final {
int64_t RootFSFDInode = 0;
int64_t ProcFDInode = 0;
dev_t ProcFSDev;
bool HasOpenat2;
};
} // namespace FEX::HLE
4 changes: 2 additions & 2 deletions Source/Tools/LinuxEmulation/LinuxSyscalls/Syscalls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -808,8 +808,8 @@ uint32_t SyscallHandler::CalculateHostKernelVersion() {
}

uint32_t SyscallHandler::CalculateGuestKernelVersion() {
// We currently only emulate a kernel between the ranges of Kernel 5.0.0 and 6.11.0
return std::max(KernelVersion(5, 0), std::min(KernelVersion(6, 11), GetHostKernelVersion()));
// 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()));
}

uint64_t SyscallHandler::HandleSyscall(FEXCore::Core::CpuStateFrame* Frame, FEXCore::HLE::SyscallArguments* Args) {
Expand Down
53 changes: 21 additions & 32 deletions Source/Tools/LinuxEmulation/LinuxSyscalls/Syscalls/FD.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,29 +110,22 @@ void RegisterFD(FEX::HLE::SyscallHandler* Handler) {
SYSCALL_ERRNO();
});

if (Handler->IsHostKernelVersionAtLeast(5, 8, 0)) {
// Only exists on kernel 5.8+
REGISTER_SYSCALL_IMPL_FLAGS(faccessat2, SyscallFlags::OPTIMIZETHROUGH | SyscallFlags::NOSYNCSTATEONENTRY,
[](FEXCore::Core::CpuStateFrame* Frame, int dirfd, const char* pathname, int mode, int flags) -> uint64_t {
uint64_t Result = FEX::HLE::_SyscallHandler->FM.FAccessat2(dirfd, pathname, mode, flags);
SYSCALL_ERRNO();
});

REGISTER_SYSCALL_IMPL_FLAGS(
openat2, SyscallFlags::OPTIMIZETHROUGH | SyscallFlags::NOSYNCSTATEONENTRY,
[](FEXCore::Core::CpuStateFrame* Frame, int dirfs, const char* pathname, struct open_how* how, size_t usize) -> uint64_t {
open_how HostHow {};
size_t HostSize = std::min(sizeof(open_how), usize);
memcpy(&HostHow, how, HostSize);

HostHow.flags = FEX::HLE::RemapFromX86Flags(HostHow.flags);
uint64_t Result = FEX::HLE::_SyscallHandler->FM.Openat2(dirfs, pathname, &HostHow, HostSize);
SYSCALL_ERRNO();
});
} else {
REGISTER_SYSCALL_IMPL(faccessat2, UnimplementedSyscallSafe);
REGISTER_SYSCALL_IMPL(openat2, UnimplementedSyscallSafe);
}
REGISTER_SYSCALL_IMPL_FLAGS(faccessat2, SyscallFlags::OPTIMIZETHROUGH | SyscallFlags::NOSYNCSTATEONENTRY,
[](FEXCore::Core::CpuStateFrame* Frame, int dirfd, const char* pathname, int mode, int flags) -> uint64_t {
uint64_t Result = FEX::HLE::_SyscallHandler->FM.FAccessat2(dirfd, pathname, mode, flags);
SYSCALL_ERRNO();
});

REGISTER_SYSCALL_IMPL_FLAGS(openat2, SyscallFlags::OPTIMIZETHROUGH | SyscallFlags::NOSYNCSTATEONENTRY,
[](FEXCore::Core::CpuStateFrame* Frame, int dirfs, const char* pathname, struct open_how* how, size_t usize) -> uint64_t {
open_how HostHow {};
size_t HostSize = std::min(sizeof(open_how), usize);
memcpy(&HostHow, how, HostSize);

HostHow.flags = FEX::HLE::RemapFromX86Flags(HostHow.flags);
uint64_t Result = FEX::HLE::_SyscallHandler->FM.Openat2(dirfs, pathname, &HostHow, HostSize);
SYSCALL_ERRNO();
});

REGISTER_SYSCALL_IMPL_FLAGS(eventfd, SyscallFlags::OPTIMIZETHROUGH | SyscallFlags::NOSYNCSTATEONENTRY,
[](FEXCore::Core::CpuStateFrame* Frame, uint32_t count) -> uint64_t {
Expand All @@ -155,14 +148,10 @@ void RegisterFD(FEX::HLE::SyscallHandler* Handler) {
SYSCALL_ERRNO();
});

if (Handler->IsHostKernelVersionAtLeast(5, 9, 0)) {
REGISTER_SYSCALL_IMPL_FLAGS(close_range, SyscallFlags::OPTIMIZETHROUGH | SyscallFlags::NOSYNCSTATEONENTRY,
[](FEXCore::Core::CpuStateFrame* Frame, unsigned int first, unsigned int last, unsigned int flags) -> uint64_t {
uint64_t Result = FEX::HLE::_SyscallHandler->FM.CloseRange(first, last, flags);
SYSCALL_ERRNO();
});
} else {
REGISTER_SYSCALL_IMPL(close_range, UnimplementedSyscallSafe);
}
REGISTER_SYSCALL_IMPL_FLAGS(close_range, SyscallFlags::OPTIMIZETHROUGH | SyscallFlags::NOSYNCSTATEONENTRY,
[](FEXCore::Core::CpuStateFrame* Frame, unsigned int first, unsigned int last, unsigned int flags) -> uint64_t {
uint64_t Result = FEX::HLE::_SyscallHandler->FM.CloseRange(first, last, flags);
SYSCALL_ERRNO();
});
}
} // namespace FEX::HLE
Loading

0 comments on commit 6bc7a83

Please sign in to comment.