diff --git a/src/core/libraries/kernel/kernel.cpp b/src/core/libraries/kernel/kernel.cpp index 75c79cfcf..3273830e1 100644 --- a/src/core/libraries/kernel/kernel.cpp +++ b/src/core/libraries/kernel/kernel.cpp @@ -326,6 +326,11 @@ s32 PS4_SYSV_ABI sceKernelGetProcessType(s32 pid) { return 0; } +s32 PS4_SYSV_ABI __sys_regmgr_call(u32 op, u32 key, void* result, void* value, u64 len) { + LOG_ERROR(Lib_Kernel, "(STUBBED) called, op: {:#x}, key: {}, len: {}", op, key, len); + return ORBIS_OK; +} + // Nominally: long sysconf(int name); u64 PS4_SYSV_ABI posix_sysconf(s32 name) { switch (name) { @@ -481,6 +486,7 @@ void RegisterLib(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("9BcDykPmo1I", "libkernel", 1, "libkernel", __Error); LIB_FUNCTION("k+AXqu2-eBc", "libkernel", 1, "libkernel", posix_getpagesize); LIB_FUNCTION("k+AXqu2-eBc", "libScePosix", 1, "libkernel", posix_getpagesize); + LIB_FUNCTION("7NwggrWJ5cA", "libkernel", 1, "libkernel", __sys_regmgr_call); LIB_FUNCTION("mkawd0NA9ts", "libkernel", 1, "libkernel", posix_sysconf); LIB_FUNCTION("mkawd0NA9ts", "libScePosix", 1, "libkernel", posix_sysconf); diff --git a/src/core/libraries/kernel/memory.cpp b/src/core/libraries/kernel/memory.cpp index 266b05059..ef4d39cce 100644 --- a/src/core/libraries/kernel/memory.cpp +++ b/src/core/libraries/kernel/memory.cpp @@ -342,6 +342,45 @@ s32 PS4_SYSV_ABI sceKernelMapFlexibleMemory(void** addr_in_out, u64 len, s32 pro return sceKernelMapNamedFlexibleMemory(addr_in_out, len, prot, flags, "anon"); } +s32 PS4_SYSV_ABI sceKernelMapNamedSystemFlexibleMemory(void** addr_in_out, u64 len, s32 prot, + s32 flags, const char* name) { + LOG_INFO(Kernel_Vmm, "in_addr = {}, len = {:#x}, prot = {:#x}, flags = {:#x}, name = '{}'", + fmt::ptr(*addr_in_out), len, prot, flags, name); + if (len == 0 || !Common::Is16KBAligned(len)) { + LOG_ERROR(Kernel_Vmm, "len is 0 or not 16kb multiple"); + return ORBIS_KERNEL_ERROR_EINVAL; + } + + if (name == nullptr) { + LOG_ERROR(Kernel_Vmm, "name is invalid!"); + return ORBIS_KERNEL_ERROR_EFAULT; + } + + auto map_flags = static_cast(flags); + VAddr in_addr = reinterpret_cast(*addr_in_out); + if (True(map_flags & Core::MemoryMapFlags::Fixed) && in_addr == 0) { + if (Common::ElfInfo::FW_170 <= g_sdk_version) { + return ORBIS_KERNEL_ERROR_EINVAL; + } + map_flags &= ~Core::MemoryMapFlags::Fixed; + } + + if (std::strlen(name) >= ORBIS_KERNEL_MAXIMUM_NAME_LENGTH) { + LOG_ERROR(Kernel_Vmm, "name exceeds 32 bytes!"); + return ORBIS_KERNEL_ERROR_ENAMETOOLONG; + } + + if (in_addr == 0) { + in_addr = 0x880000000; + } + const auto mem_prot = static_cast(prot); + auto* memory = Core::Memory::Instance(); + const auto ret = memory->MapMemory(addr_in_out, in_addr, len, mem_prot, map_flags, + Core::VMAType::System, name); + LOG_INFO(Kernel_Vmm, "out_addr = {}", fmt::ptr(*addr_in_out)); + return ret; +} + s32 PS4_SYSV_ABI sceKernelQueryMemoryProtection(void* addr, void** start, void** end, u32* prot) { auto* memory = Core::Memory::Instance(); return memory->QueryProtection(std::bit_cast(addr), start, end, prot); @@ -728,9 +767,12 @@ void* PS4_SYSV_ABI posix_mmap(void* addr, u64 len, s32 prot, s32 flags, s32 fd, s32 result = ORBIS_OK; if (True(mem_flags & Core::MemoryMapFlags::Anon)) { - // Maps flexible memory + // Maps flexible or system memory + const Core::VMAType mapping_type = True(mem_flags & Core::MemoryMapFlags::System) + ? Core::VMAType::System + : Core::VMAType::Flexible; result = memory->MapMemory(&addr_out, aligned_addr, aligned_size, mem_prot, mem_flags, - Core::VMAType::Flexible, "anon", false); + mapping_type, "anon", false); } else if (True(mem_flags & Core::MemoryMapFlags::Stack)) { // Maps stack memory result = memory->MapMemory(&addr_out, aligned_addr, aligned_size, mem_prot, mem_flags, @@ -876,6 +918,7 @@ void RegisterMemory(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("PGhQHd-dzv8", "libkernel", 1, "libkernel", sceKernelMmap); LIB_FUNCTION("cQke9UuBQOk", "libkernel", 1, "libkernel", sceKernelMunmap); LIB_FUNCTION("mL8NDH86iQI", "libkernel", 1, "libkernel", sceKernelMapNamedFlexibleMemory); + LIB_FUNCTION("kc+LEEIYakc", "libkernel", 1, "libkernel", sceKernelMapNamedSystemFlexibleMemory); LIB_FUNCTION("aNz11fnnzi4", "libkernel", 1, "libkernel", sceKernelAvailableFlexibleMemorySize); LIB_FUNCTION("aNz11fnnzi4", "libkernel_avlfmem", 1, "libkernel", sceKernelAvailableFlexibleMemorySize); diff --git a/src/core/libraries/libc_internal/libc_internal.cpp b/src/core/libraries/libc_internal/libc_internal.cpp index 6a92d2317..c87effdb3 100644 --- a/src/core/libraries/libc_internal/libc_internal.cpp +++ b/src/core/libraries/libc_internal/libc_internal.cpp @@ -24,8 +24,4 @@ void RegisterLib(Core::Loader::SymbolsResolver* sym) { RegisterlibSceLibcInternalThreads(sym); } -void ForceRegisterLib(Core::Loader::SymbolsResolver* sym) { - // Used to forcibly enable HLEs for broken LLE functions. - ForceRegisterlibSceLibcInternalIo(sym); -} } // namespace Libraries::LibcInternal \ No newline at end of file diff --git a/src/core/libraries/libc_internal/libc_internal.h b/src/core/libraries/libc_internal/libc_internal.h index 1494a2ab2..9b00b72d8 100644 --- a/src/core/libraries/libc_internal/libc_internal.h +++ b/src/core/libraries/libc_internal/libc_internal.h @@ -15,5 +15,4 @@ namespace Libraries::LibcInternal { // so everything is just in the .cpp file void RegisterLib(Core::Loader::SymbolsResolver* sym); -void ForceRegisterLib(Core::Loader::SymbolsResolver* sym); } // namespace Libraries::LibcInternal \ No newline at end of file diff --git a/src/core/libraries/libc_internal/libc_internal_io.cpp b/src/core/libraries/libc_internal/libc_internal_io.cpp index 0bb23eb78..6e6bfef8e 100644 --- a/src/core/libraries/libc_internal/libc_internal_io.cpp +++ b/src/core/libraries/libc_internal/libc_internal_io.cpp @@ -465,7 +465,6 @@ s32 PS4_SYSV_ABI internal_fclose(OrbisFILE* file) { void RegisterlibSceLibcInternalIo(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("eLdDw6l0-bU", "libSceLibcInternal", 1, "libSceLibcInternal", internal_snprintf); - LIB_FUNCTION("MUjC4lbHrK4", "libSceLibcInternal", 1, "libSceLibcInternal", internal_fflush); LIB_FUNCTION("xGT4Mc55ViQ", "libSceLibcInternal", 1, "libSceLibcInternal", internal__Fofind); LIB_FUNCTION("dREVnZkAKRE", "libSceLibcInternal", 1, "libSceLibcInternal", internal__Foprep); LIB_FUNCTION("sQL8D-jio7U", "libSceLibcInternal", 1, "libSceLibcInternal", internal__Fopen); @@ -477,13 +476,11 @@ void RegisterlibSceLibcInternalIo(Core::Loader::SymbolsResolver* sym) { internal__Lockfilelock); LIB_FUNCTION("0x7rx8TKy2Y", "libSceLibcInternal", 1, "libSceLibcInternal", internal__Unlockfilelock); -} -void ForceRegisterlibSceLibcInternalIo(Core::Loader::SymbolsResolver* sym) { - // Goal is to be minimally intrusive here to allow LLE for printf/stdout writes. LIB_FUNCTION("xeYO4u7uyJ0", "libSceLibcInternal", 1, "libSceLibcInternal", internal_fopen); LIB_FUNCTION("rQFVBXp-Cxg", "libSceLibcInternal", 1, "libSceLibcInternal", internal_fseek); LIB_FUNCTION("lbB+UlZqVG0", "libSceLibcInternal", 1, "libSceLibcInternal", internal_fread); + LIB_FUNCTION("MUjC4lbHrK4", "libSceLibcInternal", 1, "libSceLibcInternal", internal_fflush); LIB_FUNCTION("uodLYyUip20", "libSceLibcInternal", 1, "libSceLibcInternal", internal_fclose); } diff --git a/src/core/libraries/libc_internal/libc_internal_io.h b/src/core/libraries/libc_internal/libc_internal_io.h index 27915d8fa..f3edff811 100644 --- a/src/core/libraries/libc_internal/libc_internal_io.h +++ b/src/core/libraries/libc_internal/libc_internal_io.h @@ -94,5 +94,4 @@ u64 PS4_SYSV_ABI internal_fread(char* ptr, u64 size, u64 nmemb, OrbisFILE* file) s32 PS4_SYSV_ABI internal_fclose(OrbisFILE* file); void RegisterlibSceLibcInternalIo(Core::Loader::SymbolsResolver* sym); -void ForceRegisterlibSceLibcInternalIo(Core::Loader::SymbolsResolver* sym); } // namespace Libraries::LibcInternal \ No newline at end of file diff --git a/src/core/libraries/libs.cpp b/src/core/libraries/libs.cpp index 1bc57efd7..f68b8ad3d 100644 --- a/src/core/libraries/libs.cpp +++ b/src/core/libraries/libs.cpp @@ -83,7 +83,6 @@ namespace Libraries { void InitHLELibs(Core::Loader::SymbolsResolver* sym) { LOG_INFO(Lib_Kernel, "Initializing HLE libraries"); Libraries::Kernel::RegisterLib(sym); - Libraries::LibcInternal::ForceRegisterLib(sym); Libraries::GnmDriver::RegisterLib(sym); Libraries::VideoOut::RegisterLib(sym); Libraries::UserService::RegisterLib(sym); diff --git a/src/core/libraries/sysmodule/sysmodule_internal.cpp b/src/core/libraries/sysmodule/sysmodule_internal.cpp index aef4576aa..6a380564e 100644 --- a/src/core/libraries/sysmodule/sysmodule_internal.cpp +++ b/src/core/libraries/sysmodule/sysmodule_internal.cpp @@ -434,6 +434,13 @@ s32 preloadModulesForLibkernel() { continue; } + if (module_index == 1 || module_index == 2) { + // libkernel and libSceLibcInternal aren't directly loaded here. + // All we do for those is increment is_loaded + g_modules_array[module_index].is_loaded++; + continue; + } + // Load the actual module s32 result = loadModuleInternal(module_index, 0, nullptr, nullptr); if (result != ORBIS_OK) { diff --git a/src/core/linker.cpp b/src/core/linker.cpp index 2a073d40a..4ae002c68 100644 --- a/src/core/linker.cpp +++ b/src/core/linker.cpp @@ -72,11 +72,38 @@ void Linker::Execute(const std::vector& args) { Module* module = m_modules[0].get(); static_tls_size = module->tls.offset = module->tls.image_size; + // Map libSceLibcInternal + const auto& libc_internal_path = + EmulatorSettings.GetSysModulesDir() / "libSceLibcInternal.sprx"; + if (std::filesystem::exists(libc_internal_path)) { + LoadModule(libc_internal_path); + } + // Relocate all modules for (const auto& m : m_modules) { Relocate(m.get()); } + // Before we can run guest code, we need to properly initialize the heap API and + // libSceLibcInternal. libSceLibcInternal's _malloc_init serves as an additional initialization + // function called by libkernel. + heap_api = new HeapAPI{}; + static PS4_SYSV_ABI s32 (*malloc_init)() = nullptr; + + for (const auto& m : m_modules) { + const auto& mod = m.get(); + if (mod->name.contains("libSceLibcInternal.sprx")) { + // Found libSceLibcInternal, now search through function exports. + // Looking for _malloc_init to init libSceLibcInternal properly + // and for all the memory allocating functions, so we can initialize our heap API + for (const auto& sym : mod->export_sym.GetSymbols()) { + if (sym.nid_name.compare("_malloc_init") == 0) { + malloc_init = reinterpret_cast(sym.virtual_address); + } + } + } + } + // Configure the direct and flexible memory regions. u64 fmem_size = ORBIS_KERNEL_FLEXIBLE_MEMORY_SIZE; bool use_extended_mem1 = true, use_extended_mem2 = true; @@ -125,6 +152,15 @@ void Linker::Execute(const std::vector& args) { ipc.WaitForStart(); } + // Load libSceLibcInternal, run malloc_init. + LoadLibcInternal(); + + if (malloc_init != nullptr) { + // Call _malloc_init + s32 ret = malloc_init(); + ASSERT_MSG(ret == 0, "malloc_init failed"); + } + // Have libSceSysmodule preload our libraries. Libraries::SysModule::sceSysmodulePreloadModuleForLibkernel(); diff --git a/src/core/linker.h b/src/core/linker.h index f210c2e57..eb8d77e50 100644 --- a/src/core/linker.h +++ b/src/core/linker.h @@ -131,6 +131,14 @@ public: } } + void LoadLibcInternal() { + for (auto& module : m_modules) { + if (module->name.contains("libSceLibcInternal")) { + module->Start(0, nullptr, nullptr); + } + } + } + void SetHeapAPI(void* func[]) { heap_api = reinterpret_cast(func); } diff --git a/src/core/memory.h b/src/core/memory.h index 2588fbd6a..58857d12d 100644 --- a/src/core/memory.h +++ b/src/core/memory.h @@ -52,6 +52,7 @@ enum class MemoryMapFlags : u32 { Stack = 0x400, NoSync = 0x800, Anon = 0x1000, + System = 0x2000, NoCore = 0x20000, NoCoalesce = 0x400000, }; @@ -100,6 +101,7 @@ enum class VMAType : u32 { Stack = 6, Code = 7, File = 8, + System = 9, }; struct VirtualMemoryArea {