mirror of
https://github.com/yuzu-emu/yuzu.git
synced 2024-12-27 06:20:07 +00:00
kernel: svc: Updates for new VMM.
- Includes removing some SVC impls. that are untested.
This commit is contained in:
parent
ff5d5b6f41
commit
c629e544a7
@ -24,6 +24,8 @@
|
|||||||
#include "core/hle/kernel/errors.h"
|
#include "core/hle/kernel/errors.h"
|
||||||
#include "core/hle/kernel/handle_table.h"
|
#include "core/hle/kernel/handle_table.h"
|
||||||
#include "core/hle/kernel/kernel.h"
|
#include "core/hle/kernel/kernel.h"
|
||||||
|
#include "core/hle/kernel/memory/memory_block.h"
|
||||||
|
#include "core/hle/kernel/memory/page_table.h"
|
||||||
#include "core/hle/kernel/mutex.h"
|
#include "core/hle/kernel/mutex.h"
|
||||||
#include "core/hle/kernel/process.h"
|
#include "core/hle/kernel/process.h"
|
||||||
#include "core/hle/kernel/readable_event.h"
|
#include "core/hle/kernel/readable_event.h"
|
||||||
@ -59,8 +61,8 @@ constexpr u64 MAIN_MEMORY_SIZE = 0x200000000;
|
|||||||
// Helper function that performs the common sanity checks for svcMapMemory
|
// Helper function that performs the common sanity checks for svcMapMemory
|
||||||
// and svcUnmapMemory. This is doable, as both functions perform their sanitizing
|
// and svcUnmapMemory. This is doable, as both functions perform their sanitizing
|
||||||
// in the same order.
|
// in the same order.
|
||||||
ResultCode MapUnmapMemorySanityChecks(const VMManager& vm_manager, VAddr dst_addr, VAddr src_addr,
|
ResultCode MapUnmapMemorySanityChecks(const Memory::PageTable& manager, VAddr dst_addr,
|
||||||
u64 size) {
|
VAddr src_addr, u64 size) {
|
||||||
if (!Common::Is4KBAligned(dst_addr)) {
|
if (!Common::Is4KBAligned(dst_addr)) {
|
||||||
LOG_ERROR(Kernel_SVC, "Destination address is not aligned to 4KB, 0x{:016X}", dst_addr);
|
LOG_ERROR(Kernel_SVC, "Destination address is not aligned to 4KB, 0x{:016X}", dst_addr);
|
||||||
return ERR_INVALID_ADDRESS;
|
return ERR_INVALID_ADDRESS;
|
||||||
@ -94,36 +96,33 @@ ResultCode MapUnmapMemorySanityChecks(const VMManager& vm_manager, VAddr dst_add
|
|||||||
return ERR_INVALID_ADDRESS_STATE;
|
return ERR_INVALID_ADDRESS_STATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!vm_manager.IsWithinAddressSpace(src_addr, size)) {
|
if (!manager.IsInsideAddressSpace(src_addr, size)) {
|
||||||
LOG_ERROR(Kernel_SVC,
|
LOG_ERROR(Kernel_SVC,
|
||||||
"Source is not within the address space, addr=0x{:016X}, size=0x{:016X}",
|
"Source is not within the address space, addr=0x{:016X}, size=0x{:016X}",
|
||||||
src_addr, size);
|
src_addr, size);
|
||||||
return ERR_INVALID_ADDRESS_STATE;
|
return ERR_INVALID_ADDRESS_STATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!vm_manager.IsWithinStackRegion(dst_addr, size)) {
|
if (manager.IsOutsideStackRegion(dst_addr, size)) {
|
||||||
LOG_ERROR(Kernel_SVC,
|
LOG_ERROR(Kernel_SVC,
|
||||||
"Destination is not within the stack region, addr=0x{:016X}, size=0x{:016X}",
|
"Destination is not within the stack region, addr=0x{:016X}, size=0x{:016X}",
|
||||||
dst_addr, size);
|
dst_addr, size);
|
||||||
return ERR_INVALID_MEMORY_RANGE;
|
return ERR_INVALID_MEMORY_RANGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
const VAddr dst_end_address = dst_addr + size;
|
if (manager.IsInsideHeapRegion(dst_addr, size)) {
|
||||||
if (dst_end_address > vm_manager.GetHeapRegionBaseAddress() &&
|
|
||||||
vm_manager.GetHeapRegionEndAddress() > dst_addr) {
|
|
||||||
LOG_ERROR(Kernel_SVC,
|
LOG_ERROR(Kernel_SVC,
|
||||||
"Destination does not fit within the heap region, addr=0x{:016X}, "
|
"Destination does not fit within the heap region, addr=0x{:016X}, "
|
||||||
"size=0x{:016X}, end_addr=0x{:016X}",
|
"size=0x{:016X}",
|
||||||
dst_addr, size, dst_end_address);
|
dst_addr, size);
|
||||||
return ERR_INVALID_MEMORY_RANGE;
|
return ERR_INVALID_MEMORY_RANGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dst_end_address > vm_manager.GetMapRegionBaseAddress() &&
|
if (manager.IsInsideAliasRegion(dst_addr, size)) {
|
||||||
vm_manager.GetMapRegionEndAddress() > dst_addr) {
|
|
||||||
LOG_ERROR(Kernel_SVC,
|
LOG_ERROR(Kernel_SVC,
|
||||||
"Destination does not fit within the map region, addr=0x{:016X}, "
|
"Destination does not fit within the map region, addr=0x{:016X}, "
|
||||||
"size=0x{:016X}, end_addr=0x{:016X}",
|
"size=0x{:016X}",
|
||||||
dst_addr, size, dst_end_address);
|
dst_addr, size);
|
||||||
return ERR_INVALID_MEMORY_RANGE;
|
return ERR_INVALID_MEMORY_RANGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -178,13 +177,10 @@ static ResultCode SetHeapSize(Core::System& system, VAddr* heap_addr, u64 heap_s
|
|||||||
return ERR_INVALID_SIZE;
|
return ERR_INVALID_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& vm_manager = system.Kernel().CurrentProcess()->VMManager();
|
auto& page_table{system.Kernel().CurrentProcess()->PageTable()};
|
||||||
const auto alloc_result = vm_manager.SetHeapSize(heap_size);
|
|
||||||
if (alloc_result.Failed()) {
|
CASCADE_RESULT(*heap_addr, page_table.SetHeapSize(heap_size));
|
||||||
return alloc_result.Code();
|
|
||||||
}
|
|
||||||
|
|
||||||
*heap_addr = *alloc_result;
|
|
||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -195,63 +191,6 @@ static ResultCode SetHeapSize32(Core::System& system, u32* heap_addr, u32 heap_s
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ResultCode SetMemoryPermission(Core::System& system, VAddr addr, u64 size, u32 prot) {
|
|
||||||
LOG_TRACE(Kernel_SVC, "called, addr=0x{:X}, size=0x{:X}, prot=0x{:X}", addr, size, prot);
|
|
||||||
|
|
||||||
if (!Common::Is4KBAligned(addr)) {
|
|
||||||
LOG_ERROR(Kernel_SVC, "Address is not aligned to 4KB, addr=0x{:016X}", addr);
|
|
||||||
return ERR_INVALID_ADDRESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (size == 0) {
|
|
||||||
LOG_ERROR(Kernel_SVC, "Size is 0");
|
|
||||||
return ERR_INVALID_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Common::Is4KBAligned(size)) {
|
|
||||||
LOG_ERROR(Kernel_SVC, "Size is not aligned to 4KB, size=0x{:016X}", size);
|
|
||||||
return ERR_INVALID_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!IsValidAddressRange(addr, size)) {
|
|
||||||
LOG_ERROR(Kernel_SVC, "Region is not a valid address range, addr=0x{:016X}, size=0x{:016X}",
|
|
||||||
addr, size);
|
|
||||||
return ERR_INVALID_ADDRESS_STATE;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto permission = static_cast<MemoryPermission>(prot);
|
|
||||||
if (permission != MemoryPermission::None && permission != MemoryPermission::Read &&
|
|
||||||
permission != MemoryPermission::ReadWrite) {
|
|
||||||
LOG_ERROR(Kernel_SVC, "Invalid memory permission specified, Got memory permission=0x{:08X}",
|
|
||||||
static_cast<u32>(permission));
|
|
||||||
return ERR_INVALID_MEMORY_PERMISSIONS;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* const current_process = system.Kernel().CurrentProcess();
|
|
||||||
auto& vm_manager = current_process->VMManager();
|
|
||||||
|
|
||||||
if (!vm_manager.IsWithinAddressSpace(addr, size)) {
|
|
||||||
LOG_ERROR(Kernel_SVC,
|
|
||||||
"Source is not within the address space, addr=0x{:016X}, size=0x{:016X}", addr,
|
|
||||||
size);
|
|
||||||
return ERR_INVALID_ADDRESS_STATE;
|
|
||||||
}
|
|
||||||
|
|
||||||
const VMManager::VMAHandle iter = vm_manager.FindVMA(addr);
|
|
||||||
if (!vm_manager.IsValidHandle(iter)) {
|
|
||||||
LOG_ERROR(Kernel_SVC, "Unable to find VMA for address=0x{:016X}", addr);
|
|
||||||
return ERR_INVALID_ADDRESS_STATE;
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG_WARNING(Kernel_SVC, "Uniformity check on protected memory is not implemented.");
|
|
||||||
// TODO: Performs a uniformity check to make sure only protected memory is changed (it doesn't
|
|
||||||
// make sense to allow changing permissions on kernel memory itself, etc).
|
|
||||||
|
|
||||||
const auto converted_permissions = SharedMemory::ConvertPermissions(permission);
|
|
||||||
|
|
||||||
return vm_manager.ReprotectRange(addr, size, converted_permissions);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ResultCode SetMemoryAttribute(Core::System& system, VAddr address, u64 size, u32 mask,
|
static ResultCode SetMemoryAttribute(Core::System& system, VAddr address, u64 size, u32 mask,
|
||||||
u32 attribute) {
|
u32 attribute) {
|
||||||
LOG_DEBUG(Kernel_SVC,
|
LOG_DEBUG(Kernel_SVC,
|
||||||
@ -275,30 +214,19 @@ static ResultCode SetMemoryAttribute(Core::System& system, VAddr address, u64 si
|
|||||||
return ERR_INVALID_ADDRESS_STATE;
|
return ERR_INVALID_ADDRESS_STATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto mem_attribute = static_cast<MemoryAttribute>(attribute);
|
const auto attributes{static_cast<Memory::MemoryAttribute>(mask | attribute)};
|
||||||
const auto mem_mask = static_cast<MemoryAttribute>(mask);
|
if (attributes != static_cast<Memory::MemoryAttribute>(mask) ||
|
||||||
const auto attribute_with_mask = mem_attribute | mem_mask;
|
(attributes | Memory::MemoryAttribute::Uncached) != Memory::MemoryAttribute::Uncached) {
|
||||||
|
|
||||||
if (attribute_with_mask != mem_mask) {
|
|
||||||
LOG_ERROR(Kernel_SVC,
|
LOG_ERROR(Kernel_SVC,
|
||||||
"Memory attribute doesn't match the given mask (Attribute: 0x{:X}, Mask: {:X}",
|
"Memory attribute doesn't match the given mask (Attribute: 0x{:X}, Mask: {:X}",
|
||||||
attribute, mask);
|
attribute, mask);
|
||||||
return ERR_INVALID_COMBINATION;
|
return ERR_INVALID_COMBINATION;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((attribute_with_mask | MemoryAttribute::Uncached) != MemoryAttribute::Uncached) {
|
auto& page_table{system.Kernel().CurrentProcess()->PageTable()};
|
||||||
LOG_ERROR(Kernel_SVC, "Specified attribute isn't equal to MemoryAttributeUncached (8).");
|
|
||||||
return ERR_INVALID_COMBINATION;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto& vm_manager = system.Kernel().CurrentProcess()->VMManager();
|
return page_table.SetMemoryAttribute(address, size, static_cast<Memory::MemoryAttribute>(mask),
|
||||||
if (!vm_manager.IsWithinAddressSpace(address, size)) {
|
static_cast<Memory::MemoryAttribute>(attribute));
|
||||||
LOG_ERROR(Kernel_SVC,
|
|
||||||
"Given address (0x{:016X}) is outside the bounds of the address space.", address);
|
|
||||||
return ERR_INVALID_ADDRESS_STATE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return vm_manager.SetMemoryAttribute(address, size, mem_mask, mem_attribute);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Maps a memory range into a different range.
|
/// Maps a memory range into a different range.
|
||||||
@ -306,14 +234,14 @@ static ResultCode MapMemory(Core::System& system, VAddr dst_addr, VAddr src_addr
|
|||||||
LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr,
|
LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr,
|
||||||
src_addr, size);
|
src_addr, size);
|
||||||
|
|
||||||
auto& vm_manager = system.Kernel().CurrentProcess()->VMManager();
|
auto& page_table{system.Kernel().CurrentProcess()->PageTable()};
|
||||||
const auto result = MapUnmapMemorySanityChecks(vm_manager, dst_addr, src_addr, size);
|
|
||||||
|
|
||||||
if (result.IsError()) {
|
if (const ResultCode result{MapUnmapMemorySanityChecks(page_table, dst_addr, src_addr, size)};
|
||||||
|
result.IsError()) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
return vm_manager.MirrorMemory(dst_addr, src_addr, size, MemoryState::Stack);
|
return page_table.Map(dst_addr, src_addr, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Unmaps a region that was previously mapped with svcMapMemory
|
/// Unmaps a region that was previously mapped with svcMapMemory
|
||||||
@ -321,21 +249,14 @@ static ResultCode UnmapMemory(Core::System& system, VAddr dst_addr, VAddr src_ad
|
|||||||
LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr,
|
LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr,
|
||||||
src_addr, size);
|
src_addr, size);
|
||||||
|
|
||||||
auto& vm_manager = system.Kernel().CurrentProcess()->VMManager();
|
auto& page_table{system.Kernel().CurrentProcess()->PageTable()};
|
||||||
const auto result = MapUnmapMemorySanityChecks(vm_manager, dst_addr, src_addr, size);
|
|
||||||
|
|
||||||
if (result.IsError()) {
|
if (const ResultCode result{MapUnmapMemorySanityChecks(page_table, dst_addr, src_addr, size)};
|
||||||
|
result.IsError()) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto unmap_res = vm_manager.UnmapRange(dst_addr, size);
|
return page_table.Unmap(dst_addr, src_addr, size);
|
||||||
|
|
||||||
// Reprotect the source mapping on success
|
|
||||||
if (unmap_res.IsSuccess()) {
|
|
||||||
ASSERT(vm_manager.ReprotectRange(src_addr, size, VMAPermission::ReadWrite).IsSuccess());
|
|
||||||
}
|
|
||||||
|
|
||||||
return unmap_res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Connect to an OS service given the port name, returns the handle to the port to out
|
/// Connect to an OS service given the port name, returns the handle to the port to out
|
||||||
@ -368,6 +289,8 @@ static ResultCode ConnectToNamedPort(Core::System& system, Handle* out_handle,
|
|||||||
return ERR_NOT_FOUND;
|
return ERR_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ASSERT(kernel.CurrentProcess()->GetResourceLimit()->Reserve(ResourceType::Sessions, 1));
|
||||||
|
|
||||||
auto client_port = it->second;
|
auto client_port = it->second;
|
||||||
|
|
||||||
std::shared_ptr<ClientSession> client_session;
|
std::shared_ptr<ClientSession> client_session;
|
||||||
@ -684,7 +607,6 @@ static void Break(Core::System& system, u32 reason, u64 info1, u64 info2) {
|
|||||||
auto* const current_thread = system.CurrentScheduler().GetCurrentThread();
|
auto* const current_thread = system.CurrentScheduler().GetCurrentThread();
|
||||||
const auto thread_processor_id = current_thread->GetProcessorID();
|
const auto thread_processor_id = current_thread->GetProcessorID();
|
||||||
system.ArmInterface(static_cast<std::size_t>(thread_processor_id)).LogBacktrace();
|
system.ArmInterface(static_cast<std::size_t>(thread_processor_id)).LogBacktrace();
|
||||||
ASSERT(false);
|
|
||||||
|
|
||||||
system.Kernel().CurrentProcess()->PrepareForTermination();
|
system.Kernel().CurrentProcess()->PrepareForTermination();
|
||||||
|
|
||||||
@ -786,35 +708,35 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, u64 ha
|
|||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
|
|
||||||
case GetInfoType::MapRegionBaseAddr:
|
case GetInfoType::MapRegionBaseAddr:
|
||||||
*result = process->VMManager().GetMapRegionBaseAddress();
|
*result = process->PageTable().GetAliasRegionStart();
|
||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
|
|
||||||
case GetInfoType::MapRegionSize:
|
case GetInfoType::MapRegionSize:
|
||||||
*result = process->VMManager().GetMapRegionSize();
|
*result = process->PageTable().GetAliasRegionSize();
|
||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
|
|
||||||
case GetInfoType::HeapRegionBaseAddr:
|
case GetInfoType::HeapRegionBaseAddr:
|
||||||
*result = process->VMManager().GetHeapRegionBaseAddress();
|
*result = process->PageTable().GetHeapRegionStart();
|
||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
|
|
||||||
case GetInfoType::HeapRegionSize:
|
case GetInfoType::HeapRegionSize:
|
||||||
*result = process->VMManager().GetHeapRegionSize();
|
*result = process->PageTable().GetHeapRegionSize();
|
||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
|
|
||||||
case GetInfoType::ASLRRegionBaseAddr:
|
case GetInfoType::ASLRRegionBaseAddr:
|
||||||
*result = process->VMManager().GetASLRRegionBaseAddress();
|
*result = process->PageTable().GetAliasCodeRegionStart();
|
||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
|
|
||||||
case GetInfoType::ASLRRegionSize:
|
case GetInfoType::ASLRRegionSize:
|
||||||
*result = process->VMManager().GetASLRRegionSize();
|
*result = process->PageTable().GetAliasCodeRegionSize();
|
||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
|
|
||||||
case GetInfoType::StackRegionBaseAddr:
|
case GetInfoType::StackRegionBaseAddr:
|
||||||
*result = process->VMManager().GetStackRegionBaseAddress();
|
*result = process->PageTable().GetStackRegionStart();
|
||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
|
|
||||||
case GetInfoType::StackRegionSize:
|
case GetInfoType::StackRegionSize:
|
||||||
*result = process->VMManager().GetStackRegionSize();
|
*result = process->PageTable().GetStackRegionSize();
|
||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
|
|
||||||
case GetInfoType::TotalPhysicalMemoryAvailable:
|
case GetInfoType::TotalPhysicalMemoryAvailable:
|
||||||
@ -988,20 +910,29 @@ static ResultCode MapPhysicalMemory(Core::System& system, VAddr addr, u64 size)
|
|||||||
return ERR_INVALID_MEMORY_RANGE;
|
return ERR_INVALID_MEMORY_RANGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
Process* const current_process = system.Kernel().CurrentProcess();
|
Process* const current_process{system.Kernel().CurrentProcess()};
|
||||||
auto& vm_manager = current_process->VMManager();
|
auto& page_table{current_process->PageTable()};
|
||||||
|
|
||||||
if (current_process->GetSystemResourceSize() == 0) {
|
if (current_process->GetSystemResourceSize() == 0) {
|
||||||
LOG_ERROR(Kernel_SVC, "System Resource Size is zero");
|
LOG_ERROR(Kernel_SVC, "System Resource Size is zero");
|
||||||
return ERR_INVALID_STATE;
|
return ERR_INVALID_STATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!vm_manager.IsWithinMapRegion(addr, size)) {
|
if (!page_table.IsInsideAddressSpace(addr, size)) {
|
||||||
LOG_ERROR(Kernel_SVC, "Range not within map region");
|
LOG_ERROR(Kernel_SVC,
|
||||||
|
"Address is not within the address space, addr=0x{:016X}, size=0x{:016X}", addr,
|
||||||
|
size);
|
||||||
return ERR_INVALID_MEMORY_RANGE;
|
return ERR_INVALID_MEMORY_RANGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return vm_manager.MapPhysicalMemory(addr, size);
|
if (page_table.IsOutsideAliasRegion(addr, size)) {
|
||||||
|
LOG_ERROR(Kernel_SVC,
|
||||||
|
"Address is not within the alias region, addr=0x{:016X}, size=0x{:016X}", addr,
|
||||||
|
size);
|
||||||
|
return ERR_INVALID_MEMORY_RANGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return page_table.MapPhysicalMemory(addr, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Unmaps memory previously mapped via MapPhysicalMemory
|
/// Unmaps memory previously mapped via MapPhysicalMemory
|
||||||
@ -1028,20 +959,29 @@ static ResultCode UnmapPhysicalMemory(Core::System& system, VAddr addr, u64 size
|
|||||||
return ERR_INVALID_MEMORY_RANGE;
|
return ERR_INVALID_MEMORY_RANGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
Process* const current_process = system.Kernel().CurrentProcess();
|
Process* const current_process{system.Kernel().CurrentProcess()};
|
||||||
auto& vm_manager = current_process->VMManager();
|
auto& page_table{current_process->PageTable()};
|
||||||
|
|
||||||
if (current_process->GetSystemResourceSize() == 0) {
|
if (current_process->GetSystemResourceSize() == 0) {
|
||||||
LOG_ERROR(Kernel_SVC, "System Resource Size is zero");
|
LOG_ERROR(Kernel_SVC, "System Resource Size is zero");
|
||||||
return ERR_INVALID_STATE;
|
return ERR_INVALID_STATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!vm_manager.IsWithinMapRegion(addr, size)) {
|
if (!page_table.IsInsideAddressSpace(addr, size)) {
|
||||||
LOG_ERROR(Kernel_SVC, "Range not within map region");
|
LOG_ERROR(Kernel_SVC,
|
||||||
|
"Address is not within the address space, addr=0x{:016X}, size=0x{:016X}", addr,
|
||||||
|
size);
|
||||||
return ERR_INVALID_MEMORY_RANGE;
|
return ERR_INVALID_MEMORY_RANGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return vm_manager.UnmapPhysicalMemory(addr, size);
|
if (page_table.IsOutsideAliasRegion(addr, size)) {
|
||||||
|
LOG_ERROR(Kernel_SVC,
|
||||||
|
"Address is not within the alias region, addr=0x{:016X}, size=0x{:016X}", addr,
|
||||||
|
size);
|
||||||
|
return ERR_INVALID_MEMORY_RANGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return page_table.UnmapPhysicalMemory(addr, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the thread activity
|
/// Sets the thread activity
|
||||||
@ -1198,74 +1138,49 @@ static ResultCode MapSharedMemory(Core::System& system, Handle shared_memory_han
|
|||||||
return ERR_INVALID_ADDRESS_STATE;
|
return ERR_INVALID_ADDRESS_STATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto permissions_type = static_cast<MemoryPermission>(permissions);
|
const auto permission_type = static_cast<Memory::MemoryPermission>(permissions);
|
||||||
if (permissions_type != MemoryPermission::Read &&
|
if ((permission_type | Memory::MemoryPermission::Write) !=
|
||||||
permissions_type != MemoryPermission::ReadWrite) {
|
Memory::MemoryPermission::ReadAndWrite) {
|
||||||
LOG_ERROR(Kernel_SVC, "Expected Read or ReadWrite permission but got permissions=0x{:08X}",
|
LOG_ERROR(Kernel_SVC, "Expected Read or ReadWrite permission but got permissions=0x{:08X}",
|
||||||
permissions);
|
permissions);
|
||||||
return ERR_INVALID_MEMORY_PERMISSIONS;
|
return ERR_INVALID_MEMORY_PERMISSIONS;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* const current_process = system.Kernel().CurrentProcess();
|
auto* const current_process{system.Kernel().CurrentProcess()};
|
||||||
auto shared_memory = current_process->GetHandleTable().Get<SharedMemory>(shared_memory_handle);
|
auto& page_table{current_process->PageTable()};
|
||||||
|
|
||||||
|
if (page_table.IsInvalidRegion(addr, size)) {
|
||||||
|
LOG_ERROR(Kernel_SVC,
|
||||||
|
"Addr does not fit within the valid region, addr=0x{:016X}, "
|
||||||
|
"size=0x{:016X}",
|
||||||
|
addr, size);
|
||||||
|
return ERR_INVALID_MEMORY_RANGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (page_table.IsInsideHeapRegion(addr, size)) {
|
||||||
|
LOG_ERROR(Kernel_SVC,
|
||||||
|
"Addr does not fit within the heap region, addr=0x{:016X}, "
|
||||||
|
"size=0x{:016X}",
|
||||||
|
addr, size);
|
||||||
|
return ERR_INVALID_MEMORY_RANGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (page_table.IsInsideAliasRegion(addr, size)) {
|
||||||
|
LOG_ERROR(Kernel_SVC,
|
||||||
|
"Address does not fit within the map region, addr=0x{:016X}, "
|
||||||
|
"size=0x{:016X}",
|
||||||
|
addr, size);
|
||||||
|
return ERR_INVALID_MEMORY_RANGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto shared_memory{current_process->GetHandleTable().Get<SharedMemory>(shared_memory_handle)};
|
||||||
if (!shared_memory) {
|
if (!shared_memory) {
|
||||||
LOG_ERROR(Kernel_SVC, "Shared memory does not exist, shared_memory_handle=0x{:08X}",
|
LOG_ERROR(Kernel_SVC, "Shared memory does not exist, shared_memory_handle=0x{:08X}",
|
||||||
shared_memory_handle);
|
shared_memory_handle);
|
||||||
return ERR_INVALID_HANDLE;
|
return ERR_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& vm_manager = current_process->VMManager();
|
return shared_memory->Map(*current_process, addr, size, permission_type);
|
||||||
if (!vm_manager.IsWithinASLRRegion(addr, size)) {
|
|
||||||
LOG_ERROR(Kernel_SVC, "Region is not within the ASLR region. addr=0x{:016X}, size={:016X}",
|
|
||||||
addr, size);
|
|
||||||
return ERR_INVALID_MEMORY_RANGE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return shared_memory->Map(*current_process, addr, permissions_type, MemoryPermission::DontCare);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ResultCode UnmapSharedMemory(Core::System& system, Handle shared_memory_handle, VAddr addr,
|
|
||||||
u64 size) {
|
|
||||||
LOG_WARNING(Kernel_SVC, "called, shared_memory_handle=0x{:08X}, addr=0x{:X}, size=0x{:X}",
|
|
||||||
shared_memory_handle, addr, size);
|
|
||||||
|
|
||||||
if (!Common::Is4KBAligned(addr)) {
|
|
||||||
LOG_ERROR(Kernel_SVC, "Address is not aligned to 4KB, addr=0x{:016X}", addr);
|
|
||||||
return ERR_INVALID_ADDRESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (size == 0) {
|
|
||||||
LOG_ERROR(Kernel_SVC, "Size is 0");
|
|
||||||
return ERR_INVALID_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Common::Is4KBAligned(size)) {
|
|
||||||
LOG_ERROR(Kernel_SVC, "Size is not aligned to 4KB, size=0x{:016X}", size);
|
|
||||||
return ERR_INVALID_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!IsValidAddressRange(addr, size)) {
|
|
||||||
LOG_ERROR(Kernel_SVC, "Region is not a valid address range, addr=0x{:016X}, size=0x{:016X}",
|
|
||||||
addr, size);
|
|
||||||
return ERR_INVALID_ADDRESS_STATE;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* const current_process = system.Kernel().CurrentProcess();
|
|
||||||
auto shared_memory = current_process->GetHandleTable().Get<SharedMemory>(shared_memory_handle);
|
|
||||||
if (!shared_memory) {
|
|
||||||
LOG_ERROR(Kernel_SVC, "Shared memory does not exist, shared_memory_handle=0x{:08X}",
|
|
||||||
shared_memory_handle);
|
|
||||||
return ERR_INVALID_HANDLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto& vm_manager = current_process->VMManager();
|
|
||||||
if (!vm_manager.IsWithinASLRRegion(addr, size)) {
|
|
||||||
LOG_ERROR(Kernel_SVC, "Region is not within the ASLR region. addr=0x{:016X}, size={:016X}",
|
|
||||||
addr, size);
|
|
||||||
return ERR_INVALID_MEMORY_RANGE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return shared_memory->Unmap(*current_process, addr, size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static ResultCode QueryProcessMemory(Core::System& system, VAddr memory_info_address,
|
static ResultCode QueryProcessMemory(Core::System& system, VAddr memory_info_address,
|
||||||
@ -1280,18 +1195,17 @@ static ResultCode QueryProcessMemory(Core::System& system, VAddr memory_info_add
|
|||||||
return ERR_INVALID_HANDLE;
|
return ERR_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& memory = system.Memory();
|
auto& memory{system.Memory()};
|
||||||
const auto& vm_manager = process->VMManager();
|
const Svc::MemoryInfo memory_info{process->PageTable().QueryInfo(address).GetSvcMemoryInfo()};
|
||||||
const MemoryInfo memory_info = vm_manager.QueryMemory(address);
|
|
||||||
|
|
||||||
memory.Write64(memory_info_address, memory_info.base_address);
|
memory.Write64(memory_info_address + 0x00, memory_info.addr);
|
||||||
memory.Write64(memory_info_address + 8, memory_info.size);
|
memory.Write64(memory_info_address + 0x08, memory_info.size);
|
||||||
memory.Write32(memory_info_address + 16, memory_info.state);
|
memory.Write32(memory_info_address + 0x10, static_cast<u32>(memory_info.state) & 0xff);
|
||||||
memory.Write32(memory_info_address + 20, memory_info.attributes);
|
memory.Write32(memory_info_address + 0x14, static_cast<u32>(memory_info.attr));
|
||||||
memory.Write32(memory_info_address + 24, memory_info.permission);
|
memory.Write32(memory_info_address + 0x18, static_cast<u32>(memory_info.perm));
|
||||||
memory.Write32(memory_info_address + 32, memory_info.ipc_ref_count);
|
memory.Write32(memory_info_address + 0x1c, memory_info.ipc_refcount);
|
||||||
memory.Write32(memory_info_address + 28, memory_info.device_ref_count);
|
memory.Write32(memory_info_address + 0x20, memory_info.device_refcount);
|
||||||
memory.Write32(memory_info_address + 36, 0);
|
memory.Write32(memory_info_address + 0x24, 0);
|
||||||
|
|
||||||
// Page info appears to be currently unused by the kernel and is always set to zero.
|
// Page info appears to be currently unused by the kernel and is always set to zero.
|
||||||
memory.Write32(page_info_address, 0);
|
memory.Write32(page_info_address, 0);
|
||||||
@ -1315,142 +1229,6 @@ static ResultCode QueryMemory32(Core::System& system, u32 memory_info_address,
|
|||||||
return QueryMemory(system, memory_info_address, page_info_address, query_address);
|
return QueryMemory(system, memory_info_address, page_info_address, query_address);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ResultCode MapProcessCodeMemory(Core::System& system, Handle process_handle, u64 dst_address,
|
|
||||||
u64 src_address, u64 size) {
|
|
||||||
LOG_DEBUG(Kernel_SVC,
|
|
||||||
"called. process_handle=0x{:08X}, dst_address=0x{:016X}, "
|
|
||||||
"src_address=0x{:016X}, size=0x{:016X}",
|
|
||||||
process_handle, dst_address, src_address, size);
|
|
||||||
|
|
||||||
if (!Common::Is4KBAligned(src_address)) {
|
|
||||||
LOG_ERROR(Kernel_SVC, "src_address is not page-aligned (src_address=0x{:016X}).",
|
|
||||||
src_address);
|
|
||||||
return ERR_INVALID_ADDRESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Common::Is4KBAligned(dst_address)) {
|
|
||||||
LOG_ERROR(Kernel_SVC, "dst_address is not page-aligned (dst_address=0x{:016X}).",
|
|
||||||
dst_address);
|
|
||||||
return ERR_INVALID_ADDRESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (size == 0 || !Common::Is4KBAligned(size)) {
|
|
||||||
LOG_ERROR(Kernel_SVC, "Size is zero or not page-aligned (size=0x{:016X})", size);
|
|
||||||
return ERR_INVALID_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!IsValidAddressRange(dst_address, size)) {
|
|
||||||
LOG_ERROR(Kernel_SVC,
|
|
||||||
"Destination address range overflows the address space (dst_address=0x{:016X}, "
|
|
||||||
"size=0x{:016X}).",
|
|
||||||
dst_address, size);
|
|
||||||
return ERR_INVALID_ADDRESS_STATE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!IsValidAddressRange(src_address, size)) {
|
|
||||||
LOG_ERROR(Kernel_SVC,
|
|
||||||
"Source address range overflows the address space (src_address=0x{:016X}, "
|
|
||||||
"size=0x{:016X}).",
|
|
||||||
src_address, size);
|
|
||||||
return ERR_INVALID_ADDRESS_STATE;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
|
|
||||||
auto process = handle_table.Get<Process>(process_handle);
|
|
||||||
if (!process) {
|
|
||||||
LOG_ERROR(Kernel_SVC, "Invalid process handle specified (handle=0x{:08X}).",
|
|
||||||
process_handle);
|
|
||||||
return ERR_INVALID_HANDLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto& vm_manager = process->VMManager();
|
|
||||||
if (!vm_manager.IsWithinAddressSpace(src_address, size)) {
|
|
||||||
LOG_ERROR(Kernel_SVC,
|
|
||||||
"Source address range is not within the address space (src_address=0x{:016X}, "
|
|
||||||
"size=0x{:016X}).",
|
|
||||||
src_address, size);
|
|
||||||
return ERR_INVALID_ADDRESS_STATE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!vm_manager.IsWithinASLRRegion(dst_address, size)) {
|
|
||||||
LOG_ERROR(Kernel_SVC,
|
|
||||||
"Destination address range is not within the ASLR region (dst_address=0x{:016X}, "
|
|
||||||
"size=0x{:016X}).",
|
|
||||||
dst_address, size);
|
|
||||||
return ERR_INVALID_MEMORY_RANGE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return vm_manager.MapCodeMemory(dst_address, src_address, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ResultCode UnmapProcessCodeMemory(Core::System& system, Handle process_handle,
|
|
||||||
u64 dst_address, u64 src_address, u64 size) {
|
|
||||||
LOG_DEBUG(Kernel_SVC,
|
|
||||||
"called. process_handle=0x{:08X}, dst_address=0x{:016X}, src_address=0x{:016X}, "
|
|
||||||
"size=0x{:016X}",
|
|
||||||
process_handle, dst_address, src_address, size);
|
|
||||||
|
|
||||||
if (!Common::Is4KBAligned(dst_address)) {
|
|
||||||
LOG_ERROR(Kernel_SVC, "dst_address is not page-aligned (dst_address=0x{:016X}).",
|
|
||||||
dst_address);
|
|
||||||
return ERR_INVALID_ADDRESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Common::Is4KBAligned(src_address)) {
|
|
||||||
LOG_ERROR(Kernel_SVC, "src_address is not page-aligned (src_address=0x{:016X}).",
|
|
||||||
src_address);
|
|
||||||
return ERR_INVALID_ADDRESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (size == 0 || Common::Is4KBAligned(size)) {
|
|
||||||
LOG_ERROR(Kernel_SVC, "Size is zero or not page-aligned (size=0x{:016X}).", size);
|
|
||||||
return ERR_INVALID_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!IsValidAddressRange(dst_address, size)) {
|
|
||||||
LOG_ERROR(Kernel_SVC,
|
|
||||||
"Destination address range overflows the address space (dst_address=0x{:016X}, "
|
|
||||||
"size=0x{:016X}).",
|
|
||||||
dst_address, size);
|
|
||||||
return ERR_INVALID_ADDRESS_STATE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!IsValidAddressRange(src_address, size)) {
|
|
||||||
LOG_ERROR(Kernel_SVC,
|
|
||||||
"Source address range overflows the address space (src_address=0x{:016X}, "
|
|
||||||
"size=0x{:016X}).",
|
|
||||||
src_address, size);
|
|
||||||
return ERR_INVALID_ADDRESS_STATE;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
|
|
||||||
auto process = handle_table.Get<Process>(process_handle);
|
|
||||||
if (!process) {
|
|
||||||
LOG_ERROR(Kernel_SVC, "Invalid process handle specified (handle=0x{:08X}).",
|
|
||||||
process_handle);
|
|
||||||
return ERR_INVALID_HANDLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto& vm_manager = process->VMManager();
|
|
||||||
if (!vm_manager.IsWithinAddressSpace(src_address, size)) {
|
|
||||||
LOG_ERROR(Kernel_SVC,
|
|
||||||
"Source address range is not within the address space (src_address=0x{:016X}, "
|
|
||||||
"size=0x{:016X}).",
|
|
||||||
src_address, size);
|
|
||||||
return ERR_INVALID_ADDRESS_STATE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!vm_manager.IsWithinASLRRegion(dst_address, size)) {
|
|
||||||
LOG_ERROR(Kernel_SVC,
|
|
||||||
"Destination address range is not within the ASLR region (dst_address=0x{:016X}, "
|
|
||||||
"size=0x{:016X}).",
|
|
||||||
dst_address, size);
|
|
||||||
return ERR_INVALID_MEMORY_RANGE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return vm_manager.UnmapCodeMemory(dst_address, src_address, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Exits the current process
|
/// Exits the current process
|
||||||
static void ExitProcess(Core::System& system) {
|
static void ExitProcess(Core::System& system) {
|
||||||
auto* current_process = system.Kernel().CurrentProcess();
|
auto* current_process = system.Kernel().CurrentProcess();
|
||||||
@ -1507,6 +1285,9 @@ static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr e
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto& kernel = system.Kernel();
|
auto& kernel = system.Kernel();
|
||||||
|
|
||||||
|
ASSERT(kernel.CurrentProcess()->GetResourceLimit()->Reserve(ResourceType::Threads, 1));
|
||||||
|
|
||||||
CASCADE_RESULT(std::shared_ptr<Thread> thread,
|
CASCADE_RESULT(std::shared_ptr<Thread> thread,
|
||||||
Thread::Create(kernel, "", entry_point, priority, arg, processor_id, stack_top,
|
Thread::Create(kernel, "", entry_point, priority, arg, processor_id, stack_top,
|
||||||
*current_process));
|
*current_process));
|
||||||
@ -1866,9 +1647,9 @@ static ResultCode CreateTransferMemory(Core::System& system, Handle* handle, VAd
|
|||||||
return ERR_INVALID_ADDRESS_STATE;
|
return ERR_INVALID_ADDRESS_STATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto perms = static_cast<MemoryPermission>(permissions);
|
const auto perms{static_cast<Memory::MemoryPermission>(permissions)};
|
||||||
if (perms != MemoryPermission::None && perms != MemoryPermission::Read &&
|
if (perms > Memory::MemoryPermission::ReadAndWrite ||
|
||||||
perms != MemoryPermission::ReadWrite) {
|
perms == Memory::MemoryPermission::Write) {
|
||||||
LOG_ERROR(Kernel_SVC, "Invalid memory permissions for transfer memory! (perms={:08X})",
|
LOG_ERROR(Kernel_SVC, "Invalid memory permissions for transfer memory! (perms={:08X})",
|
||||||
permissions);
|
permissions);
|
||||||
return ERR_INVALID_MEMORY_PERMISSIONS;
|
return ERR_INVALID_MEMORY_PERMISSIONS;
|
||||||
@ -1891,111 +1672,6 @@ static ResultCode CreateTransferMemory(Core::System& system, Handle* handle, VAd
|
|||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ResultCode MapTransferMemory(Core::System& system, Handle handle, VAddr address, u64 size,
|
|
||||||
u32 permission_raw) {
|
|
||||||
LOG_DEBUG(Kernel_SVC,
|
|
||||||
"called. handle=0x{:08X}, address=0x{:016X}, size=0x{:016X}, permissions=0x{:08X}",
|
|
||||||
handle, address, size, permission_raw);
|
|
||||||
|
|
||||||
if (!Common::Is4KBAligned(address)) {
|
|
||||||
LOG_ERROR(Kernel_SVC, "Transfer memory addresses must be 4KB aligned (size=0x{:016X}).",
|
|
||||||
address);
|
|
||||||
return ERR_INVALID_ADDRESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (size == 0 || !Common::Is4KBAligned(size)) {
|
|
||||||
LOG_ERROR(Kernel_SVC,
|
|
||||||
"Transfer memory sizes must be 4KB aligned and not be zero (size=0x{:016X}).",
|
|
||||||
size);
|
|
||||||
return ERR_INVALID_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!IsValidAddressRange(address, size)) {
|
|
||||||
LOG_ERROR(Kernel_SVC,
|
|
||||||
"Given address and size overflows the 64-bit range (address=0x{:016X}, "
|
|
||||||
"size=0x{:016X}).",
|
|
||||||
address, size);
|
|
||||||
return ERR_INVALID_ADDRESS_STATE;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto permissions = static_cast<MemoryPermission>(permission_raw);
|
|
||||||
if (permissions != MemoryPermission::None && permissions != MemoryPermission::Read &&
|
|
||||||
permissions != MemoryPermission::ReadWrite) {
|
|
||||||
LOG_ERROR(Kernel_SVC, "Invalid transfer memory permissions given (permissions=0x{:08X}).",
|
|
||||||
permission_raw);
|
|
||||||
return ERR_INVALID_STATE;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto& kernel = system.Kernel();
|
|
||||||
const auto* const current_process = kernel.CurrentProcess();
|
|
||||||
const auto& handle_table = current_process->GetHandleTable();
|
|
||||||
|
|
||||||
auto transfer_memory = handle_table.Get<TransferMemory>(handle);
|
|
||||||
if (!transfer_memory) {
|
|
||||||
LOG_ERROR(Kernel_SVC, "Nonexistent transfer memory handle given (handle=0x{:08X}).",
|
|
||||||
handle);
|
|
||||||
return ERR_INVALID_HANDLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!current_process->VMManager().IsWithinASLRRegion(address, size)) {
|
|
||||||
LOG_ERROR(Kernel_SVC,
|
|
||||||
"Given address and size don't fully fit within the ASLR region "
|
|
||||||
"(address=0x{:016X}, size=0x{:016X}).",
|
|
||||||
address, size);
|
|
||||||
return ERR_INVALID_MEMORY_RANGE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return transfer_memory->MapMemory(address, size, permissions);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ResultCode UnmapTransferMemory(Core::System& system, Handle handle, VAddr address,
|
|
||||||
u64 size) {
|
|
||||||
LOG_DEBUG(Kernel_SVC, "called. handle=0x{:08X}, address=0x{:016X}, size=0x{:016X}", handle,
|
|
||||||
address, size);
|
|
||||||
|
|
||||||
if (!Common::Is4KBAligned(address)) {
|
|
||||||
LOG_ERROR(Kernel_SVC, "Transfer memory addresses must be 4KB aligned (size=0x{:016X}).",
|
|
||||||
address);
|
|
||||||
return ERR_INVALID_ADDRESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (size == 0 || !Common::Is4KBAligned(size)) {
|
|
||||||
LOG_ERROR(Kernel_SVC,
|
|
||||||
"Transfer memory sizes must be 4KB aligned and not be zero (size=0x{:016X}).",
|
|
||||||
size);
|
|
||||||
return ERR_INVALID_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!IsValidAddressRange(address, size)) {
|
|
||||||
LOG_ERROR(Kernel_SVC,
|
|
||||||
"Given address and size overflows the 64-bit range (address=0x{:016X}, "
|
|
||||||
"size=0x{:016X}).",
|
|
||||||
address, size);
|
|
||||||
return ERR_INVALID_ADDRESS_STATE;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto& kernel = system.Kernel();
|
|
||||||
const auto* const current_process = kernel.CurrentProcess();
|
|
||||||
const auto& handle_table = current_process->GetHandleTable();
|
|
||||||
|
|
||||||
auto transfer_memory = handle_table.Get<TransferMemory>(handle);
|
|
||||||
if (!transfer_memory) {
|
|
||||||
LOG_ERROR(Kernel_SVC, "Nonexistent transfer memory handle given (handle=0x{:08X}).",
|
|
||||||
handle);
|
|
||||||
return ERR_INVALID_HANDLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!current_process->VMManager().IsWithinASLRRegion(address, size)) {
|
|
||||||
LOG_ERROR(Kernel_SVC,
|
|
||||||
"Given address and size don't fully fit within the ASLR region "
|
|
||||||
"(address=0x{:016X}, size=0x{:016X}).",
|
|
||||||
address, size);
|
|
||||||
return ERR_INVALID_MEMORY_RANGE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return transfer_memory->UnmapMemory(address, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ResultCode GetThreadCoreMask(Core::System& system, Handle thread_handle, u32* core,
|
static ResultCode GetThreadCoreMask(Core::System& system, Handle thread_handle, u32* core,
|
||||||
u64* mask) {
|
u64* mask) {
|
||||||
LOG_TRACE(Kernel_SVC, "called, handle=0x{:08X}", thread_handle);
|
LOG_TRACE(Kernel_SVC, "called, handle=0x{:08X}", thread_handle);
|
||||||
@ -2074,52 +1750,6 @@ static ResultCode SetThreadCoreMask(Core::System& system, Handle thread_handle,
|
|||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ResultCode CreateSharedMemory(Core::System& system, Handle* handle, u64 size,
|
|
||||||
u32 local_permissions, u32 remote_permissions) {
|
|
||||||
LOG_TRACE(Kernel_SVC, "called, size=0x{:X}, localPerms=0x{:08X}, remotePerms=0x{:08X}", size,
|
|
||||||
local_permissions, remote_permissions);
|
|
||||||
if (size == 0) {
|
|
||||||
LOG_ERROR(Kernel_SVC, "Size is 0");
|
|
||||||
return ERR_INVALID_SIZE;
|
|
||||||
}
|
|
||||||
if (!Common::Is4KBAligned(size)) {
|
|
||||||
LOG_ERROR(Kernel_SVC, "Size is not aligned to 4KB, 0x{:016X}", size);
|
|
||||||
return ERR_INVALID_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (size >= MAIN_MEMORY_SIZE) {
|
|
||||||
LOG_ERROR(Kernel_SVC, "Size is not less than 8GB, 0x{:016X}", size);
|
|
||||||
return ERR_INVALID_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto local_perms = static_cast<MemoryPermission>(local_permissions);
|
|
||||||
if (local_perms != MemoryPermission::Read && local_perms != MemoryPermission::ReadWrite) {
|
|
||||||
LOG_ERROR(Kernel_SVC,
|
|
||||||
"Invalid local memory permissions, expected Read or ReadWrite but got "
|
|
||||||
"local_permissions={}",
|
|
||||||
static_cast<u32>(local_permissions));
|
|
||||||
return ERR_INVALID_MEMORY_PERMISSIONS;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto remote_perms = static_cast<MemoryPermission>(remote_permissions);
|
|
||||||
if (remote_perms != MemoryPermission::Read && remote_perms != MemoryPermission::ReadWrite &&
|
|
||||||
remote_perms != MemoryPermission::DontCare) {
|
|
||||||
LOG_ERROR(Kernel_SVC,
|
|
||||||
"Invalid remote memory permissions, expected Read, ReadWrite or DontCare but got "
|
|
||||||
"remote_permissions={}",
|
|
||||||
static_cast<u32>(remote_permissions));
|
|
||||||
return ERR_INVALID_MEMORY_PERMISSIONS;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto& kernel = system.Kernel();
|
|
||||||
auto process = kernel.CurrentProcess();
|
|
||||||
auto& handle_table = process->GetHandleTable();
|
|
||||||
auto shared_mem_handle = SharedMemory::Create(kernel, process, size, local_perms, remote_perms);
|
|
||||||
|
|
||||||
CASCADE_RESULT(*handle, handle_table.Create(shared_mem_handle));
|
|
||||||
return RESULT_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ResultCode CreateEvent(Core::System& system, Handle* write_handle, Handle* read_handle) {
|
static ResultCode CreateEvent(Core::System& system, Handle* write_handle, Handle* read_handle) {
|
||||||
LOG_DEBUG(Kernel_SVC, "called");
|
LOG_DEBUG(Kernel_SVC, "called");
|
||||||
|
|
||||||
@ -2306,11 +1936,10 @@ static ResultCode GetProcessList(Core::System& system, u32* out_num_processes,
|
|||||||
}
|
}
|
||||||
|
|
||||||
const auto& kernel = system.Kernel();
|
const auto& kernel = system.Kernel();
|
||||||
const auto& vm_manager = kernel.CurrentProcess()->VMManager();
|
|
||||||
const auto total_copy_size = out_process_ids_size * sizeof(u64);
|
const auto total_copy_size = out_process_ids_size * sizeof(u64);
|
||||||
|
|
||||||
if (out_process_ids_size > 0 &&
|
if (out_process_ids_size > 0 && !kernel.CurrentProcess()->PageTable().IsInsideAddressSpace(
|
||||||
!vm_manager.IsWithinAddressSpace(out_process_ids, total_copy_size)) {
|
out_process_ids, total_copy_size)) {
|
||||||
LOG_ERROR(Kernel_SVC, "Address range outside address space. begin=0x{:016X}, end=0x{:016X}",
|
LOG_ERROR(Kernel_SVC, "Address range outside address space. begin=0x{:016X}, end=0x{:016X}",
|
||||||
out_process_ids, out_process_ids + total_copy_size);
|
out_process_ids, out_process_ids + total_copy_size);
|
||||||
return ERR_INVALID_ADDRESS_STATE;
|
return ERR_INVALID_ADDRESS_STATE;
|
||||||
@ -2346,11 +1975,10 @@ static ResultCode GetThreadList(Core::System& system, u32* out_num_threads, VAdd
|
|||||||
}
|
}
|
||||||
|
|
||||||
const auto* const current_process = system.Kernel().CurrentProcess();
|
const auto* const current_process = system.Kernel().CurrentProcess();
|
||||||
const auto& vm_manager = current_process->VMManager();
|
|
||||||
const auto total_copy_size = out_thread_ids_size * sizeof(u64);
|
const auto total_copy_size = out_thread_ids_size * sizeof(u64);
|
||||||
|
|
||||||
if (out_thread_ids_size > 0 &&
|
if (out_thread_ids_size > 0 &&
|
||||||
!vm_manager.IsWithinAddressSpace(out_thread_ids, total_copy_size)) {
|
!current_process->PageTable().IsInsideAddressSpace(out_thread_ids, total_copy_size)) {
|
||||||
LOG_ERROR(Kernel_SVC, "Address range outside address space. begin=0x{:016X}, end=0x{:016X}",
|
LOG_ERROR(Kernel_SVC, "Address range outside address space. begin=0x{:016X}, end=0x{:016X}",
|
||||||
out_thread_ids, out_thread_ids + total_copy_size);
|
out_thread_ids, out_thread_ids + total_copy_size);
|
||||||
return ERR_INVALID_ADDRESS_STATE;
|
return ERR_INVALID_ADDRESS_STATE;
|
||||||
@ -2511,7 +2139,7 @@ static const FunctionDef SVC_Table_32[] = {
|
|||||||
static const FunctionDef SVC_Table_64[] = {
|
static const FunctionDef SVC_Table_64[] = {
|
||||||
{0x00, nullptr, "Unknown"},
|
{0x00, nullptr, "Unknown"},
|
||||||
{0x01, SvcWrap64<SetHeapSize>, "SetHeapSize"},
|
{0x01, SvcWrap64<SetHeapSize>, "SetHeapSize"},
|
||||||
{0x02, SvcWrap64<SetMemoryPermission>, "SetMemoryPermission"},
|
{0x02, nullptr, "SetMemoryPermission"},
|
||||||
{0x03, SvcWrap64<SetMemoryAttribute>, "SetMemoryAttribute"},
|
{0x03, SvcWrap64<SetMemoryAttribute>, "SetMemoryAttribute"},
|
||||||
{0x04, SvcWrap64<MapMemory>, "MapMemory"},
|
{0x04, SvcWrap64<MapMemory>, "MapMemory"},
|
||||||
{0x05, SvcWrap64<UnmapMemory>, "UnmapMemory"},
|
{0x05, SvcWrap64<UnmapMemory>, "UnmapMemory"},
|
||||||
@ -2529,7 +2157,7 @@ static const FunctionDef SVC_Table_64[] = {
|
|||||||
{0x11, SvcWrap64<SignalEvent>, "SignalEvent"},
|
{0x11, SvcWrap64<SignalEvent>, "SignalEvent"},
|
||||||
{0x12, SvcWrap64<ClearEvent>, "ClearEvent"},
|
{0x12, SvcWrap64<ClearEvent>, "ClearEvent"},
|
||||||
{0x13, SvcWrap64<MapSharedMemory>, "MapSharedMemory"},
|
{0x13, SvcWrap64<MapSharedMemory>, "MapSharedMemory"},
|
||||||
{0x14, SvcWrap64<UnmapSharedMemory>, "UnmapSharedMemory"},
|
{0x14, nullptr, "UnmapSharedMemory"},
|
||||||
{0x15, SvcWrap64<CreateTransferMemory>, "CreateTransferMemory"},
|
{0x15, SvcWrap64<CreateTransferMemory>, "CreateTransferMemory"},
|
||||||
{0x16, SvcWrap64<CloseHandle>, "CloseHandle"},
|
{0x16, SvcWrap64<CloseHandle>, "CloseHandle"},
|
||||||
{0x17, SvcWrap64<ResetSignal>, "ResetSignal"},
|
{0x17, SvcWrap64<ResetSignal>, "ResetSignal"},
|
||||||
@ -2589,9 +2217,9 @@ static const FunctionDef SVC_Table_64[] = {
|
|||||||
{0x4D, nullptr, "SleepSystem"},
|
{0x4D, nullptr, "SleepSystem"},
|
||||||
{0x4E, nullptr, "ReadWriteRegister"},
|
{0x4E, nullptr, "ReadWriteRegister"},
|
||||||
{0x4F, nullptr, "SetProcessActivity"},
|
{0x4F, nullptr, "SetProcessActivity"},
|
||||||
{0x50, SvcWrap64<CreateSharedMemory>, "CreateSharedMemory"},
|
{0x50, nullptr, "CreateSharedMemory"},
|
||||||
{0x51, SvcWrap64<MapTransferMemory>, "MapTransferMemory"},
|
{0x51, nullptr, "MapTransferMemory"},
|
||||||
{0x52, SvcWrap64<UnmapTransferMemory>, "UnmapTransferMemory"},
|
{0x52, nullptr, "UnmapTransferMemory"},
|
||||||
{0x53, nullptr, "CreateInterruptEvent"},
|
{0x53, nullptr, "CreateInterruptEvent"},
|
||||||
{0x54, nullptr, "QueryPhysicalAddress"},
|
{0x54, nullptr, "QueryPhysicalAddress"},
|
||||||
{0x55, nullptr, "QueryIoMapping"},
|
{0x55, nullptr, "QueryIoMapping"},
|
||||||
@ -2628,8 +2256,8 @@ static const FunctionDef SVC_Table_64[] = {
|
|||||||
{0x74, nullptr, "MapProcessMemory"},
|
{0x74, nullptr, "MapProcessMemory"},
|
||||||
{0x75, nullptr, "UnmapProcessMemory"},
|
{0x75, nullptr, "UnmapProcessMemory"},
|
||||||
{0x76, SvcWrap64<QueryProcessMemory>, "QueryProcessMemory"},
|
{0x76, SvcWrap64<QueryProcessMemory>, "QueryProcessMemory"},
|
||||||
{0x77, SvcWrap64<MapProcessCodeMemory>, "MapProcessCodeMemory"},
|
{0x77, nullptr, "MapProcessCodeMemory"},
|
||||||
{0x78, SvcWrap64<UnmapProcessCodeMemory>, "UnmapProcessCodeMemory"},
|
{0x78, nullptr, "UnmapProcessCodeMemory"},
|
||||||
{0x79, nullptr, "CreateProcess"},
|
{0x79, nullptr, "CreateProcess"},
|
||||||
{0x7A, nullptr, "StartProcess"},
|
{0x7A, nullptr, "StartProcess"},
|
||||||
{0x7B, nullptr, "TerminateProcess"},
|
{0x7B, nullptr, "TerminateProcess"},
|
||||||
|
Loading…
Reference in New Issue
Block a user