kern: update Initialize0 for new arguments/randomization semantics

This commit is contained in:
Michael Scire 2021-09-18 09:58:02 -07:00 committed by SciresM
parent 2f2c36b22b
commit 481ce12b7b
13 changed files with 160 additions and 115 deletions

View file

@ -346,8 +346,11 @@ namespace ams::kern::board::nintendo::nx {
}
}
KPhysicalAddress KSystemControl::Init::GetInitialProcessBinaryPhysicalAddress() {
return GetKernelPhysicalBaseAddress(DramPhysicalAddress) + GetIntendedMemorySize() - KTraceBufferSize - InitialProcessBinarySizeMax;
void KSystemControl::Init::GetInitialProcessBinaryLayout(InitialProcessBinaryLayout *out) {
*out = {
.address = GetInteger(GetKernelPhysicalBaseAddress(DramPhysicalAddress)) + GetIntendedMemorySize() - KTraceBufferSize - InitialProcessBinarySizeMax,
._08 = 0,
};
}
bool KSystemControl::Init::ShouldIncreaseThreadResourceLimit() {

View file

@ -25,18 +25,18 @@ namespace ams::kern {
s32 priority;
};
constinit KPhysicalAddress g_initial_process_binary_phys_addr = Null<KPhysicalAddress>;
constinit KVirtualAddress g_initial_process_binary_address = Null<KVirtualAddress>;
constinit InitialProcessBinaryHeader g_initial_process_binary_header = {};
constinit size_t g_initial_process_secure_memory_size = 0;
constinit u64 g_initial_process_id_min = std::numeric_limits<u64>::max();
constinit u64 g_initial_process_id_max = std::numeric_limits<u64>::min();
void LoadInitialProcessBinaryHeader(KVirtualAddress virt_addr = Null<KVirtualAddress>) {
void LoadInitialProcessBinaryHeader() {
if (g_initial_process_binary_header.magic != InitialProcessBinaryMagic) {
/* Get the virtual address, if it's not overridden. */
if (virt_addr == Null<KVirtualAddress>) {
virt_addr = GetInitialProcessBinaryAddress();
}
/* Get the virtual address. */
MESOSPHERE_INIT_ABORT_UNLESS(g_initial_process_binary_phys_addr != Null<KPhysicalAddress>);
const KVirtualAddress virt_addr = KMemoryLayout::GetLinearVirtualAddress(g_initial_process_binary_phys_addr);
/* Copy and validate the header. */
g_initial_process_binary_header = *GetPointer<InitialProcessBinaryHeader>(virt_addr);
@ -273,10 +273,18 @@ namespace ams::kern {
}
}
ALWAYS_INLINE KVirtualAddress GetInitialProcessBinaryAddress(KVirtualAddress pool_end) {
return pool_end - InitialProcessBinarySizeMax;
}
}
void SetInitialProcessBinaryPhysicalAddress(KPhysicalAddress phys_addr) {
MESOSPHERE_INIT_ABORT_UNLESS(g_initial_process_binary_phys_addr == Null<KPhysicalAddress>);
g_initial_process_binary_phys_addr = phys_addr;
}
KPhysicalAddress GetInitialProcessBinaryPhysicalAddress() {
MESOSPHERE_INIT_ABORT_UNLESS(g_initial_process_binary_phys_addr != Null<KPhysicalAddress>);
return g_initial_process_binary_phys_addr;
}
u64 GetInitialProcessIdMin() {
@ -287,15 +295,6 @@ namespace ams::kern {
return g_initial_process_id_max;
}
KVirtualAddress GetInitialProcessBinaryAddress() {
/* Get, validate the pool region. */
const auto *pool_region = KMemoryLayout::GetVirtualMemoryRegionTree().FindLastDerived(KMemoryRegionType_VirtualDramUserPool);
MESOSPHERE_INIT_ABORT_UNLESS(pool_region != nullptr);
MESOSPHERE_INIT_ABORT_UNLESS(pool_region->GetEndAddress() != 0);
MESOSPHERE_ABORT_UNLESS(pool_region->GetSize() >= InitialProcessBinarySizeMax);
return GetInitialProcessBinaryAddress(pool_region->GetEndAddress());
}
size_t GetInitialProcessesSecureMemorySize() {
LoadInitialProcessBinaryHeader();
@ -321,10 +320,6 @@ namespace ams::kern {
}
}
void LoadInitialProcessBinaryHeaderDeprecated(KPhysicalAddress pool_end) {
LoadInitialProcessBinaryHeader(GetInitialProcessBinaryAddress(KMemoryLayout::GetLinearVirtualAddress(pool_end)));
}
void CreateAndRunInitialProcesses() {
/* Allocate space for the processes. */
InitialProcessInfo *infos = static_cast<InitialProcessInfo *>(__builtin_alloca(sizeof(InitialProcessInfo) * g_initial_process_binary_header.num_processes));

View file

@ -190,12 +190,6 @@ namespace ams::kern {
static_assert(KMemoryManager::Pool_Unsafe == KMemoryManager::Pool_Application);
static_assert(KMemoryManager::Pool_Secure == KMemoryManager::Pool_System);
/* NOTE: Beginning with 12.0.0 (and always, in mesosphere), the initial process binary is at the end of the pool region. */
/* However, this is problematic for < 5.0.0, because we require the initial process binary to be parsed in order */
/* to determine the pool sizes. Hence, we will force an initial binary load with the known pool end directly, so */
/* that we retain compatibility with lower firmware versions. */
LoadInitialProcessBinaryHeaderDeprecated(pool_end);
/* Get Secure pool size. */
const size_t secure_pool_size = [] ALWAYS_INLINE_LAMBDA (auto target_firmware) -> size_t {
constexpr size_t LegacySecureKernelSize = 8_MB; /* KPageBuffer pages, other small kernel allocations. */

View file

@ -111,43 +111,6 @@ namespace ams::kern {
return true;
}
KVirtualAddress KMemoryRegionTree::GetRandomAlignedRegion(size_t size, size_t alignment, u32 type_id) {
/* We want to find the total extents of the type id. */
const auto extents = this->GetDerivedRegionExtents(type_id);
/* Ensure that our alignment is correct. */
MESOSPHERE_INIT_ABORT_UNLESS(util::IsAligned(extents.GetAddress(), alignment));
const uintptr_t first_address = extents.GetAddress();
const uintptr_t last_address = extents.GetLastAddress();
const uintptr_t first_index = first_address / alignment;
const uintptr_t last_index = last_address / alignment;
while (true) {
const uintptr_t candidate = KSystemControl::Init::GenerateRandomRange(first_index, last_index) * alignment;
/* Ensure that the candidate doesn't overflow with the size. */
if (!(candidate < candidate + size)) {
continue;
}
const uintptr_t candidate_last = candidate + size - 1;
/* Ensure that the candidate fits within the region. */
if (candidate_last > last_address) {
continue;
}
/* Locate the candidate region, and ensure it fits and has the correct type id. */
if (const auto &candidate_region = *this->Find(candidate); !(candidate_last <= candidate_region.GetLastAddress() && candidate_region.GetType() == type_id)) {
continue;
}
return candidate;
}
}
void KMemoryLayout::InitializeLinearMemoryRegionTrees() {
/* Initialize linear trees. */
for (auto &region : GetPhysicalMemoryRegionTree()) {

View file

@ -107,7 +107,7 @@ namespace ams::kern {
/* Free each region to its corresponding heap. */
size_t reserved_sizes[MaxManagerCount] = {};
const KPhysicalAddress ini_start = KMemoryLayout::GetLinearPhysicalAddress(GetInitialProcessBinaryAddress());
const KPhysicalAddress ini_start = GetInitialProcessBinaryPhysicalAddress();
const KPhysicalAddress ini_end = ini_start + InitialProcessBinarySizeMax;
const KPhysicalAddress ini_last = ini_end - 1;
for (const auto &it : KMemoryLayout::GetPhysicalMemoryRegionTree()) {