mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2025-01-08 21:47:57 +00:00
kern: implement SvcUnmapMemory, more of SvcGetInfo
This commit is contained in:
parent
faad5609b9
commit
1a0696f8a3
14 changed files with 231 additions and 37 deletions
|
@ -56,6 +56,10 @@ namespace ams::kern::arch::arm64 {
|
||||||
return this->page_table.QueryInfo(out_info, out_page_info, addr);
|
return this->page_table.QueryInfo(out_info, out_page_info, addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result UnmapMemory(uintptr_t dst_address, uintptr_t src_address, size_t size) {
|
||||||
|
return this->page_table.UnmapMemory(dst_address, src_address, size);
|
||||||
|
}
|
||||||
|
|
||||||
Result MapIo(KPhysicalAddress phys_addr, size_t size, KMemoryPermission perm) {
|
Result MapIo(KPhysicalAddress phys_addr, size_t size, KMemoryPermission perm) {
|
||||||
return this->page_table.MapIo(phys_addr, size, perm);
|
return this->page_table.MapIo(phys_addr, size, perm);
|
||||||
}
|
}
|
||||||
|
@ -109,6 +113,8 @@ namespace ams::kern::arch::arm64 {
|
||||||
size_t GetKernelMapRegionSize() const { return this->page_table.GetKernelMapRegionSize(); }
|
size_t GetKernelMapRegionSize() const { return this->page_table.GetKernelMapRegionSize(); }
|
||||||
size_t GetAliasCodeRegionSize() const { return this->page_table.GetAliasCodeRegionSize(); }
|
size_t GetAliasCodeRegionSize() const { return this->page_table.GetAliasCodeRegionSize(); }
|
||||||
|
|
||||||
|
size_t GetNormalMemorySize() const { return this->page_table.GetNormalMemorySize(); }
|
||||||
|
|
||||||
KPhysicalAddress GetHeapPhysicalAddress(KVirtualAddress address) const {
|
KPhysicalAddress GetHeapPhysicalAddress(KVirtualAddress address) const {
|
||||||
/* TODO: Better way to convert address type? */
|
/* TODO: Better way to convert address type? */
|
||||||
return this->page_table.GetHeapPhysicalAddress(address);
|
return this->page_table.GetHeapPhysicalAddress(address);
|
||||||
|
|
|
@ -67,6 +67,9 @@ namespace ams::kern::board::nintendo::nx {
|
||||||
|
|
||||||
/* User access. */
|
/* User access. */
|
||||||
static void CallSecureMonitorFromUser(ams::svc::lp64::SecureMonitorArguments *args);
|
static void CallSecureMonitorFromUser(ams::svc::lp64::SecureMonitorArguments *args);
|
||||||
|
|
||||||
|
/* Constant calculations. */
|
||||||
|
static size_t CalculateRequiredSecureMemorySize(size_t size, u32 pool);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
|
@ -147,7 +147,11 @@ namespace ams::kern {
|
||||||
if constexpr (std::is_same<T, KAutoObject>::value) {
|
if constexpr (std::is_same<T, KAutoObject>::value) {
|
||||||
return this->GetObjectImpl(handle);
|
return this->GetObjectImpl(handle);
|
||||||
} else {
|
} else {
|
||||||
return this->GetObjectImpl(handle)->DynamicCast<T*>();
|
if (auto *obj = this->GetObjectImpl(handle); obj != nullptr) {
|
||||||
|
return obj->DynamicCast<T*>();
|
||||||
|
} else {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,7 +181,11 @@ namespace ams::kern {
|
||||||
if constexpr (std::is_same<T, KAutoObject>::value) {
|
if constexpr (std::is_same<T, KAutoObject>::value) {
|
||||||
return obj;
|
return obj;
|
||||||
} else {
|
} else {
|
||||||
|
if (auto *obj = this->GetObjectImpl(handle); obj != nullptr) {
|
||||||
return obj->DynamicCast<T*>();
|
return obj->DynamicCast<T*>();
|
||||||
|
} else {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -170,6 +170,8 @@ namespace ams::kern {
|
||||||
KMemoryAttribute_IpcLocked = ams::svc::MemoryAttribute_IpcLocked,
|
KMemoryAttribute_IpcLocked = ams::svc::MemoryAttribute_IpcLocked,
|
||||||
KMemoryAttribute_DeviceShared = ams::svc::MemoryAttribute_DeviceShared,
|
KMemoryAttribute_DeviceShared = ams::svc::MemoryAttribute_DeviceShared,
|
||||||
KMemoryAttribute_Uncached = ams::svc::MemoryAttribute_Uncached,
|
KMemoryAttribute_Uncached = ams::svc::MemoryAttribute_Uncached,
|
||||||
|
|
||||||
|
KMemoryAttribute_AnyLocked = 0x80,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct KMemoryInfo {
|
struct KMemoryInfo {
|
||||||
|
|
|
@ -52,7 +52,6 @@ namespace ams::kern {
|
||||||
OperationType_Unmap = 2,
|
OperationType_Unmap = 2,
|
||||||
OperationType_ChangePermissions = 3,
|
OperationType_ChangePermissions = 3,
|
||||||
OperationType_ChangePermissionsAndRefresh = 4,
|
OperationType_ChangePermissionsAndRefresh = 4,
|
||||||
/* TODO: perm/attr operations */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static constexpr size_t MaxPhysicalMapAlignment = 1_GB;
|
static constexpr size_t MaxPhysicalMapAlignment = 1_GB;
|
||||||
|
@ -134,7 +133,7 @@ namespace ams::kern {
|
||||||
KProcessAddress code_region_start;
|
KProcessAddress code_region_start;
|
||||||
KProcessAddress code_region_end;
|
KProcessAddress code_region_end;
|
||||||
size_t max_heap_size;
|
size_t max_heap_size;
|
||||||
size_t max_physical_memory_size;
|
size_t mapped_physical_memory_size;
|
||||||
size_t mapped_unsafe_physical_memory;
|
size_t mapped_unsafe_physical_memory;
|
||||||
mutable KLightLock general_lock;
|
mutable KLightLock general_lock;
|
||||||
mutable KLightLock map_physical_memory_lock;
|
mutable KLightLock map_physical_memory_lock;
|
||||||
|
@ -157,7 +156,7 @@ namespace ams::kern {
|
||||||
address_space_start(), address_space_end(), heap_region_start(), heap_region_end(), current_heap_end(),
|
address_space_start(), address_space_end(), heap_region_start(), heap_region_end(), current_heap_end(),
|
||||||
alias_region_start(), alias_region_end(), stack_region_start(), stack_region_end(), kernel_map_region_start(),
|
alias_region_start(), alias_region_end(), stack_region_start(), stack_region_end(), kernel_map_region_start(),
|
||||||
kernel_map_region_end(), alias_code_region_start(), alias_code_region_end(), code_region_start(), code_region_end(),
|
kernel_map_region_end(), alias_code_region_start(), alias_code_region_end(), code_region_start(), code_region_end(),
|
||||||
max_heap_size(), max_physical_memory_size(),mapped_unsafe_physical_memory(), general_lock(), map_physical_memory_lock(),
|
max_heap_size(), mapped_physical_memory_size(), mapped_unsafe_physical_memory(), general_lock(), map_physical_memory_lock(),
|
||||||
impl(), memory_block_manager(), allocate_option(), address_space_width(), is_kernel(), enable_aslr(), memory_block_slab_manager(),
|
impl(), memory_block_manager(), allocate_option(), address_space_width(), is_kernel(), enable_aslr(), memory_block_slab_manager(),
|
||||||
block_info_manager(), cached_physical_linear_region(), cached_physical_heap_region(), cached_virtual_heap_region(),
|
block_info_manager(), cached_physical_linear_region(), cached_physical_heap_region(), cached_virtual_heap_region(),
|
||||||
heap_fill_value(), ipc_fill_value(), stack_fill_value()
|
heap_fill_value(), ipc_fill_value(), stack_fill_value()
|
||||||
|
@ -251,6 +250,7 @@ namespace ams::kern {
|
||||||
Result SetHeapSize(KProcessAddress *out, size_t size);
|
Result SetHeapSize(KProcessAddress *out, size_t size);
|
||||||
Result SetMaxHeapSize(size_t size);
|
Result SetMaxHeapSize(size_t size);
|
||||||
Result QueryInfo(KMemoryInfo *out_info, ams::svc::PageInfo *out_page_info, KProcessAddress addr) const;
|
Result QueryInfo(KMemoryInfo *out_info, ams::svc::PageInfo *out_page_info, KProcessAddress addr) const;
|
||||||
|
Result UnmapMemory(uintptr_t dst_address, uintptr_t src_address, size_t size);
|
||||||
Result MapIo(KPhysicalAddress phys_addr, size_t size, KMemoryPermission perm);
|
Result MapIo(KPhysicalAddress phys_addr, size_t size, KMemoryPermission perm);
|
||||||
Result MapStatic(KPhysicalAddress phys_addr, size_t size, KMemoryPermission perm);
|
Result MapStatic(KPhysicalAddress phys_addr, size_t size, KMemoryPermission perm);
|
||||||
Result MapRegion(KMemoryRegionType region_type, KMemoryPermission perm);
|
Result MapRegion(KMemoryRegionType region_type, KMemoryPermission perm);
|
||||||
|
@ -287,6 +287,13 @@ namespace ams::kern {
|
||||||
size_t GetStackRegionSize() const { return this->stack_region_end - this->stack_region_start; }
|
size_t GetStackRegionSize() const { return this->stack_region_end - this->stack_region_start; }
|
||||||
size_t GetKernelMapRegionSize() const { return this->kernel_map_region_end - this->kernel_map_region_start; }
|
size_t GetKernelMapRegionSize() const { return this->kernel_map_region_end - this->kernel_map_region_start; }
|
||||||
size_t GetAliasCodeRegionSize() const { return this->alias_code_region_end - this->alias_code_region_start; }
|
size_t GetAliasCodeRegionSize() const { return this->alias_code_region_end - this->alias_code_region_start; }
|
||||||
|
|
||||||
|
size_t GetNormalMemorySize() const {
|
||||||
|
/* Lock the table. */
|
||||||
|
KScopedLightLock lk(this->general_lock);
|
||||||
|
|
||||||
|
return this->GetHeapRegionSize() + this->mapped_physical_memory_size;
|
||||||
|
}
|
||||||
public:
|
public:
|
||||||
static ALWAYS_INLINE KVirtualAddress GetLinearVirtualAddress(KPhysicalAddress addr) {
|
static ALWAYS_INLINE KVirtualAddress GetLinearVirtualAddress(KPhysicalAddress addr) {
|
||||||
return KMemoryLayout::GetLinearVirtualAddress(addr);
|
return KMemoryLayout::GetLinearVirtualAddress(addr);
|
||||||
|
|
|
@ -126,6 +126,8 @@ namespace ams::kern {
|
||||||
|
|
||||||
constexpr const char *GetName() const { return this->name; }
|
constexpr const char *GetName() const { return this->name; }
|
||||||
|
|
||||||
|
constexpr ams::svc::ProgramId GetProgramId() const { return this->program_id; }
|
||||||
|
|
||||||
constexpr u64 GetProcessId() const { return this->process_id; }
|
constexpr u64 GetProcessId() const { return this->process_id; }
|
||||||
|
|
||||||
constexpr u64 GetCoreMask() const { return this->capabilities.GetCoreMask(); }
|
constexpr u64 GetCoreMask() const { return this->capabilities.GetCoreMask(); }
|
||||||
|
@ -163,9 +165,14 @@ namespace ams::kern {
|
||||||
constexpr KHandleTable &GetHandleTable() { return this->handle_table; }
|
constexpr KHandleTable &GetHandleTable() { return this->handle_table; }
|
||||||
constexpr const KHandleTable &GetHandleTable() const { return this->handle_table; }
|
constexpr const KHandleTable &GetHandleTable() const { return this->handle_table; }
|
||||||
|
|
||||||
|
size_t GetUsedNonSystemUserPhysicalMemorySize() const;
|
||||||
|
size_t GetTotalNonSystemUserPhysicalMemorySize() const;
|
||||||
|
|
||||||
Result CreateThreadLocalRegion(KProcessAddress *out);
|
Result CreateThreadLocalRegion(KProcessAddress *out);
|
||||||
void *GetThreadLocalRegionPointer(KProcessAddress addr);
|
void *GetThreadLocalRegionPointer(KProcessAddress addr);
|
||||||
|
|
||||||
|
constexpr KProcessAddress GetProcessLocalRegionAddress() const { return this->plr_address; }
|
||||||
|
|
||||||
void AddCpuTime(s64 diff) { this->cpu_time += diff; }
|
void AddCpuTime(s64 diff) { this->cpu_time += diff; }
|
||||||
void IncrementScheduledCount() { ++this->schedule_count; }
|
void IncrementScheduledCount() { ++this->schedule_count; }
|
||||||
|
|
||||||
|
|
|
@ -51,9 +51,7 @@ namespace ams::kern::svc {
|
||||||
|
|
||||||
#pragma GCC pop_options
|
#pragma GCC pop_options
|
||||||
|
|
||||||
}
|
constexpr const std::array<SvcTableEntry, NumSupervisorCalls> SvcTable64From32Impl = [] {
|
||||||
|
|
||||||
const std::array<SvcTableEntry, NumSupervisorCalls> SvcTable64From32 = [] {
|
|
||||||
std::array<SvcTableEntry, NumSupervisorCalls> table = {};
|
std::array<SvcTableEntry, NumSupervisorCalls> table = {};
|
||||||
|
|
||||||
#define AMS_KERN_SVC_SET_TABLE_ENTRY(ID, RETURN_TYPE, NAME, ...) \
|
#define AMS_KERN_SVC_SET_TABLE_ENTRY(ID, RETURN_TYPE, NAME, ...) \
|
||||||
|
@ -64,7 +62,7 @@ namespace ams::kern::svc {
|
||||||
return table;
|
return table;
|
||||||
}();
|
}();
|
||||||
|
|
||||||
const std::array<SvcTableEntry, NumSupervisorCalls> SvcTable64 = [] {
|
constexpr const std::array<SvcTableEntry, NumSupervisorCalls> SvcTable64Impl = [] {
|
||||||
std::array<SvcTableEntry, NumSupervisorCalls> table = {};
|
std::array<SvcTableEntry, NumSupervisorCalls> table = {};
|
||||||
|
|
||||||
#define AMS_KERN_SVC_SET_TABLE_ENTRY(ID, RETURN_TYPE, NAME, ...) \
|
#define AMS_KERN_SVC_SET_TABLE_ENTRY(ID, RETURN_TYPE, NAME, ...) \
|
||||||
|
@ -75,4 +73,23 @@ namespace ams::kern::svc {
|
||||||
return table;
|
return table;
|
||||||
}();
|
}();
|
||||||
|
|
||||||
|
constexpr bool IsValidSvcTable(const std::array<SvcTableEntry, NumSupervisorCalls> &table) {
|
||||||
|
for (size_t i = 0; i < NumSupervisorCalls; i++) {
|
||||||
|
if (table[i] != nullptr) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static_assert(IsValidSvcTable(SvcTable64Impl));
|
||||||
|
static_assert(IsValidSvcTable(SvcTable64From32Impl));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
constinit const std::array<SvcTableEntry, NumSupervisorCalls> SvcTable64 = SvcTable64Impl;
|
||||||
|
|
||||||
|
constinit const std::array<SvcTableEntry, NumSupervisorCalls> SvcTable64From32 = SvcTable64From32Impl;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -389,4 +389,12 @@ namespace ams::kern::board::nintendo::nx {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Constant calculations. */
|
||||||
|
size_t KSystemControl::CalculateRequiredSecureMemorySize(size_t size, u32 pool) {
|
||||||
|
if (pool == KMemoryManager::Pool_Applet) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -40,7 +40,7 @@ namespace ams::kern {
|
||||||
this->code_region_start = 0;
|
this->code_region_start = 0;
|
||||||
this->code_region_end = 0;
|
this->code_region_end = 0;
|
||||||
this->max_heap_size = 0;
|
this->max_heap_size = 0;
|
||||||
this->max_physical_memory_size = 0;
|
this->mapped_physical_memory_size = 0;
|
||||||
this->mapped_unsafe_physical_memory = 0;
|
this->mapped_unsafe_physical_memory = 0;
|
||||||
|
|
||||||
this->memory_block_slab_manager = std::addressof(Kernel::GetSystemMemoryBlockManager());
|
this->memory_block_slab_manager = std::addressof(Kernel::GetSystemMemoryBlockManager());
|
||||||
|
@ -225,7 +225,7 @@ namespace ams::kern {
|
||||||
/* Set heap and fill members. */
|
/* Set heap and fill members. */
|
||||||
this->current_heap_end = this->heap_region_start;
|
this->current_heap_end = this->heap_region_start;
|
||||||
this->max_heap_size = 0;
|
this->max_heap_size = 0;
|
||||||
this->max_physical_memory_size = 0;
|
this->mapped_physical_memory_size = 0;
|
||||||
this->mapped_unsafe_physical_memory = 0;
|
this->mapped_unsafe_physical_memory = 0;
|
||||||
|
|
||||||
const bool fill_memory = KTargetSystem::IsDebugMemoryFillEnabled();
|
const bool fill_memory = KTargetSystem::IsDebugMemoryFillEnabled();
|
||||||
|
@ -452,6 +452,68 @@ namespace ams::kern {
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result KPageTableBase::UnmapMemory(uintptr_t dst_address, uintptr_t src_address, size_t size) {
|
||||||
|
/* Lock the table. */
|
||||||
|
KScopedLightLock lk(this->general_lock);
|
||||||
|
|
||||||
|
/* Validate that the source address's state is valid. */
|
||||||
|
KMemoryState src_state;
|
||||||
|
R_TRY(this->CheckMemoryState(std::addressof(src_state), nullptr, nullptr, src_address, size, KMemoryState_FlagCanAlias, KMemoryState_FlagCanAlias, KMemoryPermission_All, KMemoryPermission_NotMapped | KMemoryPermission_KernelRead, KMemoryAttribute_All, KMemoryAttribute_AnyLocked | KMemoryAttribute_Locked));
|
||||||
|
|
||||||
|
/* Validate that the dst address's state is valid. */
|
||||||
|
KMemoryPermission dst_perm;
|
||||||
|
R_TRY(this->CheckMemoryState(nullptr, std::addressof(dst_perm), nullptr, dst_address, size, KMemoryState_All, KMemoryState_Stack, KMemoryPermission_None, KMemoryPermission_None, KMemoryAttribute_All, KMemoryAttribute_None));
|
||||||
|
|
||||||
|
/* Create an update allocator for the source. */
|
||||||
|
KMemoryBlockManagerUpdateAllocator src_allocator(this->memory_block_slab_manager);
|
||||||
|
R_TRY(src_allocator.GetResult());
|
||||||
|
|
||||||
|
/* Create an update allocator for the destination. */
|
||||||
|
KMemoryBlockManagerUpdateAllocator dst_allocator(this->memory_block_slab_manager);
|
||||||
|
R_TRY(dst_allocator.GetResult());
|
||||||
|
|
||||||
|
/* Unmap the memory. */
|
||||||
|
{
|
||||||
|
/* Determine the number of pages being operated on. */
|
||||||
|
const size_t num_pages = size / PageSize;
|
||||||
|
|
||||||
|
/* Create page groups for the memory being unmapped. */
|
||||||
|
KPageGroup pg(this->block_info_manager);
|
||||||
|
|
||||||
|
/* Create the page group representing the destination. */
|
||||||
|
R_TRY(this->MakePageGroup(pg, dst_address, num_pages));
|
||||||
|
|
||||||
|
/* Ensure the page group is the valid for the source. */
|
||||||
|
R_UNLESS(this->IsValidPageGroup(pg, src_address, num_pages), svc::ResultInvalidMemoryRegion());
|
||||||
|
|
||||||
|
/* We're going to perform an update, so create a helper. */
|
||||||
|
KScopedPageTableUpdater updater(this);
|
||||||
|
|
||||||
|
/* Unmap the aliased copy of the pages. */
|
||||||
|
const KPageProperties dst_unmap_properties = { KMemoryPermission_None, false, false, false };
|
||||||
|
R_TRY(this->Operate(updater.GetPageList(), dst_address, num_pages, Null<KPhysicalAddress>, false, dst_unmap_properties, OperationType_Unmap, false));
|
||||||
|
|
||||||
|
/* Ensure that we re-map the aliased pages on failure. */
|
||||||
|
auto remap_guard = SCOPE_GUARD {
|
||||||
|
const KPageProperties dst_remap_properties = { dst_perm, false, false, false };
|
||||||
|
MESOSPHERE_R_ABORT_UNLESS(this->MapPageGroupImpl(updater.GetPageList(), dst_address, pg, dst_remap_properties, true));
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Try to set the permissions for the source pages back to what they should be. */
|
||||||
|
const KPageProperties src_properties = { KMemoryPermission_UserReadWrite, false, false, false };
|
||||||
|
R_TRY(this->Operate(updater.GetPageList(), src_address, num_pages, Null<KPhysicalAddress>, false, src_properties, OperationType_ChangePermissions, false));
|
||||||
|
|
||||||
|
/* We successfully changed the permissions for the source pages, so we don't need to re-map the dst pages on failure. */
|
||||||
|
remap_guard.Cancel();
|
||||||
|
|
||||||
|
/* Apply the memory block updates. */
|
||||||
|
this->memory_block_manager.Update(std::addressof(src_allocator), src_address, num_pages, src_state, KMemoryPermission_UserReadWrite, KMemoryAttribute_None);
|
||||||
|
this->memory_block_manager.Update(std::addressof(dst_allocator), dst_address, num_pages, KMemoryState_None, KMemoryPermission_None, KMemoryAttribute_None);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ResultSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
KProcessAddress KPageTableBase::FindFreeArea(KProcessAddress region_start, size_t region_num_pages, size_t num_pages, size_t alignment, size_t offset, size_t guard_pages) const {
|
KProcessAddress KPageTableBase::FindFreeArea(KProcessAddress region_start, size_t region_num_pages, size_t num_pages, size_t alignment, size_t offset, size_t guard_pages) const {
|
||||||
KProcessAddress address = Null<KProcessAddress>;
|
KProcessAddress address = Null<KProcessAddress>;
|
||||||
|
|
||||||
|
|
|
@ -280,6 +280,28 @@ namespace ams::kern {
|
||||||
this->thread_list.erase(this->thread_list.iterator_to(*thread));
|
this->thread_list.erase(this->thread_list.iterator_to(*thread));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t KProcess::GetUsedNonSystemUserPhysicalMemorySize() const {
|
||||||
|
const size_t norm_size = this->page_table.GetNormalMemorySize();
|
||||||
|
const size_t other_size = this->code_size + this->main_thread_stack_size;
|
||||||
|
const size_t sec_size = KSystemControl::CalculateRequiredSecureMemorySize(this->system_resource_num_pages * PageSize, this->memory_pool);
|
||||||
|
|
||||||
|
return norm_size + other_size + sec_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t KProcess::GetTotalNonSystemUserPhysicalMemorySize() const {
|
||||||
|
/* Get the amount of free and used size. */
|
||||||
|
const size_t free_size = this->resource_limit->GetFreeValue(ams::svc::LimitableResource_PhysicalMemoryMax);
|
||||||
|
const size_t used_size = this->GetUsedNonSystemUserPhysicalMemorySize();
|
||||||
|
const size_t sec_size = KSystemControl::CalculateRequiredSecureMemorySize(this->system_resource_num_pages * PageSize, this->memory_pool);
|
||||||
|
const size_t max_size = this->max_process_memory;
|
||||||
|
|
||||||
|
if (used_size + free_size > max_size) {
|
||||||
|
return max_size - sec_size;
|
||||||
|
} else {
|
||||||
|
return free_size + used_size - sec_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Result KProcess::Run(s32 priority, size_t stack_size) {
|
Result KProcess::Run(s32 priority, size_t stack_size) {
|
||||||
MESOSPHERE_ASSERT_THIS();
|
MESOSPHERE_ASSERT_THIS();
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,10 @@ namespace ams::kern::svc {
|
||||||
case ams::svc::InfoType_AslrRegionSize:
|
case ams::svc::InfoType_AslrRegionSize:
|
||||||
case ams::svc::InfoType_StackRegionAddress:
|
case ams::svc::InfoType_StackRegionAddress:
|
||||||
case ams::svc::InfoType_StackRegionSize:
|
case ams::svc::InfoType_StackRegionSize:
|
||||||
|
case ams::svc::InfoType_ProgramId:
|
||||||
|
case ams::svc::InfoType_InitialProcessIdRange:
|
||||||
|
case ams::svc::InfoType_UserExceptionContextAddress:
|
||||||
|
case ams::svc::InfoType_TotalNonSystemMemorySize:
|
||||||
{
|
{
|
||||||
/* These info types don't support non-zero subtypes. */
|
/* These info types don't support non-zero subtypes. */
|
||||||
R_UNLESS(info_subtype == 0, svc::ResultInvalidCombination());
|
R_UNLESS(info_subtype == 0, svc::ResultInvalidCombination());
|
||||||
|
@ -67,6 +71,18 @@ namespace ams::kern::svc {
|
||||||
case ams::svc::InfoType_StackRegionSize:
|
case ams::svc::InfoType_StackRegionSize:
|
||||||
*out = process->GetPageTable().GetStackRegionSize();
|
*out = process->GetPageTable().GetStackRegionSize();
|
||||||
break;
|
break;
|
||||||
|
case ams::svc::InfoType_ProgramId:
|
||||||
|
*out = process->GetProgramId();
|
||||||
|
break;
|
||||||
|
case ams::svc::InfoType_InitialProcessIdRange:
|
||||||
|
/* TODO: Detect exactly 4.0.0 target firmware, do the right thing. */
|
||||||
|
return svc::ResultInvalidEnumValue();
|
||||||
|
case ams::svc::InfoType_UserExceptionContextAddress:
|
||||||
|
*out = GetInteger(process->GetProcessLocalRegionAddress());
|
||||||
|
break;
|
||||||
|
case ams::svc::InfoType_TotalNonSystemMemorySize:
|
||||||
|
*out = process->GetTotalNonSystemUserPhysicalMemorySize();
|
||||||
|
break;
|
||||||
MESOSPHERE_UNREACHABLE_DEFAULT_CASE();
|
MESOSPHERE_UNREACHABLE_DEFAULT_CASE();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,32 @@ namespace ams::kern::svc {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
Result UnmapMemory(uintptr_t dst_address, uintptr_t src_address, size_t size) {
|
||||||
|
/* Log the call parameters for debugging. */
|
||||||
|
MESOSPHERE_LOG("UnmapMemory(%zx, %zx, %zx)\n", dst_address, src_address, size);
|
||||||
|
|
||||||
|
/* Validate that addresses are page aligned. */
|
||||||
|
R_UNLESS(util::IsAligned(dst_address, PageSize), svc::ResultInvalidAddress());
|
||||||
|
R_UNLESS(util::IsAligned(src_address, PageSize), svc::ResultInvalidAddress());
|
||||||
|
|
||||||
|
/* Validate that size is positive and page aligned. */
|
||||||
|
R_UNLESS(size > 0, svc::ResultInvalidSize());
|
||||||
|
R_UNLESS(util::IsAligned(size, PageSize), svc::ResultInvalidSize());
|
||||||
|
|
||||||
|
/* Ensure that neither mapping overflows. */
|
||||||
|
R_UNLESS(src_address < src_address + size, svc::ResultInvalidCurrentMemory());
|
||||||
|
R_UNLESS(dst_address < dst_address + size, svc::ResultInvalidCurrentMemory());
|
||||||
|
|
||||||
|
/* Get the page table we're operating on. */
|
||||||
|
auto &page_table = GetCurrentProcess().GetPageTable();
|
||||||
|
|
||||||
|
/* Ensure that the memory we're unmapping is in range. */
|
||||||
|
R_UNLESS(page_table.Contains(src_address, size), svc::ResultInvalidCurrentMemory());
|
||||||
|
R_UNLESS(page_table.CanContain(dst_address, size, KMemoryState_Stack), svc::ResultInvalidMemoryRegion());
|
||||||
|
|
||||||
|
/* Unmap the memory. */
|
||||||
|
return page_table.UnmapMemory(dst_address, src_address, size);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,7 +65,7 @@ namespace ams::kern::svc {
|
||||||
}
|
}
|
||||||
|
|
||||||
Result UnmapMemory64(ams::svc::Address dst_address, ams::svc::Address src_address, ams::svc::Size size) {
|
Result UnmapMemory64(ams::svc::Address dst_address, ams::svc::Address src_address, ams::svc::Size size) {
|
||||||
MESOSPHERE_PANIC("Stubbed SvcUnmapMemory64 was called.");
|
return UnmapMemory(dst_address, src_address, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ============================= 64From32 ABI ============================= */
|
/* ============================= 64From32 ABI ============================= */
|
||||||
|
@ -58,7 +83,7 @@ namespace ams::kern::svc {
|
||||||
}
|
}
|
||||||
|
|
||||||
Result UnmapMemory64From32(ams::svc::Address dst_address, ams::svc::Address src_address, ams::svc::Size size) {
|
Result UnmapMemory64From32(ams::svc::Address dst_address, ams::svc::Address src_address, ams::svc::Size size) {
|
||||||
MESOSPHERE_PANIC("Stubbed SvcUnmapMemory64From32 was called.");
|
return UnmapMemory(dst_address, src_address, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -515,6 +515,7 @@ namespace ams::svc::codegen::impl {
|
||||||
using Traits = FunctionTraits<Function>;
|
using Traits = FunctionTraits<Function>;
|
||||||
public:
|
public:
|
||||||
using Impl = KernelSvcWrapperHelperImpl<_SvcAbiType, _UserAbiType, _KernelAbiType, typename Traits::ReturnType, typename Traits::ArgsType>;
|
using Impl = KernelSvcWrapperHelperImpl<_SvcAbiType, _UserAbiType, _KernelAbiType, typename Traits::ReturnType, typename Traits::ArgsType>;
|
||||||
|
using ReturnType = typename Traits::ReturnType;
|
||||||
|
|
||||||
static constexpr bool IsAarch64Kernel = std::is_same<_KernelAbiType, Aarch64Lp64Abi>::value;
|
static constexpr bool IsAarch64Kernel = std::is_same<_KernelAbiType, Aarch64Lp64Abi>::value;
|
||||||
static constexpr bool IsAarch32Kernel = std::is_same<_KernelAbiType, Aarch32Ilp32Abi>::value;
|
static constexpr bool IsAarch32Kernel = std::is_same<_KernelAbiType, Aarch32Ilp32Abi>::value;
|
||||||
|
@ -525,17 +526,16 @@ namespace ams::svc::codegen::impl {
|
||||||
static constexpr auto BeforeMetaCode = Impl::OptimizedBeforeMetaCode;
|
static constexpr auto BeforeMetaCode = Impl::OptimizedBeforeMetaCode;
|
||||||
static constexpr auto AfterMetaCode = Impl::OptimizedAfterMetaCode;
|
static constexpr auto AfterMetaCode = Impl::OptimizedAfterMetaCode;
|
||||||
|
|
||||||
|
|
||||||
/* Set omit-frame-pointer to prevent GCC from emitting MOV X29, SP instructions. */
|
/* Set omit-frame-pointer to prevent GCC from emitting MOV X29, SP instructions. */
|
||||||
#pragma GCC push_options
|
#pragma GCC push_options
|
||||||
#pragma GCC optimize ("omit-frame-pointer")
|
#pragma GCC optimize ("omit-frame-pointer")
|
||||||
|
|
||||||
static ALWAYS_INLINE void WrapSvcFunction() {
|
static ALWAYS_INLINE ReturnType WrapSvcFunction() {
|
||||||
/* Generate appropriate assembly. */
|
/* Generate appropriate assembly. */
|
||||||
GenerateCodeForMetaCode<CodeGenerator, BeforeMetaCode>();
|
GenerateCodeForMetaCode<CodeGenerator, BeforeMetaCode>();
|
||||||
ON_SCOPE_EXIT { GenerateCodeForMetaCode<CodeGenerator, AfterMetaCode>(); };
|
ON_SCOPE_EXIT { GenerateCodeForMetaCode<CodeGenerator, AfterMetaCode>(); };
|
||||||
|
|
||||||
return reinterpret_cast<void (*)()>(Function)();
|
return reinterpret_cast<ReturnType (*)()>(Function)();
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma GCC pop_options
|
#pragma GCC pop_options
|
||||||
|
|
|
@ -20,7 +20,7 @@ namespace ams::svc::codegen {
|
||||||
|
|
||||||
#if defined(ATMOSPHERE_ARCH_ARM64) || defined(ATMOSPHERE_ARCH_ARM)
|
#if defined(ATMOSPHERE_ARCH_ARM64) || defined(ATMOSPHERE_ARCH_ARM)
|
||||||
|
|
||||||
template<auto Function64, auto Function64From32>
|
template<auto &Function64, auto &Function64From32>
|
||||||
class KernelSvcWrapper {
|
class KernelSvcWrapper {
|
||||||
private:
|
private:
|
||||||
/* TODO: using Aarch32 = */
|
/* TODO: using Aarch32 = */
|
||||||
|
@ -32,11 +32,22 @@ namespace ams::svc::codegen {
|
||||||
#pragma GCC optimize ("omit-frame-pointer")
|
#pragma GCC optimize ("omit-frame-pointer")
|
||||||
|
|
||||||
static ALWAYS_INLINE void Call64() {
|
static ALWAYS_INLINE void Call64() {
|
||||||
|
if constexpr (std::is_same<typename Aarch64::ReturnType, void>::value) {
|
||||||
Aarch64::WrapSvcFunction();
|
Aarch64::WrapSvcFunction();
|
||||||
|
} else {
|
||||||
|
const auto &res = Aarch64::WrapSvcFunction();
|
||||||
|
__asm__ __volatile__("" :: [res]"r"(res));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static ALWAYS_INLINE void Call64From32() {
|
static ALWAYS_INLINE void Call64From32() {
|
||||||
|
if constexpr (std::is_same<typename Aarch64::ReturnType, void>::value) {
|
||||||
Aarch64From32::WrapSvcFunction();
|
Aarch64From32::WrapSvcFunction();
|
||||||
|
} else {
|
||||||
|
const auto &res = Aarch64From32::WrapSvcFunction();
|
||||||
|
__asm__ __volatile__("" :: [res]"r"(res));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma GCC pop_options
|
#pragma GCC pop_options
|
||||||
|
|
Loading…
Reference in a new issue