merge rpcsx-gpu and rpcsx-os

initial watchdog implementation
implement gpu -> os events
implement main gfx queue
This commit is contained in:
DH 2024-10-12 05:24:58 +03:00
parent 8e9711e0f6
commit 0c16e294d4
236 changed files with 4649 additions and 4669 deletions

View file

@ -9,6 +9,8 @@
#include <unistd.h>
static const std::uint64_t g_allocProtWord = 0xDEADBEAFBADCAFE1;
static constexpr auto kHeapBaseAddress = 0x600'0000'0000;
static constexpr auto kHeapSize = 0x2'0000'0000;
namespace orbis {
thread_local Thread *g_currentThread;
@ -16,7 +18,7 @@ thread_local Thread *g_currentThread;
KernelContext &g_context = *[]() -> KernelContext * {
// Allocate global shared kernel memory
// TODO: randomize for hardening and reduce size
auto ptr = mmap(reinterpret_cast<void *>(0x200'0000'0000), 0x2'0000'0000,
auto ptr = mmap(reinterpret_cast<void *>(kHeapBaseAddress), kHeapSize,
PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
if (ptr == MAP_FAILED)
@ -166,15 +168,32 @@ void *KernelContext::kalloc(std::size_t size, std::size_t align) {
align = std::max<std::size_t>(align, __STDCPP_DEFAULT_NEW_ALIGNMENT__);
auto heap = reinterpret_cast<std::uintptr_t>(m_heap_next);
heap = (heap + (align - 1)) & ~(align - 1);
if (heap + size > kHeapBaseAddress + kHeapSize) {
std::fprintf(stderr, "out of kernel memory");
std::abort();
}
// Check overflow
if (heap + size < heap) {
std::fprintf(stderr, "too big allocation");
std::abort();
}
auto result = reinterpret_cast<void *>(heap);
std::memcpy(std::bit_cast<std::byte *>(result) + size, &g_allocProtWord,
sizeof(g_allocProtWord));
m_heap_next = reinterpret_cast<void *>(heap + size + sizeof(g_allocProtWord));
// Check overflow
if (heap + size < heap)
std::abort();
if (heap + size > (uintptr_t)&g_context + 0x1'0000'0000)
std::abort();
if (true) {
heap = reinterpret_cast<std::uintptr_t>(m_heap_next);
align = std::min<std::size_t>(align, 4096);
heap = (heap + (align - 1)) & ~(align - 1);
size = 4096;
::mmap(reinterpret_cast<void *>(heap), size, PROT_NONE, MAP_FIXED, -1, 0);
m_heap_next = reinterpret_cast<void *>(heap + size);
}
return result;
}

View file

@ -1,7 +1,13 @@
#include "event.hpp"
#include "thread/Process.hpp"
#include <algorithm>
orbis::KNote::~KNote() {
while (!emitters.empty()) {
emitters.back()->unsubscribe(this);
}
if (linked == nullptr) {
return;
}
@ -14,7 +20,7 @@ orbis::KNote::~KNote() {
}
}
void orbis::EventEmitter::emit(uint filter, uint fflags, intptr_t data) {
void orbis::EventEmitter::emit(sshort filter, uint fflags, intptr_t data) {
std::lock_guard lock(mutex);
for (auto note : notes) {
@ -40,3 +46,28 @@ void orbis::EventEmitter::emit(uint filter, uint fflags, intptr_t data) {
note->queue->cv.notify_all(note->queue->mtx);
}
}
void orbis::EventEmitter::subscribe(KNote *note) {
std::lock_guard lock(mutex);
notes.insert(note);
note->emitters.emplace_back(this);
}
void orbis::EventEmitter::unsubscribe(KNote *note) {
std::lock_guard lock(mutex);
notes.erase(note);
auto it = std::ranges::find(note->emitters, this);
if (it == note->emitters.end()) {
return;
}
std::size_t index = it - note->emitters.begin();
auto lastEmitter = note->emitters.size() - 1;
if (index != lastEmitter) {
std::swap(note->emitters[index], note->emitters[lastEmitter]);
}
note->emitters.pop_back();
}

View file

@ -223,6 +223,10 @@ orbis::SysResult orbis::sysIpmiServerReceivePacket(Thread *thread,
ptr<uint> unk;
};
if (paramsSz != sizeof(IpmiServerReceivePacketParams)) {
return orbis::ErrorCode::INVAL;
}
IpmiServerReceivePacketParams _params;
ORBIS_RET_ON_ERROR(
@ -265,9 +269,6 @@ orbis::SysResult orbis::sysIpmiServerReceivePacket(Thread *thread,
auto asyncMessage = (IpmiAsyncMessageHeader *)_packet.message.data();
ORBIS_LOG_ERROR(__FUNCTION__, server->name, asyncMessage->methodId,
asyncMessage->numInData, asyncMessage->pid);
ORBIS_LOG_ERROR(__FUNCTION__, server->name,
*(std::uint64_t *)(*(long *)server->eventHandler + 0x18));
}
if (_params.bufferSize < _packet.message.size()) {
@ -380,11 +381,13 @@ orbis::SysResult orbis::sysIpmiSessionRespondSync(Thread *thread,
clientTid = session->server->tidToClientTid.at(thread->tid);
}
ORBIS_LOG_ERROR(__FUNCTION__, session->client->name, _params.errorCode);
if (_params.errorCode != 0) {
ORBIS_LOG_ERROR(__FUNCTION__, session->client->name, _params.errorCode);
thread->where();
// HACK: completely broken audio audio support should not be visible
// HACK: completely broken audio support should not be visible
if (session->client->name == "SceSysAudioSystemIpc" &&
_params.errorCode == -1) {
_params.errorCode = 0;
@ -1268,6 +1271,10 @@ orbis::SysResult orbis::sysIpmiClientWaitEventFlag(Thread *thread,
static_assert(sizeof(IpmiWaitEventFlagParam) == 0x28);
if (paramsSz != sizeof(IpmiWaitEventFlagParam)) {
return ErrorCode::INVAL;
}
IpmiWaitEventFlagParam _params;
ORBIS_RET_ON_ERROR(uread(_params, ptr<IpmiWaitEventFlagParam>(params)));

View file

@ -113,17 +113,15 @@ static SysResult keventChange(KQueue *kq, KEvent &change, Thread *thread) {
nodeIt->file = fd;
if (auto eventEmitter = fd->event) {
std::unique_lock lock(eventEmitter->mutex);
// if (change.filter == kEvFiltWrite) {
// nodeIt->triggered = true;
// kq->cv.notify_all(kq->mtx);
// }
eventEmitter->subscribe(&*nodeIt);
nodeIt->triggered = true;
eventEmitter->notes.insert(&*nodeIt);
kq->cv.notify_all(kq->mtx);
} else if (note.file->hostFd < 0) {
ORBIS_LOG_ERROR("Unimplemented event emitter", change.ident);
}
} else if (change.filter == kEvFiltGraphicsCore ||
change.filter == kEvFiltDisplay) {
g_context.deviceEventEmitter->subscribe(&*nodeIt);
}
}
}
@ -172,19 +170,14 @@ static SysResult keventChange(KQueue *kq, KEvent &change, Thread *thread) {
nodeIt->triggered = true;
kq->cv.notify_all(kq->mtx);
}
} else if (change.filter == kEvFiltGraphicsCore) {
} else if (change.filter == kEvFiltDisplay && change.ident >> 48 == 0x6301) {
nodeIt->triggered = true;
if (change.ident == 0x84) {
// clock change event
nodeIt->event.data |= 1000ull << 16; // clock
}
kq->cv.notify_all(kq->mtx);
} else if (change.filter == kEvFiltDisplay) {
if (change.ident != 0x51000100000000 && change.ident != 0x63010100000000) {
nodeIt->triggered = true;
kq->cv.notify_all(kq->mtx);
}
} else if (change.filter == kEvFiltGraphicsCore && change.ident == 0x84) {
nodeIt->triggered = true;
nodeIt->event.data |= 1000ull << 16; // clock
kq->cv.notify_all(kq->mtx);
}
return {};

View file

@ -307,8 +307,8 @@ SysResult kern_sysctl(Thread *thread, ptr<sint> name, uint namelen,
case sysctl_ctl::unspec: {
switch (name[1]) {
case 3: {
std::fprintf(stderr, " unspec - get name of '%s'\n",
std::string((char *)new_, newlen).c_str());
// std::fprintf(stderr, " unspec - get name of '%s'\n",
// std::string((char *)new_, newlen).c_str());
auto searchName = std::string_view((char *)new_, newlen);
auto *dest = (std::uint32_t *)old;
std::uint32_t count = 0;

View file

@ -305,7 +305,7 @@ orbis::ErrorCode orbis::umtx_cv_wait(Thread *thread, ptr<ucond> cv,
ORBIS_LOG_FATAL("umtx_cv_wait: UNKNOWN wflags", wflags);
return ErrorCode::INVAL;
}
if ((wflags & kCvWaitClockId) != 0 && ut + 1) {
if ((wflags & kCvWaitClockId) != 0 && ut + 1 && cv->clockid != 0) {
ORBIS_LOG_WARNING("umtx_cv_wait: CLOCK_ID", wflags, cv->clockid);
// std::abort();
return ErrorCode::NOSYS;