diff --git a/orbis-kernel/src/sys/sys_sce.cpp b/orbis-kernel/src/sys/sys_sce.cpp index 3fe095cbe..c4be2ecc3 100644 --- a/orbis-kernel/src/sys/sys_sce.cpp +++ b/orbis-kernel/src/sys/sys_sce.cpp @@ -792,7 +792,7 @@ orbis::SysResult orbis::sys_get_authinfo(Thread *thread, pid_t pid, orbis::SysResult orbis::sys_mname(Thread *thread, uint64_t addr, uint64_t len, ptr name) { ORBIS_LOG_NOTICE(__FUNCTION__, addr, len, name); - if (addr < 0x40000 || addr >= 0x100'0000'0000 || 0x100'0000'0000 - addr < len) + if (addr < kMinAddress || addr >= kMaxAddress || kMaxAddress - addr < len) return ErrorCode::INVAL; char _name[32]; if (auto result = ureadString(_name, sizeof(_name), (const char *)name); diff --git a/rpcsx/gpu/Device.cpp b/rpcsx/gpu/Device.cpp index 95d8c92c5..69b1ea30c 100644 --- a/rpcsx/gpu/Device.cpp +++ b/rpcsx/gpu/Device.cpp @@ -4,8 +4,10 @@ #include "amdgpu/tiler.hpp" #include "gnm/constants.hpp" #include "gnm/pm4.hpp" +#include "orbis-config.hpp" #include "orbis/KernelContext.hpp" #include "orbis/note.hpp" +#include "rx/AddressRange.hpp" #include "rx/Config.hpp" #include "rx/bits.hpp" #include "rx/die.hpp" @@ -61,10 +63,13 @@ static vk::Context createVkContext(Device *device) { std::vector optionalLayers; bool enableValidation = rx::g_config.validateGpu; - std::uint64_t minAddress = 0x40000; - if (!rx::mem::reserve(reinterpret_cast(minAddress), - 0x600'0000'0000 - minAddress)) { - rx::die("failed to reserve userspace memory"); + for (std::size_t process = 0; process < 6; ++process) { + if (!rx::mem::reserve( + reinterpret_cast(orbis::kMinAddress + + orbis::kMaxAddress * process), + orbis::kMaxAddress - orbis::kMinAddress)) { + rx::die("failed to reserve userspace memory"); + } } auto createWindow = [=] { @@ -256,10 +261,10 @@ Device::Device() : vkContext(createVkContext(this)) { commandPipe.device = this; commandPipe.ring = { - .base = cmdRing, + .base = std::data(cmdRing), .size = std::size(cmdRing), - .rptr = cmdRing, - .wptr = cmdRing, + .rptr = std::data(cmdRing), + .wptr = std::data(cmdRing), }; for (auto &pipe : computePipes) { @@ -509,6 +514,12 @@ void Device::start() { } void Device::submitCommand(Ring &ring, std::span command) { + if (ring.size < command.size()) { + std::println(stderr, "too big command: ring size {}, command size {}", + ring.size, command.size()); + std::abort(); + } + std::scoped_lock lock(writeCommandMtx); if (ring.wptr + command.size() > ring.base + ring.size) { while (ring.wptr != ring.rptr) { diff --git a/rpcsx/main.cpp b/rpcsx/main.cpp index e8f6e3c2f..5d2e9be56 100644 --- a/rpcsx/main.cpp +++ b/rpcsx/main.cpp @@ -59,7 +59,8 @@ handle_signal(int sig, siginfo_t *info, void *ucontext) { if (orbis::g_currentThread != nullptr && orbis::g_currentThread->tproc->vmId >= 0 && sig == SIGSEGV && - signalAddress >= 0x40000 && signalAddress < 0x100'0000'0000) { + signalAddress >= orbis::kMinAddress && + signalAddress < orbis::kMaxAddress) { auto vmid = orbis::g_currentThread->tproc->vmId; auto ctx = reinterpret_cast(ucontext); bool isWrite = (ctx->uc_mcontext.gregs[REG_ERR] & 0x2) != 0; @@ -93,7 +94,8 @@ handle_signal(int sig, siginfo_t *info, void *ucontext) { continue; } - gpuContext.gpuCacheCommandIdle.fetch_add(1, std::memory_order::release); + gpuContext.gpuCacheCommandIdle.fetch_add( + 1, std::memory_order::release); gpuContext.gpuCacheCommandIdle.notify_all(); while (!gpuContext.cachePages[vmid][page].compare_exchange_weak( diff --git a/rpcsx/orbis-kernel-config/orbis-config.hpp b/rpcsx/orbis-kernel-config/orbis-config.hpp index 8d6721122..696843118 100644 --- a/rpcsx/orbis-kernel-config/orbis-config.hpp +++ b/rpcsx/orbis-kernel-config/orbis-config.hpp @@ -41,11 +41,14 @@ template using cptr = T *const; using caddr_t = ptr; +static constexpr auto kMinAddress = 0x400000; +static constexpr auto kMaxAddress = 0x100'0000'0000; + [[nodiscard]] inline ErrorCode ureadRaw(void *kernelAddress, ptr userAddress, size_t size) { if (size != 0) { auto addr = reinterpret_cast(userAddress); - if (addr < 0x40000 || addr + size > 0x100'0000'0000 || addr + size < addr) + if (addr < kMinAddress || addr + size >= kMaxAddress || addr + size < addr) return ErrorCode::FAULT; std::memcpy(kernelAddress, userAddress, size); } @@ -56,7 +59,7 @@ ureadRaw(void *kernelAddress, ptr userAddress, size_t size) { uwriteRaw(ptr userAddress, const void *kernelAddress, size_t size) { if (size != 0) { auto addr = reinterpret_cast(userAddress); - if (addr < 0x40000 || addr + size > 0x100'0000'0000 || addr + size < addr) + if (addr < kMinAddress || addr + size > kMaxAddress || addr + size < addr) return ErrorCode::FAULT; std::memcpy(userAddress, kernelAddress, size); } @@ -66,7 +69,7 @@ uwriteRaw(ptr userAddress, const void *kernelAddress, size_t size) { [[nodiscard]] inline ErrorCode ureadString(char *kernelAddress, size_t size, ptr userAddress) { auto addr = reinterpret_cast(userAddress); - if (addr < 0x40000 || addr + size > 0x100'0000'0000 || addr + size < addr) + if (addr < kMinAddress || addr + size > kMaxAddress || addr + size < addr) return ErrorCode::FAULT; std::strncpy(kernelAddress, userAddress, size); if (kernelAddress[size - 1] != '\0') { diff --git a/rpcsx/thread.cpp b/rpcsx/thread.cpp index 39e83af30..7947ca894 100644 --- a/rpcsx/thread.cpp +++ b/rpcsx/thread.cpp @@ -1,4 +1,5 @@ #include "thread.hpp" +#include "orbis-config.hpp" #include "orbis/sys/sysentry.hpp" #include "orbis/thread/Process.hpp" #include "orbis/thread/Thread.hpp" @@ -268,7 +269,7 @@ void rx::thread::setupThisThread() { } if (prctl(PR_SET_SYSCALL_USER_DISPATCH, PR_SYS_DISPATCH_ON, - (void *)0x100'0000'0000, ~0ull - 0x100'0000'0000, nullptr)) { + (void *)orbis::kMaxAddress, ~0ull - orbis::kMaxAddress, nullptr)) { perror("prctl failed\n"); std::exit(-1); } diff --git a/rpcsx/vm.cpp b/rpcsx/vm.cpp index d55adf9ad..58e0b6831 100644 --- a/rpcsx/vm.cpp +++ b/rpcsx/vm.cpp @@ -2,6 +2,7 @@ #include "gpu/DeviceCtl.hpp" #include "io-device.hpp" #include "iodev/dmem.hpp" +#include "orbis-config.hpp" #include "orbis/KernelContext.hpp" #include "orbis/thread/Process.hpp" #include "orbis/thread/Thread.hpp" @@ -240,11 +241,12 @@ static constexpr std::uint64_t kBlockCount = kLastBlock - kFirstBlock + 1; static constexpr std::uint64_t kGroupSize = 64; static constexpr std::uint64_t kGroupMask = kGroupSize - 1; static constexpr std::uint64_t kGroupsInBlock = kPagesInBlock / kGroupSize; -static constexpr std::uint64_t kMinAddress = - kFirstBlock * kBlockSize + vm::kPageSize * 0x100; -static constexpr std::uint64_t kMaxAddress = (kLastBlock + 1) * kBlockSize - 1; +static constexpr std::uint64_t kMinAddress = orbis::kMinAddress; +static constexpr std::uint64_t kMaxAddress = orbis::kMaxAddress; static constexpr std::uint64_t kMemorySize = kBlockCount * kBlockSize; +static_assert((kLastBlock + 1) * kBlockSize == orbis::kMaxAddress); + static int gMemoryShm = -1; struct Group { @@ -964,7 +966,7 @@ bool vm::unmap(void *addr, std::uint64_t size) { auto pages = (size + (kPageSize - 1)) >> kPageShift; auto address = reinterpret_cast(addr); - if (address < kMinAddress || address >= kMaxAddress || size > kMaxAddress || + if (address < kMinAddress || address >= kMaxAddress || size >= kMaxAddress || address > kMaxAddress - size) { std::println(stderr, "Memory error: unmap out of memory"); return false; @@ -994,6 +996,7 @@ bool vm::unmap(void *addr, std::uint64_t size) { std::println(stderr, "ignoring unmapping {:x}-{:x}", address, address + size); } + gMapInfo.unmap(address, address + size); return rx::mem::unmap(addr, size); } @@ -1007,7 +1010,7 @@ bool vm::protect(void *addr, std::uint64_t size, std::int32_t prot) { endAddress = rx::alignUp(endAddress, kPageSize); size = endAddress - address; auto pages = size >> kPageShift; - if (address < kMinAddress || address >= kMaxAddress || size > kMaxAddress || + if (address < kMinAddress || address >= kMaxAddress || size >= kMaxAddress || address > kMaxAddress - size) { std::println(stderr, "Memory error: protect out of memory"); return false;