kern: update Initialize0 to account for new ordering

This commit is contained in:
Michael Scire 2020-12-01 17:29:42 -08:00
parent a56bdab820
commit 3b3cb337f0
3 changed files with 68 additions and 19 deletions

View file

@ -668,6 +668,7 @@ namespace ams::kern::arch::arm64::init {
this->PhysicallyRandomize(virt_addr, size, L2BlockSize, do_copy); this->PhysicallyRandomize(virt_addr, size, L2BlockSize, do_copy);
this->PhysicallyRandomize(virt_addr, size, L3ContiguousBlockSize, do_copy); this->PhysicallyRandomize(virt_addr, size, L3ContiguousBlockSize, do_copy);
this->PhysicallyRandomize(virt_addr, size, L3BlockSize, do_copy); this->PhysicallyRandomize(virt_addr, size, L3BlockSize, do_copy);
cpu::StoreEntireCacheForInit();
} }
}; };

View file

@ -29,6 +29,8 @@ namespace ams::kern::init {
/* Prototypes for functions declared in ASM that we need to reference. */ /* Prototypes for functions declared in ASM that we need to reference. */
void StartOtherCore(const ams::kern::init::KInitArguments *init_args); void StartOtherCore(const ams::kern::init::KInitArguments *init_args);
size_t GetMiscUnknownDebugRegionSize();
namespace { namespace {
/* Global Allocator. */ /* Global Allocator. */
@ -165,11 +167,42 @@ namespace ams::kern::init {
const size_t code_region_size = GetInteger(code_region_end) - GetInteger(code_region_start); const size_t code_region_size = GetInteger(code_region_end) - GetInteger(code_region_start);
MESOSPHERE_INIT_ABORT_UNLESS(KMemoryLayout::GetVirtualMemoryRegionTree().Insert(GetInteger(code_region_start), code_region_size, KMemoryRegionType_KernelCode)); MESOSPHERE_INIT_ABORT_UNLESS(KMemoryLayout::GetVirtualMemoryRegionTree().Insert(GetInteger(code_region_start), code_region_size, KMemoryRegionType_KernelCode));
/* Setup the misc region. */ /* Setup board-specific device physical regions. */
constexpr size_t MiscRegionSize = 32_MB; SetupDevicePhysicalMemoryRegions();
/* Determine the amount of space needed for the misc region. */
size_t misc_region_needed_size;
{
/* Each core has a one page stack for all three stack types (Main, Idle, Exception). */
misc_region_needed_size = cpu::NumCores * (3 * (PageSize + PageSize));
/* Account for each auto-map device. */
for (const auto &region : KMemoryLayout::GetPhysicalMemoryRegionTree()) {
if (region.HasTypeAttribute(KMemoryRegionAttr_ShouldKernelMap)) {
/* Check that the region is valid. */
MESOSPHERE_INIT_ABORT_UNLESS(region.GetEndAddress() != 0);
/* Account for the region. */
misc_region_needed_size += PageSize + (util::AlignUp(region.GetLastAddress(), PageSize) - util::AlignDown(region.GetAddress(), PageSize));
}
}
/* Account for the unknown debug region. */
misc_region_needed_size += GetMiscUnknownDebugRegionSize();
/* Multiply the needed size by three, to account for the need for guard space. */
misc_region_needed_size *= 3;
}
/* Decide on the actual size for the misc region. */
constexpr size_t MiscRegionAlign = KernelAslrAlignment; constexpr size_t MiscRegionAlign = KernelAslrAlignment;
const KVirtualAddress misc_region_start = KMemoryLayout::GetVirtualMemoryRegionTree().GetRandomAlignedRegion(MiscRegionSize, MiscRegionAlign, KMemoryRegionType_Kernel); constexpr size_t MiscRegionMinimumSize = 32_MB;
MESOSPHERE_INIT_ABORT_UNLESS(KMemoryLayout::GetVirtualMemoryRegionTree().Insert(GetInteger(misc_region_start), MiscRegionSize, KMemoryRegionType_KernelMisc)); const size_t misc_region_size = util::AlignUp(std::max(misc_region_needed_size, MiscRegionMinimumSize), MiscRegionAlign);
MESOSPHERE_INIT_ABORT_UNLESS(misc_region_size > 0);
/* Setup the misc region. */
const KVirtualAddress misc_region_start = KMemoryLayout::GetVirtualMemoryRegionTree().GetRandomAlignedRegion(misc_region_size, MiscRegionAlign, KMemoryRegionType_Kernel);
MESOSPHERE_INIT_ABORT_UNLESS(KMemoryLayout::GetVirtualMemoryRegionTree().Insert(GetInteger(misc_region_start), misc_region_size, KMemoryRegionType_KernelMisc));
/* Setup the stack region. */ /* Setup the stack region. */
constexpr size_t StackRegionSize = 14_MB; constexpr size_t StackRegionSize = 14_MB;
@ -202,16 +235,13 @@ namespace ams::kern::init {
/* Setup the Misc Unknown Debug region, if it's not zero. */ /* Setup the Misc Unknown Debug region, if it's not zero. */
if (misc_unk_debug_phys_addr) { if (misc_unk_debug_phys_addr) {
constexpr size_t MiscUnknownDebugRegionSize = PageSize;
constexpr size_t MiscUnknownDebugRegionAlign = PageSize; constexpr size_t MiscUnknownDebugRegionAlign = PageSize;
const KVirtualAddress misc_unk_debug_virt_addr = KMemoryLayout::GetVirtualMemoryRegionTree().GetRandomAlignedRegionWithGuard(MiscUnknownDebugRegionSize, MiscUnknownDebugRegionAlign, KMemoryRegionType_KernelMisc, PageSize); const size_t misc_unk_debug_size = GetMiscUnknownDebugRegionSize();
MESOSPHERE_INIT_ABORT_UNLESS(KMemoryLayout::GetVirtualMemoryRegionTree().Insert(GetInteger(misc_unk_debug_virt_addr), MiscUnknownDebugRegionSize, KMemoryRegionType_KernelMiscUnknownDebug)); const KVirtualAddress misc_unk_debug_virt_addr = KMemoryLayout::GetVirtualMemoryRegionTree().GetRandomAlignedRegionWithGuard(misc_unk_debug_size, MiscUnknownDebugRegionAlign, KMemoryRegionType_KernelMisc, PageSize);
ttbr1_table.Map(misc_unk_debug_virt_addr, MiscUnknownDebugRegionSize, misc_unk_debug_phys_addr, KernelRoDataAttribute, g_initial_page_allocator); MESOSPHERE_INIT_ABORT_UNLESS(KMemoryLayout::GetVirtualMemoryRegionTree().Insert(GetInteger(misc_unk_debug_virt_addr), misc_unk_debug_size, KMemoryRegionType_KernelMiscUnknownDebug));
ttbr1_table.Map(misc_unk_debug_virt_addr, misc_unk_debug_size, misc_unk_debug_phys_addr, KernelRoDataAttribute, g_initial_page_allocator);
} }
/* Setup board-specific device physical regions. */
SetupDevicePhysicalMemoryRegions();
/* Automatically map in devices that have auto-map attributes. */ /* Automatically map in devices that have auto-map attributes. */
for (auto &region : KMemoryLayout::GetPhysicalMemoryRegionTree()) { for (auto &region : KMemoryLayout::GetPhysicalMemoryRegionTree()) {
/* We only care about kernel regions. */ /* We only care about kernel regions. */
@ -229,6 +259,9 @@ namespace ams::kern::init {
continue; continue;
} }
/* Check that the region is valid. */
MESOSPHERE_INIT_ABORT_UNLESS(region.GetEndAddress() != 0);
/* Set the attribute to note we've mapped this region. */ /* Set the attribute to note we've mapped this region. */
region.SetTypeAttribute(KMemoryRegionAttr_DidKernelMap); region.SetTypeAttribute(KMemoryRegionAttr_DidKernelMap);
@ -258,10 +291,6 @@ namespace ams::kern::init {
/* Physically randomize the slab region. */ /* Physically randomize the slab region. */
/* NOTE: Nintendo does this only on 10.0.0+ */ /* NOTE: Nintendo does this only on 10.0.0+ */
ttbr1_table.PhysicallyRandomize(slab_region_start, slab_region_size, false); ttbr1_table.PhysicallyRandomize(slab_region_start, slab_region_size, false);
cpu::StoreEntireCacheForInit();
/* Clear the slab region. */
std::memset(GetVoidPointer(slab_region_start), 0, slab_region_size);
/* Determine size available for kernel page table heaps, requiring > 8 MB. */ /* Determine size available for kernel page table heaps, requiring > 8 MB. */
const KPhysicalAddress resource_end_phys_addr = slab_start_phys_addr + resource_region_size; const KPhysicalAddress resource_end_phys_addr = slab_start_phys_addr + resource_region_size;
@ -282,15 +311,22 @@ namespace ams::kern::init {
/* All DRAM regions that we haven't tagged by this point will be mapped under the linear mapping. Tag them. */ /* All DRAM regions that we haven't tagged by this point will be mapped under the linear mapping. Tag them. */
for (auto &region : KMemoryLayout::GetPhysicalMemoryRegionTree()) { for (auto &region : KMemoryLayout::GetPhysicalMemoryRegionTree()) {
if (region.GetType() == KMemoryRegionType_Dram) { if (region.GetType() == KMemoryRegionType_Dram) {
/* Check that the region is valid. */
MESOSPHERE_INIT_ABORT_UNLESS(region.GetEndAddress() != 0);
/* Set the linear map attribute. */
region.SetTypeAttribute(KMemoryRegionAttr_LinearMapped); region.SetTypeAttribute(KMemoryRegionAttr_LinearMapped);
} }
} }
/* Get the linear region extents. */
const auto linear_extents = KMemoryLayout::GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionAttr_LinearMapped);
MESOSPHERE_INIT_ABORT_UNLESS(linear_extents.GetEndAddress() != 0);
/* Setup the linear mapping region. */ /* Setup the linear mapping region. */
constexpr size_t LinearRegionAlign = 1_GB; constexpr size_t LinearRegionAlign = 1_GB;
const auto linear_extents = KMemoryLayout::GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionAttr_LinearMapped); const KPhysicalAddress aligned_linear_phys_start = util::AlignDown(linear_extents.GetAddress(), LinearRegionAlign);
const KPhysicalAddress aligned_linear_phys_start = util::AlignDown(linear_extents.first_region->GetAddress(), LinearRegionAlign); const size_t linear_region_size = util::AlignUp(linear_extents.GetEndAddress(), LinearRegionAlign) - GetInteger(aligned_linear_phys_start);
const size_t linear_region_size = util::AlignUp(linear_extents.last_region->GetEndAddress(), LinearRegionAlign) - GetInteger(aligned_linear_phys_start);
const KVirtualAddress linear_region_start = KMemoryLayout::GetVirtualMemoryRegionTree().GetRandomAlignedRegionWithGuard(linear_region_size, LinearRegionAlign, KMemoryRegionType_None, LinearRegionAlign); const KVirtualAddress linear_region_start = KMemoryLayout::GetVirtualMemoryRegionTree().GetRandomAlignedRegionWithGuard(linear_region_size, LinearRegionAlign, KMemoryRegionType_None, LinearRegionAlign);
const uintptr_t linear_region_phys_to_virt_diff = GetInteger(linear_region_start) - GetInteger(aligned_linear_phys_start); const uintptr_t linear_region_phys_to_virt_diff = GetInteger(linear_region_start) - GetInteger(aligned_linear_phys_start);
@ -304,6 +340,8 @@ namespace ams::kern::init {
continue; continue;
} }
MESOSPHERE_INIT_ABORT_UNLESS(region.GetEndAddress() != 0);
if (cur_size == 0) { if (cur_size == 0) {
cur_phys_addr = region.GetAddress(); cur_phys_addr = region.GetAddress();
cur_size = region.GetSize(); cur_size = region.GetSize();
@ -332,6 +370,13 @@ namespace ams::kern::init {
} }
} }
/* Clear the slab region. */
std::memset(GetVoidPointer(slab_region_start), 0, slab_region_size);
/* NOTE: Unknown function is called here which is ifdef'd out on retail kernel. */
/* The unknown function is immediately before the function which gets the unknown debug region size, inside this translation unit. */
/* It's likely that this is some kind of initializer for the unknown debug region. */
/* Create regions for and map all core-specific stacks. */ /* Create regions for and map all core-specific stacks. */
for (size_t i = 0; i < cpu::NumCores; i++) { for (size_t i = 0; i < cpu::NumCores; i++) {
MapStackForCore(ttbr1_table, KMemoryRegionType_KernelMiscMainStack, i); MapStackForCore(ttbr1_table, KMemoryRegionType_KernelMiscMainStack, i);
@ -443,4 +488,8 @@ namespace ams::kern::init {
cpu::EnsureInstructionConsistency(); cpu::EnsureInstructionConsistency();
} }
size_t GetMiscUnknownDebugRegionSize() {
return 0;
}
} }

View file

@ -303,7 +303,6 @@ namespace ams::kern::init::loader {
/* On 10.0.0+, Physically randomize the kernel region. */ /* On 10.0.0+, Physically randomize the kernel region. */
if (kern::GetTargetFirmware() >= ams::TargetFirmware_10_0_0) { if (kern::GetTargetFirmware() >= ams::TargetFirmware_10_0_0) {
ttbr1_table.PhysicallyRandomize(virtual_base_address + rx_offset, bss_end_offset - rx_offset, true); ttbr1_table.PhysicallyRandomize(virtual_base_address + rx_offset, bss_end_offset - rx_offset, true);
cpu::StoreEntireCacheForInit();
} }
/* Clear kernel .bss. */ /* Clear kernel .bss. */