[rpcsx-os] implement shm

This commit is contained in:
DH 2023-07-29 22:46:28 +03:00
parent d52a53cfcd
commit 645e41eed8
28 changed files with 187 additions and 47 deletions

View file

@ -124,6 +124,8 @@ public:
return getUmtxChainIndexed(1, t, flags, ptr);
}
Ref<RcBase> shmDevice;
private:
mutable pthread_mutex_t m_heap_mtx;
void *m_heap_next = this + 1;

View file

@ -32,8 +32,11 @@ struct ProcessOps {
SysResult (*open)(Thread *thread, ptr<const char> path, sint flags, sint mode,
Ref<File> *file);
SysResult (*shm_open)(Thread *thread, const char *path, sint flags, sint mode,
Ref<File> *file);
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);
SysResult (*dynlib_get_obj_member)(Thread *thread, ModuleHandle handle,
uint64_t index, ptr<ptr<void>> addrp);
SysResult (*dynlib_dlsym)(Thread *thread, ModuleHandle handle,

View file

@ -17,10 +17,6 @@ orbis::SysResult orbis::sys_fcntl(Thread *thread, sint fd, sint cmd,
}
orbis::SysResult orbis::sys_close(Thread *thread, sint fd) {
ORBIS_LOG_NOTICE(__FUNCTION__, fd);
if (fd == 0) {
return {}; // FIXME: remove when shm would be implemented
}
if (thread->tproc->fileDescriptors.close(fd)) {
return {};
}

View file

@ -275,10 +275,6 @@ orbis::SysResult orbis::sys_pwritev(Thread *thread, sint fd, ptr<IoVec> iovp,
return {};
}
orbis::SysResult orbis::sys_ftruncate(Thread *thread, sint fd, off_t length) {
ORBIS_LOG_WARNING(__FUNCTION__, fd, length);
if (fd == 0) {
return {}; // FIXME: remove when shm implemented
}
Ref<File> file = thread->tproc->fileDescriptors.get(fd);
if (file == nullptr) {
return ErrorCode::BADF;

View file

@ -1,6 +1,5 @@
#include "orbis-config.hpp"
#include "sys/sysproto.hpp"
#include "utils/Logs.hpp"
orbis::SysResult orbis::sys_shm_open(Thread *thread, ptr<const char> path,
sint flags, mode_t mode) {
@ -10,9 +9,19 @@ orbis::SysResult orbis::sys_shm_open(Thread *thread, ptr<const char> path,
return result;
}
ORBIS_LOG_TODO(__FUNCTION__, _name, flags, mode);
return {};
if (auto shm_open = thread->tproc->ops->shm_open) {
Ref<File> file;
auto result = shm_open(thread, path, flags, mode, &file);
if (result.isError()) {
return result;
}
thread->retval[0] = thread->tproc->fileDescriptors.insert(file);
return {};
}
return ErrorCode::NOSYS;
}
orbis::SysResult orbis::sys_shm_unlink(Thread *thread, ptr<const char> path) {
char _name[256];
if (auto result = ureadString(_name, sizeof(_name), path);
@ -20,6 +29,16 @@ orbis::SysResult orbis::sys_shm_unlink(Thread *thread, ptr<const char> path) {
return result;
}
ORBIS_LOG_TODO(__FUNCTION__, _name);
return {};
if (auto shm_unlink = thread->tproc->ops->shm_unlink) {
Ref<File> file;
auto result = shm_unlink(thread, path);
if (result.isError()) {
return result;
}
thread->retval[0] = thread->tproc->fileDescriptors.insert(file);
return {};
}
return ErrorCode::NOSYS;
}

View file

@ -15,6 +15,7 @@ add_executable(rpcsx-os
iodev/hmd_snsr.cpp
iodev/null.cpp
iodev/rng.cpp
iodev/shm.cpp
iodev/zero.cpp
main.cpp

View file

@ -4,10 +4,12 @@
#include "orbis/stat.hpp"
#include "orbis/uio.hpp"
#include "orbis/utils/Logs.hpp"
#include "vm.hpp"
#include <cerrno>
#include <fcntl.h>
#include <span>
#include <string>
#include <sys/mman.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/uio.h>
@ -18,6 +20,8 @@ struct HostFile : orbis::File {
int hostFd = -1;
~HostFile() {
std::printf("Destroying host file\n");
if (hostFd > 0) {
::close(hostFd);
}
@ -40,7 +44,8 @@ struct HostFsDevice : IoDevice {
explicit HostFsDevice(orbis::kstring path) : hostPath(std::move(path)) {}
orbis::ErrorCode open(orbis::Ref<orbis::File> *file, const char *path,
std::uint32_t flags, std::uint32_t mode) override;
std::uint32_t flags, std::uint32_t mode,
orbis::Thread *thread) override;
};
static orbis::ErrorCode convertErrno() {
@ -137,6 +142,32 @@ static orbis::ErrorCode host_write(orbis::File *file, orbis::Uio *uio,
return {};
}
static orbis::ErrorCode host_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 hostFile = static_cast<HostFile *>(file);
auto result =
rx::vm::map(*address, size, prot, flags, rx::vm::kMapInternalReserveOnly);
if (result == (void *)-1) {
return orbis::ErrorCode::NOMEM;
}
result = ::mmap(result, size, prot & rx::vm::kMapProtCpuAll,
MAP_SHARED | MAP_FIXED, hostFile->hostFd, offset);
if (result == (void *)-1) {
auto result = convertErrno();
return result;
}
std::printf("shm mapped at %p-%p\n", result, (char *)result + size);
*address = result;
return {};
}
static orbis::ErrorCode host_stat(orbis::File *file, orbis::Stat *sb,
orbis::Thread *thread) {
auto hostFile = static_cast<HostFile *>(file);
@ -198,6 +229,7 @@ static const orbis::FileOps hostOps = {
.write = host_write,
.truncate = host_truncate,
.stat = host_stat,
.mmap = host_mmap,
};
static const orbis::FileOps socketOps = {
@ -226,7 +258,7 @@ orbis::ErrorCode createSocket(orbis::Ref<orbis::File> *file,
orbis::ErrorCode HostFsDevice::open(orbis::Ref<orbis::File> *file,
const char *path, std::uint32_t flags,
std::uint32_t mode) {
std::uint32_t mode, orbis::Thread *thread) {
auto realPath = hostPath + "/" + path;
int realFlags = flags & O_ACCMODE;
@ -304,7 +336,8 @@ struct FdWrapDevice : public IoDevice {
int fd;
orbis::ErrorCode open(orbis::Ref<orbis::File> *file, const char *path,
std::uint32_t flags, std::uint32_t mode) override {
std::uint32_t flags, std::uint32_t mode,
orbis::Thread *thread) override {
*file = createHostFile(fd, this);
return {};
}

View file

@ -25,7 +25,11 @@ enum OpenFlags {
struct IoDevice : orbis::RcBase {
virtual orbis::ErrorCode open(orbis::Ref<orbis::File> *file, const char *path,
std::uint32_t flags, std::uint32_t mode) = 0;
std::uint32_t flags, std::uint32_t mode,
orbis::Thread *thread) = 0;
virtual orbis::ErrorCode unlink(const char *path, orbis::Thread *thread) {
return orbis::ErrorCode::NOTSUP;
}
};
IoDevice *createHostIoDevice(orbis::kstring hostPath);

View file

@ -15,3 +15,4 @@ IoDevice *createNullCharacterDevice();
IoDevice *createZeroCharacterDevice();
IoDevice *createRngCharacterDevice();
IoDevice *createAjmCharacterDevice();
IoDevice *createShmDevice();

View file

@ -18,7 +18,8 @@ static const orbis::FileOps fileOps = {
struct AjmDevice : IoDevice {
orbis::ErrorCode open(orbis::Ref<orbis::File> *file, const char *path,
std::uint32_t flags, std::uint32_t mode) override {
std::uint32_t flags, std::uint32_t mode,
orbis::Thread *thread) override {
auto newFile = orbis::knew<AjmFile>();
newFile->ops = &fileOps;
newFile->device = this;

View file

@ -88,7 +88,8 @@ struct DceDevice : IoDevice {
orbis::shared_mutex mtx;
VideoOutBuffer bufferAttributes{}; // TODO
orbis::ErrorCode open(orbis::Ref<orbis::File> *file, const char *path,
std::uint32_t flags, std::uint32_t mode) override;
std::uint32_t flags, std::uint32_t mode,
orbis::Thread *thread) override;
};
static orbis::ErrorCode dce_ioctl(orbis::File *file, std::uint64_t request,
@ -262,7 +263,7 @@ static const orbis::FileOps ops = {
orbis::ErrorCode DceDevice::open(orbis::Ref<orbis::File> *file,
const char *path, std::uint32_t flags,
std::uint32_t mode) {
std::uint32_t mode, orbis::Thread *thread) {
auto newFile = orbis::knew<DceFile>();
newFile->device = this;
newFile->ops = &ops;

View file

@ -48,7 +48,8 @@ static const orbis::FileOps ops = {
struct DipswDevice : public IoDevice {
orbis::ErrorCode open(orbis::Ref<orbis::File> *file, const char *path,
std::uint32_t flags, std::uint32_t mode) override {
std::uint32_t flags, std::uint32_t mode,
orbis::Thread *thread) override {
auto newFile = orbis::knew<DipswFile>();
newFile->device = this;
newFile->ops = &ops;

View file

@ -13,7 +13,8 @@ struct DmemDevice : public IoDevice {
std::uint64_t memBeginAddress;
orbis::ErrorCode open(orbis::Ref<orbis::File> *file, const char *path,
std::uint32_t flags, std::uint32_t mode) override;
std::uint32_t flags, std::uint32_t mode,
orbis::Thread *thread) override;
};
struct DmemFile : public orbis::File {};
@ -111,7 +112,7 @@ static const orbis::FileOps ops = {
orbis::ErrorCode DmemDevice::open(orbis::Ref<orbis::File> *file,
const char *path, std::uint32_t flags,
std::uint32_t mode) {
std::uint32_t mode, orbis::Thread *thread) {
auto newFile = orbis::knew<DmemFile>();
newFile->device = this;
newFile->ops = &ops;

View file

@ -9,7 +9,8 @@
struct GcDevice : public IoDevice {
orbis::ErrorCode open(orbis::Ref<orbis::File> *file, const char *path,
std::uint32_t flags, std::uint32_t mode) override;
std::uint32_t flags, std::uint32_t mode,
orbis::Thread *thread) override;
};
struct GcFile : public orbis::File {};
static std::uint64_t g_submitDoneFlag;
@ -256,7 +257,8 @@ static const orbis::FileOps ops = {
};
orbis::ErrorCode GcDevice::open(orbis::Ref<orbis::File> *file, const char *path,
std::uint32_t flags, std::uint32_t mode) {
std::uint32_t flags, std::uint32_t mode,
orbis::Thread *thread) {
auto newFile = orbis::knew<GcFile>();
newFile->device = this;
newFile->ops = &ops;

View file

@ -5,7 +5,8 @@
struct HidDevice : public IoDevice {
orbis::ErrorCode open(orbis::Ref<orbis::File> *file, const char *path,
std::uint32_t flags, std::uint32_t mode) override;
std::uint32_t flags, std::uint32_t mode,
orbis::Thread *thread) override;
};
struct HidFile : public orbis::File {};
@ -23,7 +24,7 @@ static const orbis::FileOps ops = {
orbis::ErrorCode HidDevice::open(orbis::Ref<orbis::File> *file,
const char *path, std::uint32_t flags,
std::uint32_t mode) {
std::uint32_t mode, orbis::Thread *thread) {
auto newFile = orbis::knew<HidFile>();
newFile->device = this;
newFile->ops = &ops;

View file

@ -5,7 +5,8 @@
struct Hmd3daDevice : public IoDevice {
orbis::ErrorCode open(orbis::Ref<orbis::File> *file, const char *path,
std::uint32_t flags, std::uint32_t mode) override;
std::uint32_t flags, std::uint32_t mode,
orbis::Thread *thread) override;
};
struct Hmd3daFile : public orbis::File {};
@ -23,7 +24,7 @@ static const orbis::FileOps ops = {
orbis::ErrorCode Hmd3daDevice::open(orbis::Ref<orbis::File> *file,
const char *path, std::uint32_t flags,
std::uint32_t mode) {
std::uint32_t mode, orbis::Thread *thread) {
auto newFile = orbis::knew<Hmd3daFile>();
newFile->device = this;
newFile->ops = &ops;

View file

@ -4,7 +4,8 @@
struct HmdCmdDevice : public IoDevice {
orbis::ErrorCode open(orbis::Ref<orbis::File> *file, const char *path,
std::uint32_t flags, std::uint32_t mode) override;
std::uint32_t flags, std::uint32_t mode,
orbis::Thread *thread) override;
};
struct HmdCmdFile : public orbis::File {};
@ -22,7 +23,7 @@ static const orbis::FileOps ops = {
orbis::ErrorCode HmdCmdDevice::open(orbis::Ref<orbis::File> *file,
const char *path, std::uint32_t flags,
std::uint32_t mode) {
std::uint32_t mode, orbis::Thread *thread) {
auto newFile = orbis::knew<HmdCmdFile>();
newFile->device = this;
newFile->ops = &ops;

View file

@ -5,7 +5,8 @@
struct HmdMmapDevice : public IoDevice {
orbis::ErrorCode open(orbis::Ref<orbis::File> *file, const char *path,
std::uint32_t flags, std::uint32_t mode) override;
std::uint32_t flags, std::uint32_t mode,
orbis::Thread *thread) override;
};
struct HmdMmapFile : public orbis::File {};
@ -39,7 +40,8 @@ static const orbis::FileOps ops = {
orbis::ErrorCode HmdMmapDevice::open(orbis::Ref<orbis::File> *file,
const char *path, std::uint32_t flags,
std::uint32_t mode) {
std::uint32_t mode,
orbis::Thread *thread) {
auto newFile = orbis::knew<HmdMmapFile>();
newFile->device = this;
newFile->ops = &ops;

View file

@ -5,7 +5,8 @@
struct HmdSnsrDevice : public IoDevice {
orbis::ErrorCode open(orbis::Ref<orbis::File> *file, const char *path,
std::uint32_t flags, std::uint32_t mode) override;
std::uint32_t flags, std::uint32_t mode,
orbis::Thread *thread) override;
};
struct HmdSnsrFile : public orbis::File {};
@ -23,7 +24,8 @@ static const orbis::FileOps ops = {
orbis::ErrorCode HmdSnsrDevice::open(orbis::Ref<orbis::File> *file,
const char *path, std::uint32_t flags,
std::uint32_t mode) {
std::uint32_t mode,
orbis::Thread *thread) {
auto newFile = orbis::knew<HmdSnsrFile>();
newFile->device = this;
newFile->ops = &ops;

View file

@ -4,7 +4,8 @@
struct NullDevice : public IoDevice {
orbis::ErrorCode open(orbis::Ref<orbis::File> *file, const char *path,
std::uint32_t flags, std::uint32_t mode) override;
std::uint32_t flags, std::uint32_t mode,
orbis::Thread *thread) override;
};
struct NullFile : public orbis::File {};
@ -20,7 +21,7 @@ static const orbis::FileOps ops = {
orbis::ErrorCode NullDevice::open(orbis::Ref<orbis::File> *file,
const char *path, std::uint32_t flags,
std::uint32_t mode) {
std::uint32_t mode, orbis::Thread *thread) {
auto newFile = orbis::knew<NullFile>();
newFile->device = this;
newFile->ops = &ops;

View file

@ -5,7 +5,8 @@
struct RngDevice : public IoDevice {
orbis::ErrorCode open(orbis::Ref<orbis::File> *file, const char *path,
std::uint32_t flags, std::uint32_t mode) override;
std::uint32_t flags, std::uint32_t mode,
orbis::Thread *thread) override;
};
struct RngFile : public orbis::File {};
@ -39,7 +40,7 @@ static const orbis::FileOps ops = {
orbis::ErrorCode RngDevice::open(orbis::Ref<orbis::File> *file,
const char *path, std::uint32_t flags,
std::uint32_t mode) {
std::uint32_t mode, orbis::Thread *thread) {
auto newFile = orbis::knew<RngFile>();
newFile->device = this;
newFile->ops = &ops;

52
rpcsx-os/iodev/shm.cpp Normal file
View file

@ -0,0 +1,52 @@
#include "io-device.hpp"
#include "orbis/KernelAllocator.hpp"
#include "orbis/error/ErrorCode.hpp"
#include "orbis/file.hpp"
#include "orbis/utils/Logs.hpp"
#include <fcntl.h>
#include <sys/mman.h>
struct ShmDevice : IoDevice {
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 ShmDevice::open(orbis::Ref<orbis::File> *file,
const char *path, std::uint32_t flags,
std::uint32_t mode, orbis::Thread *thread) {
ORBIS_LOG_WARNING("shm_open", path, flags, mode);
std::string name = "/rpcsx-";
if (std::string_view{path}.starts_with("/")) {
name += path + 1;
} else {
name += path;
}
auto realFlags = O_RDWR; // TODO
std::size_t size = 0;
if (name == "/rpcsx-SceShellCoreUtil") {
// TODO
realFlags |= O_CREAT;
size = 0x4000;
}
realFlags |= O_CREAT; // TODO
int fd = shm_open(name.c_str(), realFlags, S_IRUSR | S_IWUSR);
if (fd < 0) {
std::printf("shm_open: error %u\n", errno);
return orbis::ErrorCode::ACCES;
}
auto hostFile = createHostFile(fd, this);
if (size != 0) {
hostFile->ops->truncate(hostFile, size, thread);
}
*file = hostFile;
return {};
}
IoDevice *createShmDevice() { return orbis::knew<ShmDevice>(); }

View file

@ -6,7 +6,8 @@
struct ZeroDevice : public IoDevice {
orbis::ErrorCode open(orbis::Ref<orbis::File> *file, const char *path,
std::uint32_t flags, std::uint32_t mode) override;
std::uint32_t flags, std::uint32_t mode,
orbis::Thread *thread) override;
};
struct ZeroFile : public orbis::File {};
@ -26,7 +27,7 @@ static const orbis::FileOps ops = {
orbis::ErrorCode ZeroDevice::open(orbis::Ref<orbis::File> *file,
const char *path, std::uint32_t flags,
std::uint32_t mode) {
std::uint32_t mode, orbis::Thread *thread) {
auto newFile = orbis::knew<ZeroFile>();
newFile->device = this;
newFile->ops = &ops;

View file

@ -846,7 +846,7 @@ Ref<orbis::Module> rx::linker::loadModuleFile(std::string_view path,
}
orbis::Ref<orbis::File> instance;
if (vfs::open(path, kOpenFlagReadOnly, 0, &instance).isError()) {
if (vfs::open(path, kOpenFlagReadOnly, 0, &instance, thread).isError()) {
return {};
}

View file

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

View file

@ -3,6 +3,7 @@
#include "backtrace.hpp"
#include "io-device.hpp"
#include "linker.hpp"
#include "orbis/KernelContext.hpp"
#include "orbis/module/ModuleHandle.hpp"
#include "orbis/thread/Process.hpp"
#include "orbis/thread/Thread.hpp"
@ -15,7 +16,6 @@
#include <chrono>
#include <csignal>
#include <cstdio>
#include <filesystem>
#include <map>
#include <optional>
#include <set>
@ -232,7 +232,14 @@ orbis::SysResult virtual_query(orbis::Thread *thread,
orbis::SysResult open(orbis::Thread *thread, orbis::ptr<const char> path,
orbis::sint flags, orbis::sint mode,
orbis::Ref<orbis::File> *file) {
return rx::vfs::open(path, flags, mode, file);
return rx::vfs::open(path, flags, mode, file, thread);
}
orbis::SysResult shm_open(orbis::Thread *thread, const char *path,
orbis::sint flags, orbis::sint mode,
orbis::Ref<orbis::File> *file) {
auto dev = static_cast<IoDevice *>(orbis::g_context.shmDevice.get());
return dev->open(file, path, flags, mode, thread);
}
orbis::SysResult socket(orbis::Thread *thread, orbis::ptr<const char> name,
@ -241,6 +248,11 @@ orbis::SysResult socket(orbis::Thread *thread, orbis::ptr<const char> name,
return createSocket(file, name, domain, type, protocol);
}
orbis::SysResult shm_unlink(orbis::Thread *thread, const char *path) {
auto dev = static_cast<IoDevice *>(orbis::g_context.shmDevice.get());
return dev->unlink(path, thread);
}
orbis::SysResult dynlib_get_obj_member(orbis::Thread *thread,
orbis::ModuleHandle handle,
orbis::uint64_t index,
@ -531,7 +543,9 @@ ProcessOps rx::procOpsTable = {
.munlock = munlock,
.virtual_query = virtual_query,
.open = open,
.shm_open = shm_open,
.socket = socket,
.shm_unlink = shm_unlink,
.dynlib_get_obj_member = dynlib_get_obj_member,
.dynlib_dlsym = dynlib_dlsym,
.dynlib_do_copy_relocations = dynlib_do_copy_relocations,

View file

@ -26,7 +26,8 @@ orbis::SysResult rx::vfs::mount(const std::filesystem::path &guestPath,
}
orbis::SysResult rx::vfs::open(std::string_view path, int flags, int mode,
orbis::Ref<orbis::File> *file) {
orbis::Ref<orbis::File> *file,
orbis::Thread *thread) {
orbis::Ref<IoDevice> device;
bool isCharacterDevice = path.starts_with("/dev/");
@ -51,7 +52,7 @@ orbis::SysResult rx::vfs::open(std::string_view path, int flags, int mode,
if (device != nullptr) {
return (orbis::ErrorCode)device->open(file, std::string(path).c_str(),
flags, mode);
flags, mode, thread);
}
if (isCharacterDevice) {

View file

@ -12,5 +12,5 @@ void initialize();
void deinitialize();
orbis::SysResult mount(const std::filesystem::path &guestPath, IoDevice *dev);
orbis::SysResult open(std::string_view path, int flags, int mode,
orbis::Ref<orbis::File> *file);
orbis::Ref<orbis::File> *file, orbis::Thread *thread);
} // namespace rx::vfs