mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-07-26 20:15:03 +00:00
core: Implement memory manager for linux
This commit is contained in:
parent
77b7f66ee2
commit
609a995fc4
@ -10,10 +10,6 @@
|
|||||||
|
|
||||||
namespace Audio {
|
namespace Audio {
|
||||||
|
|
||||||
int SDLAudio::AudioInit() {
|
|
||||||
return SDL_InitSubSystem(SDL_INIT_AUDIO);
|
|
||||||
}
|
|
||||||
|
|
||||||
int SDLAudio::AudioOutOpen(int type, u32 samples_num, u32 freq,
|
int SDLAudio::AudioOutOpen(int type, u32 samples_num, u32 freq,
|
||||||
Libraries::AudioOut::OrbisAudioOutParam format) {
|
Libraries::AudioOut::OrbisAudioOutParam format) {
|
||||||
using Libraries::AudioOut::OrbisAudioOutParam;
|
using Libraries::AudioOut::OrbisAudioOutParam;
|
||||||
|
@ -14,7 +14,6 @@ public:
|
|||||||
SDLAudio() = default;
|
SDLAudio() = default;
|
||||||
virtual ~SDLAudio() = default;
|
virtual ~SDLAudio() = default;
|
||||||
|
|
||||||
int AudioInit();
|
|
||||||
int AudioOutOpen(int type, u32 samples_num, u32 freq,
|
int AudioOutOpen(int type, u32 samples_num, u32 freq,
|
||||||
Libraries::AudioOut::OrbisAudioOutParam format);
|
Libraries::AudioOut::OrbisAudioOutParam format);
|
||||||
s32 AudioOutOutput(s32 handle, const void* ptr);
|
s32 AudioOutOutput(s32 handle, const void* ptr);
|
||||||
|
@ -183,9 +183,8 @@ void IOFile::Open(const fs::path& path, FileAccessMode mode, FileType type, File
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!IsOpen()) {
|
if (!IsOpen()) {
|
||||||
const auto ec = std::error_code{errno, std::generic_category()};
|
LOG_ERROR(Common_Filesystem, "Failed to open the file at path={}",
|
||||||
LOG_ERROR(Common_Filesystem, "Failed to open the file at path={}, ec_message={}",
|
PathToUTF8String(file_path));
|
||||||
PathToUTF8String(file_path), ec.message());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#else
|
#else
|
||||||
|
#include <fcntl.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -215,25 +216,96 @@ enum PosixPageProtection {
|
|||||||
|
|
||||||
struct AddressSpace::Impl {
|
struct AddressSpace::Impl {
|
||||||
Impl() {
|
Impl() {
|
||||||
UNREACHABLE();
|
// Allocate virtual address placeholder for our address space.
|
||||||
|
void* hint_address = reinterpret_cast<void*>(SYSTEM_MANAGED_MIN);
|
||||||
|
virtual_size = SystemSize + UserSize;
|
||||||
|
virtual_base = reinterpret_cast<u8*>(
|
||||||
|
mmap(reinterpret_cast<void*>(hint_address), virtual_size, PROT_READ | PROT_WRITE,
|
||||||
|
MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0));
|
||||||
|
if (virtual_base == MAP_FAILED) {
|
||||||
|
LOG_CRITICAL(Kernel_Vmm, "mmap failed: {}", strerror(errno));
|
||||||
|
throw std::bad_alloc{};
|
||||||
|
}
|
||||||
|
madvise(virtual_base, virtual_size, MADV_HUGEPAGE);
|
||||||
|
|
||||||
|
backing_fd = memfd_create("BackingDmem", 0);
|
||||||
|
if (backing_fd < 0) {
|
||||||
|
LOG_CRITICAL(Kernel_Vmm, "memfd_create failed: {}", strerror(errno));
|
||||||
|
throw std::bad_alloc{};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Defined to extend the file with zeros
|
||||||
|
int ret = ftruncate(backing_fd, BackingSize);
|
||||||
|
if (ret != 0) {
|
||||||
|
LOG_CRITICAL(Kernel_Vmm, "ftruncate failed with {}, are you out-of-memory?",
|
||||||
|
strerror(errno));
|
||||||
|
throw std::bad_alloc{};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map backing dmem handle.
|
||||||
|
backing_base = static_cast<u8*>(
|
||||||
|
mmap(nullptr, BackingSize, PROT_READ | PROT_WRITE, MAP_SHARED, backing_fd, 0));
|
||||||
|
if (backing_base == MAP_FAILED) {
|
||||||
|
LOG_CRITICAL(Kernel_Vmm, "mmap failed: {}", strerror(errno));
|
||||||
|
throw std::bad_alloc{};
|
||||||
|
}
|
||||||
|
|
||||||
|
const VAddr start_addr = reinterpret_cast<VAddr>(virtual_base);
|
||||||
|
m_free_regions.insert({start_addr, start_addr + virtual_size});
|
||||||
}
|
}
|
||||||
|
|
||||||
void* Map(VAddr virtual_addr, PAddr phys_addr, size_t size, PosixPageProtection prot) {
|
void* Map(VAddr virtual_addr, PAddr phys_addr, size_t size, PosixPageProtection prot) {
|
||||||
UNREACHABLE();
|
m_free_regions.subtract({virtual_addr, virtual_addr + size});
|
||||||
return nullptr;
|
const int fd = phys_addr != -1 ? backing_fd : -1;
|
||||||
|
const int host_offset = phys_addr != -1 ? phys_addr : 0;
|
||||||
|
const int flag = phys_addr != -1 ? MAP_SHARED : (MAP_ANONYMOUS | MAP_PRIVATE);
|
||||||
|
void* ret = mmap(reinterpret_cast<void*>(virtual_addr), size, prot, MAP_FIXED | flag, fd,
|
||||||
|
host_offset);
|
||||||
|
ASSERT_MSG(ret != MAP_FAILED, "mmap failed: {}", strerror(errno));
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Unmap(VAddr virtual_addr, PAddr phys_addr, size_t size) {
|
void Unmap(VAddr virtual_addr, PAddr phys_addr, size_t size) {
|
||||||
UNREACHABLE();
|
// Check to see if we are adjacent to any regions.
|
||||||
|
auto start_address = virtual_addr;
|
||||||
|
auto end_address = start_address + size;
|
||||||
|
auto it = m_free_regions.find({start_address - 1, end_address + 1});
|
||||||
|
|
||||||
|
// If we are, join with them, ensuring we stay in bounds.
|
||||||
|
if (it != m_free_regions.end()) {
|
||||||
|
start_address = std::min(start_address, it->lower());
|
||||||
|
end_address = std::max(end_address, it->upper());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Free the relevant region.
|
||||||
|
m_free_regions.insert({start_address, end_address});
|
||||||
|
|
||||||
|
// Return the adjusted pointers.
|
||||||
|
void* ret = mmap(reinterpret_cast<void*>(start_address), end_address - start_address,
|
||||||
|
PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
|
||||||
|
ASSERT_MSG(ret != MAP_FAILED, "mmap failed: {}", strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Protect(VAddr virtual_addr, size_t size, bool read, bool write, bool execute) {
|
void Protect(VAddr virtual_addr, size_t size, bool read, bool write, bool execute) {
|
||||||
UNREACHABLE();
|
int flags = PROT_NONE;
|
||||||
|
if (read) {
|
||||||
|
flags |= PROT_READ;
|
||||||
|
}
|
||||||
|
if (write) {
|
||||||
|
flags |= PROT_WRITE;
|
||||||
|
}
|
||||||
|
if (execute) {
|
||||||
|
flags |= PROT_EXEC;
|
||||||
|
}
|
||||||
|
int ret = mprotect(reinterpret_cast<void*>(virtual_addr), size, flags);
|
||||||
|
ASSERT_MSG(ret == 0, "mprotect failed: {}", strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int backing_fd;
|
||||||
u8* backing_base{};
|
u8* backing_base{};
|
||||||
u8* virtual_base{};
|
u8* virtual_base{};
|
||||||
size_t virtual_size{};
|
size_t virtual_size{};
|
||||||
|
boost::icl::interval_set<VAddr> m_free_regions;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -192,9 +192,8 @@ int PS4_SYSV_ABI sceAudioOutGetSystemState() {
|
|||||||
|
|
||||||
int PS4_SYSV_ABI sceAudioOutInit() {
|
int PS4_SYSV_ABI sceAudioOutInit() {
|
||||||
audio = std::make_unique<Audio::SDLAudio>();
|
audio = std::make_unique<Audio::SDLAudio>();
|
||||||
u32 result = audio->AudioInit() == 0 ? ORBIS_OK : ORBIS_AUDIO_OUT_ERROR_NOT_INIT;
|
LOG_INFO(Lib_AudioOut, "called");
|
||||||
LOG_INFO(Lib_AudioOut, "AudioInit returned {}", result);
|
return ORBIS_OK;
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceAudioOutInitIpmiGetSession() {
|
int PS4_SYSV_ABI sceAudioOutInitIpmiGetSession() {
|
||||||
|
@ -393,6 +393,8 @@ void* createMutex(void* addr) {
|
|||||||
if (addr == nullptr || *static_cast<ScePthreadMutex*>(addr) != nullptr) {
|
if (addr == nullptr || *static_cast<ScePthreadMutex*>(addr) != nullptr) {
|
||||||
return addr;
|
return addr;
|
||||||
}
|
}
|
||||||
|
static std::mutex mutex;
|
||||||
|
std::scoped_lock lk{mutex};
|
||||||
auto vaddr = reinterpret_cast<u64>(addr);
|
auto vaddr = reinterpret_cast<u64>(addr);
|
||||||
|
|
||||||
std::string name = fmt::format("mutex{:#x}", vaddr);
|
std::string name = fmt::format("mutex{:#x}", vaddr);
|
||||||
@ -464,7 +466,7 @@ int PS4_SYSV_ABI scePthreadMutexattrInit(ScePthreadMutexattr* attr) {
|
|||||||
|
|
||||||
int result = pthread_mutexattr_init(&(*attr)->pth_mutex_attr);
|
int result = pthread_mutexattr_init(&(*attr)->pth_mutex_attr);
|
||||||
|
|
||||||
result = (result == 0 ? scePthreadMutexattrSettype(attr, 1) : result);
|
result = (result == 0 ? scePthreadMutexattrSettype(attr, 2) : result);
|
||||||
result = (result == 0 ? scePthreadMutexattrSetprotocol(attr, 0) : result);
|
result = (result == 0 ? scePthreadMutexattrSetprotocol(attr, 0) : result);
|
||||||
|
|
||||||
switch (result) {
|
switch (result) {
|
||||||
@ -1165,6 +1167,10 @@ int PS4_SYSV_ABI posix_pthread_create_name_np(ScePthread* thread, const ScePthre
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int PS4_SYSV_ABI scePthreadOnce(int* once_control, void (*init_routine)(void)) {
|
||||||
|
return pthread_once(reinterpret_cast<pthread_once_t*>(once_control), init_routine);
|
||||||
|
}
|
||||||
|
|
||||||
void pthreadSymbolsRegister(Core::Loader::SymbolsResolver* sym) {
|
void pthreadSymbolsRegister(Core::Loader::SymbolsResolver* sym) {
|
||||||
LIB_FUNCTION("4+h9EzwKF4I", "libkernel", 1, "libkernel", 1, 1, scePthreadAttrSetschedpolicy);
|
LIB_FUNCTION("4+h9EzwKF4I", "libkernel", 1, "libkernel", 1, 1, scePthreadAttrSetschedpolicy);
|
||||||
LIB_FUNCTION("-Wreprtu0Qs", "libkernel", 1, "libkernel", 1, 1, scePthreadAttrSetdetachstate);
|
LIB_FUNCTION("-Wreprtu0Qs", "libkernel", 1, "libkernel", 1, 1, scePthreadAttrSetdetachstate);
|
||||||
@ -1191,6 +1197,7 @@ void pthreadSymbolsRegister(Core::Loader::SymbolsResolver* sym) {
|
|||||||
LIB_FUNCTION("6UgtwV+0zb4", "libkernel", 1, "libkernel", 1, 1, scePthreadCreate);
|
LIB_FUNCTION("6UgtwV+0zb4", "libkernel", 1, "libkernel", 1, 1, scePthreadCreate);
|
||||||
LIB_FUNCTION("T72hz6ffq08", "libkernel", 1, "libkernel", 1, 1, scePthreadYield);
|
LIB_FUNCTION("T72hz6ffq08", "libkernel", 1, "libkernel", 1, 1, scePthreadYield);
|
||||||
LIB_FUNCTION("-quPa4SEJUw", "libkernel", 1, "libkernel", 1, 1, scePthreadAttrGetstack);
|
LIB_FUNCTION("-quPa4SEJUw", "libkernel", 1, "libkernel", 1, 1, scePthreadAttrGetstack);
|
||||||
|
LIB_FUNCTION("14bOACANTBo", "libkernel", 1, "libkernel", 1, 1, scePthreadOnce);
|
||||||
|
|
||||||
// mutex calls
|
// mutex calls
|
||||||
LIB_FUNCTION("cmo1RIYva9o", "libkernel", 1, "libkernel", 1, 1, scePthreadMutexInit);
|
LIB_FUNCTION("cmo1RIYva9o", "libkernel", 1, "libkernel", 1, 1, scePthreadMutexInit);
|
||||||
|
@ -27,7 +27,7 @@ struct PthreadMutexattrInternal;
|
|||||||
struct PthreadCondInternal;
|
struct PthreadCondInternal;
|
||||||
struct PthreadCondAttrInternal;
|
struct PthreadCondAttrInternal;
|
||||||
struct PthreadRwInternal;
|
struct PthreadRwInternal;
|
||||||
struct PthreadRwLockAttrInernal;
|
struct PthreadRwLockAttrInternal;
|
||||||
|
|
||||||
using SceKernelSchedParam = ::sched_param;
|
using SceKernelSchedParam = ::sched_param;
|
||||||
using ScePthread = PthreadInternal*;
|
using ScePthread = PthreadInternal*;
|
||||||
@ -37,7 +37,7 @@ using ScePthreadMutexattr = PthreadMutexattrInternal*;
|
|||||||
using ScePthreadCond = PthreadCondInternal*;
|
using ScePthreadCond = PthreadCondInternal*;
|
||||||
using ScePthreadCondattr = PthreadCondAttrInternal*;
|
using ScePthreadCondattr = PthreadCondAttrInternal*;
|
||||||
using OrbisPthreadRwlock = PthreadRwInternal*;
|
using OrbisPthreadRwlock = PthreadRwInternal*;
|
||||||
using OrbisPthreadRwlockattr = PthreadRwLockAttrInernal*;
|
using OrbisPthreadRwlockattr = PthreadRwLockAttrInternal*;
|
||||||
|
|
||||||
using pthreadEntryFunc = PS4_SYSV_ABI void* (*)(void*);
|
using pthreadEntryFunc = PS4_SYSV_ABI void* (*)(void*);
|
||||||
|
|
||||||
@ -86,7 +86,7 @@ struct PthreadCondAttrInternal {
|
|||||||
pthread_condattr_t cond_attr;
|
pthread_condattr_t cond_attr;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PthreadRwLockAttrInernal {
|
struct PthreadRwLockAttrInternal {
|
||||||
u8 reserved[64];
|
u8 reserved[64];
|
||||||
pthread_rwlockattr_t attr_rwlock;
|
pthread_rwlockattr_t attr_rwlock;
|
||||||
int type;
|
int type;
|
||||||
|
@ -121,7 +121,7 @@ int PS4_SYSV_ABI posix_pthread_rwlockattr_gettype_np() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI posix_pthread_rwlockattr_init(OrbisPthreadRwlockattr* attr) {
|
int PS4_SYSV_ABI posix_pthread_rwlockattr_init(OrbisPthreadRwlockattr* attr) {
|
||||||
*attr = new PthreadRwLockAttrInernal{};
|
*attr = new PthreadRwLockAttrInternal{};
|
||||||
int result = pthread_rwlockattr_init(&(*attr)->attr_rwlock);
|
int result = pthread_rwlockattr_init(&(*attr)->attr_rwlock);
|
||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
LOG_ERROR(Kernel_Pthread, "posix_pthread_rwlockattr_init: error = {}", result);
|
LOG_ERROR(Kernel_Pthread, "posix_pthread_rwlockattr_init: error = {}", result);
|
||||||
@ -161,7 +161,7 @@ int PS4_SYSV_ABI scePthreadRwlockattrGettype() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI scePthreadRwlockattrInit(OrbisPthreadRwlockattr* attr) {
|
int PS4_SYSV_ABI scePthreadRwlockattrInit(OrbisPthreadRwlockattr* attr) {
|
||||||
*attr = new PthreadRwLockAttrInernal{};
|
*attr = new PthreadRwLockAttrInternal{};
|
||||||
int result = pthread_rwlockattr_init(&(*attr)->attr_rwlock);
|
int result = pthread_rwlockattr_init(&(*attr)->attr_rwlock);
|
||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
LOG_ERROR(Kernel_Pthread, "scePthreadRwlockattrInit: error = {}", result);
|
LOG_ERROR(Kernel_Pthread, "scePthreadRwlockattrInit: error = {}", result);
|
||||||
|
@ -125,12 +125,12 @@ static void PatchFsAccess(u8* code, const TLSPattern& tls_pattern, Xbyak::CodeGe
|
|||||||
const auto target_reg = Xbyak::Reg64(tls_pattern.target_reg);
|
const auto target_reg = Xbyak::Reg64(tls_pattern.target_reg);
|
||||||
c.putSeg(fs);
|
c.putSeg(fs);
|
||||||
c.mov(target_reg, qword[SelfInTcbheadOffset]); // Load self member pointer of tcbhead_t.
|
c.mov(target_reg, qword[SelfInTcbheadOffset]); // Load self member pointer of tcbhead_t.
|
||||||
c.lea(target_reg,
|
c.add(target_reg, SpecificFirstBlockOffset + sizeof(uintptr_t) + slot * PthreadKeyDataSize);
|
||||||
ptr[SpecificFirstBlockOffset + slot * PthreadKeyDataSize +
|
c.jmp(code + total_size); // Return to the instruction right after the mov.
|
||||||
sizeof(uintptr_t)]); // Load the pointer to our data.
|
|
||||||
c.jmp(code + total_size); // Return to the instruction right after the mov.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
void PatchTLS(u64 segment_addr, u64 segment_size, Xbyak::CodeGenerator& c) {
|
void PatchTLS(u64 segment_addr, u64 segment_size, Xbyak::CodeGenerator& c) {
|
||||||
u8* code = reinterpret_cast<u8*>(segment_addr);
|
u8* code = reinterpret_cast<u8*>(segment_addr);
|
||||||
auto remaining_size = segment_size;
|
auto remaining_size = segment_size;
|
||||||
@ -187,6 +187,4 @@ void PatchTLS(u64 segment_addr, u64 segment_size, Xbyak::CodeGenerator& c) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} // namespace Core
|
} // namespace Core
|
||||||
|
@ -111,7 +111,7 @@ void Emulator::Run(const std::filesystem::path& file) {
|
|||||||
std::jthread([this](std::stop_token stop_token) { linker->Execute(); });
|
std::jthread([this](std::stop_token stop_token) { linker->Execute(); });
|
||||||
|
|
||||||
// Begin main window loop until the application exits
|
// Begin main window loop until the application exits
|
||||||
static constexpr std::chrono::microseconds FlipPeriod{100000};
|
static constexpr std::chrono::microseconds FlipPeriod{10};
|
||||||
|
|
||||||
while (window.isOpen()) {
|
while (window.isOpen()) {
|
||||||
window.waitEvent();
|
window.waitEvent();
|
||||||
|
@ -19,6 +19,7 @@ WindowSDL::WindowSDL(s32 width_, s32 height_, Input::GameController* controller_
|
|||||||
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
|
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
|
||||||
UNREACHABLE_MSG("Failed to initialize SDL video subsystem: {}", SDL_GetError());
|
UNREACHABLE_MSG("Failed to initialize SDL video subsystem: {}", SDL_GetError());
|
||||||
}
|
}
|
||||||
|
SDL_InitSubSystem(SDL_INIT_AUDIO);
|
||||||
|
|
||||||
const std::string title = "shadPS4 v" + std::string(Common::VERSION);
|
const std::string title = "shadPS4 v" + std::string(Common::VERSION);
|
||||||
SDL_PropertiesID props = SDL_CreateProperties();
|
SDL_PropertiesID props = SDL_CreateProperties();
|
||||||
|
Loading…
Reference in New Issue
Block a user