vm: use virtual address range from orbis config

This commit is contained in:
DH 2024-11-12 12:55:06 +03:00
parent 3b57880040
commit 89c1601d49
6 changed files with 39 additions and 19 deletions

View file

@ -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<const char[32]> 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);

View file

@ -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<const char *> optionalLayers;
bool enableValidation = rx::g_config.validateGpu;
std::uint64_t minAddress = 0x40000;
if (!rx::mem::reserve(reinterpret_cast<void *>(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<void *>(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<const std::uint32_t> 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) {

View file

@ -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_t *>(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(

View file

@ -41,11 +41,14 @@ template <typename T> using cptr = T *const;
using caddr_t = ptr<char>;
static constexpr auto kMinAddress = 0x400000;
static constexpr auto kMaxAddress = 0x100'0000'0000;
[[nodiscard]] inline ErrorCode
ureadRaw(void *kernelAddress, ptr<const void> userAddress, size_t size) {
if (size != 0) {
auto addr = reinterpret_cast<std::uintptr_t>(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<const void> userAddress, size_t size) {
uwriteRaw(ptr<void> userAddress, const void *kernelAddress, size_t size) {
if (size != 0) {
auto addr = reinterpret_cast<std::uintptr_t>(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<void> userAddress, const void *kernelAddress, size_t size) {
[[nodiscard]] inline ErrorCode ureadString(char *kernelAddress, size_t size,
ptr<const char> userAddress) {
auto addr = reinterpret_cast<std::uintptr_t>(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') {

View file

@ -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);
}

View file

@ -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<std::uint64_t>(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;