mirror of
https://github.com/RPCSX/rpcsx.git
synced 2025-12-06 07:12:14 +01:00
orbis-kernel: implement debug kalloc
This commit is contained in:
parent
fe5618063d
commit
00b9f016e3
|
|
@ -2,15 +2,18 @@
|
|||
#include "orbis/thread/Process.hpp"
|
||||
#include "orbis/thread/ProcessOps.hpp"
|
||||
#include "orbis/utils/Logs.hpp"
|
||||
#include <bit>
|
||||
#include <chrono>
|
||||
#include <csignal>
|
||||
#include <mutex>
|
||||
#include <sys/mman.h>
|
||||
#include <thread>
|
||||
#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;
|
||||
static constexpr auto kHeapBaseAddress = 0x00000800'0000'0000;
|
||||
static constexpr auto kHeapSize = 0x10'0000'0000;
|
||||
static constexpr int kDebugHeap = 2;
|
||||
|
||||
namespace orbis {
|
||||
thread_local Thread *g_currentThread;
|
||||
|
|
@ -53,7 +56,6 @@ Process *KernelContext::createProcess(pid_t pid) {
|
|||
|
||||
void KernelContext::deleteProcess(Process *proc) {
|
||||
auto procNode = reinterpret_cast<utils::LinkedNode<Process> *>(proc);
|
||||
auto pid = proc->pid;
|
||||
|
||||
{
|
||||
std::lock_guard lock(m_proc_mtx);
|
||||
|
|
@ -154,11 +156,19 @@ void *KernelContext::kalloc(std::size_t size, std::size_t align) {
|
|||
// Try to reuse previously freed block
|
||||
for (auto [it, end] = m_free_heap.equal_range(size); it != end; ++it) {
|
||||
auto result = it->second;
|
||||
if (!(reinterpret_cast<std::uintptr_t>(result) & (align - 1))) {
|
||||
if (!(std::bit_cast<std::uintptr_t>(result) & (align - 1))) {
|
||||
auto node = m_free_heap.extract(it);
|
||||
node.key() = 0;
|
||||
node.mapped() = nullptr;
|
||||
m_used_node.insert(m_used_node.begin(), std::move(node));
|
||||
|
||||
// std::fprintf(stderr, "kalloc: reuse %p-%p, size = %lx\n", result,
|
||||
// (char *)result + size, size);
|
||||
|
||||
if (kDebugHeap > 0) {
|
||||
std::memcpy(std::bit_cast<std::byte *>(result) + size,
|
||||
&g_allocProtWord, sizeof(g_allocProtWord));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
@ -169,6 +179,13 @@ void *KernelContext::kalloc(std::size_t size, std::size_t align) {
|
|||
auto heap = reinterpret_cast<std::uintptr_t>(m_heap_next);
|
||||
heap = (heap + (align - 1)) & ~(align - 1);
|
||||
|
||||
if (kDebugHeap > 1) {
|
||||
if (auto diff = (heap + size + sizeof(g_allocProtWord)) % 4096; diff != 0) {
|
||||
heap += 4096 - diff;
|
||||
heap &= ~(align - 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (heap + size > kHeapBaseAddress + kHeapSize) {
|
||||
std::fprintf(stderr, "out of kernel memory");
|
||||
std::abort();
|
||||
|
|
@ -179,18 +196,36 @@ void *KernelContext::kalloc(std::size_t size, std::size_t align) {
|
|||
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));
|
||||
std::fprintf(stderr, "kalloc: allocate %lx-%lx, size = %lx, align=%lx\n",
|
||||
heap, heap + size, size, align);
|
||||
|
||||
if (true) {
|
||||
auto result = reinterpret_cast<void *>(heap);
|
||||
if (kDebugHeap > 0) {
|
||||
std::memcpy(std::bit_cast<std::byte *>(result) + size, &g_allocProtWord,
|
||||
sizeof(g_allocProtWord));
|
||||
}
|
||||
|
||||
if (kDebugHeap > 0) {
|
||||
m_heap_next =
|
||||
reinterpret_cast<void *>(heap + size + sizeof(g_allocProtWord));
|
||||
} else {
|
||||
m_heap_next = reinterpret_cast<void *>(heap + size);
|
||||
}
|
||||
|
||||
if (kDebugHeap > 1) {
|
||||
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);
|
||||
std::fprintf(stderr, "kalloc: protect %lx-%lx, size = %lx, align=%lx\n",
|
||||
heap, heap + size, size, align);
|
||||
|
||||
auto result = ::mmap(reinterpret_cast<void *>(heap), size, PROT_NONE,
|
||||
MAP_FIXED | MAP_ANONYMOUS | MAP_SHARED, -1, 0);
|
||||
if (result == MAP_FAILED) {
|
||||
std::fprintf(stderr, "failed to protect memory");
|
||||
std::abort();
|
||||
}
|
||||
m_heap_next = reinterpret_cast<void *>(heap + size);
|
||||
}
|
||||
|
||||
|
|
@ -203,14 +238,26 @@ void KernelContext::kfree(void *ptr, std::size_t size) {
|
|||
if (!size)
|
||||
std::abort();
|
||||
|
||||
std::memset(ptr, 0xcc, size);
|
||||
|
||||
if (std::memcmp(std::bit_cast<std::byte *>(ptr) + size, &g_allocProtWord,
|
||||
sizeof(g_allocProtWord)) != 0) {
|
||||
std::fprintf(stderr, "kernel heap corruption\n");
|
||||
if (std::bit_cast<std::uintptr_t>(ptr) < kHeapBaseAddress ||
|
||||
std::bit_cast<std::uintptr_t>(ptr) + size >
|
||||
kHeapBaseAddress + kHeapSize) {
|
||||
std::fprintf(stderr, "kfree: invalid address");
|
||||
std::abort();
|
||||
}
|
||||
|
||||
if (kDebugHeap > 0) {
|
||||
if (std::memcmp(std::bit_cast<std::byte *>(ptr) + size, &g_allocProtWord,
|
||||
sizeof(g_allocProtWord)) != 0) {
|
||||
std::fprintf(stderr, "kernel heap corruption\n");
|
||||
std::abort();
|
||||
}
|
||||
|
||||
std::memset(ptr, 0xcc, size + sizeof(g_allocProtWord));
|
||||
}
|
||||
|
||||
// std::fprintf(stderr, "kfree: release %p-%p, size = %lx\n", ptr,
|
||||
// (char *)ptr + size, size);
|
||||
|
||||
std::lock_guard lock(m_heap_map_mtx);
|
||||
if (!m_used_node.empty()) {
|
||||
auto node = m_used_node.extract(m_used_node.begin());
|
||||
|
|
|
|||
Loading…
Reference in a new issue