Implement sceKernelReserveVirtualRange, misc fixes

This commit is contained in:
Daniel R. 2024-07-10 14:59:43 +02:00
parent ec48aa8cd6
commit 27b87ebc35
No known key found for this signature in database
GPG Key ID: B8ADC8F57BA18DBA
10 changed files with 180 additions and 21 deletions

View File

@ -261,6 +261,7 @@ set(COMMON src/common/logging/backend.cpp
src/common/types.h src/common/types.h
src/common/uint128.h src/common/uint128.h
src/common/version.h src/common/version.h
src/common/ntapi.h
) )
set(CORE src/core/aerolib/stubs.cpp set(CORE src/core/aerolib/stubs.cpp

View File

@ -11,6 +11,8 @@
#include "common/path_util.h" #include "common/path_util.h"
#ifdef _WIN32 #ifdef _WIN32
#include "common/ntapi.h"
#include <io.h> #include <io.h>
#include <share.h> #include <share.h>
#include <windows.h> #include <windows.h>
@ -216,6 +218,26 @@ void IOFile::Close() {
#endif #endif
} }
void IOFile::Unlink() {
if (!IsOpen()) {
return;
}
// Mark the file for deletion
// TODO: Also remove the file path?
#if _WIN64
FILE_DISPOSITION_INFORMATION disposition;
IO_STATUS_BLOCK iosb;
const int fd = fileno(file);
HANDLE hfile = reinterpret_cast<HANDLE>(_get_osfhandle(fd));
disposition.DeleteFile = TRUE;
NtSetInformationFile(hfile, &iosb, &disposition, sizeof(disposition),
FileDispositionInformation);
#endif
}
uintptr_t IOFile::GetFileMapping() { uintptr_t IOFile::GetFileMapping() {
if (file_mapping) { if (file_mapping) {
return file_mapping; return file_mapping;

View File

@ -107,6 +107,8 @@ public:
FileShareFlag flag = FileShareFlag::ShareReadOnly); FileShareFlag flag = FileShareFlag::ShareReadOnly);
void Close(); void Close();
void Unlink();
bool Flush() const; bool Flush() const;
bool Commit() const; bool Commit() const;

120
src/common/ntapi.h Normal file
View File

@ -0,0 +1,120 @@
#pragma once
#ifdef _WIN32
#include "common/types.h"
#include <windows.h>
typedef enum _FILE_INFORMATION_CLASS {
FileDirectoryInformation = 1,
FileFullDirectoryInformation = 2,
FileBothDirectoryInformation = 3,
FileBasicInformation = 4,
FileStandardInformation = 5,
FileInternalInformation = 6,
FileEaInformation = 7,
FileAccessInformation = 8,
FileNameInformation = 9,
FileRenameInformation = 10,
FileLinkInformation = 11,
FileNamesInformation = 12,
FileDispositionInformation = 13,
FilePositionInformation = 14,
FileFullEaInformation = 15,
FileModeInformation = 16,
FileAlignmentInformation = 17,
FileAllInformation = 18,
FileAllocationInformation = 19,
FileEndOfFileInformation = 20,
FileAlternateNameInformation = 21,
FileStreamInformation = 22,
FilePipeInformation = 23,
FilePipeLocalInformation = 24,
FilePipeRemoteInformation = 25,
FileMailslotQueryInformation = 26,
FileMailslotSetInformation = 27,
FileCompressionInformation = 28,
FileObjectIdInformation = 29,
FileCompletionInformation = 30,
FileMoveClusterInformation = 31,
FileQuotaInformation = 32,
FileReparsePointInformation = 33,
FileNetworkOpenInformation = 34,
FileAttributeTagInformation = 35,
FileTrackingInformation = 36,
FileIdBothDirectoryInformation = 37,
FileIdFullDirectoryInformation = 38,
FileValidDataLengthInformation = 39,
FileShortNameInformation = 40,
FileIoCompletionNotificationInformation = 41,
FileIoStatusBlockRangeInformation = 42,
FileIoPriorityHintInformation = 43,
FileSfioReserveInformation = 44,
FileSfioVolumeInformation = 45,
FileHardLinkInformation = 46,
FileProcessIdsUsingFileInformation = 47,
FileNormalizedNameInformation = 48,
FileNetworkPhysicalNameInformation = 49,
FileIdGlobalTxDirectoryInformation = 50,
FileIsRemoteDeviceInformation = 51,
FileUnusedInformation = 52,
FileNumaNodeInformation = 53,
FileStandardLinkInformation = 54,
FileRemoteProtocolInformation = 55,
FileRenameInformationBypassAccessCheck = 56,
FileLinkInformationBypassAccessCheck = 57,
FileVolumeNameInformation = 58,
FileIdInformation = 59,
FileIdExtdDirectoryInformation = 60,
FileReplaceCompletionInformation = 61,
FileHardLinkFullIdInformation = 62,
FileIdExtdBothDirectoryInformation = 63,
FileDispositionInformationEx = 64,
FileRenameInformationEx = 65,
FileRenameInformationExBypassAccessCheck = 66,
FileDesiredStorageClassInformation = 67,
FileStatInformation = 68,
FileMemoryPartitionInformation = 69,
FileStatLxInformation = 70,
FileCaseSensitiveInformation = 71,
FileLinkInformationEx = 72,
FileLinkInformationExBypassAccessCheck = 73,
FileStorageReserveIdInformation = 74,
FileCaseSensitiveInformationForceAccessCheck = 75,
FileKnownFolderInformation = 76,
FileStatBasicInformation = 77,
FileId64ExtdDirectoryInformation = 78,
FileId64ExtdBothDirectoryInformation = 79,
FileIdAllExtdDirectoryInformation = 80,
FileIdAllExtdBothDirectoryInformation = 81,
FileStreamReservationInformation,
FileMupProviderInfo,
FileMaximumInformation
} FILE_INFORMATION_CLASS,
*PFILE_INFORMATION_CLASS;
typedef struct _IO_STATUS_BLOCK {
union {
u32 Status;
PVOID Pointer;
};
ULONG_PTR Information;
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
typedef struct _FILE_DISPOSITION_INFORMATION {
BOOLEAN DeleteFile;
} FILE_DISPOSITION_INFORMATION, *PFILE_DISPOSITION_INFORMATION;
// http://stackoverflow.com/a/31411628/4725495
static u32(__stdcall* NtDelayExecution)(BOOL Alertable, PLARGE_INTEGER DelayInterval) =
(u32(__stdcall*)(BOOL, PLARGE_INTEGER))GetProcAddress(GetModuleHandleA("ntdll.dll"),
"NtDelayExecution");
static u32(__stdcall* NtSetInformationFile)(HANDLE FileHandle, PIO_STATUS_BLOCK IoStatusBlock,
PVOID FileInformation, ULONG Length,
FILE_INFORMATION_CLASS FileInformationClass) =
(u32(__stdcall*)(HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, FILE_INFORMATION_CLASS))
GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtSetInformationFile");
#endif

View File

@ -179,16 +179,11 @@ int PS4_SYSV_ABI sceKernelUnlink(const char* path) {
} }
auto* file = h->getFile(host_path); auto* file = h->getFile(host_path);
if (file == nullptr) { if (file != nullptr) {
return SCE_KERNEL_ERROR_EIO; file->f.Unlink();
} }
file->f.Close(); LOG_INFO(Kernel_Fs, "Unlinked {}", path);
if (!std::filesystem::remove(host_path)) {
return SCE_KERNEL_ERROR_ENOENT;
}
LOG_INFO(Kernel_Fs, "Deleted {}", path);
return SCE_OK; return SCE_OK;
} }
@ -403,14 +398,7 @@ int PS4_SYSV_ABI sceKernelFtruncate(int fd, s64 length) {
return SCE_KERNEL_ERROR_EACCES; return SCE_KERNEL_ERROR_EACCES;
} }
// CUSA05289 (PSPHD emulator): Tries to resize a temporary file after deleting it file->f.SetSize(length);
try {
// TODO: Check for sufficient space?
std::filesystem::resize_file(file->m_host_name, length);
} catch (std::filesystem::filesystem_error& e) {
LOG_ERROR(Kernel_Fs, "Error: {}", e.what());
}
return SCE_OK; return SCE_OK;
} }

View File

@ -326,6 +326,7 @@ void LibKernel_Register(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("hwVSPCmp5tM", "libkernel", 1, "libkernel", 1, 1, LIB_FUNCTION("hwVSPCmp5tM", "libkernel", 1, "libkernel", 1, 1,
sceKernelCheckedReleaseDirectMemory); sceKernelCheckedReleaseDirectMemory);
LIB_FUNCTION("rVjRvHJ0X6c", "libkernel", 1, "libkernel", 1, 1, sceKernelVirtualQuery); LIB_FUNCTION("rVjRvHJ0X6c", "libkernel", 1, "libkernel", 1, 1, sceKernelVirtualQuery);
LIB_FUNCTION("7oxv3PPCumo", "libkernel", 1, "libkernel", 1, 1, sceKernelReserveVirtualRange);
LIB_FUNCTION("pO96TwzOm5E", "libkernel", 1, "libkernel", 1, 1, sceKernelGetDirectMemorySize); LIB_FUNCTION("pO96TwzOm5E", "libkernel", 1, "libkernel", 1, 1, sceKernelGetDirectMemorySize);
LIB_FUNCTION("NcaWUxfMNIQ", "libkernel", 1, "libkernel", 1, 1, sceKernelMapNamedDirectMemory); LIB_FUNCTION("NcaWUxfMNIQ", "libkernel", 1, "libkernel", 1, 1, sceKernelMapNamedDirectMemory);
LIB_FUNCTION("L-Q3LEjIbgA", "libkernel", 1, "libkernel", 1, 1, sceKernelMapDirectMemory); LIB_FUNCTION("L-Q3LEjIbgA", "libkernel", 1, "libkernel", 1, 1, sceKernelMapDirectMemory);

View File

@ -87,6 +87,33 @@ s32 PS4_SYSV_ABI sceKernelVirtualQuery(const void* addr, int flags, OrbisVirtual
return memory->VirtualQuery(std::bit_cast<VAddr>(addr), flags, info); return memory->VirtualQuery(std::bit_cast<VAddr>(addr), flags, info);
} }
s32 PS4_SYSV_ABI sceKernelReserveVirtualRange(void** addr, u64 len, int flags, u64 alignment) {
LOG_INFO(Kernel_Vmm, "addr = {}, len = {:#x}, flags = {:#x}, alignment = {:#x}",
fmt::ptr(*addr), len, flags, alignment);
if (addr == nullptr) {
LOG_ERROR(Kernel_Vmm, "Address is invalid!");
return SCE_KERNEL_ERROR_EINVAL;
}
if (len == 0 || !Common::Is16KBAligned(len)) {
LOG_ERROR(Kernel_Vmm, "Map size is either zero or not 16KB aligned!");
return SCE_KERNEL_ERROR_EINVAL;
}
if (alignment != 0) {
if ((!std::has_single_bit(alignment) && !Common::Is16KBAligned(alignment))) {
LOG_ERROR(Kernel_Vmm, "Alignment value is invalid!");
return SCE_KERNEL_ERROR_EINVAL;
}
}
auto* memory = Core::Memory::Instance();
const auto map_flags = static_cast<Core::MemoryMapFlags>(flags);
memory->MapMemory(addr, 0, len, Core::MemoryProt::NoAccess, map_flags, Core::VMAType::Direct,
"", false, -1, alignment);
return SCE_OK;
}
int PS4_SYSV_ABI sceKernelMapNamedDirectMemory(void** addr, u64 len, int prot, int flags, int PS4_SYSV_ABI sceKernelMapNamedDirectMemory(void** addr, u64 len, int prot, int flags,
s64 directMemoryStart, u64 alignment, s64 directMemoryStart, u64 alignment,
const char* name) { const char* name) {

View File

@ -70,6 +70,7 @@ s32 PS4_SYSV_ABI sceKernelAvailableDirectMemorySize(u64 searchStart, u64 searchE
size_t* sizeOut); size_t* sizeOut);
s32 PS4_SYSV_ABI sceKernelVirtualQuery(const void* addr, int flags, OrbisVirtualQueryInfo* info, s32 PS4_SYSV_ABI sceKernelVirtualQuery(const void* addr, int flags, OrbisVirtualQueryInfo* info,
size_t infoSize); size_t infoSize);
s32 PS4_SYSV_ABI sceKernelReserveVirtualRange(void** addr, u64 len, int flags, u64 alignment);
s32 PS4_SYSV_ABI sceKernelMapNamedFlexibleMemory(void** addrInOut, std::size_t len, int prot, s32 PS4_SYSV_ABI sceKernelMapNamedFlexibleMemory(void** addrInOut, std::size_t len, int prot,
int flags, const char* name); int flags, const char* name);
s32 PS4_SYSV_ABI sceKernelMapFlexibleMemory(void** addr_in_out, std::size_t len, int prot, s32 PS4_SYSV_ABI sceKernelMapFlexibleMemory(void** addr_in_out, std::size_t len, int prot,

View File

@ -12,10 +12,8 @@
#include <pthread_time.h> #include <pthread_time.h>
#include <windows.h> #include <windows.h>
// http://stackoverflow.com/a/31411628/4725495 #include "common/ntapi.h"
static u32(__stdcall* NtDelayExecution)(BOOL Alertable, PLARGE_INTEGER DelayInterval) =
(u32(__stdcall*)(BOOL, PLARGE_INTEGER))GetProcAddress(GetModuleHandleA("ntdll.dll"),
"NtDelayExecution");
#else #else
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>

View File

@ -146,7 +146,6 @@ int MemoryManager::MapMemory(void** out_addr, VAddr virtual_addr, size_t size, M
int MemoryManager::MapFile(void** out_addr, VAddr virtual_addr, size_t size, MemoryProt prot, int MemoryManager::MapFile(void** out_addr, VAddr virtual_addr, size_t size, MemoryProt prot,
MemoryMapFlags flags, uintptr_t fd, size_t offset) { MemoryMapFlags flags, uintptr_t fd, size_t offset) {
ASSERT(virtual_addr == 0);
virtual_addr = impl.VirtualBase(); virtual_addr = impl.VirtualBase();
const size_t size_aligned = Common::AlignUp(size, 16_KB); const size_t size_aligned = Common::AlignUp(size, 16_KB);