Fixed ORBIS_KERNEL_MAP_OP_TYPE_PROTECT for batchmap2
This commit is contained in:
parent
a2cd1669b6
commit
c6c679ca0c
|
@ -14,6 +14,7 @@
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#endif
|
#endif
|
||||||
|
#include "libraries/error_codes.h"
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
// Reserve space for the system address space using a zerofill section.
|
// Reserve space for the system address space using a zerofill section.
|
||||||
|
@ -240,6 +241,8 @@ struct AddressSpace::Impl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
HANDLE process{};
|
HANDLE process{};
|
||||||
HANDLE backing_handle{};
|
HANDLE backing_handle{};
|
||||||
u8* backing_base{};
|
u8* backing_base{};
|
||||||
|
@ -462,4 +465,25 @@ void AddressSpace::Protect(VAddr virtual_addr, size_t size, MemoryPermission per
|
||||||
return impl->Protect(virtual_addr, size, true, true, true);
|
return impl->Protect(virtual_addr, size, true, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int AddressSpace::MProtect(VAddr addr, size_t size, int prot) {
|
||||||
|
|
||||||
|
// Use conditional compilation to switch between mprotect and VirtualProtect
|
||||||
|
int result;
|
||||||
|
#ifdef _WIN32
|
||||||
|
// Windows-specific API call
|
||||||
|
result = VirtualProtect(reinterpret_cast<void*>(addr), size, prot, nullptr);
|
||||||
|
#else
|
||||||
|
// POSIX-specific API call
|
||||||
|
result = ::mprotect(reinterpret_cast<void*>(addr), size, prot);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (result != 0) {
|
||||||
|
LOG_ERROR(Core, "Failed to change memory protection: {}", strerror(errno));
|
||||||
|
return ORBIS_KERNEL_ERROR_EACCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_INFO(Core, "Changed protection on range {:#x}-{:#x} to {:#x}", addr, addr + size, prot);
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Core
|
} // namespace Core
|
||||||
|
|
|
@ -98,6 +98,8 @@ public:
|
||||||
|
|
||||||
void Protect(VAddr virtual_addr, size_t size, MemoryPermission perms);
|
void Protect(VAddr virtual_addr, size_t size, MemoryPermission perms);
|
||||||
|
|
||||||
|
int MProtect(VAddr addr, size_t size, int prot);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct Impl;
|
struct Impl;
|
||||||
std::unique_ptr<Impl> impl;
|
std::unique_ptr<Impl> impl;
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
#include "core/libraries/kernel/memory_management.h"
|
#include "core/libraries/kernel/memory_management.h"
|
||||||
#include "core/linker.h"
|
#include "core/linker.h"
|
||||||
#include "core/memory.h"
|
#include "core/memory.h"
|
||||||
|
#include "core/address_space.h"
|
||||||
|
|
||||||
|
|
||||||
namespace Libraries::Kernel {
|
namespace Libraries::Kernel {
|
||||||
|
|
||||||
|
@ -198,6 +200,22 @@ int PS4_SYSV_ABI sceKernelQueryMemoryProtection(void* addr, void** start, void**
|
||||||
return memory->QueryProtection(std::bit_cast<VAddr>(addr), start, end, prot);
|
return memory->QueryProtection(std::bit_cast<VAddr>(addr), start, end, prot);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int PS4_SYSV_ABI sceKernelMProtect(void* addr, size_t size, int prot) {
|
||||||
|
LOG_INFO(Kernel_Vmm, "called addr = {}, size = {:#x}, prot = {:#x}", fmt::ptr(addr), size,
|
||||||
|
prot);
|
||||||
|
Core::MemoryManager* memory_manager = Core::Memory::Instance();
|
||||||
|
if (!memory_manager) {
|
||||||
|
LOG_ERROR(Kernel_Vmm, "Failed to get MemoryManager instance");
|
||||||
|
return ORBIS_KERNEL_ERROR_EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int result = memory_manager->MProtect(std::bit_cast<VAddr>(addr), size, prot);
|
||||||
|
if (result != ORBIS_OK) {
|
||||||
|
LOG_ERROR(Kernel_Vmm, "MProtect failed with result {}", result);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceKernelDirectMemoryQuery(u64 offset, int flags, OrbisQueryInfo* query_info,
|
int PS4_SYSV_ABI sceKernelDirectMemoryQuery(u64 offset, int flags, OrbisQueryInfo* query_info,
|
||||||
size_t infoSize) {
|
size_t infoSize) {
|
||||||
LOG_WARNING(Kernel_Vmm, "called offset = {:#x}, flags = {:#x}", offset, flags);
|
LOG_WARNING(Kernel_Vmm, "called offset = {:#x}, flags = {:#x}", offset, flags);
|
||||||
|
@ -256,14 +274,28 @@ s32 PS4_SYSV_ABI sceKernelBatchMap2(OrbisKernelBatchMapEntry* entries, int numEn
|
||||||
|
|
||||||
if (result == 0)
|
if (result == 0)
|
||||||
processed++;
|
processed++;
|
||||||
} else if (entries[i].operation == 1) {
|
} else if (entries[i].operation == 1) { // UNMAP
|
||||||
result = sceKernelMunmap(entries[i].start, entries[i].length);
|
result = sceKernelMunmap(entries[i].start, entries[i].length);
|
||||||
LOG_INFO(Kernel_Vmm, "BatchMap: entry = {}, operation = {}, len = {:#x}, result = {}",
|
LOG_INFO(Kernel_Vmm, "BatchMap: entry = {}, operation = {}, len = {:#x}, result = {}",
|
||||||
i, entries[i].operation, entries[i].length, result);
|
i, entries[i].operation, entries[i].length, result);
|
||||||
|
|
||||||
if (result == 0)
|
if (result == 0)
|
||||||
processed++;
|
processed++;
|
||||||
} else {
|
} else if (entries[i].operation == 4) { // MPROTECT
|
||||||
|
result =
|
||||||
|
sceKernelMProtect(entries[i].start, entries[i].length, entries[i].protection);
|
||||||
|
LOG_INFO(Kernel_Vmm,
|
||||||
|
"BatchMap: entry = {}, operation = {}, len = {:#x}, result = {}", i,
|
||||||
|
entries[i].operation, entries[i].length, result);
|
||||||
|
if (result != ORBIS_OK) {
|
||||||
|
LOG_ERROR(Kernel_Vmm, "BatchMap: MProtect failed on entry {} with result {}", i,
|
||||||
|
result);
|
||||||
|
}
|
||||||
|
if (result == 0) {
|
||||||
|
processed++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
UNREACHABLE_MSG("called: Unimplemented Operation = {}", entries[i].operation);
|
UNREACHABLE_MSG("called: Unimplemented Operation = {}", entries[i].operation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,11 @@
|
||||||
#include "core/libraries/kernel/memory_management.h"
|
#include "core/libraries/kernel/memory_management.h"
|
||||||
#include "core/memory.h"
|
#include "core/memory.h"
|
||||||
#include "video_core/renderer_vulkan/vk_instance.h"
|
#include "video_core/renderer_vulkan/vk_instance.h"
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#else
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
|
|
||||||
|
@ -261,6 +266,55 @@ int MemoryManager::QueryProtection(VAddr addr, void** start, void** end, u32* pr
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int MemoryManager::MProtect(VAddr addr, size_t size, int prot) {
|
||||||
|
std::scoped_lock lk{mutex};
|
||||||
|
|
||||||
|
// Find the virtual memory area that contains the specified address range.
|
||||||
|
auto it = FindVMA(addr);
|
||||||
|
if (it == vma_map.end() || !it->second.Contains(addr, size)) {
|
||||||
|
LOG_ERROR(Core, "Address range not mapped");
|
||||||
|
return ORBIS_KERNEL_ERROR_EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
VirtualMemoryArea& vma = it->second;
|
||||||
|
if (vma.type == VMAType::Free) {
|
||||||
|
LOG_ERROR(Core, "Cannot change protection on free memory region");
|
||||||
|
return ORBIS_KERNEL_ERROR_EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the new protection flags are valid.
|
||||||
|
if ((static_cast<int>(prot) &
|
||||||
|
~(static_cast<int>(MemoryProt::NoAccess) | static_cast<int>(MemoryProt::CpuRead) |
|
||||||
|
static_cast<int>(MemoryProt::CpuReadWrite) | static_cast<int>(MemoryProt::GpuRead) |
|
||||||
|
static_cast<int>(MemoryProt::GpuWrite) | static_cast<int>(MemoryProt::GpuReadWrite))) !=
|
||||||
|
0) {
|
||||||
|
LOG_ERROR(Core, "Invalid protection flags, prot: {:#x}, GpuWrite: {:#x}",
|
||||||
|
static_cast<uint32_t>(prot), static_cast<uint32_t>(MemoryProt::GpuWrite));
|
||||||
|
return ORBIS_KERNEL_ERROR_EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Change the protection on the specified address range.
|
||||||
|
vma.prot = static_cast<MemoryProt>(prot);
|
||||||
|
|
||||||
|
// Use the Protect function from the AddressSpace class.
|
||||||
|
Core::MemoryPermission perms;
|
||||||
|
if ((static_cast<int>(prot) & static_cast<int>(MemoryProt::CpuRead)) != 0)
|
||||||
|
perms |= Core::MemoryPermission::Read;
|
||||||
|
if ((static_cast<int>(prot) & static_cast<int>(MemoryProt::CpuReadWrite)) != 0)
|
||||||
|
perms |= Core::MemoryPermission::ReadWrite;
|
||||||
|
if ((static_cast<int>(prot) & static_cast<int>(MemoryProt::GpuRead)) != 0)
|
||||||
|
perms |= Core::MemoryPermission::Read;
|
||||||
|
if ((static_cast<int>(prot) & static_cast<int>(MemoryProt::GpuWrite)) != 0)
|
||||||
|
perms |= Core::MemoryPermission::Write;
|
||||||
|
if ((static_cast<int>(prot) & static_cast<int>(MemoryProt::GpuReadWrite)) != 0)
|
||||||
|
perms |= Core::MemoryPermission::ReadWrite; // Add this line
|
||||||
|
impl.Protect(addr, size, perms);
|
||||||
|
|
||||||
|
LOG_INFO(Core, "Changed protection on range {:#x}-{:#x} to {:#x}", addr, addr + size, prot);
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int MemoryManager::VirtualQuery(VAddr addr, int flags,
|
int MemoryManager::VirtualQuery(VAddr addr, int flags,
|
||||||
Libraries::Kernel::OrbisVirtualQueryInfo* info) {
|
Libraries::Kernel::OrbisVirtualQueryInfo* info) {
|
||||||
std::scoped_lock lk{mutex};
|
std::scoped_lock lk{mutex};
|
||||||
|
|
|
@ -165,6 +165,8 @@ public:
|
||||||
|
|
||||||
int QueryProtection(VAddr addr, void** start, void** end, u32* prot);
|
int QueryProtection(VAddr addr, void** start, void** end, u32* prot);
|
||||||
|
|
||||||
|
int MProtect(VAddr addr, size_t size, int prot);
|
||||||
|
|
||||||
int VirtualQuery(VAddr addr, int flags, Libraries::Kernel::OrbisVirtualQueryInfo* info);
|
int VirtualQuery(VAddr addr, int flags, Libraries::Kernel::OrbisVirtualQueryInfo* info);
|
||||||
|
|
||||||
int DirectMemoryQuery(PAddr addr, bool find_next, Libraries::Kernel::OrbisQueryInfo* out_info);
|
int DirectMemoryQuery(PAddr addr, bool find_next, Libraries::Kernel::OrbisQueryInfo* out_info);
|
||||||
|
|
Loading…
Reference in New Issue