From dc6abf9f6805bc26b8d3c7781bf22781f977c4ca Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Tue, 12 May 2020 17:14:46 -0700 Subject: [PATCH] exo2: Implement the rest of main/return-to-el1 --- exosphere2/program/program.ld | 7 +- .../program/source/boot/secmon_boot_setup.cpp | 8 +- exosphere2/program/source/secmon_map.cpp | 52 +++++ exosphere2/program/source/secmon_map.hpp | 23 ++ exosphere2/program/source/secmon_setup.cpp | 219 +++++++++++++++++- .../program/source/secmon_setup_warm.cpp | 4 + exosphere2/program/source/secmon_stack_warm.s | 21 ++ .../program/source/secmon_start_virtual.s | 127 +++++++++- exosphere2/program/source/secmon_start_warm.s | 110 +++++++++ .../libexosphere/include/exosphere/clkrst.hpp | 1 + .../libexosphere/include/exosphere/tegra.hpp | 1 + .../include/exosphere/tegra/tegra_clkrst.hpp | 87 +++++++ .../include/exosphere/tegra/tegra_evp.hpp | 11 +- .../exosphere/tegra/tegra_flow_ctlr.hpp | 4 + .../include/exosphere/tegra/tegra_mc.hpp | 25 ++ .../libexosphere/source/actmon/actmon_api.cpp | 58 ++++- .../source/actmon/actmon_registers.hpp | 52 +++++ .../libexosphere/source/clkrst/clkrst_api.cpp | 13 +- .../source/clkrst/clkrst_registers.hpp | 71 ------ 19 files changed, 801 insertions(+), 93 deletions(-) create mode 100644 exosphere2/program/source/secmon_map.cpp create mode 100644 exosphere2/program/source/secmon_map.hpp create mode 100644 exosphere2/program/source/secmon_stack_warm.s create mode 100644 exosphere2/program/source/secmon_start_warm.s create mode 100644 libraries/libexosphere/include/exosphere/tegra/tegra_clkrst.hpp create mode 100644 libraries/libexosphere/source/actmon/actmon_registers.hpp delete mode 100644 libraries/libexosphere/source/clkrst/clkrst_registers.hpp diff --git a/exosphere2/program/program.ld b/exosphere2/program/program.ld index 61e8720dc..b451dd5c7 100644 --- a/exosphere2/program/program.ld +++ b/exosphere2/program/program.ld @@ -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) diff --git a/exosphere2/program/source/boot/secmon_boot_setup.cpp b/exosphere2/program/source/boot/secmon_boot_setup.cpp index 03a3be3f8..d0daa30d9 100644 --- a/exosphere2/program/source/boot/secmon_boot_setup.cpp +++ b/exosphere2/program/source/boot/secmon_boot_setup.cpp @@ -361,8 +361,8 @@ namespace ams::secmon::boot { void UnmapPhysicalIdentityMapping() { /* Get the tables. */ - u64 * const l1 = MemoryRegionPhysicalTzramL1PageTable.GetPointer(); - u64 * const l2_l3 = MemoryRegionPhysicalTzramL2L3PageTable.GetPointer(); + u64 * const l1 = MemoryRegionVirtualTzramL1PageTable.GetPointer(); + u64 * const l2_l3 = MemoryRegionVirtualTzramL2L3PageTable.GetPointer(); /* 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 * const l2_l3 = MemoryRegionPhysicalTzramL2L3PageTable.GetPointer(); + u64 * const l1 = MemoryRegionVirtualTzramL1PageTable.GetPointer(); + u64 * const l2_l3 = MemoryRegionVirtualTzramL2L3PageTable.GetPointer(); /* Unmap. */ UnmapDramImpl(l1, l2_l3, l2_l3); diff --git a/exosphere2/program/source/secmon_map.cpp b/exosphere2/program/source/secmon_map.cpp new file mode 100644 index 000000000..a2c1d0088 --- /dev/null +++ b/exosphere2/program/source/secmon_map.cpp @@ -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 . + */ +#include +#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 * const l2_l3 = MemoryRegionVirtualTzramL2L3PageTable.GetPointer(); + + /* 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(boot_code), boot_code_size); + + /* Unmap. */ + UnmapBootCodeImpl(l1, l2_l3, l2_l3, boot_code, boot_code_size); + + /* Ensure the mappings are consistent. */ + secmon::EnsureMappingConsistency(); + } + +} diff --git a/exosphere2/program/source/secmon_map.hpp b/exosphere2/program/source/secmon_map.hpp new file mode 100644 index 000000000..9d0aac678 --- /dev/null +++ b/exosphere2/program/source/secmon_map.hpp @@ -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 . + */ +#pragma once +#include + +namespace ams::secmon { + + /* TODO */ + +} \ No newline at end of file diff --git a/exosphere2/program/source/secmon_setup.cpp b/exosphere2/program/source/secmon_setup.cpp index 71c8fa190..fa791e079 100644 --- a/exosphere2/program/source/secmon_setup.cpp +++ b/exosphere2/program/source/secmon_setup.cpp @@ -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(MemoryRegionDramGpuCarveout.GetAddress() >> 0)); + reg::Write(MC + MC_SECURITY_CARVEOUT2_BOM_HI, static_cast(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((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() { diff --git a/exosphere2/program/source/secmon_setup_warm.cpp b/exosphere2/program/source/secmon_setup_warm.cpp index e0b661d3b..b463d321e 100644 --- a/exosphere2/program/source/secmon_setup_warm.cpp +++ b/exosphere2/program/source/secmon_setup_warm.cpp @@ -203,4 +203,8 @@ namespace ams::secmon { } } + void SetupSocDmaControllersCpuMemoryControllersEnableMmuWarmboot() { + /* TODO */ + } + } \ No newline at end of file diff --git a/exosphere2/program/source/secmon_stack_warm.s b/exosphere2/program/source/secmon_stack_warm.s new file mode 100644 index 000000000..85dad852b --- /dev/null +++ b/exosphere2/program/source/secmon_stack_warm.s @@ -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 . + */ + +.section .warmboot.data._ZN3ams6secmon23CommonWarmbootStackLockE, "aw", %progbits +.global _ZN3ams6secmon23CommonWarmbootStackLockE +_ZN3ams6secmon23CommonWarmbootStackLockE: + /* Define storage for the global common warmboot stack bakery lock. */ + .word 0 diff --git a/exosphere2/program/source/secmon_start_virtual.s b/exosphere2/program/source/secmon_start_virtual.s index e71744dad..8d918fbf3 100644 --- a/exosphere2/program/source/secmon_start_virtual.s +++ b/exosphere2/program/source/secmon_start_virtual.s @@ -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 diff --git a/exosphere2/program/source/secmon_start_warm.s b/exosphere2/program/source/secmon_start_warm.s new file mode 100644 index 000000000..84b9cf901 --- /dev/null +++ b/exosphere2/program/source/secmon_start_warm.s @@ -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 . + */ + +/* 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 + + diff --git a/libraries/libexosphere/include/exosphere/clkrst.hpp b/libraries/libexosphere/include/exosphere/clkrst.hpp index c26dfb118..2f0143977 100644 --- a/libraries/libexosphere/include/exosphere/clkrst.hpp +++ b/libraries/libexosphere/include/exosphere/clkrst.hpp @@ -25,5 +25,6 @@ namespace ams::clkrst { void EnableUartAClock(); void EnableUartBClock(); void EnableUartCClock(); + void EnableActmonClock(); } \ No newline at end of file diff --git a/libraries/libexosphere/include/exosphere/tegra.hpp b/libraries/libexosphere/include/exosphere/tegra.hpp index 370bcc3bc..a6c8a0dda 100644 --- a/libraries/libexosphere/include/exosphere/tegra.hpp +++ b/libraries/libexosphere/include/exosphere/tegra.hpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include diff --git a/libraries/libexosphere/include/exosphere/tegra/tegra_clkrst.hpp b/libraries/libexosphere/include/exosphere/tegra/tegra_clkrst.hpp new file mode 100644 index 000000000..035b28594 --- /dev/null +++ b/libraries/libexosphere/include/exosphere/tegra/tegra_clkrst.hpp @@ -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 . + */ +#pragma once +#include + +/* 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) diff --git a/libraries/libexosphere/include/exosphere/tegra/tegra_evp.hpp b/libraries/libexosphere/include/exosphere/tegra/tegra_evp.hpp index 27d61f7cf..24135720c 100644 --- a/libraries/libexosphere/include/exosphere/tegra/tegra_evp.hpp +++ b/libraries/libexosphere/include/exosphere/tegra/tegra_evp.hpp @@ -16,4 +16,13 @@ #pragma once #include -#define EVP_CPU_RESET_VECTOR (0x100) +#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) diff --git a/libraries/libexosphere/include/exosphere/tegra/tegra_flow_ctlr.hpp b/libraries/libexosphere/include/exosphere/tegra/tegra_flow_ctlr.hpp index eca5115ff..d30493330 100644 --- a/libraries/libexosphere/include/exosphere/tegra/tegra_flow_ctlr.hpp +++ b/libraries/libexosphere/include/exosphere/tegra/tegra_flow_ctlr.hpp @@ -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); diff --git a/libraries/libexosphere/include/exosphere/tegra/tegra_mc.hpp b/libraries/libexosphere/include/exosphere/tegra/tegra_mc.hpp index b97b5c631..7f309daf1 100644 --- a/libraries/libexosphere/include/exosphere/tegra/tegra_mc.hpp +++ b/libraries/libexosphere/include/exosphere/tegra/tegra_mc.hpp @@ -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); diff --git a/libraries/libexosphere/source/actmon/actmon_api.cpp b/libraries/libexosphere/source/actmon/actmon_api.cpp index ee7843cbf..f6c6764eb 100644 --- a/libraries/libexosphere/source/actmon/actmon_api.cpp +++ b/libraries/libexosphere/source/actmon/actmon_api.cpp @@ -14,6 +14,7 @@ * along with this program. If not, see . */ #include +#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; } } \ No newline at end of file diff --git a/libraries/libexosphere/source/actmon/actmon_registers.hpp b/libraries/libexosphere/source/actmon/actmon_registers.hpp new file mode 100644 index 000000000..7cfb3cdc1 --- /dev/null +++ b/libraries/libexosphere/source/actmon/actmon_registers.hpp @@ -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 . + */ +#include + +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); + +} diff --git a/libraries/libexosphere/source/clkrst/clkrst_api.cpp b/libraries/libexosphere/source/clkrst/clkrst_api.cpp index c2de3028e..76601b6eb 100644 --- a/libraries/libexosphere/source/clkrst/clkrst_api.cpp +++ b/libraries/libexosphere/source/clkrst/clkrst_api.cpp @@ -14,7 +14,6 @@ * along with this program. If not, see . */ #include -#include "clkrst_registers.hpp" namespace ams::clkrst { @@ -68,9 +67,10 @@ namespace ams::clkrst { .clk_div = _DIV_, \ } - 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(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); + } -} \ No newline at end of file +} diff --git a/libraries/libexosphere/source/clkrst/clkrst_registers.hpp b/libraries/libexosphere/source/clkrst/clkrst_registers.hpp deleted file mode 100644 index 5d5cd0874..000000000 --- a/libraries/libexosphere/source/clkrst/clkrst_registers.hpp +++ /dev/null @@ -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 . - */ -#include - -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) - -}