kern/loader: make aware of new address space and shadow stack region
This commit is contained in:
@@ -81,6 +81,7 @@ namespace ams::kern::arch::arm64::cpu {
|
||||
MESOSPHERE_CPU_DEFINE_SYSREG_ACCESSORS(SpEl0, sp_el0)
|
||||
|
||||
MESOSPHERE_CPU_DEFINE_SYSREG_ACCESSORS(IdAa64Dfr0El1, id_aa64dfr0_el1)
|
||||
MESOSPHERE_CPU_DEFINE_SYSREG_ACCESSORS(IdAa64Mmfr0El1, id_aa64mmfr0_el1)
|
||||
|
||||
MESOSPHERE_CPU_DEFINE_SYSREG_ACCESSORS(PmcrEl0, pmcr_el0)
|
||||
MESOSPHERE_CPU_DEFINE_SYSREG_ACCESSORS(PmUserEnrEl0, pmuserenr_el0)
|
||||
|
||||
@@ -94,10 +94,10 @@ namespace ams::kern::arch::arm64 {
|
||||
return KPageTable::GetBlockSize(static_cast<KPageTable::BlockType>(KPageTable::GetBlockType(alignment) + 1));
|
||||
}
|
||||
public:
|
||||
/* TODO: How should this size be determined. Does the KProcess slab count need to go in a header as a define? */
|
||||
static constexpr size_t NumTtbr0Entries = 81;
|
||||
static constexpr size_t NumPTEntries = ::ams::kern::init::SlabCountKProcess + 1; /* +1 for kernel. */
|
||||
private:
|
||||
static constinit inline const volatile u64 s_ttbr0_entries[NumTtbr0Entries] = {};
|
||||
static constinit inline const volatile u64 s_ttbr0_entries[NumPTEntries] = {};
|
||||
static constinit inline const volatile u64 s_tcr_el1_entries[NumPTEntries] = {};
|
||||
private:
|
||||
KPageTableManager *m_manager;
|
||||
u8 m_asid;
|
||||
@@ -188,6 +188,12 @@ namespace ams::kern::arch::arm64 {
|
||||
return s_ttbr0_entries[0];
|
||||
}
|
||||
|
||||
static const volatile u64 &GetTcrEL1Entry(size_t index) { return s_tcr_el1_entries[index]; }
|
||||
|
||||
static ALWAYS_INLINE u64 GetKernelTcrEL1() {
|
||||
return s_tcr_el1_entries[0];
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE void ActivateKernel() {
|
||||
/* Activate, using asid 0 and process id = 0xFFFFFFFF */
|
||||
cpu::SwitchProcess(GetKernelTtbr0(), 0xFFFFFFFF);
|
||||
|
||||
@@ -302,19 +302,21 @@ 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); }
|
||||
|
||||
KProcessAddress GetAddressSpaceStart() const { return m_page_table.GetAddressSpaceStart(); }
|
||||
KProcessAddress GetHeapRegionStart() const { return m_page_table.GetHeapRegionStart(); }
|
||||
KProcessAddress GetAliasRegionStart() const { return m_page_table.GetAliasRegionStart(); }
|
||||
KProcessAddress GetStackRegionStart() const { return m_page_table.GetStackRegionStart(); }
|
||||
KProcessAddress GetKernelMapRegionStart() const { return m_page_table.GetKernelMapRegionStart(); }
|
||||
KProcessAddress GetAliasCodeRegionStart() const { return m_page_table.GetAliasCodeRegionStart(); }
|
||||
KProcessAddress GetAddressSpaceStart() const { return m_page_table.GetAddressSpaceStart(); }
|
||||
KProcessAddress GetShadowStackRegionStart() const { return m_page_table.GetShadowStackRegionStart(); }
|
||||
KProcessAddress GetHeapRegionStart() const { return m_page_table.GetHeapRegionStart(); }
|
||||
KProcessAddress GetAliasRegionStart() const { return m_page_table.GetAliasRegionStart(); }
|
||||
KProcessAddress GetStackRegionStart() const { return m_page_table.GetStackRegionStart(); }
|
||||
KProcessAddress GetKernelMapRegionStart() const { return m_page_table.GetKernelMapRegionStart(); }
|
||||
KProcessAddress GetAliasCodeRegionStart() const { return m_page_table.GetAliasCodeRegionStart(); }
|
||||
|
||||
size_t GetAddressSpaceSize() const { return m_page_table.GetAddressSpaceSize(); }
|
||||
size_t GetHeapRegionSize() const { return m_page_table.GetHeapRegionSize(); }
|
||||
size_t GetAliasRegionSize() const { return m_page_table.GetAliasRegionSize(); }
|
||||
size_t GetStackRegionSize() const { return m_page_table.GetStackRegionSize(); }
|
||||
size_t GetKernelMapRegionSize() const { return m_page_table.GetKernelMapRegionSize(); }
|
||||
size_t GetAliasCodeRegionSize() const { return m_page_table.GetAliasCodeRegionSize(); }
|
||||
size_t GetAddressSpaceSize() const { return m_page_table.GetAddressSpaceSize(); }
|
||||
size_t GetShadowStackRegionSize() const { return m_page_table.GetShadowStackRegionSize(); }
|
||||
size_t GetHeapRegionSize() const { return m_page_table.GetHeapRegionSize(); }
|
||||
size_t GetAliasRegionSize() const { return m_page_table.GetAliasRegionSize(); }
|
||||
size_t GetStackRegionSize() const { return m_page_table.GetStackRegionSize(); }
|
||||
size_t GetKernelMapRegionSize() const { return m_page_table.GetKernelMapRegionSize(); }
|
||||
size_t GetAliasCodeRegionSize() const { return m_page_table.GetAliasCodeRegionSize(); }
|
||||
|
||||
size_t GetAliasRegionExtraSize() const { return m_page_table.GetAliasRegionExtraSize(); }
|
||||
|
||||
|
||||
@@ -18,6 +18,25 @@
|
||||
#include <mesosphere/kern_k_slab_heap.hpp>
|
||||
|
||||
namespace ams::kern::init {
|
||||
/* Constexpr counts. */
|
||||
constexpr size_t SlabCountKProcess = 80;
|
||||
constexpr size_t SlabCountKThread = 800;
|
||||
constexpr size_t SlabCountKEvent = 900;
|
||||
constexpr size_t SlabCountKInterruptEvent = 100;
|
||||
constexpr size_t SlabCountKPort = 384;
|
||||
constexpr size_t SlabCountKSharedMemory = 80;
|
||||
constexpr size_t SlabCountKTransferMemory = 200;
|
||||
constexpr size_t SlabCountKCodeMemory = 10;
|
||||
constexpr size_t SlabCountKDeviceAddressSpace = 300;
|
||||
constexpr size_t SlabCountKSession = 1133;
|
||||
constexpr size_t SlabCountKLightSession = 100;
|
||||
constexpr size_t SlabCountKObjectName = 7;
|
||||
constexpr size_t SlabCountKResourceLimit = 5;
|
||||
constexpr size_t SlabCountKDebug = cpu::NumCores;
|
||||
constexpr size_t SlabCountKIoPool = 1;
|
||||
constexpr size_t SlabCountKIoRegion = 6;
|
||||
constexpr size_t SlabcountKSessionRequestMappings = 40;
|
||||
|
||||
|
||||
struct KSlabResourceCounts {
|
||||
size_t num_KProcess;
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace ams::kern {
|
||||
enum Type {
|
||||
Type_MapSmall = 0,
|
||||
Type_MapLarge = 1,
|
||||
Type_Map39Bit = 2,
|
||||
Type_MapHuge = 2,
|
||||
Type_Heap = 3,
|
||||
Type_Stack = 4,
|
||||
Type_Alias = 5,
|
||||
|
||||
@@ -211,15 +211,15 @@ namespace ams::kern {
|
||||
uintptr_t m_address;
|
||||
size_t m_size;
|
||||
KMemoryState m_state;
|
||||
u16 m_device_disable_merge_left_count;
|
||||
u16 m_device_disable_merge_right_count;
|
||||
u16 m_ipc_lock_count;
|
||||
u16 m_device_use_count;
|
||||
u16 m_ipc_disable_merge_count;
|
||||
KMemoryPermission m_permission;
|
||||
KMemoryAttribute m_attribute;
|
||||
KMemoryPermission m_original_permission;
|
||||
u16 m_ipc_lock_count;
|
||||
u16 m_device_use_count;
|
||||
KMemoryBlockDisableMergeAttribute m_disable_merge_attribute;
|
||||
u16 m_ipc_disable_merge_count;
|
||||
u16 m_device_disable_merge_left_count;
|
||||
u16 m_device_disable_merge_right_count;
|
||||
|
||||
constexpr ams::svc::MemoryInfo GetSvcMemoryInfo() const {
|
||||
return {
|
||||
@@ -365,15 +365,15 @@ namespace ams::kern {
|
||||
.m_address = GetInteger(this->GetAddress()),
|
||||
.m_size = this->GetSize(),
|
||||
.m_state = m_memory_state,
|
||||
.m_device_disable_merge_left_count = m_device_disable_merge_left_count,
|
||||
.m_device_disable_merge_right_count = m_device_disable_merge_right_count,
|
||||
.m_ipc_lock_count = m_ipc_lock_count,
|
||||
.m_device_use_count = m_device_use_count,
|
||||
.m_ipc_disable_merge_count = m_ipc_disable_merge_count,
|
||||
.m_permission = m_permission,
|
||||
.m_attribute = m_attribute,
|
||||
.m_original_permission = m_original_permission,
|
||||
.m_ipc_lock_count = m_ipc_lock_count,
|
||||
.m_device_use_count = m_device_use_count,
|
||||
.m_disable_merge_attribute = m_disable_merge_attribute,
|
||||
.m_ipc_disable_merge_count = m_ipc_disable_merge_count,
|
||||
.m_device_disable_merge_left_count = m_device_disable_merge_left_count,
|
||||
.m_device_disable_merge_right_count = m_device_disable_merge_right_count,
|
||||
};
|
||||
}
|
||||
public:
|
||||
|
||||
@@ -90,10 +90,11 @@ namespace ams::kern {
|
||||
};
|
||||
|
||||
enum RegionType {
|
||||
RegionType_KernelMap = 0,
|
||||
RegionType_Stack = 1,
|
||||
RegionType_Alias = 2,
|
||||
RegionType_Heap = 3,
|
||||
RegionType_KernelMap = 0,
|
||||
RegionType_Stack = 1,
|
||||
RegionType_Alias = 2,
|
||||
RegionType_Heap = 3,
|
||||
RegionType_ShadowStack = 4,
|
||||
|
||||
RegionType_Count,
|
||||
};
|
||||
@@ -196,7 +197,6 @@ namespace ams::kern {
|
||||
KPageTableImpl m_impl;
|
||||
KMemoryBlockManager m_memory_block_manager;
|
||||
u32 m_allocate_option;
|
||||
u32 m_address_space_width;
|
||||
bool m_is_kernel;
|
||||
bool m_enable_aslr;
|
||||
bool m_enable_device_address_space_merge;
|
||||
@@ -212,23 +212,24 @@ namespace ams::kern {
|
||||
public:
|
||||
constexpr explicit KPageTableBase(util::ConstantInitializeTag)
|
||||
: m_address_space_start(Null<KProcessAddress>), m_address_space_end(Null<KProcessAddress>),
|
||||
m_region_starts{Null<KProcessAddress>, Null<KProcessAddress>, Null<KProcessAddress>, Null<KProcessAddress>},
|
||||
m_region_ends{Null<KProcessAddress>, Null<KProcessAddress>, Null<KProcessAddress>, Null<KProcessAddress>},
|
||||
m_region_starts{Null<KProcessAddress>, Null<KProcessAddress>, Null<KProcessAddress>, Null<KProcessAddress>, Null<KProcessAddress>},
|
||||
m_region_ends{Null<KProcessAddress>, Null<KProcessAddress>, Null<KProcessAddress>, Null<KProcessAddress>, Null<KProcessAddress>},
|
||||
m_current_heap_end(Null<KProcessAddress>), m_alias_code_region_start(Null<KProcessAddress>),
|
||||
m_alias_code_region_end(Null<KProcessAddress>), m_code_region_start(Null<KProcessAddress>), m_code_region_end(Null<KProcessAddress>),
|
||||
m_max_heap_size(), m_mapped_physical_memory_size(), m_mapped_unsafe_physical_memory(), m_mapped_insecure_memory(), m_mapped_ipc_server_memory(), m_alias_region_extra_size(),
|
||||
m_general_lock(), m_map_physical_memory_lock(), m_device_map_lock(), m_impl(util::ConstantInitialize), m_memory_block_manager(util::ConstantInitialize),
|
||||
m_allocate_option(), m_address_space_width(), m_is_kernel(), m_enable_aslr(), m_enable_device_address_space_merge(), m_allowed_exec_device_mapping(),
|
||||
m_memory_block_slab_manager(), m_block_info_manager(), m_resource_limit(), m_cached_physical_linear_region(), m_cached_physical_heap_region(),
|
||||
m_heap_fill_value(), m_ipc_fill_value(), m_stack_fill_value()
|
||||
m_max_heap_size(), m_mapped_physical_memory_size(), m_mapped_unsafe_physical_memory(), m_mapped_insecure_memory(),
|
||||
m_mapped_ipc_server_memory(), m_alias_region_extra_size(), m_general_lock(), m_map_physical_memory_lock(),
|
||||
m_device_map_lock(), m_impl(util::ConstantInitialize), m_memory_block_manager(util::ConstantInitialize),
|
||||
m_allocate_option(), m_is_kernel(), m_enable_aslr(), m_enable_device_address_space_merge(), m_allowed_exec_device_mapping(),
|
||||
m_memory_block_slab_manager(), m_block_info_manager(), m_resource_limit(), m_cached_physical_linear_region(),
|
||||
m_cached_physical_heap_region(), m_heap_fill_value(), m_ipc_fill_value(), m_stack_fill_value()
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
explicit KPageTableBase() { /* ... */ }
|
||||
|
||||
NOINLINE void InitializeForKernel(bool is_64_bit, void *table, KVirtualAddress start, KVirtualAddress end);
|
||||
NOINLINE Result InitializeForProcess(ams::svc::CreateProcessFlag flags, bool from_back, KMemoryManager::Pool pool, void *table, KProcessAddress start, KProcessAddress end, KProcessAddress code_address, size_t code_size, KSystemResource *system_resource, KResourceLimit *resource_limit);
|
||||
NOINLINE void InitializeForKernel(void *table, KVirtualAddress start, KVirtualAddress end);
|
||||
NOINLINE Result InitializeForProcess(ams::svc::CreateProcessFlag flags, bool from_back, void *table, KProcessAddress start, KProcessAddress end, KMemoryManager::Pool pool, KProcessAddress code_address, size_t code_size, KSystemResource *system_resource, KResourceLimit *resource_limit);
|
||||
|
||||
void Finalize();
|
||||
|
||||
@@ -247,6 +248,14 @@ namespace ams::kern {
|
||||
return this->Contains(addr, size) && m_region_starts[RegionType_Alias] <= addr && addr + size - 1 <= m_region_ends[RegionType_Alias] - 1;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
constexpr bool IsSafeUserPointer(KProcessAddress addr, size_t size) const {
|
||||
return this->Contains(addr, size) && !this->IsInShadowStackRegion(addr, size);
|
||||
}
|
||||
|
||||
bool IsInUnsafeAliasRegion(KProcessAddress addr, size_t size) const {
|
||||
/* Even though Unsafe physical memory is KMemoryState_Normal, it must be mapped inside the alias code region. */
|
||||
return this->CanContain(addr, size, ams::svc::MemoryState_AliasCode);
|
||||
@@ -490,19 +499,21 @@ namespace ams::kern {
|
||||
public:
|
||||
KProcessAddress GetAddressSpaceStart() const { return m_address_space_start; }
|
||||
|
||||
KProcessAddress GetHeapRegionStart() const { return m_region_starts[RegionType_Heap]; }
|
||||
KProcessAddress GetAliasRegionStart() const { return m_region_starts[RegionType_Alias]; }
|
||||
KProcessAddress GetStackRegionStart() const { return m_region_starts[RegionType_Stack]; }
|
||||
KProcessAddress GetKernelMapRegionStart() const { return m_region_starts[RegionType_KernelMap]; }
|
||||
KProcessAddress GetShadowStackRegionStart() const { return m_region_starts[RegionType_ShadowStack]; }
|
||||
KProcessAddress GetHeapRegionStart() const { return m_region_starts[RegionType_Heap]; }
|
||||
KProcessAddress GetAliasRegionStart() const { return m_region_starts[RegionType_Alias]; }
|
||||
KProcessAddress GetStackRegionStart() const { return m_region_starts[RegionType_Stack]; }
|
||||
KProcessAddress GetKernelMapRegionStart() const { return m_region_starts[RegionType_KernelMap]; }
|
||||
|
||||
KProcessAddress GetAliasCodeRegionStart() const { return m_alias_code_region_start; }
|
||||
|
||||
size_t GetAddressSpaceSize() const { return m_address_space_end - m_address_space_start; }
|
||||
|
||||
size_t GetHeapRegionSize() const { return m_region_ends[RegionType_Heap] - m_region_starts[RegionType_Heap]; }
|
||||
size_t GetAliasRegionSize() const { return m_region_ends[RegionType_Alias] - m_region_starts[RegionType_Alias]; }
|
||||
size_t GetStackRegionSize() const { return m_region_ends[RegionType_Stack] - m_region_starts[RegionType_Stack]; }
|
||||
size_t GetKernelMapRegionSize() const { return m_region_ends[RegionType_KernelMap] - m_region_starts[RegionType_KernelMap]; }
|
||||
size_t GetShadowStackRegionSize() const { return m_region_ends[RegionType_ShadowStack] - m_region_starts[RegionType_ShadowStack]; }
|
||||
size_t GetHeapRegionSize() const { return m_region_ends[RegionType_Heap] - m_region_starts[RegionType_Heap]; }
|
||||
size_t GetAliasRegionSize() const { return m_region_ends[RegionType_Alias] - m_region_starts[RegionType_Alias]; }
|
||||
size_t GetStackRegionSize() const { return m_region_ends[RegionType_Stack] - m_region_starts[RegionType_Stack]; }
|
||||
size_t GetKernelMapRegionSize() const { return m_region_ends[RegionType_KernelMap] - m_region_starts[RegionType_KernelMap]; }
|
||||
|
||||
size_t GetAliasCodeRegionSize() const { return m_alias_code_region_end - m_alias_code_region_start; }
|
||||
|
||||
|
||||
@@ -215,6 +215,7 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
u32 GetAllocateOption() const { return m_page_table.GetAllocateOption(); }
|
||||
size_t GetAddressSpaceSize() const { return m_page_table.GetAddressSpaceSize(); }
|
||||
|
||||
ThreadList &GetThreadList() { return m_thread_list; }
|
||||
const ThreadList &GetThreadList() const { return m_thread_list; }
|
||||
|
||||
@@ -125,7 +125,7 @@ namespace ams::kern::arch::arm64 {
|
||||
m_manager = Kernel::GetSystemSystemResource().GetPageTableManagerPointer();
|
||||
|
||||
/* Initialize the base page table. */
|
||||
KPageTableBase::InitializeForKernel(true, table, start, end);
|
||||
KPageTableBase::InitializeForKernel(table, start, end);
|
||||
}
|
||||
|
||||
Result KPageTable::InitializeForProcess(ams::svc::CreateProcessFlag flags, bool from_back, KMemoryManager::Pool pool, KProcessAddress code_address, size_t code_size, KSystemResource *system_resource, KResourceLimit *resource_limit, size_t process_index) {
|
||||
@@ -144,7 +144,7 @@ namespace ams::kern::arch::arm64 {
|
||||
const size_t as_width = GetAddressSpaceWidth(flags);
|
||||
const KProcessAddress as_start = 0;
|
||||
const KProcessAddress as_end = (1ul << as_width);
|
||||
R_TRY(KPageTableBase::InitializeForProcess(flags, from_back, pool, GetVoidPointer(ttbr0_virt), as_start, as_end, code_address, code_size, system_resource, resource_limit));
|
||||
R_TRY(KPageTableBase::InitializeForProcess(flags, from_back, GetVoidPointer(ttbr0_virt), as_start, as_end, pool, code_address, code_size, system_resource, resource_limit));
|
||||
|
||||
/* Note that we've updated the table (since we created it). */
|
||||
this->NoteUpdated();
|
||||
|
||||
@@ -60,25 +60,6 @@ namespace ams::kern::init {
|
||||
|
||||
#undef DEFINE_SLAB_TYPE_ENUM_MEMBER
|
||||
|
||||
/* Constexpr counts. */
|
||||
constexpr size_t SlabCountKProcess = 80;
|
||||
constexpr size_t SlabCountKThread = 800;
|
||||
constexpr size_t SlabCountKEvent = 900;
|
||||
constexpr size_t SlabCountKInterruptEvent = 100;
|
||||
constexpr size_t SlabCountKPort = 384;
|
||||
constexpr size_t SlabCountKSharedMemory = 80;
|
||||
constexpr size_t SlabCountKTransferMemory = 200;
|
||||
constexpr size_t SlabCountKCodeMemory = 10;
|
||||
constexpr size_t SlabCountKDeviceAddressSpace = 300;
|
||||
constexpr size_t SlabCountKSession = 1133;
|
||||
constexpr size_t SlabCountKLightSession = 100;
|
||||
constexpr size_t SlabCountKObjectName = 7;
|
||||
constexpr size_t SlabCountKResourceLimit = 5;
|
||||
constexpr size_t SlabCountKDebug = cpu::NumCores;
|
||||
constexpr size_t SlabCountKIoPool = 1;
|
||||
constexpr size_t SlabCountKIoRegion = 6;
|
||||
constexpr size_t SlabcountKSessionRequestMappings = 40;
|
||||
|
||||
constexpr size_t SlabCountExtraKThread = (1024 + 256 + 256) - SlabCountKThread;
|
||||
|
||||
namespace test {
|
||||
|
||||
@@ -30,15 +30,20 @@ namespace ams::kern {
|
||||
{ 36, ams::svc::AddressLargeMap36Start, ams::svc::AddressLargeMap36Size, KAddressSpaceInfo::Type_MapLarge, },
|
||||
{ 36, Invalid, ams::svc::AddressMemoryRegionHeap36Size, KAddressSpaceInfo::Type_Heap, },
|
||||
{ 36, Invalid, ams::svc::AddressMemoryRegionAlias36Size, KAddressSpaceInfo::Type_Alias, },
|
||||
{ 39, ams::svc::AddressMap39Start, ams::svc::AddressMap39Size, KAddressSpaceInfo::Type_Map39Bit, },
|
||||
{ 39, ams::svc::AddressMap39Start, ams::svc::AddressMap39Size, KAddressSpaceInfo::Type_MapHuge, },
|
||||
{ 39, Invalid, ams::svc::AddressMemoryRegionSmall39Size, KAddressSpaceInfo::Type_MapSmall, },
|
||||
{ 39, Invalid, ams::svc::AddressMemoryRegionHeap39Size, KAddressSpaceInfo::Type_Heap, },
|
||||
{ 39, Invalid, ams::svc::AddressMemoryRegionAlias39Size, KAddressSpaceInfo::Type_Alias, },
|
||||
{ 39, Invalid, ams::svc::AddressMemoryRegionStack39Size, KAddressSpaceInfo::Type_Stack, },
|
||||
{ 42, ams::svc::AddressMap42Start, ams::svc::AddressMap42Size, KAddressSpaceInfo::Type_MapHuge, },
|
||||
{ 42, Invalid, ams::svc::AddressMemoryRegionSmall42Size, KAddressSpaceInfo::Type_MapSmall, },
|
||||
{ 42, Invalid, 0, KAddressSpaceInfo::Type_Heap, },
|
||||
{ 42, Invalid, ams::svc::AddressMemoryRegionAlias42Size, KAddressSpaceInfo::Type_Alias, },
|
||||
{ 42, Invalid, ams::svc::AddressMemoryRegionStack42Size, KAddressSpaceInfo::Type_Stack, },
|
||||
};
|
||||
|
||||
constexpr u8 FlagsToAddressSpaceWidthTable[4] = {
|
||||
32, 36, 32, 39
|
||||
constexpr u8 FlagsToAddressSpaceWidthTable[5] = {
|
||||
32, 36, 32, 39, 42
|
||||
};
|
||||
|
||||
constexpr size_t GetAddressSpaceWidth(ams::svc::CreateProcessFlag flags) {
|
||||
@@ -54,6 +59,7 @@ namespace ams::kern {
|
||||
static_assert(GetAddressSpaceWidth(ams::svc::CreateProcessFlag_AddressSpace64BitDeprecated) == 36);
|
||||
static_assert(GetAddressSpaceWidth(ams::svc::CreateProcessFlag_AddressSpace32BitWithoutAlias) == 32);
|
||||
static_assert(GetAddressSpaceWidth(ams::svc::CreateProcessFlag_AddressSpace64Bit) == 39);
|
||||
static_assert(GetAddressSpaceWidth(ams::svc::CreateProcessFlag_AddressSpace64Bit64KPage) == 42);
|
||||
|
||||
KAddressSpaceInfo &GetAddressSpaceInfo(size_t width, KAddressSpaceInfo::Type type) {
|
||||
for (auto &info : AddressSpaceInfos) {
|
||||
|
||||
@@ -233,7 +233,7 @@ namespace ams::kern {
|
||||
/* a number of pages here. Even though this is presumably only used for debug assertions, this is */
|
||||
/* almost certainly a bug. */
|
||||
using ASType = KAddressSpaceInfo::Type;
|
||||
const ASType as_type = this->Is64BitAddressSpace() ? ((GetTargetFirmware() >= TargetFirmware_2_0_0) ? KAddressSpaceInfo::Type_Map39Bit : KAddressSpaceInfo::Type_MapSmall) : KAddressSpaceInfo::Type_MapSmall;
|
||||
const ASType as_type = this->Is64BitAddressSpace() ? ((GetTargetFirmware() >= TargetFirmware_2_0_0) ? KAddressSpaceInfo::Type_MapHuge : KAddressSpaceInfo::Type_MapSmall) : KAddressSpaceInfo::Type_MapSmall;
|
||||
const uintptr_t map_start = KAddressSpaceInfo::GetAddressSpaceStart(static_cast<ams::svc::CreateProcessFlag>(out->flags), as_type, out->code_num_pages);
|
||||
const size_t map_size = KAddressSpaceInfo::GetAddressSpaceSize(static_cast<ams::svc::CreateProcessFlag>(out->flags), as_type);
|
||||
const uintptr_t map_end = map_start + map_size;
|
||||
|
||||
@@ -88,14 +88,14 @@ namespace ams::kern {
|
||||
}
|
||||
}
|
||||
|
||||
void KPageTableBase::InitializeForKernel(bool is_64_bit, void *table, KVirtualAddress start, KVirtualAddress end) {
|
||||
void KPageTableBase::InitializeForKernel(void *table, KVirtualAddress start, KVirtualAddress end) {
|
||||
/* Initialize our members. */
|
||||
m_address_space_width = (is_64_bit) ? BITSIZEOF(u64) : BITSIZEOF(u32);
|
||||
m_address_space_start = KProcessAddress(GetInteger(start));
|
||||
m_address_space_end = KProcessAddress(GetInteger(end));
|
||||
m_is_kernel = true;
|
||||
m_enable_aslr = true;
|
||||
m_enable_device_address_space_merge = false;
|
||||
m_allowed_exec_device_mapping = false;
|
||||
|
||||
for (auto i = 0; i < RegionType_Count; ++i) {
|
||||
m_region_starts[i] = 0;
|
||||
@@ -133,7 +133,7 @@ namespace ams::kern {
|
||||
MESOSPHERE_R_ABORT_UNLESS(m_memory_block_manager.Initialize(m_address_space_start, m_address_space_end, m_memory_block_slab_manager));
|
||||
}
|
||||
|
||||
Result KPageTableBase::InitializeForProcess(ams::svc::CreateProcessFlag flags, bool from_back, KMemoryManager::Pool pool, void *table, KProcessAddress start, KProcessAddress end, KProcessAddress code_address, size_t code_size, KSystemResource *system_resource, KResourceLimit *resource_limit) {
|
||||
Result KPageTableBase::InitializeForProcess(ams::svc::CreateProcessFlag flags, bool from_back, void *table, KProcessAddress start, KProcessAddress end, KMemoryManager::Pool pool, KProcessAddress code_address, size_t code_size, KSystemResource *system_resource, KResourceLimit *resource_limit) {
|
||||
/* Validate the region. */
|
||||
MESOSPHERE_ABORT_UNLESS(start <= code_address);
|
||||
MESOSPHERE_ABORT_UNLESS(code_address < code_address + code_size);
|
||||
@@ -151,9 +151,9 @@ namespace ams::kern {
|
||||
m_alias_region_extra_size = 0;
|
||||
|
||||
/* Set our width and heap/alias sizes. */
|
||||
m_address_space_width = GetAddressSpaceWidth(flags);
|
||||
size_t alias_region_size = GetSpaceSize(KAddressSpaceInfo::Type_Alias);
|
||||
size_t heap_region_size = GetSpaceSize(KAddressSpaceInfo::Type_Heap);
|
||||
size_t address_space_width = GetAddressSpaceWidth(flags);
|
||||
size_t alias_region_size = GetSpaceSize(KAddressSpaceInfo::Type_Alias);
|
||||
size_t heap_region_size = GetSpaceSize(KAddressSpaceInfo::Type_Heap);
|
||||
|
||||
/* Set code regions and determine remaining sizes. */
|
||||
KProcessAddress process_code_start;
|
||||
@@ -162,12 +162,12 @@ namespace ams::kern {
|
||||
size_t kernel_map_region_size;
|
||||
KProcessAddress before_process_code_start, after_process_code_start;
|
||||
size_t before_process_code_size, after_process_code_size;
|
||||
if (m_address_space_width == 39) {
|
||||
if (address_space_width == 39 || address_space_width == 42) {
|
||||
stack_region_size = GetSpaceSize(KAddressSpaceInfo::Type_Stack);
|
||||
kernel_map_region_size = GetSpaceSize(KAddressSpaceInfo::Type_MapSmall);
|
||||
|
||||
m_code_region_start = GetSpaceStart(KAddressSpaceInfo::Type_Map39Bit);
|
||||
m_code_region_end = m_code_region_start + GetSpaceSize(KAddressSpaceInfo::Type_Map39Bit);
|
||||
m_code_region_start = GetSpaceStart(KAddressSpaceInfo::Type_MapHuge);
|
||||
m_code_region_end = m_code_region_start + GetSpaceSize(KAddressSpaceInfo::Type_MapHuge);
|
||||
m_alias_code_region_start = m_code_region_start;
|
||||
m_alias_code_region_end = m_code_region_end;
|
||||
|
||||
@@ -182,7 +182,7 @@ namespace ams::kern {
|
||||
/* If we have a 39-bit address space and should, enable extra size to the alias region. */
|
||||
if (flags & ams::svc::CreateProcessFlag_EnableAliasRegionExtraSize) {
|
||||
/* Extra size is 1/8th of the address space. */
|
||||
m_alias_region_extra_size = (static_cast<size_t>(1) << m_address_space_width) / 8;
|
||||
m_alias_region_extra_size = (static_cast<size_t>(1) << address_space_width) / 8;
|
||||
|
||||
alias_region_size += m_alias_region_extra_size;
|
||||
}
|
||||
@@ -208,6 +208,9 @@ namespace ams::kern {
|
||||
after_process_code_size = GetSpaceSize(KAddressSpaceInfo::Type_MapLarge);
|
||||
}
|
||||
|
||||
m_region_starts[RegionType_ShadowStack] = Null<KProcessAddress>;
|
||||
m_region_ends[RegionType_ShadowStack] = Null<KProcessAddress>;
|
||||
|
||||
/* Set other basic fields. */
|
||||
m_enable_aslr = (flags & ams::svc::CreateProcessFlag_EnableAslr) != 0;
|
||||
m_enable_device_address_space_merge = (flags & ams::svc::CreateProcessFlag_DisableDeviceAddressSpaceMerge) == 0;
|
||||
@@ -237,6 +240,9 @@ namespace ams::kern {
|
||||
|
||||
region_layouts[num_regions++] = { .size = alias_region_size, .type = RegionType_Alias, .alloc_index = 0, };
|
||||
region_layouts[num_regions++] = { .size = heap_region_size, .type = RegionType_Heap, .alloc_index = 0, };
|
||||
if (flags & ams::svc::CreateProcessFlag_EnableShadowStack) {
|
||||
region_layouts[num_regions++] = { .size = ams::svc::AddressShadowStackRegionSize, .type = RegionType_ShadowStack, .alloc_index = 0, };
|
||||
}
|
||||
|
||||
/* Selection-sort the regions by size largest-to-smallest. */
|
||||
for (size_t i = 0; i < num_regions - 1; ++i) {
|
||||
@@ -399,6 +405,18 @@ namespace ams::kern {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -494,6 +512,25 @@ namespace ams::kern {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Set heap and fill members. */
|
||||
@@ -1997,15 +2034,15 @@ namespace ams::kern {
|
||||
.m_address = GetInteger(m_address_space_end),
|
||||
.m_size = 0 - GetInteger(m_address_space_end),
|
||||
.m_state = static_cast<KMemoryState>(ams::svc::MemoryState_Inaccessible),
|
||||
.m_device_disable_merge_left_count = 0,
|
||||
.m_device_disable_merge_right_count = 0,
|
||||
.m_ipc_lock_count = 0,
|
||||
.m_device_use_count = 0,
|
||||
.m_ipc_disable_merge_count = 0,
|
||||
.m_permission = KMemoryPermission_None,
|
||||
.m_attribute = KMemoryAttribute_None,
|
||||
.m_original_permission = KMemoryPermission_None,
|
||||
.m_ipc_lock_count = 0,
|
||||
.m_device_use_count = 0,
|
||||
.m_disable_merge_attribute = KMemoryBlockDisableMergeAttribute_None,
|
||||
.m_ipc_disable_merge_count = 0,
|
||||
.m_device_disable_merge_left_count = 0,
|
||||
.m_device_disable_merge_right_count = 0,
|
||||
};
|
||||
out_page_info->flags = 0;
|
||||
|
||||
|
||||
@@ -109,6 +109,15 @@ namespace ams::kern::svc {
|
||||
case ams::svc::InfoType_AliasRegionExtraSize:
|
||||
*out = process->GetPageTable().GetAliasRegionExtraSize();
|
||||
break;
|
||||
case ams::svc::InfoType_AddressSpaceSize:
|
||||
*out = process->GetAddressSpaceSize();
|
||||
break;
|
||||
case ams::svc::InfoType_ShadowStackRegionAddress:
|
||||
*out = GetInteger(process->GetPageTable().GetShadowStackRegionStart());
|
||||
break;
|
||||
case ams::svc::InfoType_ShadowStackRegionSize:
|
||||
*out = process->GetPageTable().GetShadowStackRegionSize();
|
||||
break;
|
||||
MESOSPHERE_UNREACHABLE_DEFAULT_CASE();
|
||||
}
|
||||
|
||||
@@ -138,6 +147,9 @@ namespace ams::kern::svc {
|
||||
case ams::svc::InfoType_IsApplication:
|
||||
case ams::svc::InfoType_FreeThreadCount:
|
||||
case ams::svc::InfoType_AliasRegionExtraSize:
|
||||
case ams::svc::InfoType_AddressSpaceSize:
|
||||
case ams::svc::InfoType_ShadowStackRegionAddress:
|
||||
case ams::svc::InfoType_ShadowStackRegionSize:
|
||||
{
|
||||
/* These info types don't support non-zero subtypes. */
|
||||
R_UNLESS(info_subtype == 0, svc::ResultInvalidCombination());
|
||||
|
||||
@@ -100,6 +100,9 @@ namespace ams::kern::svc {
|
||||
/* Validate that the parameter flags are valid. */
|
||||
R_UNLESS((params.flags & ~ams::svc::CreateProcessFlag_All) == 0, svc::ResultInvalidEnumValue());
|
||||
|
||||
/* The 64KB page size is not yet allowed. */
|
||||
R_UNLESS((params.flags & ams::svc::CreateProcessFlag_AddressSpaceMask) != ams::svc::CreateProcessFlag_AddressSpace64Bit64KPage, svc::ResultInvalidCombination());
|
||||
|
||||
/* Validate that 64-bit process is okay. */
|
||||
const bool is_64_bit = (params.flags & ams::svc::CreateProcessFlag_Is64Bit) != 0;
|
||||
if constexpr (sizeof(void *) < sizeof(u64)) {
|
||||
@@ -130,12 +133,13 @@ namespace ams::kern::svc {
|
||||
}
|
||||
break;
|
||||
case ams::svc::CreateProcessFlag_AddressSpace64Bit:
|
||||
case ams::svc::CreateProcessFlag_AddressSpace64Bit64KPage:
|
||||
{
|
||||
/* 64-bit address space requires 64-bit process. */
|
||||
R_UNLESS(is_64_bit, svc::ResultInvalidCombination());
|
||||
|
||||
map_start = KAddressSpaceInfo::GetAddressSpaceStart(static_cast<ams::svc::CreateProcessFlag>(params.flags), KAddressSpaceInfo::Type_Map39Bit, code_size);
|
||||
map_end = map_start + KAddressSpaceInfo::GetAddressSpaceSize(static_cast<ams::svc::CreateProcessFlag>(params.flags), KAddressSpaceInfo::Type_Map39Bit);
|
||||
map_start = KAddressSpaceInfo::GetAddressSpaceStart(static_cast<ams::svc::CreateProcessFlag>(params.flags), KAddressSpaceInfo::Type_MapHuge, code_size);
|
||||
map_end = map_start + KAddressSpaceInfo::GetAddressSpaceSize(static_cast<ams::svc::CreateProcessFlag>(params.flags), KAddressSpaceInfo::Type_MapHuge);
|
||||
|
||||
map_size = KAddressSpaceInfo::GetAddressSpaceSize(static_cast<ams::svc::CreateProcessFlag>(params.flags), KAddressSpaceInfo::Type_Heap);
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ namespace ams::cfg {
|
||||
OverrideStatusFlag_AddressSpace64BitDeprecated = (svc::CreateProcessFlag_AddressSpace64BitDeprecated >> svc::CreateProcessFlag_AddressSpaceShift) << OverrideStatusFlag_AddressSpaceShift,
|
||||
OverrideStatusFlag_AddressSpace32BitWithoutAlias = (svc::CreateProcessFlag_AddressSpace32BitWithoutAlias >> svc::CreateProcessFlag_AddressSpaceShift) << OverrideStatusFlag_AddressSpaceShift,
|
||||
OverrideStatusFlag_AddressSpace64Bit = (svc::CreateProcessFlag_AddressSpace64Bit >> svc::CreateProcessFlag_AddressSpaceShift) << OverrideStatusFlag_AddressSpaceShift,
|
||||
OverrideStatusFlag_AddressSpace64Bit64KPage = (svc::CreateProcessFlag_AddressSpace64Bit64KPage >> svc::CreateProcessFlag_AddressSpaceShift) << OverrideStatusFlag_AddressSpaceShift,
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@@ -235,11 +235,16 @@ namespace ams::ldr {
|
||||
MetaFlag_PreventCodeReads = (1 << 7),
|
||||
};
|
||||
|
||||
enum MetaFlag2 {
|
||||
MetaFlag2_EnableShadowStack = (1 << 0),
|
||||
};
|
||||
|
||||
enum AddressSpaceType {
|
||||
AddressSpaceType_32Bit = 0,
|
||||
AddressSpaceType_64BitDeprecated = 1,
|
||||
AddressSpaceType_32BitWithoutAlias = 2,
|
||||
AddressSpaceType_64Bit = 3,
|
||||
AddressSpaceType_64Bit64KPage = 4,
|
||||
};
|
||||
|
||||
#if defined(ATMOSPHERE_OS_HORIZON)
|
||||
@@ -247,13 +252,14 @@ namespace ams::ldr {
|
||||
static_assert(AddressSpaceType_64BitDeprecated == (svc::CreateProcessFlag_AddressSpace64BitDeprecated >> svc::CreateProcessFlag_AddressSpaceShift));
|
||||
static_assert(AddressSpaceType_32BitWithoutAlias == (svc::CreateProcessFlag_AddressSpace32BitWithoutAlias >> svc::CreateProcessFlag_AddressSpaceShift));
|
||||
static_assert(AddressSpaceType_64Bit == (svc::CreateProcessFlag_AddressSpace64Bit >> svc::CreateProcessFlag_AddressSpaceShift));
|
||||
static_assert(AddressSpaceType_64Bit64KPage == (svc::CreateProcessFlag_AddressSpace64Bit64KPage >> svc::CreateProcessFlag_AddressSpaceShift));
|
||||
#endif
|
||||
|
||||
u32 magic;
|
||||
u32 signature_key_generation;
|
||||
u8 reserved_08[4];
|
||||
u8 flags;
|
||||
u8 reserved_0D;
|
||||
u8 flags2;
|
||||
u8 main_thread_priority;
|
||||
u8 default_cpu_id;
|
||||
u8 reserved_10[4];
|
||||
|
||||
@@ -153,6 +153,8 @@ namespace ams::cfg {
|
||||
impl::OverrideStatusFlag ParseOverrideAddressSpace(const char *value) {
|
||||
if (strcasecmp(value, "39_bit") == 0 || strcasecmp(value, "39") == 0) {
|
||||
return impl::OverrideStatusFlag_AddressSpace64Bit;
|
||||
} else if (strcasecmp(value, "42_bit") == 0 || strcasecmp(value, "42") == 0) {
|
||||
return impl::OverrideStatusFlag_AddressSpace64Bit64KPage;
|
||||
} else if (strcasecmp(value, "36_bit") == 0 || strcasecmp(value, "36") == 0) {
|
||||
return impl::OverrideStatusFlag_AddressSpace64BitDeprecated;
|
||||
} else if (strcasecmp(value, "32_bit") == 0 || strcasecmp(value, "32") == 0) {
|
||||
|
||||
@@ -28,7 +28,9 @@ namespace ams::osdbg::impl {
|
||||
|
||||
constexpr inline bool IsLp64(const ThreadInfo *info) {
|
||||
const auto as = info->_debug_info_create_process.flags & svc::CreateProcessFlag_AddressSpaceMask;
|
||||
return as == svc::CreateProcessFlag_AddressSpace64Bit || as == svc::CreateProcessFlag_AddressSpace64BitDeprecated;
|
||||
return as == svc::CreateProcessFlag_AddressSpace64Bit
|
||||
|| as == svc::CreateProcessFlag_AddressSpace64BitDeprecated
|
||||
|| as == svc::CreateProcessFlag_AddressSpace64Bit64KPage;
|
||||
}
|
||||
|
||||
constexpr inline bool Is64BitArch(const ThreadInfo *info) {
|
||||
|
||||
@@ -37,6 +37,13 @@ namespace ams::svc {
|
||||
|
||||
constexpr inline size_t AddressMemoryRegion39Size = 512_GB;
|
||||
|
||||
constexpr inline size_t AddressMemoryRegionSmall42Size = 64_GB;
|
||||
constexpr inline size_t AddressMemoryRegionAlias42Size = 512_GB;
|
||||
constexpr inline size_t AddressMemoryRegionStack42Size = 2_GB;
|
||||
|
||||
constexpr inline size_t AddressMemoryRegion42Size = 4096_GB;
|
||||
|
||||
constexpr inline size_t AddressShadowStackRegionSize = 4_GB;
|
||||
#elif defined(ATMOSPHERE_ARCH_ARM)
|
||||
|
||||
constexpr inline size_t AddressMemoryRegionSmall32Size = 512_MB;
|
||||
@@ -56,6 +63,12 @@ namespace ams::svc {
|
||||
|
||||
constexpr inline size_t AddressMemoryRegion39Size = 0;
|
||||
|
||||
constexpr inline size_t AddressMemoryRegionSmall42Size = 0;
|
||||
constexpr inline size_t AddressMemoryRegionAlias42Size = 0;
|
||||
constexpr inline size_t AddressMemoryRegionStack42Size = 0;
|
||||
|
||||
constexpr inline size_t AddressMemoryRegion42Size = 0;
|
||||
|
||||
#else
|
||||
|
||||
#error "Unknown architecture for svc::AddressMemoryRegion*Size"
|
||||
@@ -97,4 +110,7 @@ namespace ams::svc {
|
||||
constexpr inline uintptr_t AddressMap39End = AddressMemoryRegion39Size;
|
||||
constexpr inline size_t AddressMap39Size = AddressMap39End - AddressMap39Start;
|
||||
|
||||
constexpr inline uintptr_t AddressMap42Start = 0 + AddressNullGuard64Size;
|
||||
constexpr inline uintptr_t AddressMap42End = AddressMemoryRegion42Size;
|
||||
constexpr inline size_t AddressMap42Size = AddressMap42End - AddressMap42Start;
|
||||
}
|
||||
|
||||
@@ -191,8 +191,16 @@ namespace ams::svc {
|
||||
InfoType_IsSvcPermitted = 26,
|
||||
InfoType_IoRegionHint = 27,
|
||||
InfoType_AliasRegionExtraSize = 28,
|
||||
/* ... */
|
||||
InfoType_RemoteRegionAddress = 29,
|
||||
InfoType_RemoteRegionSize = 30,
|
||||
InfoType_RemoteMemorySize = 31,
|
||||
InfoType_RemoteMemoryUsageMax = 32,
|
||||
InfoType_AllocateAlignment = 33,
|
||||
InfoType_TransferMemoryHint = 34,
|
||||
/* ... */
|
||||
InfoType_AddressSpaceSize = 36,
|
||||
InfoType_ShadowStackRegionAddress = 37,
|
||||
InfoType_ShadowStackRegionSize = 38,
|
||||
|
||||
InfoType_MesosphereMeta = 65000,
|
||||
InfoType_MesosphereCurrentProcess = 65001,
|
||||
@@ -408,11 +416,12 @@ namespace ams::svc {
|
||||
|
||||
/* What kind of address space? */
|
||||
CreateProcessFlag_AddressSpaceShift = 1,
|
||||
CreateProcessFlag_AddressSpaceMask = (7 << CreateProcessFlag_AddressSpaceShift),
|
||||
CreateProcessFlag_AddressSpaceMask = (7 << CreateProcessFlag_AddressSpaceShift), /* Should be 15 but Nintendo didn't make 64K isn't usable yet */
|
||||
CreateProcessFlag_AddressSpace32Bit = (0 << CreateProcessFlag_AddressSpaceShift),
|
||||
CreateProcessFlag_AddressSpace64BitDeprecated = (1 << CreateProcessFlag_AddressSpaceShift),
|
||||
CreateProcessFlag_AddressSpace32BitWithoutAlias = (2 << CreateProcessFlag_AddressSpaceShift),
|
||||
CreateProcessFlag_AddressSpace64Bit = (3 << CreateProcessFlag_AddressSpaceShift),
|
||||
CreateProcessFlag_AddressSpace64Bit64KPage = (4 << CreateProcessFlag_AddressSpaceShift),
|
||||
|
||||
/* Should JIT debug be done on crash? */
|
||||
CreateProcessFlag_EnableDebug = (1 << 4),
|
||||
@@ -443,6 +452,9 @@ namespace ams::svc {
|
||||
/* 18.x EnableAliasRegionExtraSize. */
|
||||
CreateProcessFlag_EnableAliasRegionExtraSize = (1 << 13),
|
||||
|
||||
/* 23.x EnableShadowStack. */
|
||||
CreateProcessFlag_EnableShadowStack = (1 << 17),
|
||||
|
||||
/* Mask of all flags. */
|
||||
CreateProcessFlag_All = CreateProcessFlag_Is64Bit |
|
||||
CreateProcessFlag_AddressSpaceMask |
|
||||
@@ -452,7 +464,8 @@ namespace ams::svc {
|
||||
CreateProcessFlag_PoolPartitionMask |
|
||||
CreateProcessFlag_OptimizeMemoryAllocation |
|
||||
CreateProcessFlag_DisableDeviceAddressSpaceMerge |
|
||||
CreateProcessFlag_EnableAliasRegionExtraSize,
|
||||
CreateProcessFlag_EnableAliasRegionExtraSize |
|
||||
CreateProcessFlag_EnableShadowStack,
|
||||
};
|
||||
|
||||
/* Debug types. */
|
||||
|
||||
@@ -57,7 +57,7 @@ namespace ams::svc {
|
||||
|
||||
/* This is the highest SVC version supported by Atmosphere, to be updated on new kernel releases. */
|
||||
/* NOTE: Official kernel versions have SVC major = SDK major + 4, SVC minor = SDK minor. */
|
||||
constexpr inline u32 SupportedKernelMajorVersion = ConvertToSvcMajorVersion(22);
|
||||
constexpr inline u32 SupportedKernelMajorVersion = ConvertToSvcMajorVersion(23);
|
||||
constexpr inline u32 SupportedKernelMinorVersion = ConvertToSvcMinorVersion( 2);
|
||||
|
||||
constexpr inline u32 SupportedKernelVersion = EncodeKernelVersion(SupportedKernelMajorVersion, SupportedKernelMinorVersion);
|
||||
|
||||
@@ -224,15 +224,20 @@ namespace ams::kern::init {
|
||||
static_assert(kern::arch::arm64::init::IsInitialPageAllocator<KInitialPageAllocatorForFinalizeIdentityMapping>);
|
||||
|
||||
void SetupAllTtbr0Entries(KInitialPageTable &init_pt, KInitialPageAllocator &allocator) {
|
||||
/* Validate that the ttbr0 array is in rodata. */
|
||||
/* Validate that the ttbr0/tcr_el1 arrays are in rodata. */
|
||||
const uintptr_t rodata_start = reinterpret_cast<uintptr_t>(__rodata_start);
|
||||
const uintptr_t rodata_end = reinterpret_cast<uintptr_t>(__rodata_end);
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(rodata_start < rodata_end);
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(rodata_start <= reinterpret_cast<uintptr_t>(std::addressof(KPageTable::GetTtbr0Entry(0))));
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(reinterpret_cast<uintptr_t>(std::addressof(KPageTable::GetTtbr0Entry(KPageTable::NumTtbr0Entries))) < rodata_end);
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(reinterpret_cast<uintptr_t>(std::addressof(KPageTable::GetTtbr0Entry(KPageTable::NumPTEntries))) < rodata_end);
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(rodata_start <= reinterpret_cast<uintptr_t>(std::addressof(KPageTable::GetTcrEL1Entry(0))));
|
||||
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);
|
||||
|
||||
/* Allocate pages for all ttbr0 entries. */
|
||||
for (size_t i = 0; i < KPageTable::NumTtbr0Entries; ++i) {
|
||||
for (size_t i = 0; i < KPageTable::NumPTEntries; ++i) {
|
||||
/* Allocate a page. */
|
||||
KPhysicalAddress page = allocator.Allocate(PageSize);
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(page != Null<KPhysicalAddress>);
|
||||
@@ -245,6 +250,12 @@ namespace ams::kern::init {
|
||||
|
||||
/* Set the entry to the newly allocated page. */
|
||||
*reinterpret_cast<volatile u64 *>(GetInteger(ttbr0_phys_ptr)) = (static_cast<u64>(i) << 48) | GetInteger(page);
|
||||
|
||||
/* Get the physical address of the tcr_el1 entry. */
|
||||
const auto tcr_el1_phys_ptr = init_pt.GetPhysicalAddress(KVirtualAddress(std::addressof(KPageTable::GetTcrEL1Entry(i))));
|
||||
|
||||
/* Set the entry to the default tcr_el1 value. */
|
||||
*reinterpret_cast<volatile u64 *>(GetInteger(tcr_el1_phys_ptr)) = tcr_el1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -270,6 +270,7 @@ namespace ams::ldr {
|
||||
case cfg::impl::OverrideStatusFlag_AddressSpace64BitDeprecated: meta->npdm->flags |= (Npdm::AddressSpaceType_64BitDeprecated) << Npdm::MetaFlag_AddressSpaceTypeShift; break;
|
||||
case cfg::impl::OverrideStatusFlag_AddressSpace32BitWithoutAlias: meta->npdm->flags |= (Npdm::AddressSpaceType_32BitWithoutAlias) << Npdm::MetaFlag_AddressSpaceTypeShift; break;
|
||||
case cfg::impl::OverrideStatusFlag_AddressSpace64Bit: meta->npdm->flags |= (Npdm::AddressSpaceType_64Bit) << Npdm::MetaFlag_AddressSpaceTypeShift; break;
|
||||
case cfg::impl::OverrideStatusFlag_AddressSpace64Bit64KPage: meta->npdm->flags |= (Npdm::AddressSpaceType_64Bit64KPage) << Npdm::MetaFlag_AddressSpaceTypeShift; break;
|
||||
AMS_UNREACHABLE_DEFAULT_CASE();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -423,6 +423,9 @@ namespace ams::ldr {
|
||||
case Npdm::AddressSpaceType_64Bit:
|
||||
flags |= svc::CreateProcessFlag_AddressSpace64Bit;
|
||||
break;
|
||||
case Npdm::AddressSpaceType_64Bit64KPage:
|
||||
flags |= svc::CreateProcessFlag_AddressSpace64Bit64KPage;
|
||||
break;
|
||||
default:
|
||||
R_THROW(ldr::ResultInvalidMeta());
|
||||
}
|
||||
@@ -597,6 +600,10 @@ namespace ams::ldr {
|
||||
aslr_start = svc::AddressMap39Start;
|
||||
aslr_size = svc::AddressMap39Size;
|
||||
break;
|
||||
case svc::CreateProcessFlag_AddressSpace64Bit64KPage:
|
||||
aslr_start = svc::AddressMap42Start;
|
||||
aslr_size = svc::AddressMap42Size;
|
||||
break;
|
||||
AMS_UNREACHABLE_DEFAULT_CASE();
|
||||
}
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user