kern: finish shadow stack region, 64k page process segregation implementation, fix some long-standing issues
This commit is contained in:
@@ -19,6 +19,7 @@
|
||||
#include <mesosphere/kern_k_page_table_base.hpp>
|
||||
#include <mesosphere/kern_k_page_group.hpp>
|
||||
#include <mesosphere/kern_k_page_table_manager.hpp>
|
||||
#include <mesosphere/init/kern_init_slab_setup.hpp>
|
||||
|
||||
namespace ams::kern::arch::arm64 {
|
||||
|
||||
|
||||
@@ -32,6 +32,11 @@ namespace ams::kern::arch::arm64 {
|
||||
R_RETURN(m_page_table.InitializeForProcess(flags, from_back, pool, code_address, code_size, system_resource, resource_limit, process_index));
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE u64 GetProcessTcrEl1(size_t process_index) {
|
||||
/* The kernel's root table is entry zero; processes are indexed from one. */
|
||||
return KPageTable::GetTcrEL1Entry(process_index + 1);
|
||||
}
|
||||
|
||||
void Finalize() { m_page_table.Finalize(); }
|
||||
|
||||
ALWAYS_INLINE KScopedLightLock AcquireDeviceMapLock() {
|
||||
@@ -302,6 +307,10 @@ namespace ams::kern::arch::arm64 {
|
||||
bool CanContain(KProcessAddress addr, size_t size, KMemoryState state) const { return m_page_table.CanContain(addr, size, state); }
|
||||
bool CanContain(KProcessAddress addr, size_t size, ams::svc::MemoryState state) const { return m_page_table.CanContain(addr, size, state); }
|
||||
|
||||
bool IsInShadowStackRegion(KProcessAddress addr, size_t size) const { return m_page_table.IsInShadowStackRegion(addr, size); }
|
||||
bool IsInShadowStackRegion(KProcessAddress addr) const { return m_page_table.IsInShadowStackRegion(addr); }
|
||||
bool IsSafeUserPointer(KProcessAddress addr, size_t size) const { return m_page_table.IsSafeUserPointer(addr, size); }
|
||||
|
||||
KProcessAddress GetAddressSpaceStart() const { return m_page_table.GetAddressSpaceStart(); }
|
||||
KProcessAddress GetShadowStackRegionStart() const { return m_page_table.GetShadowStackRegionStart(); }
|
||||
KProcessAddress GetHeapRegionStart() const { return m_page_table.GetHeapRegionStart(); }
|
||||
|
||||
@@ -77,7 +77,7 @@ namespace ams::kern::arch::arm64 {
|
||||
|
||||
static bool CopyMemoryFromUserSize32BitWithSupervisorAccess(void *dst, const void *src) {
|
||||
/* Check that the address is within the valid userspace range. */
|
||||
if (const uintptr_t src_uptr = reinterpret_cast<uintptr_t>(src); src_uptr < ams::svc::AddressNullGuard32Size || (src_uptr + sizeof(u32) - 1) >= ams::svc::AddressMemoryRegion39Size) {
|
||||
if (const uintptr_t src_uptr = reinterpret_cast<uintptr_t>(src); src_uptr < ams::svc::AddressNullGuard32Size || (src_uptr + sizeof(u32) - 1) >= ams::svc::AddressMemoryRegion42Size) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -249,7 +249,15 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
constexpr bool IsInShadowStackRegion(KProcessAddress addr, size_t size) const {
|
||||
return this->Contains(addr, size) && m_region_starts[RegionType_ShadowStack] <= addr && addr + size - 1 <= m_region_ends[RegionType_ShadowStack] - 1;
|
||||
const auto start = m_region_starts[RegionType_ShadowStack];
|
||||
const auto end = m_region_ends[RegionType_ShadowStack];
|
||||
return start != end && addr < end && start < addr + size;
|
||||
}
|
||||
|
||||
constexpr bool IsInShadowStackRegion(KProcessAddress addr) const {
|
||||
const auto start = m_region_starts[RegionType_ShadowStack];
|
||||
const auto end = m_region_ends[RegionType_ShadowStack];
|
||||
return start <= addr && addr < end;
|
||||
}
|
||||
|
||||
constexpr bool IsSafeUserPointer(KProcessAddress addr, size_t size) const {
|
||||
|
||||
@@ -353,182 +353,36 @@ namespace ams::kern {
|
||||
const KProcessAddress process_code_last = process_code_end - 1;
|
||||
auto IsInAddressSpace = [&](KProcessAddress addr) ALWAYS_INLINE_LAMBDA { return m_address_space_start <= addr && addr <= m_address_space_end; };
|
||||
|
||||
/* Ensure that the KernelMap region is valid. */
|
||||
for (size_t k = 0; k < num_regions; ++k) {
|
||||
if (const auto &kmap_region = region_layouts[k]; kmap_region.type == RegionType_KernelMap) {
|
||||
/* If there's no kmap region, we have nothing to check. */
|
||||
if (kmap_region.size == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check that the kmap region is within our address space. */
|
||||
MESOSPHERE_ABORT_UNLESS(IsInAddressSpace(m_region_starts[RegionType_KernelMap]));
|
||||
MESOSPHERE_ABORT_UNLESS(IsInAddressSpace(m_region_ends[RegionType_KernelMap]));
|
||||
|
||||
/* Check for overlap with process code. */
|
||||
const KProcessAddress kmap_start = m_region_starts[RegionType_KernelMap];
|
||||
const KProcessAddress kmap_last = m_region_ends[RegionType_KernelMap] - 1;
|
||||
MESOSPHERE_ABORT_UNLESS(kernel_map_region_size == 0 || kmap_last < process_code_start || process_code_last < kmap_start);
|
||||
|
||||
/* Check for overlap with stack. */
|
||||
for (size_t s = 0; s < num_regions; ++s) {
|
||||
if (const auto &stack_region = region_layouts[s]; stack_region.type == RegionType_Stack) {
|
||||
if (stack_region.size != 0) {
|
||||
const KProcessAddress stack_start = m_region_starts[RegionType_Stack];
|
||||
const KProcessAddress stack_last = m_region_ends[RegionType_Stack] - 1;
|
||||
MESOSPHERE_ABORT_UNLESS((kernel_map_region_size == 0 && stack_region_size == 0) || kmap_last < stack_start || stack_last < kmap_start);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for overlap with alias. */
|
||||
for (size_t a = 0; a < num_regions; ++a) {
|
||||
if (const auto &alias_region = region_layouts[a]; alias_region.type == RegionType_Alias) {
|
||||
if (alias_region.size != 0) {
|
||||
const KProcessAddress alias_start = m_region_starts[RegionType_Alias];
|
||||
const KProcessAddress alias_last = m_region_ends[RegionType_Alias] - 1;
|
||||
MESOSPHERE_ABORT_UNLESS(kmap_last < alias_start || alias_last < kmap_start);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for overlap with heap. */
|
||||
for (size_t h = 0; h < num_regions; ++h) {
|
||||
if (const auto &heap_region = region_layouts[h]; heap_region.type == RegionType_Heap) {
|
||||
if (heap_region.size != 0) {
|
||||
const KProcessAddress heap_start = m_region_starts[RegionType_Heap];
|
||||
const KProcessAddress heap_last = m_region_ends[RegionType_Heap] - 1;
|
||||
MESOSPHERE_ABORT_UNLESS(kmap_last < heap_start || heap_last < kmap_start);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for overlap with shadow stack. */
|
||||
for (size_t ss = 0; ss < num_regions; ++ss) {
|
||||
if (const auto &shadow_stack_region = region_layouts[ss]; shadow_stack_region.type == RegionType_ShadowStack) {
|
||||
if (shadow_stack_region.size != 0) {
|
||||
const KProcessAddress shadow_stack_start = m_region_starts[RegionType_ShadowStack];
|
||||
const KProcessAddress shadow_stack_last = m_region_ends[RegionType_ShadowStack] - 1;
|
||||
MESOSPHERE_ABORT_UNLESS(kmap_last < shadow_stack_start || shadow_stack_last < kmap_start);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Map each region type to its layout entry. */
|
||||
const RegionLayoutInfo *region_layouts_by_type[RegionType_Count] = {};
|
||||
for (size_t i = 0; i < num_regions; ++i) {
|
||||
region_layouts_by_type[region_layouts[i].type] = std::addressof(region_layouts[i]);
|
||||
}
|
||||
|
||||
/* Check that the Stack region is valid. */
|
||||
for (size_t s = 0; s < num_regions; ++s) {
|
||||
if (const auto &stack_region = region_layouts[s]; stack_region.type == RegionType_Stack) {
|
||||
/* If there's no stack region, we have nothing to check. */
|
||||
if (stack_region.size == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check that the stack region is within our address space. */
|
||||
MESOSPHERE_ABORT_UNLESS(IsInAddressSpace(m_region_starts[RegionType_Stack]));
|
||||
MESOSPHERE_ABORT_UNLESS(IsInAddressSpace(m_region_ends[RegionType_Stack]));
|
||||
|
||||
/* Check for overlap with process code. */
|
||||
const KProcessAddress stack_start = m_region_starts[RegionType_Stack];
|
||||
const KProcessAddress stack_last = m_region_ends[RegionType_Stack] - 1;
|
||||
MESOSPHERE_ABORT_UNLESS(stack_region_size == 0 || stack_last < process_code_start || process_code_last < stack_start);
|
||||
|
||||
/* Check for overlap with alias. */
|
||||
for (size_t a = 0; a < num_regions; ++a) {
|
||||
if (const auto &alias_region = region_layouts[a]; alias_region.type == RegionType_Alias) {
|
||||
if (alias_region.size != 0) {
|
||||
const KProcessAddress alias_start = m_region_starts[RegionType_Alias];
|
||||
const KProcessAddress alias_last = m_region_ends[RegionType_Alias] - 1;
|
||||
MESOSPHERE_ABORT_UNLESS(stack_last < alias_start || alias_last < stack_start);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for overlap with heap. */
|
||||
for (size_t h = 0; h < num_regions; ++h) {
|
||||
if (const auto &heap_region = region_layouts[h]; heap_region.type == RegionType_Heap) {
|
||||
if (heap_region.size != 0) {
|
||||
const KProcessAddress heap_start = m_region_starts[RegionType_Heap];
|
||||
const KProcessAddress heap_last = m_region_ends[RegionType_Heap] - 1;
|
||||
MESOSPHERE_ABORT_UNLESS(stack_last < heap_start || heap_last < stack_start);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Validate each region. */
|
||||
for (size_t i = 0; i < RegionType_Count; ++i) {
|
||||
/* If the region isn't present, there's nothing to check. */
|
||||
const RegionLayoutInfo * const region = region_layouts_by_type[i];
|
||||
if (region == nullptr || region->size == 0) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check that the Alias region is valid. */
|
||||
for (size_t a = 0; a < num_regions; ++a) {
|
||||
if (const auto &alias_region = region_layouts[a]; alias_region.type == RegionType_Alias) {
|
||||
/* If there's no alias region, we have nothing to check. */
|
||||
if (alias_region.size == 0) {
|
||||
break;
|
||||
/* Check that the region is within our address space. */
|
||||
MESOSPHERE_ABORT_UNLESS(IsInAddressSpace(m_region_starts[i]));
|
||||
MESOSPHERE_ABORT_UNLESS(IsInAddressSpace(m_region_ends[i]));
|
||||
|
||||
/* Check for overlap with process code. */
|
||||
MESOSPHERE_ABORT_UNLESS(m_region_ends[i] - 1 < process_code_start || process_code_last < m_region_starts[i]);
|
||||
|
||||
/* Check for overlap with every later region. */
|
||||
for (size_t j = i; j < RegionType_ShadowStack; ++j) {
|
||||
/* If the other region isn't present, there's nothing to check. */
|
||||
const RegionLayoutInfo * const other = region_layouts_by_type[j + 1];
|
||||
if (other == nullptr || other->size == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Check that the alias region is within our address space. */
|
||||
MESOSPHERE_ABORT_UNLESS(IsInAddressSpace(m_region_starts[RegionType_Alias]));
|
||||
MESOSPHERE_ABORT_UNLESS(IsInAddressSpace(m_region_ends[RegionType_Alias]));
|
||||
|
||||
/* Check for overlap with process code. */
|
||||
const KProcessAddress alias_start = m_region_starts[RegionType_Alias];
|
||||
const KProcessAddress alias_last = m_region_ends[RegionType_Alias] - 1;
|
||||
MESOSPHERE_ABORT_UNLESS(alias_last < process_code_start || process_code_last < alias_start);
|
||||
|
||||
/* Check for overlap with heap. */
|
||||
for (size_t h = 0; h < num_regions; ++h) {
|
||||
if (const auto &heap_region = region_layouts[h]; heap_region.type == RegionType_Heap) {
|
||||
if (heap_region.size != 0) {
|
||||
const KProcessAddress heap_start = m_region_starts[RegionType_Heap];
|
||||
const KProcessAddress heap_last = m_region_ends[RegionType_Heap] - 1;
|
||||
MESOSPHERE_ABORT_UNLESS(alias_last < heap_start || heap_last < alias_start);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Check that the Heap region is valid. */
|
||||
for (size_t h = 0; h < num_regions; ++h) {
|
||||
if (const auto &heap_region = region_layouts[h]; heap_region.type == RegionType_Heap) {
|
||||
/* If there's no heap region, we have nothing to check. */
|
||||
if (heap_region.size == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check that the heap region is within our address space. */
|
||||
MESOSPHERE_ABORT_UNLESS(IsInAddressSpace(m_region_starts[RegionType_Heap]));
|
||||
MESOSPHERE_ABORT_UNLESS(IsInAddressSpace(m_region_ends[RegionType_Heap]));
|
||||
|
||||
/* Check for overlap with process code. */
|
||||
const KProcessAddress heap_start = m_region_starts[RegionType_Heap];
|
||||
const KProcessAddress heap_last = m_region_ends[RegionType_Heap] - 1;
|
||||
MESOSPHERE_ABORT_UNLESS(heap_last < process_code_start || process_code_last < heap_start);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check that the ShadowStack region is valid. */
|
||||
for (size_t ss = 0; ss < num_regions; ++ss) {
|
||||
if (const auto &shadow_stack_region = region_layouts[ss]; shadow_stack_region.type == RegionType_ShadowStack) {
|
||||
/* If there's no shadow stack region, we have nothing to check. */
|
||||
if (shadow_stack_region.size == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check that the shadow stack region is within our address space. */
|
||||
MESOSPHERE_ABORT_UNLESS(IsInAddressSpace(m_region_starts[RegionType_ShadowStack]));
|
||||
MESOSPHERE_ABORT_UNLESS(IsInAddressSpace(m_region_ends[RegionType_ShadowStack]));
|
||||
|
||||
/* Check for overlap with process code. */
|
||||
const KProcessAddress shadow_stack_start = m_region_starts[RegionType_ShadowStack];
|
||||
const KProcessAddress shadow_stack_last = m_region_ends[RegionType_ShadowStack] - 1;
|
||||
MESOSPHERE_ABORT_UNLESS(shadow_stack_last < process_code_start || process_code_last < shadow_stack_start);
|
||||
MESOSPHERE_ABORT_UNLESS(m_region_ends[i] - 1 < m_region_starts[j + 1] || m_region_ends[j + 1] - 1 < m_region_starts[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -598,6 +452,8 @@ namespace ams::kern {
|
||||
case ams::svc::MemoryState_Static:
|
||||
case ams::svc::MemoryState_ThreadLocal:
|
||||
return m_region_starts[RegionType_KernelMap];
|
||||
case ams::svc::MemoryState_ShadowStack:
|
||||
return m_region_starts[RegionType_ShadowStack];
|
||||
case ams::svc::MemoryState_Io:
|
||||
case ams::svc::MemoryState_Shared:
|
||||
case ams::svc::MemoryState_AliasCode:
|
||||
@@ -633,6 +489,8 @@ namespace ams::kern {
|
||||
case ams::svc::MemoryState_Static:
|
||||
case ams::svc::MemoryState_ThreadLocal:
|
||||
return m_region_ends[RegionType_KernelMap] - m_region_starts[RegionType_KernelMap];
|
||||
case ams::svc::MemoryState_ShadowStack:
|
||||
return m_region_ends[RegionType_ShadowStack] - m_region_starts[RegionType_ShadowStack];
|
||||
case ams::svc::MemoryState_Io:
|
||||
case ams::svc::MemoryState_Shared:
|
||||
case ams::svc::MemoryState_AliasCode:
|
||||
@@ -659,12 +517,20 @@ namespace ams::kern {
|
||||
const KProcessAddress region_start = this->GetRegionAddress(state);
|
||||
const size_t region_size = this->GetRegionSize(state);
|
||||
|
||||
if (region_size == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const bool is_in_region = region_start <= addr && addr < end && last <= region_start + region_size - 1;
|
||||
const bool is_in_heap = !(end <= m_region_starts[RegionType_Heap] || m_region_ends[RegionType_Heap] <= addr || m_region_starts[RegionType_Heap] == m_region_ends[RegionType_Heap]);
|
||||
const bool is_in_alias = !(end <= m_region_starts[RegionType_Alias] || m_region_ends[RegionType_Alias] <= addr || m_region_starts[RegionType_Alias] == m_region_ends[RegionType_Alias]);
|
||||
|
||||
switch (state) {
|
||||
case ams::svc::MemoryState_Free:
|
||||
case ams::svc::MemoryState_Normal:
|
||||
case ams::svc::MemoryState_Ipc:
|
||||
case ams::svc::MemoryState_NonSecureIpc:
|
||||
case ams::svc::MemoryState_NonDeviceIpc:
|
||||
case ams::svc::MemoryState_Kernel:
|
||||
case ams::svc::MemoryState_ShadowStack:
|
||||
return is_in_region;
|
||||
case ams::svc::MemoryState_Io:
|
||||
case ams::svc::MemoryState_Static:
|
||||
@@ -682,17 +548,32 @@ namespace ams::kern {
|
||||
case ams::svc::MemoryState_CodeOut:
|
||||
case ams::svc::MemoryState_Coverage:
|
||||
case ams::svc::MemoryState_Insecure:
|
||||
return is_in_region && !is_in_heap && !is_in_alias;
|
||||
case ams::svc::MemoryState_Normal:
|
||||
MESOSPHERE_ASSERT(is_in_heap);
|
||||
return is_in_region && !is_in_alias;
|
||||
case ams::svc::MemoryState_Ipc:
|
||||
case ams::svc::MemoryState_NonSecureIpc:
|
||||
case ams::svc::MemoryState_NonDeviceIpc:
|
||||
MESOSPHERE_ASSERT(is_in_alias);
|
||||
return is_in_region && !is_in_heap;
|
||||
default:
|
||||
return false;
|
||||
{
|
||||
if (!is_in_region) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto heap_start = m_region_starts[RegionType_Heap];
|
||||
const auto heap_end = m_region_ends[RegionType_Heap];
|
||||
if (heap_start != heap_end && addr < heap_end && heap_start < end) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto alias_start = m_region_starts[RegionType_Alias];
|
||||
const auto alias_end = m_region_ends[RegionType_Alias];
|
||||
if (alias_start != alias_end && addr < alias_end && alias_start < end) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto shadow_start = m_region_starts[RegionType_ShadowStack];
|
||||
const auto shadow_end = m_region_ends[RegionType_ShadowStack];
|
||||
if (shadow_start != shadow_end && addr < shadow_end && shadow_start < end) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
MESOSPHERE_UNREACHABLE_DEFAULT_CASE();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -170,6 +170,13 @@ namespace ams::kern {
|
||||
KAddressSpaceInfo::SetAddressSpaceSize(39, KAddressSpaceInfo::Type_Alias, alias_size);
|
||||
}
|
||||
|
||||
/* Update 42-bit address space infos. */
|
||||
{
|
||||
/* Heap should be equal to the total memory size, maximum 128 GB. */
|
||||
/* Alias/Stack/MapSmall are left at their static defaults. */
|
||||
KAddressSpaceInfo::SetAddressSpaceSize(42, KAddressSpaceInfo::Type_Heap, std::min(util::AlignUp(total_memory_size, 1_GB), 128_GB));
|
||||
}
|
||||
|
||||
const auto &slab_counts = init::GetSlabResourceCounts();
|
||||
MESOSPHERE_R_ABORT_UNLESS(sys_res_limit.SetLimitValue(ams::svc::LimitableResource_PhysicalMemoryMax, total_memory_size));
|
||||
MESOSPHERE_R_ABORT_UNLESS(sys_res_limit.SetLimitValue(ams::svc::LimitableResource_ThreadCountMax, slab_counts.num_KThread));
|
||||
|
||||
@@ -86,6 +86,40 @@ namespace ams::kern::svc {
|
||||
R_RETURN(KProcess::GetProcessList(out_num_processes, out_process_ids, max_out_count));
|
||||
}
|
||||
|
||||
constexpr size_t GetProcessSlotT0Sz(ams::svc::CreateProcessFlag flags) {
|
||||
if ((flags & ams::svc::CreateProcessFlag_AddressSpaceMask) == ams::svc::CreateProcessFlag_AddressSpace64Bit64KPage) {
|
||||
return (64 - 42);
|
||||
} else {
|
||||
return (64 - 39);
|
||||
}
|
||||
}
|
||||
|
||||
KProcess *CreateProcessForAddressSpace(ams::svc::CreateProcessFlag flags) {
|
||||
/* Find a process slab slot whose root page table is meant for the requested address space. */
|
||||
const size_t desired_t0sz = GetProcessSlotT0Sz(flags);
|
||||
|
||||
KProcess *process = nullptr;
|
||||
KProcess *rejected[init::SlabCountKProcess];
|
||||
size_t num_rejected = 0;
|
||||
while ((process = KProcess::Create()) != nullptr) {
|
||||
/* Stop once we find a slot whose T0SZ matches. */
|
||||
if ((KProcessPageTable::GetProcessTcrEl1(process->GetSlabIndex()) & 0x3F) == desired_t0sz) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Otherwise, park the process and try the next slot. */
|
||||
rejected[num_rejected++] = process;
|
||||
process = nullptr;
|
||||
}
|
||||
|
||||
/* Release every process we parked while searching. */
|
||||
for (size_t i = 0; i < num_rejected; ++i) {
|
||||
rejected[i]->Close();
|
||||
}
|
||||
|
||||
return process;
|
||||
}
|
||||
|
||||
Result CreateProcess(ams::svc::Handle *out, const ams::svc::CreateProcessParameter ¶ms, KUserPointer<const uint32_t *> user_caps, int32_t num_caps) {
|
||||
/* Validate the capabilities pointer. */
|
||||
R_UNLESS(num_caps >= 0, svc::ResultInvalidPointer());
|
||||
@@ -219,8 +253,8 @@ namespace ams::kern::svc {
|
||||
/* Get the current handle table. */
|
||||
auto &handle_table = GetCurrentProcess().GetHandleTable();
|
||||
|
||||
/* Create the new process. */
|
||||
KProcess *process = KProcess::Create();
|
||||
/* Create the new process, ensuring its page table slot matches the requested address space. */
|
||||
KProcess *process = CreateProcessForAddressSpace(static_cast<ams::svc::CreateProcessFlag>(params.flags));
|
||||
R_UNLESS(process != nullptr, svc::ResultOutOfResource());
|
||||
|
||||
/* Ensure that the only reference to the process is in the handle table when we're done. */
|
||||
|
||||
@@ -96,6 +96,9 @@ namespace ams::svc {
|
||||
MemoryState_CodeOut = 0x15,
|
||||
MemoryState_Coverage = 0x16,
|
||||
MemoryState_Insecure = 0x17,
|
||||
MemoryState_Remote = 0x18,
|
||||
MemoryState_Protected = 0x19,
|
||||
MemoryState_ShadowStack = 0x1A,
|
||||
};
|
||||
|
||||
enum MemoryPermission : u32 {
|
||||
@@ -483,6 +486,7 @@ namespace ams::svc {
|
||||
DebugThreadParam_IdealCore = 2,
|
||||
DebugThreadParam_CurrentCore = 3,
|
||||
DebugThreadParam_AffinityMask = 4,
|
||||
DebugThreadParam_Unknown5 = 5,
|
||||
};
|
||||
|
||||
enum DebugException : u32 {
|
||||
|
||||
@@ -234,7 +234,7 @@ namespace ams::kern::init {
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(reinterpret_cast<uintptr_t>(std::addressof(KPageTable::GetTcrEL1Entry(KPageTable::NumPTEntries))) < rodata_end);
|
||||
|
||||
/* Get the default tcr_el1 value, with T0SZ set for a 39-bit address space. */
|
||||
const u64 tcr_el1 = (cpu::GetTcrEl1() & ~UINT64_C(0x3F)) | UINT64_C(64 - 39);
|
||||
const u64 tcr_el1 = (cpu::GetTcrEl1() & ~UINT64_C(0x3F)) | (64 - 39);
|
||||
|
||||
/* Allocate pages for all ttbr0 entries. */
|
||||
for (size_t i = 0; i < KPageTable::NumPTEntries; ++i) {
|
||||
|
||||
Reference in New Issue
Block a user