mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2026-05-26 13:50:37 +00:00
WIP: port: Add x64 FreeBSD (#3927)
* port: Add x64 FreeBSD * clang formaa * fix epoll stuffs * date-tz for fbsd, force submodule zydis * fix filesystem hang + date-tz * fix * fix freebsd SIGBUS * madvise() ifdef * signal fix + camera fix * proper %gs tls for once * better tls? + clang format --------- Co-authored-by: lizzie <lizzie@eden-emu.dev>
This commit is contained in:
+11
-2
@@ -245,7 +245,7 @@ find_package(VulkanMemoryAllocator 3.1.0 CONFIG)
|
||||
find_package(xbyak 7.07 CONFIG)
|
||||
find_package(xxHash 0.8.2 MODULE)
|
||||
find_package(ZLIB 1.3 MODULE)
|
||||
find_package(Zydis 5.0.0 CONFIG)
|
||||
find_package(Zydis 5.0.0 MODULE)
|
||||
find_package(pugixml 1.14 CONFIG)
|
||||
if (APPLE)
|
||||
find_package(date 3.0.1 CONFIG)
|
||||
@@ -1139,7 +1139,14 @@ create_target_directory_groups(shadps4)
|
||||
|
||||
target_link_libraries(shadps4 PRIVATE magic_enum::magic_enum fmt::fmt toml11::toml11 tsl::robin_map xbyak::xbyak Tracy::TracyClient RenderDoc::API FFmpeg::ffmpeg Dear_ImGui gcn half::half ZLIB::ZLIB PNG::PNG)
|
||||
target_link_libraries(shadps4 PRIVATE Boost::headers GPUOpen::VulkanMemoryAllocator LibAtrac9 sirit Vulkan::Headers xxHash::xxhash Zydis::Zydis glslang::glslang SDL3::SDL3 SDL3_mixer::SDL3_mixer pugixml::pugixml)
|
||||
target_link_libraries(shadps4 PRIVATE stb::headers libusb::usb lfreist-hwinfo::hwinfo nlohmann_json::nlohmann_json miniz::miniz fdk-aac CLI11::CLI11 OpenAL::OpenAL Cpp_Httplib)
|
||||
target_link_libraries(shadps4 PRIVATE stb::headers lfreist-hwinfo::hwinfo nlohmann_json::nlohmann_json miniz::miniz fdk-aac CLI11::CLI11 OpenAL::OpenAL Cpp_Httplib)
|
||||
|
||||
if (${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
|
||||
target_link_libraries(shadps4 PRIVATE "/usr/lib/libusb.so")
|
||||
target_link_libraries(shadps4 PRIVATE "/usr/local/lib/libuuid.so")
|
||||
else()
|
||||
target_link_libraries(shadps4 PRIVATE libusb::usb)
|
||||
endif()
|
||||
|
||||
target_compile_definitions(shadps4 PRIVATE IMGUI_USER_CONFIG="imgui/imgui_config.h")
|
||||
target_compile_definitions(Dear_ImGui PRIVATE IMGUI_USER_CONFIG="${PROJECT_SOURCE_DIR}/src/imgui/imgui_config.h")
|
||||
@@ -1185,6 +1192,8 @@ if (APPLE)
|
||||
|
||||
# Replacement for std::chrono::time_zone
|
||||
target_link_libraries(shadps4 PRIVATE date::date-tz epoll-shim)
|
||||
elseif (${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
|
||||
target_link_libraries(shadps4 PRIVATE date::date-tz epoll-shim)
|
||||
endif()
|
||||
|
||||
if (WIN32)
|
||||
|
||||
Vendored
+16
-8
@@ -210,8 +210,15 @@ endif()
|
||||
|
||||
# libusb
|
||||
if (NOT TARGET libusb::usb)
|
||||
add_subdirectory(ext-libusb)
|
||||
add_library(libusb::usb ALIAS usb-1.0)
|
||||
if (${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
|
||||
# YOU MUST USE NATIVE LIBUSB
|
||||
# using anything else will crash instantly, also freebsd will NOT like it
|
||||
# no you cant vendor this libusb, its builtin on freebsd
|
||||
find_package(libusb)
|
||||
else()
|
||||
add_subdirectory(ext-libusb)
|
||||
add_library(libusb::usb ALIAS usb-1.0)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Discord RPC
|
||||
@@ -233,25 +240,26 @@ endif()
|
||||
set(HWINFO_STATIC ON)
|
||||
add_subdirectory(hwinfo)
|
||||
|
||||
# Apple-only dependencies
|
||||
if (APPLE)
|
||||
if (APPLE OR ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
|
||||
# date
|
||||
if (NOT TARGET date::date-tz)
|
||||
option(BUILD_TZ_LIB "" ON)
|
||||
option(USE_SYSTEM_TZ_DB "" ON)
|
||||
add_subdirectory(date)
|
||||
endif()
|
||||
if (NOT TARGET epoll-shim)
|
||||
add_subdirectory(epoll-shim)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Apple-only dependencies
|
||||
if (APPLE)
|
||||
# MoltenVK
|
||||
if (NOT TARGET MoltenVK)
|
||||
set(MVK_EXCLUDE_SPIRV_TOOLS ON)
|
||||
set(MVK_USE_METAL_PRIVATE_API ON)
|
||||
add_subdirectory(MoltenVK)
|
||||
endif()
|
||||
|
||||
if (NOT TARGET epoll-shim)
|
||||
add_subdirectory(epoll-shim)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
#windows only
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __linux__
|
||||
#if __unix__
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#elif defined(__FreeBSD__)
|
||||
#include <machine/npx.h>
|
||||
#include <sys/ucontext.h>
|
||||
#else
|
||||
#include <sys/ucontext.h>
|
||||
#endif
|
||||
@@ -22,6 +25,16 @@ void* GetXmmPointer(void* ctx, u8 index) {
|
||||
#define CASE(index) \
|
||||
case index: \
|
||||
return (void*)(&((ucontext_t*)ctx)->uc_mcontext->__fs.__fpu_xmm##index);
|
||||
#elif defined(__FreeBSD__)
|
||||
// In mc_fpstate
|
||||
// See <machine/npx.h> for the internals of mc_fpstate[].
|
||||
#define CASE(index) \
|
||||
case index: { \
|
||||
auto& mctx = ((ucontext_t*)ctx)->uc_mcontext; \
|
||||
ASSERT(mctx.mc_fpformat == _MC_FPFMT_XMM); \
|
||||
auto* s_fpu = (struct savefpu*)(&mctx.mc_fpstate[0]); \
|
||||
return (void*)(&(s_fpu->sv_xmm[0])); \
|
||||
}
|
||||
#else
|
||||
#define CASE(index) \
|
||||
case index: \
|
||||
@@ -57,6 +70,8 @@ void* GetRip(void* ctx) {
|
||||
return (void*)((EXCEPTION_POINTERS*)ctx)->ContextRecord->Rip;
|
||||
#elif defined(__APPLE__)
|
||||
return (void*)((ucontext_t*)ctx)->uc_mcontext->__ss.__rip;
|
||||
#elif defined(__FreeBSD__)
|
||||
return (void*)((ucontext_t*)ctx)->uc_mcontext.mc_rip;
|
||||
#else
|
||||
return (void*)((ucontext_t*)ctx)->uc_mcontext.gregs[REG_RIP];
|
||||
#endif
|
||||
@@ -67,6 +82,8 @@ void IncrementRip(void* ctx, u64 length) {
|
||||
((EXCEPTION_POINTERS*)ctx)->ContextRecord->Rip += length;
|
||||
#elif defined(__APPLE__)
|
||||
((ucontext_t*)ctx)->uc_mcontext->__ss.__rip += length;
|
||||
#elif defined(__FreeBSD__)
|
||||
((ucontext_t*)ctx)->uc_mcontext.mc_rip += length;
|
||||
#else
|
||||
((ucontext_t*)ctx)->uc_mcontext.gregs[REG_RIP] += length;
|
||||
#endif
|
||||
@@ -75,18 +92,16 @@ void IncrementRip(void* ctx, u64 length) {
|
||||
bool IsWriteError(void* ctx) {
|
||||
#if defined(_WIN32)
|
||||
return ((EXCEPTION_POINTERS*)ctx)->ExceptionRecord->ExceptionInformation[0] == 1;
|
||||
#elif defined(__APPLE__)
|
||||
#if defined(ARCH_X86_64)
|
||||
#elif defined(__APPLE__) && defined(ARCH_X86_64)
|
||||
return ((ucontext_t*)ctx)->uc_mcontext->__es.__err & 0x2;
|
||||
#elif defined(ARCH_ARM64)
|
||||
#elif defined(__APPLE__) && defined(ARCH_ARM64)
|
||||
return ((ucontext_t*)ctx)->uc_mcontext->__es.__esr & 0x40;
|
||||
#endif
|
||||
#else
|
||||
#if defined(ARCH_X86_64)
|
||||
#elif defined(__FreeBSD__) && defined(ARCH_X86_64)
|
||||
return ((ucontext_t*)ctx)->uc_mcontext.mc_err & 0x2;
|
||||
#elif defined(ARCH_X86_64)
|
||||
return ((ucontext_t*)ctx)->uc_mcontext.gregs[REG_ERR] & 0x2;
|
||||
#else
|
||||
#error "Unsupported architecture"
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
} // namespace Common
|
||||
} // namespace Common
|
||||
|
||||
@@ -613,7 +613,11 @@ struct AddressSpace::Impl {
|
||||
user_size = UserSize;
|
||||
|
||||
constexpr int protection_flags = PROT_READ | PROT_WRITE;
|
||||
constexpr int map_flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE | MAP_FIXED;
|
||||
int map_flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED; // compiler knows its constexpr
|
||||
#if !defined(__FreeBSD__)
|
||||
map_flags |= MAP_NORESERVE;
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__) && defined(ARCH_X86_64)
|
||||
// On ARM64 Macs, we run into limitations due to the commpage from 0xFC0000000 - 0xFFFFFFFFF
|
||||
// and the GPU carveout region from 0x1000000000 - 0x6FFFFFFFFF. Because this creates gaps
|
||||
@@ -628,7 +632,7 @@ struct AddressSpace::Impl {
|
||||
mmap(reinterpret_cast<void*>(USER_MIN), user_size, protection_flags, map_flags, -1, 0));
|
||||
#else
|
||||
const auto virtual_size = system_managed_size + system_reserved_size + user_size;
|
||||
#if defined(ARCH_X86_64)
|
||||
#if defined(ARCH_X86_64) && !defined(__FreeBSD__)
|
||||
const auto virtual_base =
|
||||
reinterpret_cast<u8*>(mmap(reinterpret_cast<void*>(SYSTEM_MANAGED_MIN), virtual_size,
|
||||
protection_flags, map_flags, -1, 0));
|
||||
@@ -636,8 +640,10 @@ struct AddressSpace::Impl {
|
||||
system_reserved_base = reinterpret_cast<u8*>(SYSTEM_RESERVED_MIN);
|
||||
user_base = reinterpret_cast<u8*>(USER_MIN);
|
||||
#else
|
||||
// FreeBSD can't stand MAP_FIXED or it may overwrite mmap() itself!
|
||||
// Map memory wherever possible and instruction translation can handle offsetting to the
|
||||
// base.
|
||||
map_flags &= ~MAP_FIXED;
|
||||
const auto virtual_base =
|
||||
reinterpret_cast<u8*>(mmap(nullptr, virtual_size, protection_flags, map_flags, -1, 0));
|
||||
system_managed_base = virtual_base;
|
||||
@@ -676,8 +682,13 @@ struct AddressSpace::Impl {
|
||||
}
|
||||
shm_unlink(shm_path.c_str());
|
||||
#else
|
||||
#ifndef __FreeBSD__
|
||||
madvise(virtual_base, virtual_size, MADV_HUGEPAGE);
|
||||
|
||||
#endif
|
||||
// NOTE: If you add MFD_HUGETLB or whatever, remember that FBSD will break (libc bug)
|
||||
// so please, do not, add MFD_* whatever unless you ifdef it away (must be 0 for FBSD)
|
||||
// using sized pages as well causes incessant vm_reclaim calls in kernel, do not use on FBSD
|
||||
// under any circumstances.
|
||||
backing_fd = memfd_create("BackingDmem", 0);
|
||||
if (backing_fd < 0) {
|
||||
LOG_CRITICAL(Kernel_Vmm, "memfd_create failed: {}", strerror(errno));
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#elif defined(__linux__)
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#elif defined(__APPLE__)
|
||||
#elif defined(__APPLE__) || defined(__FreeBSD__)
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <sys/sysctl.h>
|
||||
@@ -48,6 +48,8 @@ bool Core::Debugger::IsDebuggerAttached() {
|
||||
return (info.kp_proc.p_flag & P_TRACED) != 0;
|
||||
}
|
||||
return false;
|
||||
#elif defined(__FreeBSD__)
|
||||
return false;
|
||||
#else
|
||||
#error "Unsupported platform"
|
||||
#endif
|
||||
@@ -66,7 +68,7 @@ void Core::Debugger::WaitForDebuggerAttach() {
|
||||
int Core::Debugger::GetCurrentPid() {
|
||||
#if defined(_WIN32)
|
||||
return GetCurrentProcessId();
|
||||
#elif defined(__APPLE__) || defined(__linux__)
|
||||
#elif defined(__APPLE__) || defined(__linux__) || defined(__FreeBSD__)
|
||||
return getpid();
|
||||
#else
|
||||
#error "Unsupported platform"
|
||||
@@ -88,7 +90,7 @@ void Core::Debugger::WaitForPid(int pid) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
std::cerr << "Waiting for process " << pid << " to exit..." << std::endl;
|
||||
}
|
||||
#elif defined(__APPLE__)
|
||||
#elif defined(__APPLE__) || defined(__FreeBSD__)
|
||||
while (kill(pid, 0) == 0) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
std::cerr << "Waiting for process " << pid << " to exit..." << std::endl;
|
||||
|
||||
+33
-31
@@ -95,7 +95,7 @@ std::filesystem::path MntPoints::GetHostPath(std::string_view path, bool* is_rea
|
||||
std::scoped_lock lk{m_mutex};
|
||||
path_parts.clear();
|
||||
auto current_path = host_path;
|
||||
while (!std::filesystem::exists(current_path)) {
|
||||
while (!current_path.empty() && !std::filesystem::exists(current_path)) {
|
||||
// We have probably cached this if it's a folder.
|
||||
if (auto it = path_cache.find(current_path); it != path_cache.end()) {
|
||||
current_path = it->second;
|
||||
@@ -104,38 +104,40 @@ std::filesystem::path MntPoints::GetHostPath(std::string_view path, bool* is_rea
|
||||
path_parts.emplace_back(current_path.filename());
|
||||
current_path = current_path.parent_path();
|
||||
}
|
||||
// We have found an anchor. Traverse parts we recoded and see if they
|
||||
// exist in filesystem but in different case.
|
||||
auto guest_path = current_path;
|
||||
while (!path_parts.empty()) {
|
||||
const auto part = path_parts.back();
|
||||
const auto add_match = [&](const auto& host_part) {
|
||||
current_path /= host_part;
|
||||
guest_path /= part;
|
||||
path_cache[guest_path] = current_path;
|
||||
path_parts.pop_back();
|
||||
};
|
||||
// Can happen when the mismatch is in upper folder.
|
||||
if (std::filesystem::exists(current_path / part)) {
|
||||
add_match(part);
|
||||
continue;
|
||||
}
|
||||
const auto part_low = Common::ToLower(part.string());
|
||||
bool found_match = false;
|
||||
for (const auto& path : std::filesystem::directory_iterator(current_path)) {
|
||||
const auto candidate = path.path().filename();
|
||||
const auto filename = Common::ToLower(candidate.string());
|
||||
// Check if a filename matches in case insensitive manner.
|
||||
if (filename != part_low) {
|
||||
if (!current_path.empty()) {
|
||||
// We have found an anchor. Traverse parts we recoded and see if they
|
||||
// exist in filesystem but in different case.
|
||||
auto guest_path = current_path;
|
||||
while (!path_parts.empty()) {
|
||||
const auto part = path_parts.back();
|
||||
const auto add_match = [&](const auto& host_part) {
|
||||
current_path /= host_part;
|
||||
guest_path /= part;
|
||||
path_cache[guest_path] = current_path;
|
||||
path_parts.pop_back();
|
||||
};
|
||||
// Can happen when the mismatch is in upper folder.
|
||||
if (std::filesystem::exists(current_path / part)) {
|
||||
add_match(part);
|
||||
continue;
|
||||
}
|
||||
// We found a match, record the actual path in the cache.
|
||||
add_match(candidate);
|
||||
found_match = true;
|
||||
break;
|
||||
}
|
||||
if (!found_match) {
|
||||
return std::optional<std::filesystem::path>({});
|
||||
const auto part_low = Common::ToLower(part.string());
|
||||
bool found_match = false;
|
||||
for (const auto& path : std::filesystem::directory_iterator(current_path)) {
|
||||
const auto candidate = path.path().filename();
|
||||
const auto filename = Common::ToLower(candidate.string());
|
||||
// Check if a filename matches in case insensitive manner.
|
||||
if (filename != part_low) {
|
||||
continue;
|
||||
}
|
||||
// We found a match, record the actual path in the cache.
|
||||
add_match(candidate);
|
||||
found_match = true;
|
||||
break;
|
||||
}
|
||||
if (!found_match) {
|
||||
return std::optional<std::filesystem::path>({});
|
||||
}
|
||||
}
|
||||
}
|
||||
return std::optional<std::filesystem::path>(current_path);
|
||||
|
||||
@@ -215,6 +215,28 @@ void SigactionHandler(int native_signum, siginfo_t* inf, ucontext_t* raw_context
|
||||
ctx.uc_mcontext.mc_gs = regs.__gs;
|
||||
ctx.uc_mcontext.mc_rip = regs.__rip;
|
||||
ctx.uc_mcontext.mc_addr = reinterpret_cast<uint64_t>(inf->si_addr);
|
||||
#elif defined(__FreeBSD__)
|
||||
const auto& regs = raw_context->uc_mcontext;
|
||||
ctx.uc_mcontext.mc_r8 = regs.mc_r8;
|
||||
ctx.uc_mcontext.mc_r9 = regs.mc_r9;
|
||||
ctx.uc_mcontext.mc_r10 = regs.mc_r10;
|
||||
ctx.uc_mcontext.mc_r11 = regs.mc_r11;
|
||||
ctx.uc_mcontext.mc_r12 = regs.mc_r12;
|
||||
ctx.uc_mcontext.mc_r13 = regs.mc_r13;
|
||||
ctx.uc_mcontext.mc_r14 = regs.mc_r14;
|
||||
ctx.uc_mcontext.mc_r15 = regs.mc_r15;
|
||||
ctx.uc_mcontext.mc_rdi = regs.mc_rdi;
|
||||
ctx.uc_mcontext.mc_rsi = regs.mc_rsi;
|
||||
ctx.uc_mcontext.mc_rbp = regs.mc_rbp;
|
||||
ctx.uc_mcontext.mc_rbx = regs.mc_rbx;
|
||||
ctx.uc_mcontext.mc_rdx = regs.mc_rdx;
|
||||
ctx.uc_mcontext.mc_rax = regs.mc_rax;
|
||||
ctx.uc_mcontext.mc_rcx = regs.mc_rcx;
|
||||
ctx.uc_mcontext.mc_rsp = regs.mc_rsp;
|
||||
ctx.uc_mcontext.mc_fs = regs.mc_fs;
|
||||
ctx.uc_mcontext.mc_gs = regs.mc_gs;
|
||||
ctx.uc_mcontext.mc_rip = regs.mc_rip;
|
||||
ctx.uc_mcontext.mc_addr = uint64_t(regs.mc_addr);
|
||||
#else
|
||||
const auto& regs = raw_context->uc_mcontext.gregs;
|
||||
ctx.uc_mcontext.mc_r8 = regs[REG_R8];
|
||||
@@ -303,7 +325,7 @@ s32 PS4_SYSV_ABI posix_sigaction(s32 sig, Sigaction* act, Sigaction* oact) {
|
||||
*__Error() = POSIX_EINVAL;
|
||||
return ORBIS_FAIL;
|
||||
}
|
||||
#ifndef __APPLE__
|
||||
#if !defined(__APPLE__) && !defined(__FreeBSD__)
|
||||
if (native_sig >= __SIGRTMIN && native_sig < SIGRTMIN) {
|
||||
LOG_ERROR(Lib_Kernel, "Guest is attempting to use the HLE libc-reserved signal {}!", sig);
|
||||
*__Error() = POSIX_EINVAL;
|
||||
|
||||
@@ -47,7 +47,7 @@ constexpr s32 POSIX_SIGUSR2 = 31;
|
||||
constexpr s32 POSIX_SIGTHR = 32;
|
||||
constexpr s32 POSIX_SIGLIBRT = 33;
|
||||
|
||||
#ifdef __linux__
|
||||
#if defined(__linux__) || defined(__FreeBSD__)
|
||||
constexpr s32 _SIGEMT = 128;
|
||||
constexpr s32 _SIGINFO = 129;
|
||||
#elif !defined(_WIN32)
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
#include <windows.h>
|
||||
#include "common/ntapi.h"
|
||||
#else
|
||||
#ifdef __APPLE__
|
||||
#if defined(__APPLE__) || defined(__FreeBSD__)
|
||||
#include <date/tz.h>
|
||||
#endif
|
||||
#include <ctime>
|
||||
@@ -501,7 +501,7 @@ s32 PS4_SYSV_ABI sceKernelConvertUtcToLocaltime(time_t time, time_t* local_time,
|
||||
*dst_sec = res == TIME_ZONE_ID_DAYLIGHT ? -_dstbias : 0;
|
||||
}
|
||||
#else
|
||||
#ifdef __APPLE__
|
||||
#if defined(__APPLE__) || defined(__FreeBSD__)
|
||||
// std::chrono::current_zone() not available yet.
|
||||
const auto* time_zone = date::current_zone();
|
||||
#else
|
||||
|
||||
@@ -663,10 +663,12 @@ int PS4_SYSV_ABI sceNetEpollControl(OrbisNetId epollid, OrbisNetEpollFlag op, Or
|
||||
return ORBIS_NET_ERROR_EBADF;
|
||||
}
|
||||
|
||||
#ifndef __FreeBSD__
|
||||
epoll_event native_event = {.events = ConvertEpollEventsIn(event->events),
|
||||
.data = {.fd = id}};
|
||||
ASSERT(epoll_ctl(epoll->epoll_fd, EPOLL_CTL_ADD, *native_handle, &native_event) == 0);
|
||||
epoll->events.emplace_back(id, *event);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case Core::FileSys::FileType::Resolver: {
|
||||
@@ -711,10 +713,12 @@ int PS4_SYSV_ABI sceNetEpollControl(OrbisNetId epollid, OrbisNetEpollFlag op, Or
|
||||
return ORBIS_NET_ERROR_EBADF;
|
||||
}
|
||||
|
||||
#ifndef __FreeBSD__
|
||||
epoll_event native_event = {.events = ConvertEpollEventsIn(event->events),
|
||||
.data = {.fd = id}};
|
||||
ASSERT(epoll_ctl(epoll->epoll_fd, EPOLL_CTL_MOD, *native_handle, &native_event) == 0);
|
||||
*it = {id, *event};
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -752,9 +756,10 @@ int PS4_SYSV_ABI sceNetEpollControl(OrbisNetId epollid, OrbisNetEpollFlag op, Or
|
||||
*sceNetErrnoLoc() = ORBIS_NET_EBADF;
|
||||
return ORBIS_NET_ERROR_EBADF;
|
||||
}
|
||||
|
||||
#ifndef __FreeBSD__
|
||||
ASSERT(epoll_ctl(epoll->epoll_fd, EPOLL_CTL_DEL, *native_handle, nullptr) == 0);
|
||||
epoll->events.erase(it);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case Core::FileSys::FileType::Resolver: {
|
||||
@@ -810,6 +815,9 @@ int PS4_SYSV_ABI sceNetEpollDestroy(OrbisNetId epollid) {
|
||||
|
||||
int PS4_SYSV_ABI sceNetEpollWait(OrbisNetId epollid, OrbisNetEpollEvent* events, int maxevents,
|
||||
int timeout) {
|
||||
#ifdef __FreeBSD__
|
||||
return 0;
|
||||
#else
|
||||
auto file = FDTable::Instance()->GetEpoll(epollid);
|
||||
if (!file) {
|
||||
*sceNetErrnoLoc() = ORBIS_NET_EBADF;
|
||||
@@ -836,7 +844,6 @@ int PS4_SYSV_ABI sceNetEpollWait(OrbisNetId epollid, OrbisNetEpollEvent* events,
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
|
||||
if (result < 0) {
|
||||
LOG_ERROR(Lib_Net, "epoll_wait failed with {}", Common::GetLastErrorMsg());
|
||||
switch (errno) {
|
||||
@@ -905,8 +912,8 @@ int PS4_SYSV_ABI sceNetEpollWait(OrbisNetId epollid, OrbisNetEpollEvent* events,
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
#endif
|
||||
}
|
||||
|
||||
int* PS4_SYSV_ABI sceNetErrnoLoc() {
|
||||
|
||||
@@ -10,12 +10,14 @@ namespace Libraries::Net {
|
||||
u32 ConvertEpollEventsIn(u32 orbis_events) {
|
||||
u32 ret = 0;
|
||||
|
||||
#ifndef __FreeBSD__
|
||||
if ((orbis_events & ORBIS_NET_EPOLLIN) != 0) {
|
||||
ret |= EPOLLIN;
|
||||
}
|
||||
if ((orbis_events & ORBIS_NET_EPOLLOUT) != 0) {
|
||||
ret |= EPOLLOUT;
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -23,6 +25,7 @@ u32 ConvertEpollEventsIn(u32 orbis_events) {
|
||||
u32 ConvertEpollEventsOut(u32 epoll_events) {
|
||||
u32 ret = 0;
|
||||
|
||||
#ifndef __FreeBSD__
|
||||
if ((epoll_events & EPOLLIN) != 0) {
|
||||
ret |= ORBIS_NET_EPOLLIN;
|
||||
}
|
||||
@@ -35,6 +38,7 @@ u32 ConvertEpollEventsOut(u32 epoll_events) {
|
||||
if ((epoll_events & EPOLLHUP) != 0) {
|
||||
ret |= ORBIS_NET_EPOLLHUP;
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -14,7 +14,8 @@
|
||||
#include <wepoll.h>
|
||||
#endif
|
||||
|
||||
#if defined(__linux__) || defined(__APPLE__)
|
||||
#if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__)
|
||||
// ADD libepoll-shim if using freebsd!
|
||||
#include <sys/epoll.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
@@ -82,4 +83,4 @@ private:
|
||||
std::mutex m_mutex;
|
||||
};
|
||||
|
||||
} // namespace Libraries::Net
|
||||
} // namespace Libraries::Net
|
||||
|
||||
@@ -25,7 +25,7 @@ typedef int net_socket;
|
||||
#include <net/if_dl.h>
|
||||
#include <net/route.h>
|
||||
#endif
|
||||
#if __linux__
|
||||
#if defined(__linux__) || defined(__FreeBSD__)
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
@@ -81,6 +81,8 @@ bool NetUtilInternal::RetrieveEthernetAddr() {
|
||||
}
|
||||
freeifaddrs(ifap);
|
||||
}
|
||||
#elif defined(__FreeBSD__)
|
||||
// todo
|
||||
#else
|
||||
ifreq ifr;
|
||||
ifconf ifc;
|
||||
@@ -226,7 +228,8 @@ bool NetUtilInternal::RetrieveDefaultGateway() {
|
||||
inet_ntop(AF_INET, gateAddr, str, sizeof(str));
|
||||
this->default_gateway = str;
|
||||
return true;
|
||||
|
||||
#elif defined(__FreeBSD__)
|
||||
return true;
|
||||
#else
|
||||
std::ifstream route{"/proc/net/route"};
|
||||
std::string line;
|
||||
@@ -398,4 +401,4 @@ int NetUtilInternal::ResolveHostname(const char* hostname, Libraries::Net::Orbis
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace NetUtil
|
||||
} // namespace NetUtil
|
||||
|
||||
+9
-2
@@ -10,6 +10,8 @@
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#elif defined(__FreeBSD__)
|
||||
#include <machine/sysarch.h>
|
||||
#elif defined(__APPLE__) && defined(ARCH_X86_64)
|
||||
#include <architecture/i386/table.h>
|
||||
#include <boost/icl/interval_set.hpp>
|
||||
@@ -157,12 +159,17 @@ Tcb* GetTcbBase() {
|
||||
|
||||
#elif defined(ARCH_X86_64)
|
||||
|
||||
// Other POSIX x86_64
|
||||
|
||||
// Linux x86_64
|
||||
#if defined(__FreeBSD__)
|
||||
void SetTcbBase(void* image_address) {
|
||||
amd64_set_gsbase(image_address);
|
||||
}
|
||||
#else
|
||||
void SetTcbBase(void* image_address) {
|
||||
const int ret = syscall(SYS_arch_prctl, ARCH_SET_GS, (unsigned long)image_address);
|
||||
ASSERT_MSG(ret == 0, "Failed to set GS base: errno {}", errno);
|
||||
}
|
||||
#endif
|
||||
|
||||
Tcb* GetTcbBase() {
|
||||
return Libraries::Kernel::g_curthread->tcb;
|
||||
|
||||
+1
-1
@@ -535,7 +535,7 @@ void Emulator::Restart(std::filesystem::path eboot_path,
|
||||
|
||||
CloseHandle(pi.hProcess);
|
||||
CloseHandle(pi.hThread);
|
||||
#elif defined(__APPLE__) || defined(__linux__)
|
||||
#elif defined(__APPLE__) || defined(__linux__) || defined(__FreeBSD__)
|
||||
std::vector<char*> argv;
|
||||
|
||||
// Emulator executable
|
||||
|
||||
+3
-2
@@ -96,7 +96,7 @@ WindowSDL::WindowSDL(s32 width_, s32 height_, Input::GameControllers* controller
|
||||
UNREACHABLE_MSG("Failed to initialize SDL video subsystem: {}", SDL_GetError());
|
||||
}
|
||||
if (!SDL_Init(SDL_INIT_CAMERA)) {
|
||||
UNREACHABLE_MSG("Failed to initialize SDL camera subsystem: {}", SDL_GetError());
|
||||
LOG_ERROR(Input, "Failed to initialize SDL camera subsystem: {}", SDL_GetError());
|
||||
}
|
||||
SDL_InitSubSystem(SDL_INIT_AUDIO);
|
||||
|
||||
@@ -141,7 +141,8 @@ WindowSDL::WindowSDL(s32 width_, s32 height_, Input::GameControllers* controller
|
||||
window_info.type = WindowSystemType::Windows;
|
||||
window_info.render_surface = SDL_GetPointerProperty(SDL_GetWindowProperties(window),
|
||||
SDL_PROP_WINDOW_WIN32_HWND_POINTER, NULL);
|
||||
#elif defined(SDL_PLATFORM_LINUX)
|
||||
#elif defined(SDL_PLATFORM_LINUX) || defined(__FreeBSD__)
|
||||
// SDL doesn't have a platform define for FreeBSD AAAAAAAAAA
|
||||
if (SDL_strcmp(SDL_GetCurrentVideoDriver(), "x11") == 0) {
|
||||
window_info.type = WindowSystemType::X11;
|
||||
window_info.display_connection = SDL_GetPointerProperty(
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#include "common/logging/log.h"
|
||||
#include "core/emulator_settings.h"
|
||||
|
||||
#ifdef __linux__
|
||||
#ifdef __unix__
|
||||
#include "common/adaptive_mutex.h"
|
||||
#else
|
||||
#include "common/spin_lock.h"
|
||||
|
||||
@@ -36,8 +36,8 @@
|
||||
|
||||
namespace VideoCore {
|
||||
|
||||
constexpr size_t PAGE_SIZE = 4_KB;
|
||||
constexpr size_t PAGE_BITS = 12;
|
||||
constexpr size_t PM_PAGE_SIZE = 4_KB;
|
||||
constexpr size_t PM_PAGE_BITS = 12;
|
||||
|
||||
struct PageManager::Impl {
|
||||
struct PageState {
|
||||
@@ -85,7 +85,7 @@ struct PageManager::Impl {
|
||||
};
|
||||
|
||||
static constexpr size_t ADDRESS_BITS = 40;
|
||||
static constexpr size_t NUM_ADDRESS_PAGES = 1ULL << (40 - PAGE_BITS);
|
||||
static constexpr size_t NUM_ADDRESS_PAGES = 1ULL << (40 - PM_PAGE_BITS);
|
||||
static constexpr size_t NUM_ADDRESS_LOCKS = NUM_ADDRESS_PAGES / PAGES_PER_LOCK;
|
||||
inline static Vulkan::Rasterizer* rasterizer;
|
||||
#ifdef ENABLE_USERFAULTFD
|
||||
@@ -222,8 +222,8 @@ struct PageManager::Impl {
|
||||
void UpdatePageWatchers(VAddr addr, u64 size) {
|
||||
RENDERER_TRACE;
|
||||
|
||||
size_t page = addr >> PAGE_BITS;
|
||||
const u64 page_end = Common::DivCeil(addr + size, PAGE_SIZE);
|
||||
size_t page = addr >> PM_PAGE_BITS;
|
||||
const u64 page_end = Common::DivCeil(addr + size, PM_PAGE_SIZE);
|
||||
|
||||
// Acquire locks for the range of pages
|
||||
const auto lock_start = locks.begin() + (page / PAGES_PER_LOCK);
|
||||
@@ -239,15 +239,15 @@ struct PageManager::Impl {
|
||||
if (range_bytes > 0) {
|
||||
RENDERER_TRACE;
|
||||
// Perform pending (un)protect action
|
||||
Protect(range_begin << PAGE_BITS, range_bytes, perms);
|
||||
Protect(range_begin << PM_PAGE_BITS, range_bytes, perms);
|
||||
range_bytes = 0;
|
||||
potential_range_bytes = 0;
|
||||
}
|
||||
};
|
||||
|
||||
// Iterate requested pages
|
||||
const u64 aligned_addr = page << PAGE_BITS;
|
||||
const u64 aligned_end = page_end << PAGE_BITS;
|
||||
const u64 aligned_addr = page << PM_PAGE_BITS;
|
||||
const u64 aligned_end = page_end << PM_PAGE_BITS;
|
||||
if (!rasterizer->IsMapped(aligned_addr, aligned_end - aligned_addr)) {
|
||||
LOG_WARNING(Render,
|
||||
"Tracking memory region {:#x} - {:#x} which is not fully GPU mapped.",
|
||||
@@ -266,7 +266,7 @@ struct PageManager::Impl {
|
||||
perms = new_perms;
|
||||
} else if (range_bytes != 0) {
|
||||
// If the protection did not change, extend the potential range
|
||||
potential_range_bytes += PAGE_SIZE;
|
||||
potential_range_bytes += PM_PAGE_SIZE;
|
||||
}
|
||||
|
||||
// Only start a new range if the page must be (un)protected
|
||||
@@ -274,7 +274,7 @@ struct PageManager::Impl {
|
||||
if (range_bytes == 0) {
|
||||
// Start a new potential range
|
||||
range_begin = page;
|
||||
potential_range_bytes = PAGE_SIZE;
|
||||
potential_range_bytes = PM_PAGE_SIZE;
|
||||
}
|
||||
// Extend current range up to potential range
|
||||
range_bytes = potential_range_bytes;
|
||||
@@ -293,12 +293,12 @@ struct PageManager::Impl {
|
||||
|
||||
if (start_range.second == end_range.second) {
|
||||
// if all pages are contiguous, use the regular UpdatePageWatchers
|
||||
const VAddr start_addr = base_addr + (start_range.first << PAGE_BITS);
|
||||
const u64 size = (start_range.second - start_range.first) << PAGE_BITS;
|
||||
const VAddr start_addr = base_addr + (start_range.first << PM_PAGE_BITS);
|
||||
const u64 size = (start_range.second - start_range.first) << PM_PAGE_BITS;
|
||||
return UpdatePageWatchers<track, is_read>(start_addr, size);
|
||||
}
|
||||
|
||||
size_t base_page = (base_addr >> PAGE_BITS);
|
||||
size_t base_page = (base_addr >> PM_PAGE_BITS);
|
||||
ASSERT(base_page % PAGES_PER_LOCK == 0);
|
||||
std::scoped_lock lk(locks[base_page / PAGES_PER_LOCK]);
|
||||
auto perms = cached_pages[base_page + start_range.first].Perms();
|
||||
@@ -310,7 +310,7 @@ struct PageManager::Impl {
|
||||
if (range_bytes > 0) {
|
||||
RENDERER_TRACE;
|
||||
// Perform pending (un)protect action
|
||||
Protect((range_begin << PAGE_BITS), range_bytes, perms);
|
||||
Protect((range_begin << PM_PAGE_BITS), range_bytes, perms);
|
||||
range_bytes = 0;
|
||||
potential_range_bytes = 0;
|
||||
}
|
||||
@@ -331,7 +331,7 @@ struct PageManager::Impl {
|
||||
perms = new_perms;
|
||||
} else if (range_bytes != 0) {
|
||||
// If the protection did not change, extend the potential range
|
||||
potential_range_bytes += PAGE_SIZE;
|
||||
potential_range_bytes += PM_PAGE_SIZE;
|
||||
}
|
||||
|
||||
// If the page is not being updated, skip it
|
||||
@@ -344,7 +344,7 @@ struct PageManager::Impl {
|
||||
if (range_bytes == 0) {
|
||||
// Start a new potential range
|
||||
range_begin = base_page + page;
|
||||
potential_range_bytes = PAGE_SIZE;
|
||||
potential_range_bytes = PM_PAGE_SIZE;
|
||||
}
|
||||
// Extend current rango up to potential range
|
||||
range_bytes = potential_range_bytes;
|
||||
@@ -356,7 +356,7 @@ struct PageManager::Impl {
|
||||
}
|
||||
|
||||
std::array<PageState, NUM_ADDRESS_PAGES> cached_pages{};
|
||||
#ifdef __linux__
|
||||
#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
|
||||
using LockType = Common::AdaptiveMutex;
|
||||
#else
|
||||
using LockType = Common::SpinLock;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include "common/alignment.h"
|
||||
#include "common/types.h"
|
||||
@@ -15,9 +16,10 @@ class Rasterizer;
|
||||
namespace VideoCore {
|
||||
|
||||
class PageManager {
|
||||
// PAGE_SIZE and PAGE_BITS conflicts with machine/param.h definitions on freebsd!
|
||||
// Use the same page size as the tracker.
|
||||
static constexpr size_t PAGE_BITS = TRACKER_PAGE_BITS;
|
||||
static constexpr size_t PAGE_SIZE = TRACKER_BYTES_PER_PAGE;
|
||||
static constexpr size_t PM_PAGE_BITS = TRACKER_PAGE_BITS;
|
||||
static constexpr size_t PM_PAGE_SIZE = TRACKER_BYTES_PER_PAGE;
|
||||
|
||||
// Keep the lock granularity the same as region granularity. (since each regions has
|
||||
// itself a lock)
|
||||
@@ -43,12 +45,12 @@ public:
|
||||
|
||||
/// Returns page aligned address.
|
||||
static constexpr VAddr GetPageAddr(VAddr addr) {
|
||||
return Common::AlignDown(addr, PAGE_SIZE);
|
||||
return Common::AlignDown(addr, PM_PAGE_SIZE);
|
||||
}
|
||||
|
||||
/// Returns address of the next page.
|
||||
static constexpr VAddr GetNextPageAddr(VAddr addr) {
|
||||
return Common::AlignUp(addr + 1, PAGE_SIZE);
|
||||
return Common::AlignUp(addr + 1, PM_PAGE_SIZE);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
Reference in New Issue
Block a user