mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2025-06-02 07:39:49 -04:00
exo2: Implement the rest of main/return-to-el1
This commit is contained in:
parent
87bdc46beb
commit
dc6abf9f68
19 changed files with 801 additions and 93 deletions
|
@ -361,8 +361,8 @@ namespace ams::secmon::boot {
|
|||
|
||||
void UnmapPhysicalIdentityMapping() {
|
||||
/* Get the tables. */
|
||||
u64 * const l1 = MemoryRegionPhysicalTzramL1PageTable.GetPointer<u64>();
|
||||
u64 * const l2_l3 = MemoryRegionPhysicalTzramL2L3PageTable.GetPointer<u64>();
|
||||
u64 * const l1 = MemoryRegionVirtualTzramL1PageTable.GetPointer<u64>();
|
||||
u64 * const l2_l3 = MemoryRegionVirtualTzramL2L3PageTable.GetPointer<u64>();
|
||||
|
||||
/* Unmap. */
|
||||
UnmapPhysicalIdentityMappingImpl(l1, l2_l3, l2_l3);
|
||||
|
@ -373,8 +373,8 @@ namespace ams::secmon::boot {
|
|||
|
||||
void UnmapDram() {
|
||||
/* Get the tables. */
|
||||
u64 * const l1 = MemoryRegionPhysicalTzramL1PageTable.GetPointer<u64>();
|
||||
u64 * const l2_l3 = MemoryRegionPhysicalTzramL2L3PageTable.GetPointer<u64>();
|
||||
u64 * const l1 = MemoryRegionVirtualTzramL1PageTable.GetPointer<u64>();
|
||||
u64 * const l2_l3 = MemoryRegionVirtualTzramL2L3PageTable.GetPointer<u64>();
|
||||
|
||||
/* Unmap. */
|
||||
UnmapDramImpl(l1, l2_l3, l2_l3);
|
||||
|
|
52
exosphere2/program/source/secmon_map.cpp
Normal file
52
exosphere2/program/source/secmon_map.cpp
Normal file
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <exosphere.hpp>
|
||||
#include "secmon_cache.hpp"
|
||||
#include "secmon_map.hpp"
|
||||
|
||||
namespace ams::secmon {
|
||||
|
||||
namespace {
|
||||
|
||||
using namespace ams::mmu;
|
||||
|
||||
constexpr void UnmapBootCodeImpl(u64 *l1, u64 *l2, u64 *l3, uintptr_t boot_code, size_t boot_code_size) {
|
||||
/* Unmap the L3 entries corresponding to the boot code. */
|
||||
InvalidateL3Entries(l3, boot_code, boot_code_size);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void UnmapBootCode() {
|
||||
/* Get the tables. */
|
||||
u64 * const l1 = MemoryRegionVirtualTzramL1PageTable.GetPointer<u64>();
|
||||
u64 * const l2_l3 = MemoryRegionVirtualTzramL2L3PageTable.GetPointer<u64>();
|
||||
|
||||
/* Get the boot code region. */
|
||||
const uintptr_t boot_code = MemoryRegionVirtualTzramBootCode.GetAddress();
|
||||
const size_t boot_code_size = MemoryRegionVirtualTzramBootCode.GetSize();
|
||||
|
||||
/* Clear the boot code. */
|
||||
util::ClearMemory(reinterpret_cast<void *>(boot_code), boot_code_size);
|
||||
|
||||
/* Unmap. */
|
||||
UnmapBootCodeImpl(l1, l2_l3, l2_l3, boot_code, boot_code_size);
|
||||
|
||||
/* Ensure the mappings are consistent. */
|
||||
secmon::EnsureMappingConsistency();
|
||||
}
|
||||
|
||||
}
|
23
exosphere2/program/source/secmon_map.hpp
Normal file
23
exosphere2/program/source/secmon_map.hpp
Normal file
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <exosphere.hpp>
|
||||
|
||||
namespace ams::secmon {
|
||||
|
||||
/* TODO */
|
||||
|
||||
}
|
|
@ -18,6 +18,7 @@
|
|||
#include "secmon_error.hpp"
|
||||
#include "secmon_cpu_context.hpp"
|
||||
#include "secmon_interrupt_handler.hpp"
|
||||
#include "secmon_misc.hpp"
|
||||
|
||||
namespace ams::secmon {
|
||||
|
||||
|
@ -28,6 +29,8 @@ namespace ams::secmon {
|
|||
constexpr inline const uintptr_t FLOW_CTLR = secmon::MemoryRegionVirtualDeviceFlowController.GetAddress();
|
||||
constexpr inline const uintptr_t PMC = secmon::MemoryRegionVirtualDevicePmc.GetAddress();
|
||||
constexpr inline const uintptr_t MC = secmon::MemoryRegionVirtualDeviceMemoryController.GetAddress();
|
||||
constexpr inline const uintptr_t EVP = secmon::MemoryRegionVirtualDeviceExceptionVectors.GetAddress();
|
||||
constexpr inline const uintptr_t CLK_RST = secmon::MemoryRegionVirtualDeviceClkRst.GetAddress();
|
||||
|
||||
alignas(8) constinit u8 g_se_aes_key_slot_test_vector[se::AesBlockSize] = {};
|
||||
|
||||
|
@ -621,7 +624,7 @@ namespace ams::secmon {
|
|||
reg::Read (MC + MC_SMMU_TLB_CONFIG);
|
||||
|
||||
/* Flush the entire translation lookaside buffer, and read TLB_CONFIG to ensure the flush takes. */
|
||||
reg::Write(MC + MC_SMMU_PTC_FLUSH, 0);
|
||||
reg::Write(MC + MC_SMMU_TLB_FLUSH, 0);
|
||||
reg::Read (MC + MC_SMMU_TLB_CONFIG);
|
||||
|
||||
/* Enable the SMMU, and read TLB_CONFIG to ensure the enable takes. */
|
||||
|
@ -722,6 +725,173 @@ namespace ams::secmon {
|
|||
hw::InstructionSynchronizationBarrier();
|
||||
}
|
||||
|
||||
void SetupGpuCarveout() {
|
||||
/* Configure carveout 2. */
|
||||
reg::Write(MC + MC_SECURITY_CARVEOUT2_BOM, static_cast<u32>(MemoryRegionDramGpuCarveout.GetAddress() >> 0));
|
||||
reg::Write(MC + MC_SECURITY_CARVEOUT2_BOM_HI, static_cast<u32>(MemoryRegionDramGpuCarveout.GetAddress() >> BITSIZEOF(u32)));
|
||||
reg::Write(MC + MC_SECURITY_CARVEOUT2_SIZE_128KB, MemoryRegionDramGpuCarveout.GetSize() / 128_KB);
|
||||
reg::Write(MC + MC_SECURITY_CARVEOUT2_CLIENT_ACCESS0, 0);
|
||||
reg::Write(MC + MC_SECURITY_CARVEOUT2_CLIENT_ACCESS1, 0);
|
||||
reg::Write(MC + MC_SECURITY_CARVEOUT2_CLIENT_ACCESS2, MC_REG_BITS_ENUM (CLIENT_ACCESS2_GPUSRD, ENABLE),
|
||||
MC_REG_BITS_ENUM (CLIENT_ACCESS2_GPUSWR, ENABLE),
|
||||
MC_REG_BITS_ENUM (CLIENT_ACCESS2_TSECSRD, ENABLE));
|
||||
reg::Write(MC + MC_SECURITY_CARVEOUT2_CLIENT_ACCESS3, 0);
|
||||
reg::Write(MC + MC_SECURITY_CARVEOUT2_CLIENT_ACCESS4, MC_REG_BITS_ENUM (CLIENT_ACCESS4_GPUSRD2, ENABLE),
|
||||
MC_REG_BITS_ENUM (CLIENT_ACCESS4_GPUSWR2, ENABLE));
|
||||
reg::Write(MC + MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS0, 0);
|
||||
reg::Write(MC + MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS1, 0);
|
||||
reg::Write(MC + MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS2, 0);
|
||||
reg::Write(MC + MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS3, 0);
|
||||
reg::Write(MC + MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS4, 0);
|
||||
reg::Write(MC + MC_SECURITY_CARVEOUT2_CFG0, MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_IS_WPR, DISABLED),
|
||||
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_FORCE_APERTURE_ID_MATCH, ENABLED),
|
||||
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_ALLOW_APERTURE_ID_MISMATCH, DISABLED),
|
||||
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_TZ_GLOBAL_RD_EN, DISABLED),
|
||||
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_TZ_GLOBAL_WR_EN, DISABLED),
|
||||
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_SEND_CFG_TO_GPU, ENABLED),
|
||||
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL3, ENABLE_CHECKS),
|
||||
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL2, ENABLE_CHECKS),
|
||||
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL1, ENABLE_CHECKS),
|
||||
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL0, ENABLE_CHECKS),
|
||||
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL3, ENABLE_CHECKS),
|
||||
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL2, ENABLE_CHECKS),
|
||||
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL1, ENABLE_CHECKS),
|
||||
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL0, ENABLE_CHECKS),
|
||||
MC_REG_BITS_VALUE(SECURITY_CARVEOUT_CFG0_APERTURE_ID, 2),
|
||||
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL3, ENABLED),
|
||||
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL2, ENABLED),
|
||||
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL1, DISABLED),
|
||||
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL0, DISABLED),
|
||||
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL3, ENABLED),
|
||||
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL2, ENABLED),
|
||||
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL1, ENABLED),
|
||||
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL0, ENABLED),
|
||||
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_ADDRESS_TYPE, UNTRANSLATED_ONLY),
|
||||
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_LOCK_MODE, LOCKED),
|
||||
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_PROTECT_MODE, LOCKBIT_SECURE));
|
||||
}
|
||||
|
||||
void DisableArc() {
|
||||
/* Configure IRAM top/bottom to point to memory ends (disabling redirection). */
|
||||
reg::Write(MC + MC_IRAM_BOM, (~0u) & MC_IRAM_BOM_WRITE_MASK);
|
||||
reg::Write(MC + MC_IRAM_TOM, ( 0u) & MC_IRAM_TOM_WRITE_MASK);
|
||||
|
||||
/* Lock the IRAM aperture. */
|
||||
reg::Write(MC + MC_IRAM_REG_CTRL, MC_REG_BITS_ENUM(IRAM_REG_CTRL_IRAM_CFG_WRITE_ACCESS, DISABLED));
|
||||
|
||||
/* Disable the ARC clock gate override. */
|
||||
reg::ReadWrite(CLK_RST + CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD, CLK_RST_REG_BITS_ENUM(LVL2_CLK_GATE_OVRD_ARC_CLK_OVR_ON, OFF));
|
||||
|
||||
/* Rea IRAM REG CTRL to make sure our writes take. */
|
||||
reg::Read(MC + MC_IRAM_REG_CTRL);
|
||||
}
|
||||
|
||||
void FinalizeCarveoutSecureScratchRegisters() {
|
||||
/* Define carveout scratch values. */
|
||||
constexpr uintptr_t WarmbootCarveoutAddress = MemoryRegionDram.GetAddress();
|
||||
constexpr size_t WarmbootCarveoutSize = 128_KB;
|
||||
|
||||
#define MC_ENABLE_CLIENT_ACCESS(INDEX, WHICH) MC_REG_BITS_ENUM(CLIENT_ACCESS##INDEX##_##WHICH, ENABLE)
|
||||
|
||||
constexpr u32 WarmbootCarveoutClientAccess0 = reg::Encode(MC_ENABLE_CLIENT_ACCESS(0, AVPCARM7R),
|
||||
MC_ENABLE_CLIENT_ACCESS(0, PPCSAHBSLVR));
|
||||
|
||||
constexpr u32 WarmbootCarveoutClientAccess1 = reg::Encode(MC_ENABLE_CLIENT_ACCESS(1, AVPCARM7W));
|
||||
|
||||
#undef MC_ENABLE_CLIENT_ACCESS
|
||||
|
||||
constexpr u32 WarmbootCarveoutForceInternalAccess0 = reg::Encode(MC_REG_BITS_ENUM(CLIENT_ACCESS0_AVPCARM7R, ENABLE),
|
||||
MC_REG_BITS_ENUM(CLIENT_ACCESS0_PPCSAHBSLVR, ENABLE));
|
||||
|
||||
constexpr u32 WarmbootCarveoutForceInternalAccess1 = reg::Encode(MC_REG_BITS_ENUM(CLIENT_ACCESS1_AVPCARM7W, ENABLE));
|
||||
|
||||
constexpr u32 WarmbootCarveoutConfig = reg::Encode(MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_IS_WPR, DISABLED),
|
||||
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_FORCE_APERTURE_ID_MATCH, DISABLED),
|
||||
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_ALLOW_APERTURE_ID_MISMATCH, DISABLED),
|
||||
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_TZ_GLOBAL_RD_EN, DISABLED),
|
||||
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_TZ_GLOBAL_WR_EN, DISABLED),
|
||||
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_SEND_CFG_TO_GPU, DISABLED),
|
||||
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL3, ENABLE_CHECKS),
|
||||
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL2, ENABLE_CHECKS),
|
||||
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL1, ENABLE_CHECKS),
|
||||
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL0, ENABLE_CHECKS),
|
||||
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL3, ENABLE_CHECKS),
|
||||
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL2, ENABLE_CHECKS),
|
||||
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL1, ENABLE_CHECKS),
|
||||
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL0, ENABLE_CHECKS),
|
||||
MC_REG_BITS_VALUE(SECURITY_CARVEOUT_CFG0_APERTURE_ID, 0),
|
||||
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL3, DISABLED),
|
||||
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL2, DISABLED),
|
||||
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL1, DISABLED),
|
||||
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL0, ENABLED),
|
||||
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL3, DISABLED),
|
||||
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL2, DISABLED),
|
||||
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL1, DISABLED),
|
||||
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL0, ENABLED),
|
||||
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_ADDRESS_TYPE, ANY_ADDRESS),
|
||||
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_LOCK_MODE, UNLOCKED),
|
||||
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_PROTECT_MODE, LOCKBIT_SECURE));
|
||||
|
||||
/* Save the carveout values into secure scratch. */
|
||||
|
||||
/* Save MC_SECURITY_CARVEOUT4_BOM. */
|
||||
reg::ReadWrite(PMC + APBDEV_PMC_SECURE_SCRATCH51, REG_BITS_VALUE( 0, 15, WarmbootCarveoutAddress >> 17));
|
||||
|
||||
/* Save MC_SECURITY_CARVEOUT4_BOM_HI. */
|
||||
reg::ReadWrite(PMC + APBDEV_PMC_SECURE_SCRATCH16, REG_BITS_VALUE(30, 2, WarmbootCarveoutAddress >> 32));
|
||||
|
||||
/* Save MC_SECURITY_CARVEOUT4_SIZE_128KB. */
|
||||
reg::ReadWrite(PMC + APBDEV_PMC_SECURE_SCRATCH55, REG_BITS_VALUE(12, 12, WarmbootCarveoutSize / 128_KB));
|
||||
|
||||
/* Save MC_SECURITY_CARVEOUT4_CLIENT_ACCESS. */
|
||||
reg::Write(PMC + APBDEV_PMC_SECURE_SCRATCH74, WarmbootCarveoutClientAccess0);
|
||||
reg::Write(PMC + APBDEV_PMC_SECURE_SCRATCH75, WarmbootCarveoutClientAccess1);
|
||||
reg::Write(PMC + APBDEV_PMC_SECURE_SCRATCH76, 0);
|
||||
reg::Write(PMC + APBDEV_PMC_SECURE_SCRATCH77, 0);
|
||||
reg::Write(PMC + APBDEV_PMC_SECURE_SCRATCH78, 0);
|
||||
|
||||
/* Save MC_SECURITY_CARVEOUT4_FORCE_INTERNAL_ACCESS. */
|
||||
reg::Write(PMC + APBDEV_PMC_SECURE_SCRATCH99, WarmbootCarveoutForceInternalAccess0);
|
||||
reg::Write(PMC + APBDEV_PMC_SECURE_SCRATCH100, WarmbootCarveoutForceInternalAccess1);
|
||||
reg::Write(PMC + APBDEV_PMC_SECURE_SCRATCH101, 0);
|
||||
reg::Write(PMC + APBDEV_PMC_SECURE_SCRATCH102, 0);
|
||||
reg::Write(PMC + APBDEV_PMC_SECURE_SCRATCH103, 0);
|
||||
|
||||
/* Save MC_SECURITY_CARVEOUT4_CFG0. */
|
||||
reg::ReadWrite(PMC + APBDEV_PMC_SECURE_SCRATCH39, REG_BITS_VALUE(0, 27, WarmbootCarveoutConfig));
|
||||
}
|
||||
|
||||
void EnableBpmpSmmu() {
|
||||
/* Define the ASID contents. */
|
||||
constexpr int BpmpAsid = 1;
|
||||
constexpr uintptr_t BpmpAsidPde = MemoryRegionPhysicalDeviceSecurityEngine.GetAddress();
|
||||
|
||||
/* Configure the ASID. */
|
||||
reg::Write(MC + MC_SMMU_PTB_ASID, MC_REG_BITS_VALUE(SMMU_PTB_ASID_CURRENT_ASID, BpmpAsid));
|
||||
|
||||
reg::Write(MC + MC_SMMU_PTB_DATA, MC_REG_BITS_VALUE(SMMU_PTB_DATA_ASID_PDE_BASE, BpmpAsidPde / 4_KB),
|
||||
MC_REG_BITS_ENUM (SMMU_PTB_DATA_ASID_NONSECURE, DISABLE),
|
||||
MC_REG_BITS_ENUM (SMMU_PTB_DATA_ASID_WRITABLE, DISABLE),
|
||||
MC_REG_BITS_ENUM (SMMU_PTB_DATA_ASID_READABLE, DISABLE));
|
||||
|
||||
/* Configure the BPMP and PPCS1 to use the asid. */
|
||||
reg::Write(MC + MC_SMMU_AVPC_ASID, MC_REG_BITS_ENUM(SMMU_AVPC_ASID_AVPC_SMMU_ENABLE, ENABLE), MC_REG_BITS_VALUE(SMMU_AVPC_ASID_AVPC_ASID, BpmpAsid));
|
||||
reg::Write(MC + MC_SMMU_PPCS1_ASID, MC_REG_BITS_ENUM(SMMU_PPCS1_ASID_PPCS1_SMMU_ENABLE, ENABLE), MC_REG_BITS_VALUE(SMMU_PPCS1_ASID_PPCS1_ASID, BpmpAsid));
|
||||
|
||||
/* Flush the entire page table cache, and read TLB_CONFIG to ensure the flush takes. */
|
||||
reg::Write(MC + MC_SMMU_PTC_FLUSH, 0);
|
||||
reg::Read (MC + MC_SMMU_TLB_CONFIG);
|
||||
|
||||
/* Flush the entire translation lookaside buffer, and read TLB_CONFIG to ensure the flush takes. */
|
||||
reg::Write(MC + MC_SMMU_TLB_FLUSH, 0);
|
||||
reg::Read (MC + MC_SMMU_TLB_CONFIG);
|
||||
}
|
||||
|
||||
void ActmonInterruptHandler() {
|
||||
SetError(pkg1::ErrorInfo_ActivityMonitorInterrupt);
|
||||
AMS_ABORT("actmon observed bpmp wakeup");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Setup1() {
|
||||
|
@ -783,7 +953,7 @@ namespace ams::secmon {
|
|||
SetupSmmu();
|
||||
|
||||
/* Clear the cpu reset vector. */
|
||||
reg::Write(secmon::MemoryRegionVirtualDeviceExceptionVectors.GetAddress() + EVP_CPU_RESET_VECTOR, 0);
|
||||
reg::Write(EVP + EVP_CPU_RESET_VECTOR, 0);
|
||||
|
||||
/* Configure the SB registers to our start address. */
|
||||
constexpr u32 ResetVectorLow = static_cast<u32>((PhysicalTzramProgramResetVector >> 0));
|
||||
|
@ -836,8 +1006,51 @@ namespace ams::secmon {
|
|||
}
|
||||
}
|
||||
|
||||
void SetupSocSecurityWarmboot() {
|
||||
/* ... */
|
||||
}
|
||||
|
||||
void SetupSocProtections() {
|
||||
/* TODO */
|
||||
/* Setup the GPU carveout. */
|
||||
SetupGpuCarveout();
|
||||
|
||||
/* Disable the ARC. */
|
||||
DisableArc();
|
||||
|
||||
/* Finalize and lock the carveout scratch registers. */
|
||||
FinalizeCarveoutSecureScratchRegisters();
|
||||
pmc::LockSecureRegister(pmc::SecureRegister_Carveout);
|
||||
|
||||
/* Clear all the BPMP exception vectors to a fixed value. */
|
||||
constexpr u32 BpmpExceptionVector = 0x7D000000;
|
||||
reg::Write(EVP + EVP_COP_RESET_VECTOR, BpmpExceptionVector);
|
||||
reg::Write(EVP + EVP_COP_UNDEF_VECTOR, BpmpExceptionVector);
|
||||
reg::Write(EVP + EVP_COP_SWI_VECTOR, BpmpExceptionVector);
|
||||
reg::Write(EVP + EVP_COP_PREFETCH_ABORT_VECTOR, BpmpExceptionVector);
|
||||
reg::Write(EVP + EVP_COP_DATA_ABORT_VECTOR, BpmpExceptionVector);
|
||||
reg::Write(EVP + EVP_COP_RSVD_VECTOR, BpmpExceptionVector);
|
||||
reg::Write(EVP + EVP_COP_IRQ_VECTOR, BpmpExceptionVector);
|
||||
reg::Write(EVP + EVP_COP_FIQ_VECTOR, BpmpExceptionVector);
|
||||
|
||||
/* Turn on the SMMU for the BPMP. */
|
||||
EnableBpmpSmmu();
|
||||
|
||||
/* Wait until the flow controller reports that the BPMP is halted. */
|
||||
while (!reg::HasValue(FLOW_CTLR + FLOW_CTLR_HALT_COP_EVENTS, FLOW_REG_BITS_ENUM(HALT_COP_EVENTS_MODE, FLOW_MODE_STOP))) {
|
||||
util::WaitMicroSeconds(1);
|
||||
}
|
||||
|
||||
/* If JTAG is disabled, disable JTAG. */
|
||||
if (!secmon::IsJtagEnabled()) {
|
||||
reg::Write(FLOW_CTLR + FLOW_CTLR_HALT_COP_EVENTS, FLOW_REG_BITS_ENUM(HALT_COP_EVENTS_MODE, FLOW_MODE_STOP),
|
||||
FLOW_REG_BITS_ENUM(HALT_COP_EVENTS_JTAG, DISABLED));
|
||||
|
||||
/* If version is above 4.0.0, turn on the activity monitor to prevent booting up the bpmp. */
|
||||
if (GetTargetFirmware() >= TargetFirmware_4_0_0) {
|
||||
clkrst::EnableActmonClock();
|
||||
actmon::StartMonitoringBpmp(ActmonInterruptHandler);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SetupPmcAndMcSecure() {
|
||||
|
|
|
@ -203,4 +203,8 @@ namespace ams::secmon {
|
|||
}
|
||||
}
|
||||
|
||||
void SetupSocDmaControllersCpuMemoryControllersEnableMmuWarmboot() {
|
||||
/* TODO */
|
||||
}
|
||||
|
||||
}
|
21
exosphere2/program/source/secmon_stack_warm.s
Normal file
21
exosphere2/program/source/secmon_stack_warm.s
Normal file
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
.section .warmboot.data._ZN3ams6secmon23CommonWarmbootStackLockE, "aw", %progbits
|
||||
.global _ZN3ams6secmon23CommonWarmbootStackLockE
|
||||
_ZN3ams6secmon23CommonWarmbootStackLockE:
|
||||
/* Define storage for the global common warmboot stack bakery lock. */
|
||||
.word 0
|
|
@ -15,7 +15,7 @@
|
|||
*/
|
||||
|
||||
.section .text._ZN3ams6secmon5StartEv, "ax", %progbits
|
||||
.align 6
|
||||
.align 4
|
||||
.global _ZN3ams6secmon5StartEv
|
||||
_ZN3ams6secmon5StartEv:
|
||||
/* Set SPSEL 1 stack pointer to the core 0 exception stack address. */
|
||||
|
@ -35,12 +35,102 @@ _ZN3ams6secmon5StartEv:
|
|||
bl _ZN3ams6secmon4MainEv
|
||||
|
||||
/* Set the stack pointer to the core 3 exception stack address. */
|
||||
ldr x20, =0x1F01FB000
|
||||
ldr x20, =0x1F01F9000
|
||||
mov sp, x20
|
||||
|
||||
/* TODO: JumpToLowerExceptionLevel */
|
||||
/* Unmap the boot code region. */
|
||||
bl _ZN3ams6secmon13UnmapBootCodeEv
|
||||
|
||||
/* Jump to lower exception level. */
|
||||
b _ZN3ams6secmon25JumpToLowerExceptionLevelEv
|
||||
|
||||
.section .text._ZN3ams6secmon20StartWarmbootVirtualEv, "ax", %progbits
|
||||
.align 4
|
||||
.global _ZN3ams6secmon20StartWarmbootVirtualEv
|
||||
_ZN3ams6secmon20StartWarmbootVirtualEv:
|
||||
/* Set the stack pointer to the shared warmboot stack address. */
|
||||
ldr x20, =0x1F01F67C0
|
||||
mov sp, x20
|
||||
|
||||
/* Perform final warmboot setup. */
|
||||
bl _ZN3ams6secmon24SetupSocSecurityWarmbootEv
|
||||
|
||||
/* Jump to lower exception level. */
|
||||
b _ZN3ams6secmon25JumpToLowerExceptionLevelEv
|
||||
|
||||
.section .text._ZN3ams6secmon25JumpToLowerExceptionLevelEv, "ax", %progbits
|
||||
.align 4
|
||||
.global _ZN3ams6secmon25JumpToLowerExceptionLevelEv
|
||||
_ZN3ams6secmon25JumpToLowerExceptionLevelEv:
|
||||
/* Get the EntryContext. */
|
||||
sub sp, sp, #0x10
|
||||
mov x0, sp
|
||||
bl _ZN3ams6secmon15GetEntryContextEPNS0_12EntryContextE
|
||||
|
||||
/* Load the entrypoint and argument from the context. */
|
||||
ldr x19, [sp, #0x00]
|
||||
ldr x0, [sp, #0x08]
|
||||
|
||||
/* Set the exception return address. */
|
||||
msr elr_el3, x0
|
||||
|
||||
/* Get the core exception stack. */
|
||||
bl _ZN3ams6secmon28GetCoreExceptionStackVirtualEv
|
||||
mov sp, x0
|
||||
|
||||
/* Release our exclusive access to the common warmboot stack. */
|
||||
bl _ZN3ams6secmon26ReleaseCommonWarmbootStackEv
|
||||
|
||||
/* Configure SPSR_EL3. */
|
||||
mov x0, #0x3C5
|
||||
msr spsr_el3, x0
|
||||
|
||||
/* Set x0 to the entry argument. */
|
||||
mov x0, x19
|
||||
|
||||
/* Ensure instruction reordering doesn't happen around this point. */
|
||||
isb
|
||||
|
||||
/* Return to lower level. */
|
||||
eret
|
||||
|
||||
/* Infinite loop, though we should never get here. */
|
||||
1: b 1b
|
||||
|
||||
.section .text._ZN3ams6secmon28GetCoreExceptionStackVirtualEv, "ax", %progbits
|
||||
.align 4
|
||||
.global _ZN3ams6secmon28GetCoreExceptionStackVirtualEv
|
||||
_ZN3ams6secmon28GetCoreExceptionStackVirtualEv:
|
||||
/* Get the current core id. */
|
||||
mrs x0, mpidr_el1
|
||||
and x0, x0, #3
|
||||
|
||||
/* Jump to the appropriate core's stack handler. */
|
||||
cmp x0, #3
|
||||
b.eq 3f
|
||||
|
||||
cmp x0, #2
|
||||
b.eq 2f
|
||||
|
||||
cmp x1, #1
|
||||
b.eq 1f
|
||||
|
||||
/* cmp x0, #0 */
|
||||
/* b.eq 0f */
|
||||
|
||||
0:
|
||||
ldr x0, =0x1F01F6F00
|
||||
ret
|
||||
1:
|
||||
ldr x0, =0x1F01F6F80
|
||||
ret
|
||||
2:
|
||||
ldr x0, =0x1F01F7000
|
||||
ret
|
||||
3:
|
||||
ldr x0, =0x1F01F9000
|
||||
ret
|
||||
|
||||
.section .text._ZN3ams6secmon25AcquireCommonSmcStackLockEv, "ax", %progbits
|
||||
.align 4
|
||||
.global _ZN3ams6secmon25AcquireCommonSmcStackLockEv
|
||||
|
@ -75,6 +165,37 @@ _ZN3ams6secmon25ReleaseCommonSmcStackLockEv:
|
|||
|
||||
/* Return. */
|
||||
ret
|
||||
ret
|
||||
|
||||
.section .text._ZN3ams6secmon26ReleaseCommonWarmbootStackEv, "ax", %progbits
|
||||
.align 4
|
||||
.global _ZN3ams6secmon26ReleaseCommonWarmbootStackEv
|
||||
_ZN3ams6secmon26ReleaseCommonWarmbootStackEv:
|
||||
/* Get the virtual address of the lock. */
|
||||
ldr x0, =_ZN3ams6secmon23CommonWarmbootStackLockE
|
||||
ldr x1, =(0x1F00C0000 - 0x07C012000)
|
||||
add x1, x1, x0
|
||||
|
||||
/* Get the bakery value for our core. */
|
||||
mrs x0, mpidr_el1
|
||||
and x0, x0, #3
|
||||
ldrb w2, [x1, x0]
|
||||
|
||||
/* Clear our ticket number. */
|
||||
and w2, w2, #(~0x7F)
|
||||
strb w2, [x1, x0]
|
||||
|
||||
/* Flush the cache. */
|
||||
dc civac, x1
|
||||
|
||||
/* Synchronize data for all cores. */
|
||||
dsb sy
|
||||
|
||||
/* Send an event. */
|
||||
sev
|
||||
|
||||
/* Return. */
|
||||
ret
|
||||
|
||||
.section .data._ZN3ams6secmon18CommonSmcStackLockE, "aw", %progbits
|
||||
.global _ZN3ams6secmon18CommonSmcStackLockE
|
||||
|
|
110
exosphere2/program/source/secmon_start_warm.s
Normal file
110
exosphere2/program/source/secmon_start_warm.s
Normal file
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* For some reason GAS doesn't know about it, even with .cpu cortex-a57 */
|
||||
#define cpuactlr_el1 s3_1_c15_c2_0
|
||||
#define cpuectlr_el1 s3_1_c15_c2_1
|
||||
|
||||
.macro RESET_CORE
|
||||
mov x0, #(1 << 63)
|
||||
msr cpuactlr_el1, x0 /* disable regional clock gating */
|
||||
isb
|
||||
mov x0, #3
|
||||
msr rmr_el3, x0
|
||||
isb
|
||||
dsb sy
|
||||
/* Nintendo forgot to copy-paste the branch instruction below. */
|
||||
1:
|
||||
wfi
|
||||
b 1b
|
||||
.endm
|
||||
|
||||
.macro ERRATUM_INVALIDATE_BTB_AT_BOOT
|
||||
/* Nintendo copy-pasted https://github.com/ARM-software/arm-trusted-firmware/blob/master/plat/nvidia/tegra/common/aarch64/tegra_helpers.S#L312 */
|
||||
/*
|
||||
* Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
/* The following comments are mine. */
|
||||
|
||||
/*
|
||||
Enable invalidates of branch target buffer, then flush
|
||||
the entire instruction cache at the local level, and
|
||||
with the reg change, the branch target buffer, then disable
|
||||
invalidates of the branch target buffer again.
|
||||
*/
|
||||
mrs x0, cpuactlr_el1
|
||||
orr x0, x0, #1
|
||||
msr cpuactlr_el1, x0
|
||||
|
||||
dsb sy
|
||||
isb
|
||||
ic iallu
|
||||
dsb sy
|
||||
isb
|
||||
|
||||
mrs x0, cpuactlr_el1
|
||||
bic x0, x0, #1
|
||||
msr cpuactlr_el1, x0
|
||||
|
||||
.rept 7
|
||||
nop /* wait long enough for the write to cpuactlr_el1 to have completed */
|
||||
.endr
|
||||
|
||||
/* if the OS lock is set, disable it and request a warm reset */
|
||||
mrs x0, oslsr_el1
|
||||
ands x0, x0, #2
|
||||
b.eq 2f
|
||||
mov x0, xzr
|
||||
msr oslar_el1, x0
|
||||
|
||||
RESET_CORE
|
||||
|
||||
.rept 65
|
||||
nop /* guard against speculative excecution */
|
||||
.endr
|
||||
|
||||
2:
|
||||
/* set the OS lock */
|
||||
mov x0, #1
|
||||
msr oslar_el1, x0
|
||||
.endm
|
||||
|
||||
.section .warmboot.text.start, "ax", %progbits
|
||||
.align 4
|
||||
.global _start_warm
|
||||
_start_warm:
|
||||
/* mask all interrupts */
|
||||
msr daifset, #0xF
|
||||
|
||||
/* Fixup hardware erratum */
|
||||
ERRATUM_INVALIDATE_BTB_AT_BOOT
|
||||
|
||||
/* Acquire exclusive access to the common warmboot stack. */
|
||||
|
||||
/* Set the stack pointer to the common warmboot stack address. */
|
||||
msr spsel, #1
|
||||
ldr x20, =0x1F01F67C0
|
||||
mov sp, x20
|
||||
|
||||
/* Perform warmboot setup. */
|
||||
bl _ZN3ams6secmon59SetupSocDmaControllersCpuMemoryControllersEnableMmuWarmbootEv
|
||||
|
||||
/* Jump to the newly-mapped virtual address. */
|
||||
b _ZN3ams6secmon20StartWarmbootVirtualEv
|
||||
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue