exo2: Implement the rest of main/return-to-el1

This commit is contained in:
Michael Scire 2020-05-12 17:14:46 -07:00 committed by SciresM
parent 87bdc46beb
commit dc6abf9f68
19 changed files with 801 additions and 93 deletions

View file

@ -36,15 +36,12 @@ SECTIONS
{
KEEP (*(.crt0 .crt0.*))
KEEP (secmon_crt0_cpp.o(.text*))
KEEP (secmon_boot_cache.o(.text*))
KEEP (secmon_make_page_table.o(.text*))
*(.crt0.rodata*)
secmon_crt0_cpp.o(.rodata*)
secmon_boot_cache.o(.rodata*)
secmon_make_page_table.o(.rodata*)
*(.crt0.data*)
secmon_crt0_cpp.o(.data*)
secmon_boot_cache.o(.data*)
secmon_make_page_table.o(.data*)
. = ALIGN(8);
} >iram_boot_code AT>glob
@ -95,18 +92,21 @@ SECTIONS
{
KEEP(secmon_main.o(.text*))
KEEP(secmon_boot_functions.o(.text*))
KEEP (secmon_boot_cache.o(.text*))
KEEP(secmon_boot_config.o(.text*))
KEEP(secmon_boot_setup.o(.text*))
KEEP(secmon_package2.o(.text*))
KEEP(secmon_key_data.o(.text*))
secmon_main.o(.rodata*)
secmon_boot_functions.o(.rodata*)
secmon_boot_cache.o(.rodata*)
secmon_boot_config.o(.rodata*)
secmon_boot_setup.o(.rodata*)
secmon_package2.o(.rodata*)
secmon_key_data.o(.rodata*)
secmon_main.o(.data*)
secmon_boot_functions.o(.data*)
secmon_boot_cache.o(.data*)
secmon_boot_config.o(.data*)
secmon_boot_setup.o(.data*)
secmon_package2.o(.data*)
@ -119,6 +119,7 @@ SECTIONS
__boot_bss_start__ = ABSOLUTE(.);
secmon_main.o(.bss* COMMON)
secmon_boot_functions.o(.bss* COMMON)
secmon_boot_cache.o(.bss* COMMON)
secmon_boot_config.o(.bss* COMMON)
secmon_boot_setup.o(.bss* COMMON)
secmon_package2.o(.bss* COMMON)

View file

@ -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);

View 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();
}
}

View 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 */
}

View file

@ -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() {

View file

@ -203,4 +203,8 @@ namespace ams::secmon {
}
}
void SetupSocDmaControllersCpuMemoryControllersEnableMmuWarmboot() {
/* TODO */
}
}

View 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

View file

@ -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

View 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

View file

@ -25,5 +25,6 @@ namespace ams::clkrst {
void EnableUartAClock();
void EnableUartBClock();
void EnableUartCClock();
void EnableActmonClock();
}

View file

@ -19,6 +19,7 @@
#include <exosphere/tegra/tegra_ahb_arbc.hpp>
#include <exosphere/tegra/tegra_apb_misc.hpp>
#include <exosphere/tegra/tegra_avp_cache.hpp>
#include <exosphere/tegra/tegra_clkrst.hpp>
#include <exosphere/tegra/tegra_emc.hpp>
#include <exosphere/tegra/tegra_evp.hpp>
#include <exosphere/tegra/tegra_flow_ctlr.hpp>

View file

@ -0,0 +1,87 @@
/*
* 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 <vapours.hpp>
/* Clock source enums. */
#define CLK_RST_REG_BITS_MASK(NAME) REG_NAMED_BITS_MASK (CLK_RST_CONTROLLER, NAME)
#define CLK_RST_REG_BITS_VALUE(NAME, VALUE) REG_NAMED_BITS_VALUE (CLK_RST_CONTROLLER, NAME, VALUE)
#define CLK_RST_REG_BITS_ENUM(NAME, ENUM) REG_NAMED_BITS_ENUM (CLK_RST_CONTROLLER, NAME, ENUM)
#define CLK_RST_REG_BITS_ENUM_SEL(NAME, __COND__, TRUE_ENUM, FALSE_ENUM) REG_NAMED_BITS_ENUM_SEL(CLK_RST_CONTROLLER, NAME, __COND__, TRUE_ENUM, FALSE_ENUM)
#define DEFINE_CLK_RST_REG(NAME, __OFFSET__, __WIDTH__) REG_DEFINE_NAMED_REG (CLK_RST_CONTROLLER, NAME, __OFFSET__, __WIDTH__)
#define DEFINE_CLK_RST_REG_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE) REG_DEFINE_NAMED_BIT_ENUM (CLK_RST_CONTROLLER, NAME, __OFFSET__, ZERO, ONE)
#define DEFINE_CLK_RST_REG_TWO_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE) REG_DEFINE_NAMED_TWO_BIT_ENUM (CLK_RST_CONTROLLER, NAME, __OFFSET__, ZERO, ONE, TWO, THREE)
#define DEFINE_CLK_RST_REG_THREE_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN) REG_DEFINE_NAMED_THREE_BIT_ENUM(CLK_RST_CONTROLLER, NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN)
#define DEFINE_CLK_RST_REG_FOUR_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN) REG_DEFINE_NAMED_FOUR_BIT_ENUM (CLK_RST_CONTROLLER, NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN)
#define CLK_RST_CONTROLLER_RST_SOURCE (0x000)
#define CLK_RST_CONTROLLER_MISC_CLK_ENB (0x048)
#define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD (0x3A4)
DEFINE_CLK_RST_REG(MISC_CLK_ENB_CFG_ALL_VISIBLE, 28, 1);
/* RST_DEVICES */
#define CLK_RST_CONTROLLER_RST_DEVICES_L (0x004)
#define CLK_RST_CONTROLLER_RST_DEVICES_H (0x008)
#define CLK_RST_CONTROLLER_RST_DEVICES_U (0x00C)
#define CLK_RST_CONTROLLER_RST_DEVICES_X (0x28C)
#define CLK_RST_CONTROLLER_RST_DEVICES_Y (0x2A4)
#define CLK_RST_CONTROLLER_RST_DEVICES_V (0x358)
#define CLK_RST_CONTROLLER_RST_DEVICES_W (0x35C)
/* CLK_OUT_ENB */
#define CLK_RST_CONTROLLER_CLK_OUT_ENB_L (0x010)
#define CLK_RST_CONTROLLER_CLK_OUT_ENB_H (0x014)
#define CLK_RST_CONTROLLER_CLK_OUT_ENB_U (0x018)
#define CLK_RST_CONTROLLER_CLK_OUT_ENB_X (0x280)
#define CLK_RST_CONTROLLER_CLK_OUT_ENB_Y (0x298)
#define CLK_RST_CONTROLLER_CLK_OUT_ENB_V (0x360)
#define CLK_RST_CONTROLLER_CLK_OUT_ENB_W (0x364)
/* CLK_SOURCE */
#define CLK_RST_CONTROLLER_CLK_SOURCE_UARTA (0x178)
#define CLK_RST_CONTROLLER_CLK_SOURCE_UARTB (0x17C)
#define CLK_RST_CONTROLLER_CLK_SOURCE_UARTC (0x1A0)
#define CLK_RST_CONTROLLER_CLK_SOURCE_ACTMON (0x3e8)
/* CLK_ENB_*_INDEX */
#define CLK_RST_CONTROLLER_CLK_ENB_UARTA_INDEX (0x06)
#define CLK_RST_CONTROLLER_CLK_ENB_UARTB_INDEX (0x07)
#define CLK_RST_CONTROLLER_CLK_ENB_UARTC_INDEX (0x17)
#define CLK_RST_CONTROLLER_CLK_ENB_ACTMON_INDEX (0x17)
DEFINE_CLK_RST_REG_BIT_ENUM(LVL2_CLK_GATE_OVRD_ARC_CLK_OVR_ON, 19, OFF, ON);
DEFINE_CLK_RST_REG_BIT_ENUM(LVL2_CLK_GATE_OVRD_TSEC_CLK_OVR_ON, 20, OFF, ON);
DEFINE_CLK_RST_REG_BIT_ENUM(LVL2_CLK_GATE_OVRD_TSECB_CLK_OVR_ON, 21, OFF, ON);
DEFINE_CLK_RST_REG_BIT_ENUM(LVL2_CLK_GATE_OVRD_ISPB_CLK_OVR_ON, 22, OFF, ON);
DEFINE_CLK_RST_REG_BIT_ENUM(LVL2_CLK_GATE_OVRD_TZRAM_CLK_OVR_ON, 23, OFF, ON);
DEFINE_CLK_RST_REG_BIT_ENUM(LVL2_CLK_GATE_OVRD_QSPI_CLK_OVR_ON, 24, OFF, ON);
DEFINE_CLK_RST_REG_BIT_ENUM(LVL2_CLK_GATE_OVRD_A9AVP_CLK_OVR_ON, 26, OFF, ON);
DEFINE_CLK_RST_REG_BIT_ENUM(LVL2_CLK_GATE_OVRD_MPCORE_MSELECT_CLK_OVR_ON, 27, OFF, ON);
DEFINE_CLK_RST_REG_BIT_ENUM(LVL2_CLK_GATE_OVRD_SDMMC1_LEGACY_TMCLK_OVR_ON, 28, OFF, ON);
DEFINE_CLK_RST_REG_BIT_ENUM(LVL2_CLK_GATE_OVRD_SDMMC2_LEGACY_TMCLK_OVR_ON, 29, OFF, ON);
DEFINE_CLK_RST_REG_BIT_ENUM(LVL2_CLK_GATE_OVRD_SDMMC3_LEGACY_TMCLK_OVR_ON, 30, OFF, ON);
DEFINE_CLK_RST_REG_BIT_ENUM(LVL2_CLK_GATE_OVRD_SDMMC4_LEGACY_TMCLK_OVR_ON, 31, OFF, ON);
DEFINE_CLK_RST_REG_THREE_BIT_ENUM(CLK_SOURCE_UARTA_UARTA_CLK_SRC, 29, PLLP_OUT0, PLLC2_OUT0, PLLC_OUT0, PLLC4_OUT0, RESERVED4, PLLC4_OUT1, CLK_M, PLLC4_OUT2)
DEFINE_CLK_RST_REG_THREE_BIT_ENUM(CLK_SOURCE_UARTB_UARTB_CLK_SRC, 29, PLLP_OUT0, PLLC2_OUT0, PLLC_OUT0, PLLC4_OUT0, RESERVED4, PLLC4_OUT1, CLK_M, PLLC4_OUT2)
DEFINE_CLK_RST_REG_THREE_BIT_ENUM(CLK_SOURCE_UARTC_UARTC_CLK_SRC, 29, PLLP_OUT0, PLLC2_OUT0, PLLC_OUT0, PLLC4_OUT0, RESERVED4, PLLC4_OUT1, CLK_M, PLLC4_OUT2)
DEFINE_CLK_RST_REG_THREE_BIT_ENUM(CLK_SOURCE_ACTMON_ACTMON_CLK_SRC, 29, PLLP_OUT0, PLLC2_OUT0, PLLC_OUT0, PLLC4_OUT0, CLK_S, PLLC4_OUT1, CLK_M, PLLC4_OUT2)

View file

@ -17,3 +17,12 @@
#include <vapours.hpp>
#define EVP_CPU_RESET_VECTOR (0x100)
#define EVP_COP_RESET_VECTOR (0x200)
#define EVP_COP_UNDEF_VECTOR (0x204)
#define EVP_COP_SWI_VECTOR (0x208)
#define EVP_COP_PREFETCH_ABORT_VECTOR (0x20C)
#define EVP_COP_DATA_ABORT_VECTOR (0x210)
#define EVP_COP_RSVD_VECTOR (0x214)
#define EVP_COP_IRQ_VECTOR (0x218)
#define EVP_COP_FIQ_VECTOR (0x21C)

View file

@ -29,6 +29,7 @@
#define FLOW_CTLR_HALT_CPU1_EVENTS (0x014)
#define FLOW_CTLR_HALT_CPU2_EVENTS (0x01C)
#define FLOW_CTLR_HALT_CPU3_EVENTS (0x024)
#define FLOW_CTLR_HALT_COP_EVENTS (0x004)
#define FLOW_CTLR_CC4_CORE0_CTRL (0x06C)
#define FLOW_CTLR_CC4_CORE1_CTRL (0x070)
@ -46,6 +47,9 @@
#define DEFINE_FLOW_REG_THREE_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN) REG_DEFINE_NAMED_THREE_BIT_ENUM(FLOW_CTLR, NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN)
#define DEFINE_FLOW_REG_FOUR_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN) REG_DEFINE_NAMED_FOUR_BIT_ENUM (FLOW_CTLR, NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN)
DEFINE_FLOW_REG_BIT_ENUM(HALT_COP_EVENTS_JTAG, 28, ENABLED, DISABLED);
DEFINE_FLOW_REG_THREE_BIT_ENUM(HALT_COP_EVENTS_MODE, 29, FLOW_MODE_NONE, FLOW_MODE_RUN_AND_INT, FLOW_MODE_STOP, FLOW_MODE_STOP_AND_INT, FLOW_MODE_STOP_UNTIL_IRQ, FLOW_MODE_STOP_UNTIL_IRQ_AND_INT, FLOW_MODE_STOP_UNTIL_EVENT_AND_IRQ, RESERVED7);
DEFINE_FLOW_REG_BIT_ENUM(FLOW_DBG_QUAL_FIQ2CCPLEX_ENABLE, 28, DISABLE, ENABLE);
DEFINE_FLOW_REG_BIT_ENUM(BPMP_CLUSTER_CONTROL_ACTIVE_CLUSTER, 0, FAST, SLOW);

View file

@ -29,6 +29,9 @@
#define MC_SMMU_TLB_FLUSH (0x030)
#define MC_SMMU_PTC_FLUSH (0x034)
#define MC_SMMU_AVPC_ASID (0x23C)
#define MC_SMMU_PPCS1_ASID (0x298)
#define MC_SECURITY_CFG0 (0x070)
#define MC_SECURITY_CFG1 (0x074)
#define MC_SECURITY_CFG3 (0x9BC)
@ -48,6 +51,10 @@
#define MC_SMMU_ASID_SECURITY_6 (0x9f0)
#define MC_SMMU_ASID_SECURITY_7 (0x9f4)
#define MC_IRAM_BOM (0x65c)
#define MC_IRAM_TOM (0x660)
#define MC_IRAM_REG_CTRL (0x964)
#define MC_SEC_CARVEOUT_BOM (0x670)
#define MC_SEC_CARVEOUT_SIZE_MB (0x674)
#define MC_SEC_CARVEOUT_REG_CTRL (0x678)
@ -160,6 +167,19 @@ DEFINE_MC_REG(SMMU_PTC_CONFIG_PTC_INDEX_MAP, 0, 7);
DEFINE_MC_REG(SMMU_PTC_CONFIG_PTC_REQ_LIMIT, 24, 4);
DEFINE_MC_REG_BIT_ENUM(SMMU_PTC_CONFIG_PTC_CACHE_ENABLE, 29, DISABLE, ENABLE);
DEFINE_MC_REG(SMMU_PTB_ASID_CURRENT_ASID, 0, 7);
DEFINE_MC_REG(SMMU_PTB_DATA_ASID_PDE_BASE, 0, 22);
DEFINE_MC_REG_BIT_ENUM(SMMU_PTB_DATA_ASID_NONSECURE, 29, DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(SMMU_PTB_DATA_ASID_WRITABLE, 30, DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(SMMU_PTB_DATA_ASID_READABLE, 31, DISABLE, ENABLE);
DEFINE_MC_REG(SMMU_AVPC_ASID_AVPC_ASID, 0, 7);
DEFINE_MC_REG_BIT_ENUM(SMMU_AVPC_ASID_AVPC_SMMU_ENABLE, 31, DISABLE, ENABLE);
DEFINE_MC_REG(SMMU_PPCS1_ASID_PPCS1_ASID, 0, 7);
DEFINE_MC_REG_BIT_ENUM(SMMU_PPCS1_ASID_PPCS1_SMMU_ENABLE, 31, DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(SMMU_ASID_SECURITY_SECURE_ASIDS_0, 0, NONSECURE, SECURE);
DEFINE_MC_REG_BIT_ENUM(SMMU_ASID_SECURITY_SECURE_ASIDS_1, 1, NONSECURE, SECURE);
DEFINE_MC_REG_BIT_ENUM(SMMU_ASID_SECURITY_SECURE_ASIDS_2, 2, NONSECURE, SECURE);
@ -327,3 +347,8 @@ DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS4_TSECRDB, (134 - (MC_CLIENT_ACCESS_N
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS4_TSECWRB, (135 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 4)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS4_GPUSRD2, (136 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 4)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS4_GPUSWR2, (137 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 4)), DISABLE, ENABLE);
constexpr inline u32 MC_IRAM_BOM_WRITE_MASK = 0xFFFFF000u;
constexpr inline u32 MC_IRAM_TOM_WRITE_MASK = 0xFFFFF000u;
DEFINE_MC_REG_BIT_ENUM(IRAM_REG_CTRL_IRAM_CFG_WRITE_ACCESS, 0, ENABLED, DISABLED);

View file

@ -14,6 +14,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <exosphere.hpp>
#include "actmon_registers.hpp"
namespace ams::actmon {
@ -21,6 +22,8 @@ namespace ams::actmon {
constinit uintptr_t g_register_address = secmon::MemoryRegionPhysicalDeviceActivityMonitor.GetAddress();
constinit InterruptHandler g_interrupt_handler = nullptr;
}
void SetRegisterAddress(uintptr_t address) {
@ -28,15 +31,64 @@ namespace ams::actmon {
}
void HandleInterrupt() {
/* TODO */
/* Get the registers. */
const uintptr_t ACTMON = g_register_address;
/* Disable the actmon interrupt. */
reg::Write(ACTMON + ACTMON_COP_CTRL, ACTMON_REG_BITS_ENUM(COP_CTRL_ENB, DISABLE));
/* Update the interrupt status. */
reg::Write(ACTMON + ACTMON_COP_INTR_STATUS, reg::Read(ACTMON + ACTMON_COP_INTR_STATUS));
/* Invoke the handler. */
if (g_interrupt_handler != nullptr) {
g_interrupt_handler();
g_interrupt_handler = nullptr;
}
}
void StartMonitoringBpmp(InterruptHandler handler) {
/* TODO */
/* Get the registers. */
const uintptr_t ACTMON = g_register_address;
/* Configure the activity monitor to poll once per microsecond. */
reg::Write(ACTMON + ACTMON_GLB_PERIOD_CTRL, ACTMON_REG_BITS_ENUM (GLB_PERIOD_CTRL_SOURCE, USEC),
ACTMON_REG_BITS_VALUE(GLB_PERIOD_CTRL_SAMPLE_PERIOD, 0));
/* Configure the activity monitor to generate an interrupt the first time the event occurs. */
reg::Write(ACTMON + ACTMON_COP_UPPER_WMARK, 0);
/* Set the interrupt handler. */
g_interrupt_handler = handler;
/* Configure the activity monitor to generate events whenever the bpmp is woken up. */
reg::Write(ACTMON + ACTMON_COP_CTRL, ACTMON_REG_BITS_ENUM (COP_CTRL_ENB, ENABLE),
ACTMON_REG_BITS_ENUM (COP_CTRL_CONSECUTIVE_ABOVE_WMARK_EN, ENABLE),
ACTMON_REG_BITS_ENUM (COP_CTRL_CONSECUTIVE_BELOW_WMARK_EN, DISABLE),
ACTMON_REG_BITS_VALUE(COP_CTRL_ABOVE_WMARK_NUM, 0),
ACTMON_REG_BITS_VALUE(COP_CTRL_BELOW_WMARK_NUM, 0),
ACTMON_REG_BITS_ENUM (COP_CTRL_WHEN_OVERFLOW_EN, DISABLE),
ACTMON_REG_BITS_ENUM (COP_CTRL_AVG_ABOVE_WMARK_EN, DISABLE),
ACTMON_REG_BITS_ENUM (COP_CTRL_AVG_BELOW_WMARK_EN, DISABLE),
ACTMON_REG_BITS_ENUM (COP_CTRL_AT_END_EN, DISABLE),
ACTMON_REG_BITS_ENUM (COP_CTRL_ENB_PERIODIC, ENABLE));
/* Read the activity monitor control register to make sure our configuration takes. */
reg::Read(ACTMON + ACTMON_COP_CTRL);
}
void StopMonitoringBpmp() {
/* TODO */
/* Get the registers. */
const uintptr_t ACTMON = g_register_address;
/* Disable the actmon interrupt. */
reg::Write(ACTMON + ACTMON_COP_CTRL, ACTMON_REG_BITS_ENUM(COP_CTRL_ENB, DISABLE));
/* Update the interrupt status. */
reg::Write(ACTMON + ACTMON_COP_INTR_STATUS, reg::Read(ACTMON + ACTMON_COP_INTR_STATUS));
/* Clear the interrupt handler. */
g_interrupt_handler = nullptr;
}
}

View 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>
namespace ams::actmon {
#define ACTMON_GLB_PERIOD_CTRL (0x004)
#define ACTMON_COP_CTRL (0x0C0)
#define ACTMON_COP_UPPER_WMARK (0x0C4)
#define ACTMON_COP_INTR_STATUS (0x0E4)
/* Actmon source enums. */
#define ACTMON_REG_BITS_MASK(NAME) REG_NAMED_BITS_MASK (ACTMON, NAME)
#define ACTMON_REG_BITS_VALUE(NAME, VALUE) REG_NAMED_BITS_VALUE (ACTMON, NAME, VALUE)
#define ACTMON_REG_BITS_ENUM(NAME, ENUM) REG_NAMED_BITS_ENUM (ACTMON, NAME, ENUM)
#define ACTMON_REG_BITS_ENUM_SEL(NAME, __COND__, TRUE_ENUM, FALSE_ENUM) REG_NAMED_BITS_ENUM_SEL(ACTMON, NAME, __COND__, TRUE_ENUM, FALSE_ENUM)
#define DEFINE_ACTMON_REG(NAME, __OFFSET__, __WIDTH__) REG_DEFINE_NAMED_REG (ACTMON, NAME, __OFFSET__, __WIDTH__)
#define DEFINE_ACTMON_REG_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE) REG_DEFINE_NAMED_BIT_ENUM (ACTMON, NAME, __OFFSET__, ZERO, ONE)
#define DEFINE_ACTMON_REG_TWO_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE) REG_DEFINE_NAMED_TWO_BIT_ENUM (ACTMON, NAME, __OFFSET__, ZERO, ONE, TWO, THREE)
#define DEFINE_ACTMON_REG_THREE_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN) REG_DEFINE_NAMED_THREE_BIT_ENUM(ACTMON, NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN)
#define DEFINE_ACTMON_REG_FOUR_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN) REG_DEFINE_NAMED_FOUR_BIT_ENUM (ACTMON, NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN)
DEFINE_ACTMON_REG(GLB_PERIOD_CTRL_SAMPLE_PERIOD, 0, 8);
DEFINE_ACTMON_REG_BIT_ENUM(GLB_PERIOD_CTRL_SOURCE, 8, MSEC, USEC);
DEFINE_ACTMON_REG(COP_CTRL_K_VAL, 10, 3);
DEFINE_ACTMON_REG_BIT_ENUM(COP_CTRL_ENB_PERIODIC, 18, DISABLE, ENABLE);
DEFINE_ACTMON_REG_BIT_ENUM(COP_CTRL_AT_END_EN, 19, DISABLE, ENABLE);
DEFINE_ACTMON_REG_BIT_ENUM(COP_CTRL_AVG_BELOW_WMARK_EN, 20, DISABLE, ENABLE);
DEFINE_ACTMON_REG_BIT_ENUM(COP_CTRL_AVG_ABOVE_WMARK_EN, 21, DISABLE, ENABLE);
DEFINE_ACTMON_REG_BIT_ENUM(COP_CTRL_WHEN_OVERFLOW_EN, 22, DISABLE, ENABLE);
DEFINE_ACTMON_REG(COP_CTRL_BELOW_WMARK_NUM, 23, 3);
DEFINE_ACTMON_REG(COP_CTRL_ABOVE_WMARK_NUM, 26, 3);
DEFINE_ACTMON_REG_BIT_ENUM(COP_CTRL_CONSECUTIVE_BELOW_WMARK_EN, 29, DISABLE, ENABLE);
DEFINE_ACTMON_REG_BIT_ENUM(COP_CTRL_CONSECUTIVE_ABOVE_WMARK_EN, 30, DISABLE, ENABLE);
DEFINE_ACTMON_REG_BIT_ENUM(COP_CTRL_ENB, 31, DISABLE, ENABLE);
}

View file

@ -14,7 +14,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <exosphere.hpp>
#include "clkrst_registers.hpp"
namespace ams::clkrst {
@ -71,6 +70,7 @@ namespace ams::clkrst {
DEFINE_CLOCK_PARAMETERS(UartAClock, L, UARTA, PLLP_OUT0, 0);
DEFINE_CLOCK_PARAMETERS(UartBClock, L, UARTB, PLLP_OUT0, 0);
DEFINE_CLOCK_PARAMETERS(UartCClock, H, UARTC, PLLP_OUT0, 0);
DEFINE_CLOCK_PARAMETERS(ActmonClock, V, ACTMON, CLK_M, 0);
}
@ -94,5 +94,8 @@ namespace ams::clkrst {
EnableClock(UartAClock);
}
void EnableActmonClock() {
EnableClock(ActmonClock);
}
}

View file

@ -1,71 +0,0 @@
/*
* 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>
namespace ams::clkrst {
/* Clock source enums. */
#define CLK_RST_REG_BITS_MASK(NAME) REG_NAMED_BITS_MASK (CLK_RST_CONTROLLER, NAME)
#define CLK_RST_REG_BITS_VALUE(NAME, VALUE) REG_NAMED_BITS_VALUE (CLK_RST_CONTROLLER, NAME, VALUE)
#define CLK_RST_REG_BITS_ENUM(NAME, ENUM) REG_NAMED_BITS_ENUM (CLK_RST_CONTROLLER, NAME, ENUM)
#define CLK_RST_REG_BITS_ENUM_SEL(NAME, __COND__, TRUE_ENUM, FALSE_ENUM) REG_NAMED_BITS_ENUM_SEL(CLK_RST_CONTROLLER, NAME, __COND__, TRUE_ENUM, FALSE_ENUM)
#define DEFINE_CLK_RST_REG(NAME, __OFFSET__, __WIDTH__) REG_DEFINE_NAMED_REG (CLK_RST_CONTROLLER, NAME, __OFFSET__, __WIDTH__)
#define DEFINE_CLK_RST_REG_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE) REG_DEFINE_NAMED_BIT_ENUM (CLK_RST_CONTROLLER, NAME, __OFFSET__, ZERO, ONE)
#define DEFINE_CLK_RST_REG_TWO_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE) REG_DEFINE_NAMED_TWO_BIT_ENUM (CLK_RST_CONTROLLER, NAME, __OFFSET__, ZERO, ONE, TWO, THREE)
#define DEFINE_CLK_RST_REG_THREE_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN) REG_DEFINE_NAMED_THREE_BIT_ENUM(CLK_RST_CONTROLLER, NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN)
#define DEFINE_CLK_RST_REG_FOUR_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN) REG_DEFINE_NAMED_FOUR_BIT_ENUM (CLK_RST_CONTROLLER, NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN)
#define CLK_RST_CONTROLLER_RST_SOURCE (0x000)
#define CLK_RST_CONTROLLER_MISC_CLK_ENB (0x048)
DEFINE_CLK_RST_REG(MISC_CLK_ENB_CFG_ALL_VISIBLE, 28, 1);
/* RST_DEVICES */
#define CLK_RST_CONTROLLER_RST_DEVICES_L (0x004)
#define CLK_RST_CONTROLLER_RST_DEVICES_H (0x008)
#define CLK_RST_CONTROLLER_RST_DEVICES_U (0x00C)
#define CLK_RST_CONTROLLER_RST_DEVICES_X (0x28C)
#define CLK_RST_CONTROLLER_RST_DEVICES_Y (0x2A4)
#define CLK_RST_CONTROLLER_RST_DEVICES_V (0x358)
#define CLK_RST_CONTROLLER_RST_DEVICES_W (0x35C)
/* CLK_OUT_ENB */
#define CLK_RST_CONTROLLER_CLK_OUT_ENB_L (0x010)
#define CLK_RST_CONTROLLER_CLK_OUT_ENB_H (0x014)
#define CLK_RST_CONTROLLER_CLK_OUT_ENB_U (0x018)
#define CLK_RST_CONTROLLER_CLK_OUT_ENB_X (0x280)
#define CLK_RST_CONTROLLER_CLK_OUT_ENB_Y (0x298)
#define CLK_RST_CONTROLLER_CLK_OUT_ENB_V (0x360)
#define CLK_RST_CONTROLLER_CLK_OUT_ENB_W (0x364)
/* CLK_SOURCE */
#define CLK_RST_CONTROLLER_CLK_SOURCE_UARTA (0x178)
#define CLK_RST_CONTROLLER_CLK_SOURCE_UARTB (0x17C)
#define CLK_RST_CONTROLLER_CLK_SOURCE_UARTC (0x1A0)
/* CLK_ENB_*_INDEX */
#define CLK_RST_CONTROLLER_CLK_ENB_UARTA_INDEX (0x06)
#define CLK_RST_CONTROLLER_CLK_ENB_UARTB_INDEX (0x07)
#define CLK_RST_CONTROLLER_CLK_ENB_UARTC_INDEX (0x17)
DEFINE_CLK_RST_REG_THREE_BIT_ENUM(CLK_SOURCE_UARTA_UARTA_CLK_SRC, 29, PLLP_OUT0, PLLC2_OUT0, PLLC_OUT0, PLLC4_OUT0, RESERVED4, PLLC4_OUT1, CLK_M, PLLC4_OUT2)
DEFINE_CLK_RST_REG_THREE_BIT_ENUM(CLK_SOURCE_UARTB_UARTB_CLK_SRC, 29, PLLP_OUT0, PLLC2_OUT0, PLLC_OUT0, PLLC4_OUT0, RESERVED4, PLLC4_OUT1, CLK_M, PLLC4_OUT2)
DEFINE_CLK_RST_REG_THREE_BIT_ENUM(CLK_SOURCE_UARTC_UARTC_CLK_SRC, 29, PLLP_OUT0, PLLC2_OUT0, PLLC_OUT0, PLLC4_OUT0, RESERVED4, PLLC4_OUT1, CLK_M, PLLC4_OUT2)
}