[rpcsx-os] implement blockpool device

This commit is contained in:
DH 2023-07-30 14:56:25 +03:00
parent e967c8cf80
commit 89db63ca46
10 changed files with 203 additions and 6 deletions

View file

@ -149,6 +149,7 @@ public:
Ref<RcBase> shmDevice;
Ref<RcBase> dmemDevice;
Ref<RcBase> blockpoolDevice;
private:
mutable pthread_mutex_t m_heap_mtx;

View file

@ -759,9 +759,11 @@ SysResult sys_dynlib_get_obj_member(Thread *thread, SceKernelModule handle,
SysResult sys_budget_get_ptype_of_budget(Thread *thread /* TODO */);
SysResult sys_prepare_to_resume_process(Thread *thread /* TODO */);
SysResult sys_process_terminate(Thread *thread /* TODO */);
SysResult sys_blockpool_open(Thread *thread /* TODO */);
SysResult sys_blockpool_map(Thread *thread /* TODO */);
SysResult sys_blockpool_unmap(Thread *thread /* TODO */);
SysResult sys_blockpool_open(Thread *thread);
SysResult sys_blockpool_map(Thread *thread, caddr_t addr, size_t len, sint prot,
sint flags);
SysResult sys_blockpool_unmap(Thread *thread, caddr_t addr, size_t len,
sint flags);
SysResult sys_dynlib_get_info_for_libdbg(Thread *thread /* TODO */);
SysResult sys_blockpool_batch(Thread *thread /* TODO */);
SysResult sys_fdatasync(Thread *thread /* TODO */);

View file

@ -37,6 +37,10 @@ struct ProcessOps {
Ref<File> *file);
SysResult (*shm_open)(Thread *thread, const char *path, sint flags, sint mode,
Ref<File> *file);
SysResult (*blockpool_open)(Thread *thread, Ref<File> *file);
SysResult (*blockpool_map)(Thread *thread, caddr_t addr, size_t len,
sint prot, sint flags);
SysResult (*blockpool_unmap)(Thread *thread, caddr_t addr, size_t len);
SysResult (*socket)(Thread *thread, ptr<const char> name, sint domain,
sint type, sint protocol, Ref<File> *file);
SysResult (*shm_unlink)(Thread *thread, const char *path);

View file

@ -1217,13 +1217,31 @@ orbis::sys_prepare_to_resume_process(Thread *thread /* TODO */) {
orbis::SysResult orbis::sys_process_terminate(Thread *thread /* TODO */) {
return ErrorCode::NOSYS;
}
orbis::SysResult orbis::sys_blockpool_open(Thread *thread /* TODO */) {
orbis::SysResult orbis::sys_blockpool_open(Thread *thread) {
if (auto blockpool_open = thread->tproc->ops->blockpool_open) {
Ref<File> file;
auto result = blockpool_open(thread, &file);
if (result.isError()) {
return result;
}
thread->retval[0] = thread->tproc->fileDescriptors.insert(file);
return {};
}
return ErrorCode::NOSYS;
}
orbis::SysResult orbis::sys_blockpool_map(Thread *thread /* TODO */) {
orbis::SysResult orbis::sys_blockpool_map(Thread *thread, caddr_t addr,
size_t len, sint prot, sint flags) {
if (auto blockpool_map = thread->tproc->ops->blockpool_map) {
return blockpool_map(thread, addr, len, prot, flags);
}
return ErrorCode::NOSYS;
}
orbis::SysResult orbis::sys_blockpool_unmap(Thread *thread /* TODO */) {
orbis::SysResult orbis::sys_blockpool_unmap(Thread *thread, caddr_t addr,
size_t len, sint flags) {
if (auto blockpool_unmap = thread->tproc->ops->blockpool_unmap) {
return blockpool_unmap(thread, addr, len);
}
return ErrorCode::NOSYS;
}
orbis::SysResult

View file

@ -4,6 +4,7 @@ add_library(orbis::kernel::config ALIAS standalone-config)
add_executable(rpcsx-os
iodev/ajm.cpp
iodev/blockpool.cpp
iodev/dce.cpp
iodev/dipsw.cpp
iodev/dmem.cpp

View file

@ -17,3 +17,4 @@ IoDevice *createRngCharacterDevice();
IoDevice *createAjmCharacterDevice();
IoDevice *createSblSrvCharacterDevice();
IoDevice *createShmDevice();
IoDevice *createBlockPoolDevice();

View file

@ -0,0 +1,117 @@
#include "blockpool.hpp"
#include "dmem.hpp"
#include "io-device.hpp"
#include "orbis/KernelAllocator.hpp"
#include "orbis/KernelContext.hpp"
#include "orbis/file.hpp"
#include "orbis/thread/Thread.hpp"
#include "orbis/utils/Logs.hpp"
#include "vm.hpp"
#include <mutex>
#include <sys/mman.h>
struct BlockPoolFile : public orbis::File {};
static orbis::ErrorCode blockpool_ioctl(orbis::File *file,
std::uint64_t request, void *argp,
orbis::Thread *thread) {
auto blockPool = static_cast<BlockPoolDevice *>(file->device.get());
std::lock_guard lock(blockPool->mtx);
switch (request) {
case 0xc020a801: {
auto dmem = static_cast<DmemDevice *>(orbis::g_context.dmemDevice.get());
std::lock_guard lock(dmem->mtx);
struct Args {
std::uint64_t len;
std::uint64_t searchStart;
std::uint64_t searchEnd;
std::uint32_t flags;
};
auto args = reinterpret_cast<Args *>(argp);
ORBIS_LOG_TODO("blockpool expand", args->len, args->searchStart,
args->searchEnd, args->flags);
std::uint64_t start = args->searchStart;
std::uint64_t len = std::min(args->searchEnd - start, args->len);
if (dmem->nextOffset > args->searchEnd) {
ORBIS_LOG_TODO("blockpool out of allocation", args->len,
args->searchStart, args->searchEnd, args->flags);
return orbis::ErrorCode::INVAL;
}
start = std::max(dmem->nextOffset, start);
auto end = std::min(start + len, args->searchEnd);
dmem->nextOffset = end;
args->searchStart = start;
blockPool->len += end - start;
return {};
}
}
ORBIS_LOG_FATAL("Unhandled blockpool ioctl", request);
thread->where();
return {};
}
static orbis::ErrorCode blockpool_mmap(orbis::File *file, void **address,
std::uint64_t size, std::int32_t prot,
std::int32_t flags, std::int64_t offset,
orbis::Thread *thread) {
auto blockPool = static_cast<BlockPoolDevice *>(file->device.get());
std::lock_guard lock(blockPool->mtx);
ORBIS_LOG_FATAL("blockpool mmap", *address, size, offset, blockPool->len);
size = std::min<std::uint64_t>(
0x1000000, size); // FIXME: hack, investigate why we report so many memory
size = std::min(blockPool->len, size);
auto result = rx::vm::map(*address, size, prot, flags);
if (result == (void *)-1) {
return orbis::ErrorCode::INVAL; // TODO
}
blockPool->len -= size;
*address = result;
return {};
}
static const orbis::FileOps ops = {
.ioctl = blockpool_ioctl,
.mmap = blockpool_mmap,
};
orbis::ErrorCode BlockPoolDevice::open(orbis::Ref<orbis::File> *file,
const char *path, std::uint32_t flags,
std::uint32_t mode,
orbis::Thread *thread) {
auto newFile = orbis::knew<BlockPoolFile>();
newFile->device = this;
newFile->ops = &ops;
*file = newFile;
return {};
}
orbis::ErrorCode BlockPoolDevice::map(void **address, std::uint64_t len,
std::int32_t prot, std::int32_t flags,
orbis::Thread *thread) {
ORBIS_LOG_FATAL("blockpool device map", *address, len);
auto result = rx::vm::map(*address, len, prot, flags);
if (result == (void *)-1) {
return orbis::ErrorCode::NOMEM;
}
*address = result;
return {};
}
orbis::ErrorCode BlockPoolDevice::unmap(void *address, std::uint64_t len,
orbis::Thread *thread) {
ORBIS_LOG_FATAL("blockpool device unmap", address, len);
if (rx::vm::unmap(address, len)) {
return {};
}
return orbis::ErrorCode::INVAL;
}
IoDevice *createBlockPoolDevice() { return orbis::knew<BlockPoolDevice>(); }

View file

@ -0,0 +1,21 @@
#pragma once
#include "io-device.hpp"
#include "orbis/error/ErrorCode.hpp"
#include "orbis/file.hpp"
#include "orbis/utils/Rc.hpp"
#include "orbis/utils/SharedMutex.hpp"
#include <cstdint>
struct BlockPoolDevice : public IoDevice {
orbis::shared_mutex mtx;
std::uint64_t len = 0;
orbis::ErrorCode open(orbis::Ref<orbis::File> *file, const char *path,
std::uint32_t flags, std::uint32_t mode,
orbis::Thread *thread) override;
orbis::ErrorCode map(void **address, std::uint64_t len, std::int32_t prot,
std::int32_t flags, orbis::Thread *thread);
orbis::ErrorCode unmap(void *address, std::uint64_t len,
orbis::Thread *thread);
};

View file

@ -342,6 +342,7 @@ static int ps4Exec(orbis::Thread *mainThread,
mainThread->tproc->fileDescriptors.insert(stderrFile);
orbis::g_context.shmDevice = createShmDevice();
orbis::g_context.blockpoolDevice = createBlockPoolDevice();
std::vector<std::uint64_t> argvOffsets;
std::vector<std::uint64_t> envpOffsets;

View file

@ -2,6 +2,7 @@
#include "align.hpp"
#include "backtrace.hpp"
#include "io-device.hpp"
#include "iodev/blockpool.hpp"
#include "iodev/dmem.hpp"
#include "linker.hpp"
#include "orbis/KernelContext.hpp"
@ -259,6 +260,33 @@ orbis::SysResult shm_open(orbis::Thread *thread, const char *path,
return dev->open(file, path, flags, mode, thread);
}
orbis::SysResult blockpool_open(orbis::Thread *thread,
orbis::Ref<orbis::File> *file) {
auto dev = static_cast<IoDevice *>(orbis::g_context.blockpoolDevice.get());
return dev->open(file, nullptr, 0, 0, thread);
}
orbis::SysResult blockpool_map(orbis::Thread *thread, orbis::caddr_t addr,
orbis::size_t len, orbis::sint prot,
orbis::sint flags) {
auto blockpool =
static_cast<BlockPoolDevice *>(orbis::g_context.blockpoolDevice.get());
void *address = addr;
auto result = blockpool->map(&address, len, prot, flags, thread);
if (result != ErrorCode{}) {
return result;
}
thread->retval[0] = reinterpret_cast<std::uint64_t>(address);
return {};
}
orbis::SysResult blockpool_unmap(orbis::Thread *thread, orbis::caddr_t addr,
orbis::size_t len) {
auto blockpool =
static_cast<BlockPoolDevice *>(orbis::g_context.blockpoolDevice.get());
return blockpool->unmap(addr, len, thread);
}
orbis::SysResult socket(orbis::Thread *thread, orbis::ptr<const char> name,
orbis::sint domain, orbis::sint type,
orbis::sint protocol, Ref<File> *file) {
@ -562,6 +590,9 @@ ProcessOps rx::procOpsTable = {
.virtual_query = virtual_query,
.open = open,
.shm_open = shm_open,
.blockpool_open = blockpool_open,
.blockpool_map = blockpool_map,
.blockpool_unmap = blockpool_unmap,
.socket = socket,
.shm_unlink = shm_unlink,
.dynlib_get_obj_member = dynlib_get_obj_member,