diff --git a/libraries/libmesosphere/include/mesosphere/arch/arm64/init/kern_k_init_page_table.hpp b/libraries/libmesosphere/include/mesosphere/arch/arm64/init/kern_k_init_page_table.hpp index 269858fb8..21fbb28b5 100644 --- a/libraries/libmesosphere/include/mesosphere/arch/arm64/init/kern_k_init_page_table.hpp +++ b/libraries/libmesosphere/include/mesosphere/arch/arm64/init/kern_k_init_page_table.hpp @@ -690,12 +690,7 @@ namespace ams::kern::arch::arm64::init { } ALWAYS_INLINE void InitializeFromState(uintptr_t state_val) { - if (kern::GetTargetFirmware() >= ams::TargetFirmware_10_0_0) { - m_state = *reinterpret_cast(state_val); - } else { - m_state.next_address = state_val; - m_state.free_bitmap = 0; - } + m_state = *reinterpret_cast(state_val); } ALWAYS_INLINE void GetFinalState(State *out) { diff --git a/mesosphere/kernel_ldr/source/board/nintendo/nx/kern_init_loader_board_setup.cpp b/mesosphere/kernel_ldr/source/board/nintendo/nx/kern_init_loader_board_setup.cpp new file mode 100644 index 000000000..74074fc6a --- /dev/null +++ b/mesosphere/kernel_ldr/source/board/nintendo/nx/kern_init_loader_board_setup.cpp @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include +#include "../../../kern_init_loader_board_setup.hpp" + +namespace ams::kern::init::loader { + + void PerformBoardSpecificSetup() { + /* ... */ + } + +} diff --git a/mesosphere/kernel_ldr/source/kern_init_loader.cpp b/mesosphere/kernel_ldr/source/kern_init_loader.cpp index 0d5f307ec..0f26fae46 100644 --- a/mesosphere/kernel_ldr/source/kern_init_loader.cpp +++ b/mesosphere/kernel_ldr/source/kern_init_loader.cpp @@ -14,7 +14,7 @@ * along with this program. If not, see . */ #include -#include "kern_init_loader_asm.hpp" +#include "kern_init_loader_board_setup.hpp" /* Necessary for calculating kernelldr size/base for initial identity mapping */ extern "C" { @@ -71,22 +71,6 @@ namespace ams::kern::init::loader { cpu::InvalidateEntireTlb(); } - #ifdef ATMOSPHERE_BOARD_NINTENDO_NX - - ALWAYS_INLINE bool ShouldPerformCpuSpecificSetup() { - /* Perform cpu-specific setup only on < 10.0.0. */ - return kern::GetTargetFirmware() < ams::TargetFirmware_10_0_0; - } - - #else - - consteval ALWAYS_INLINE bool ShouldPerformCpuSpecificSetup() { - /* Always perform cpu-specific setup. */ - return true; - } - - #endif - void SetupInitialIdentityMapping(KInitialPageTable &ttbr1_table, uintptr_t base_address, uintptr_t kernel_size, uintptr_t page_table_region, size_t page_table_region_size, KInitialPageTable::IPageAllocator &allocator) { /* Make a new page table for TTBR0_EL1. */ KInitialPageTable ttbr0_table(allocator.Allocate()); @@ -116,72 +100,8 @@ namespace ams::kern::init::loader { cpu::MemoryAccessIndirectionRegisterAccessor(MairValue).Store(); cpu::TranslationControlRegisterAccessor(TcrValue).Store(); - /* Perform cpu-specific setup if needed. */ - if (ShouldPerformCpuSpecificSetup()) { - SavedRegisterState saved_registers; - SaveRegistersToTpidrEl1(&saved_registers); - ON_SCOPE_EXIT { VerifyAndClearTpidrEl1(&saved_registers); }; - - /* Main ID specific setup. */ - cpu::MainIdRegisterAccessor midr_el1; - if (midr_el1.GetImplementer() == cpu::MainIdRegisterAccessor::Implementer::ArmLimited) { - /* ARM limited specific setup. */ - const auto cpu_primary_part = midr_el1.GetPrimaryPartNumber(); - const auto cpu_variant = midr_el1.GetVariant(); - const auto cpu_revision = midr_el1.GetRevision(); - if (cpu_primary_part == cpu::MainIdRegisterAccessor::PrimaryPartNumber::CortexA57) { - /* Cortex-A57 specific setup. */ - - /* Non-cacheable load forwarding enabled. */ - u64 cpuactlr_value = 0x1000000; - - /* Enable the processor to receive instruction cache and TLB maintenance */ - /* operations broadcast from other processors in the cluster; */ - /* set the L2 load/store data prefetch distance to 8 requests; */ - /* set the L2 instruction fetch prefetch distance to 3 requests. */ - u64 cpuectlr_value = 0x1B00000040; - - /* Disable load-pass DMB on certain hardware variants. */ - if (cpu_variant == 0 || (cpu_variant == 1 && cpu_revision <= 1)) { - cpuactlr_value |= 0x800000000000000; - } - - /* Set actlr and ectlr. */ - if (cpu::GetCpuActlrEl1() != cpuactlr_value) { - cpu::SetCpuActlrEl1(cpuactlr_value); - } - if (cpu::GetCpuEctlrEl1() != cpuectlr_value) { - cpu::SetCpuEctlrEl1(cpuectlr_value); - } - } else if (cpu_primary_part == cpu::MainIdRegisterAccessor::PrimaryPartNumber::CortexA53) { - /* Cortex-A53 specific setup. */ - - /* Set L1 data prefetch control to allow 5 outstanding prefetches; */ - /* enable device split throttle; */ - /* set the number of independent data prefetch streams to 2; */ - /* disable transient and no-read-allocate hints for loads; */ - /* set write streaming no-allocate threshold so the 128th consecutive streaming */ - /* cache line does not allocate in the L1 or L2 cache. */ - u64 cpuactlr_value = 0x90CA000; - - /* Enable hardware management of data coherency with other cores in the cluster. */ - u64 cpuectlr_value = 0x40; - - /* If supported, enable data cache clean as data cache clean/invalidate. */ - if (cpu_variant != 0 || (cpu_variant == 0 && cpu_revision > 2)) { - cpuactlr_value |= 0x100000000000; - } - - /* Set actlr and ectlr. */ - if (cpu::GetCpuActlrEl1() != cpuactlr_value) { - cpu::SetCpuActlrEl1(cpuactlr_value); - } - if (cpu::GetCpuEctlrEl1() != cpuectlr_value) { - cpu::SetCpuEctlrEl1(cpuectlr_value); - } - } - } - } + /* Perform board-specific setup. */ + PerformBoardSpecificSetup(); /* Ensure that the entire cache is flushed. */ EnsureEntireDataCacheFlushed(); @@ -300,10 +220,9 @@ namespace ams::kern::init::loader { ttbr1_table.Map(virtual_base_address + ro_offset, ro_end_offset - ro_offset, base_address + ro_offset, KernelRwDataAttribute, g_initial_page_allocator); ttbr1_table.Map(virtual_base_address + rw_offset, bss_end_offset - rw_offset, base_address + rw_offset, KernelRwDataAttribute, g_initial_page_allocator); - /* On 10.0.0+, Physically randomize the kernel region. */ - if (kern::GetTargetFirmware() >= ams::TargetFirmware_10_0_0) { - ttbr1_table.PhysicallyRandomize(virtual_base_address + rx_offset, bss_end_offset - rx_offset, true); - } + /* Physically randomize the kernel region. */ + /* NOTE: Nintendo does this only on 10.0.0+ */ + ttbr1_table.PhysicallyRandomize(virtual_base_address + rx_offset, bss_end_offset - rx_offset, true); /* Clear kernel .bss. */ std::memset(GetVoidPointer(virtual_base_address + bss_offset), 0, bss_end_offset - bss_offset); @@ -330,11 +249,7 @@ namespace ams::kern::init::loader { uintptr_t GetFinalPageAllocatorState() { g_initial_page_allocator.GetFinalState(std::addressof(g_final_page_allocator_state)); - if (kern::GetTargetFirmware() >= ams::TargetFirmware_10_0_0) { - return reinterpret_cast(std::addressof(g_final_page_allocator_state)); - } else { - return g_final_page_allocator_state.next_address; - } + return reinterpret_cast(std::addressof(g_final_page_allocator_state)); } } \ No newline at end of file diff --git a/mesosphere/kernel_ldr/source/kern_init_loader_board_default_setup.arch.arm64.cpp b/mesosphere/kernel_ldr/source/kern_init_loader_board_default_setup.arch.arm64.cpp new file mode 100644 index 000000000..cdf39cb57 --- /dev/null +++ b/mesosphere/kernel_ldr/source/kern_init_loader_board_default_setup.arch.arm64.cpp @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include +#include "kern_init_loader_asm.hpp" +#include "kern_init_loader_board_setup.hpp" + +namespace ams::kern::init::loader { + + void PerformDefaultAarch64SpecificSetup() { + SavedRegisterState saved_registers; + SaveRegistersToTpidrEl1(std::addressof(saved_registers)); + ON_SCOPE_EXIT { VerifyAndClearTpidrEl1(std::addressof(saved_registers)); }; + + /* Main ID specific setup. */ + cpu::MainIdRegisterAccessor midr_el1; + if (midr_el1.GetImplementer() == cpu::MainIdRegisterAccessor::Implementer::ArmLimited) { + /* ARM limited specific setup. */ + const auto cpu_primary_part = midr_el1.GetPrimaryPartNumber(); + const auto cpu_variant = midr_el1.GetVariant(); + const auto cpu_revision = midr_el1.GetRevision(); + if (cpu_primary_part == cpu::MainIdRegisterAccessor::PrimaryPartNumber::CortexA57) { + /* Cortex-A57 specific setup. */ + + /* Non-cacheable load forwarding enabled. */ + u64 cpuactlr_value = 0x1000000; + + /* Enable the processor to receive instruction cache and TLB maintenance */ + /* operations broadcast from other processors in the cluster; */ + /* set the L2 load/store data prefetch distance to 8 requests; */ + /* set the L2 instruction fetch prefetch distance to 3 requests. */ + u64 cpuectlr_value = 0x1B00000040; + + /* Disable load-pass DMB on certain hardware variants. */ + if (cpu_variant == 0 || (cpu_variant == 1 && cpu_revision <= 1)) { + cpuactlr_value |= 0x800000000000000; + } + + /* Set actlr and ectlr. */ + if (cpu::GetCpuActlrEl1() != cpuactlr_value) { + cpu::SetCpuActlrEl1(cpuactlr_value); + } + if (cpu::GetCpuEctlrEl1() != cpuectlr_value) { + cpu::SetCpuEctlrEl1(cpuectlr_value); + } + } else if (cpu_primary_part == cpu::MainIdRegisterAccessor::PrimaryPartNumber::CortexA53) { + /* Cortex-A53 specific setup. */ + + /* Set L1 data prefetch control to allow 5 outstanding prefetches; */ + /* enable device split throttle; */ + /* set the number of independent data prefetch streams to 2; */ + /* disable transient and no-read-allocate hints for loads; */ + /* set write streaming no-allocate threshold so the 128th consecutive streaming */ + /* cache line does not allocate in the L1 or L2 cache. */ + u64 cpuactlr_value = 0x90CA000; + + /* Enable hardware management of data coherency with other cores in the cluster. */ + u64 cpuectlr_value = 0x40; + + /* If supported, enable data cache clean as data cache clean/invalidate. */ + if (cpu_variant != 0 || (cpu_variant == 0 && cpu_revision > 2)) { + cpuactlr_value |= 0x100000000000; + } + + /* Set actlr and ectlr. */ + if (cpu::GetCpuActlrEl1() != cpuactlr_value) { + cpu::SetCpuActlrEl1(cpuactlr_value); + } + if (cpu::GetCpuEctlrEl1() != cpuectlr_value) { + cpu::SetCpuEctlrEl1(cpuectlr_value); + } + } + } + } + + /* This is a default implementation, which should be overridden in a source file in board/ */ + WEAK_SYMBOL void PerformBoardSpecificSetup() { + return PerformDefaultAarch64SpecificSetup(); + } + +} diff --git a/mesosphere/kernel_ldr/source/kern_init_loader_board_setup.hpp b/mesosphere/kernel_ldr/source/kern_init_loader_board_setup.hpp new file mode 100644 index 000000000..fa3c3beac --- /dev/null +++ b/mesosphere/kernel_ldr/source/kern_init_loader_board_setup.hpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once +#include + +namespace ams::kern::init::loader { + +#if defined(ATMOSPHERE_ARCH_ARM64) + void PerformDefaultAarch64SpecificSetup(); +#endif + + void PerformBoardSpecificSetup(); + +}