Skip to content

Commit

Permalink
move gpu connection to dce
Browse files Browse the repository at this point in the history
  • Loading branch information
DHrpcs3 committed Sep 1, 2024
1 parent e0729f1 commit d4840e9
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 92 deletions.
88 changes: 88 additions & 0 deletions rpcsx-os/iodev/dce.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,15 +125,95 @@ struct ResolutionStatus {
// refreshRate = 0x23, result.refreshHz = 0x42b3d1ec( 89.91) REFRESH_RATE_89_91HZ
// clang-format on

static void runBridge(int vmId) {
std::thread{[=] {
pthread_setname_np(pthread_self(), "Bridge");
auto bridge = rx::bridge.header;

std::vector<std::uint64_t> fetchedCommands;
fetchedCommands.reserve(std::size(bridge->cacheCommands));

while (true) {
for (auto &command : bridge->cacheCommands) {
std::uint64_t value = command[vmId].load(std::memory_order::relaxed);

if (value != 0) {
fetchedCommands.push_back(value);
command[vmId].store(0, std::memory_order::relaxed);
}
}

if (fetchedCommands.empty()) {
continue;
}

for (auto command : fetchedCommands) {
auto page = static_cast<std::uint32_t>(command);
auto count = static_cast<std::uint32_t>(command >> 32) + 1;

auto pageFlags =
bridge->cachePages[vmId][page].load(std::memory_order::relaxed);

auto address =
static_cast<std::uint64_t>(page) * amdgpu::bridge::kHostPageSize;
auto origVmProt = rx::vm::getPageProtection(address);
int prot = 0;

if (origVmProt & rx::vm::kMapProtCpuRead) {
prot |= PROT_READ;
}
if (origVmProt & rx::vm::kMapProtCpuWrite) {
prot |= PROT_WRITE;
}
if (origVmProt & rx::vm::kMapProtCpuExec) {
prot |= PROT_EXEC;
}

if (pageFlags & amdgpu::bridge::kPageReadWriteLock) {
prot &= ~(PROT_READ | PROT_WRITE);
} else if (pageFlags & amdgpu::bridge::kPageWriteWatch) {
prot &= ~PROT_WRITE;
}

// std::fprintf(stderr, "protection %lx-%lx\n", address,
// address + amdgpu::bridge::kHostPageSize * count);
if (::mprotect(reinterpret_cast<void *>(address),
amdgpu::bridge::kHostPageSize * count, prot)) {
perror("protection failed");
std::abort();
}
}

fetchedCommands.clear();
}
}}.detach();
}

static constexpr auto kVmIdCount = 6;
struct DceFile : public orbis::File {};

struct DceDevice : IoDevice {
orbis::shared_mutex mtx;
std::uint32_t freeVmIds = (1 << (kVmIdCount + 1)) - 1;
orbis::uint64_t dmemOffset = ~static_cast<std::uint64_t>(0);
VideoOutBuffer bufferAttributes{}; // TODO
orbis::ErrorCode open(orbis::Ref<orbis::File> *file, const char *path,
std::uint32_t flags, std::uint32_t mode,
orbis::Thread *thread) override;

int allocateVmId() {
int id = std::countr_zero(freeVmIds);

if (id >= kVmIdCount) {
std::fprintf(stderr, "out of vm slots\n");
std::abort();
}

freeVmIds &= ~(1 << id);
return id;
};

void deallocateVmId(int vmId) { freeVmIds |= (1 << vmId); };
};

static void initDceMemory(DceDevice *device) {
Expand Down Expand Up @@ -375,6 +455,14 @@ orbis::ErrorCode DceDevice::open(orbis::Ref<orbis::File> *file,
newFile->device = this;
newFile->ops = &ops;
*file = newFile;

if (thread->tproc->vmId == -1) {
auto vmId = allocateVmId();
rx::bridge.sendMapProcess(thread->tproc->pid, vmId);
thread->tproc->vmId = vmId;

runBridge(vmId);
}
return {};
}

Expand Down
92 changes: 0 additions & 92 deletions rpcsx-os/iodev/gc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,74 +20,7 @@ struct ComputeQueue {
std::uint64_t len{};
};

static void runBridge(int vmId) {
std::thread{[=] {
pthread_setname_np(pthread_self(), "Bridge");
auto bridge = rx::bridge.header;

std::vector<std::uint64_t> fetchedCommands;
fetchedCommands.reserve(std::size(bridge->cacheCommands));

while (true) {
for (auto &command : bridge->cacheCommands) {
std::uint64_t value = command[vmId].load(std::memory_order::relaxed);

if (value != 0) {
fetchedCommands.push_back(value);
command[vmId].store(0, std::memory_order::relaxed);
}
}

if (fetchedCommands.empty()) {
continue;
}

for (auto command : fetchedCommands) {
auto page = static_cast<std::uint32_t>(command);
auto count = static_cast<std::uint32_t>(command >> 32) + 1;

auto pageFlags =
bridge->cachePages[vmId][page].load(std::memory_order::relaxed);

auto address =
static_cast<std::uint64_t>(page) * amdgpu::bridge::kHostPageSize;
auto origVmProt = rx::vm::getPageProtection(address);
int prot = 0;

if (origVmProt & rx::vm::kMapProtCpuRead) {
prot |= PROT_READ;
}
if (origVmProt & rx::vm::kMapProtCpuWrite) {
prot |= PROT_WRITE;
}
if (origVmProt & rx::vm::kMapProtCpuExec) {
prot |= PROT_EXEC;
}

if (pageFlags & amdgpu::bridge::kPageReadWriteLock) {
prot &= ~(PROT_READ | PROT_WRITE);
} else if (pageFlags & amdgpu::bridge::kPageWriteWatch) {
prot &= ~PROT_WRITE;
}

// std::fprintf(stderr, "protection %lx-%lx\n", address,
// address + amdgpu::bridge::kHostPageSize * count);
if (::mprotect(reinterpret_cast<void *>(address),
amdgpu::bridge::kHostPageSize * count, prot)) {
perror("protection failed");
std::abort();
}
}

fetchedCommands.clear();
}
}}.detach();
}

static constexpr auto kVmIdCount = 6;

struct GcDevice : public IoDevice {
std::uint32_t freeVmIds = (1 << (kVmIdCount + 1)) - 1;
orbis::shared_mutex mtx;
orbis::kmap<orbis::pid_t, int> clients;
orbis::kmap<std::uint64_t, ComputeQueue> computeQueues;
Expand All @@ -97,20 +30,6 @@ struct GcDevice : public IoDevice {

void addClient(orbis::Process *process);
void removeClient(orbis::Process *process);

int allocateVmId() {
int id = std::countr_zero(freeVmIds);

if (id >= kVmIdCount) {
std::fprintf(stderr, "out of vm slots\n");
std::abort();
}

freeVmIds &= ~(1 << id);
return id;
};

void deallocateVmId(int vmId) { freeVmIds |= (1 << vmId); };
};

struct GcFile : public orbis::File {
Expand Down Expand Up @@ -425,14 +344,6 @@ void GcDevice::addClient(orbis::Process *process) {
std::lock_guard lock(mtx);
auto &client = clients[process->pid];
++client;

if (client == 1) {
auto vmId = allocateVmId();
rx::bridge.sendMapProcess(process->pid, vmId);
process->vmId = vmId;

runBridge(vmId);
}
}

void GcDevice::removeClient(orbis::Process *process) {
Expand All @@ -443,9 +354,6 @@ void GcDevice::removeClient(orbis::Process *process) {
--clientIt->second;
if (clientIt->second == 0) {
clients.erase(clientIt);
rx::bridge.sendUnmapProcess(process->pid);
deallocateVmId(process->vmId);
process->vmId = -1;
}
}

Expand Down

0 comments on commit d4840e9

Please sign in to comment.