diff --git a/libexosphere/include/exosphere.hpp b/libexosphere/include/exosphere.hpp index db9b2cb2..c92a382d 100644 --- a/libexosphere/include/exosphere.hpp +++ b/libexosphere/include/exosphere.hpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include diff --git a/libexosphere/include/exosphere/flow.hpp b/libexosphere/include/exosphere/flow.hpp new file mode 100644 index 00000000..93cfb98c --- /dev/null +++ b/libexosphere/include/exosphere/flow.hpp @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once +#include + +namespace ams::flow { + + void SetRegisterAddress(uintptr_t address); + + void ResetCpuRegisters(int core); + +} diff --git a/libexosphere/include/exosphere/hw/hw_arm64_system_registers.hpp b/libexosphere/include/exosphere/hw/hw_arm64_system_registers.hpp index 637f3c02..5792ee71 100644 --- a/libexosphere/include/exosphere/hw/hw_arm64_system_registers.hpp +++ b/libexosphere/include/exosphere/hw/hw_arm64_system_registers.hpp @@ -141,17 +141,79 @@ namespace ams::hw::arch::arm64 { #define HW_CPU_GET_DBGWCR3_EL1(value) HW_CPU_GET_SYSREG(dbgwcr3_el1, value) #define HW_CPU_SET_DBGWCR3_EL1(value) HW_CPU_SET_SYSREG(dbgwcr3_el1, value) + #define HW_CPU_GET_CNTFRQ_EL0(value) HW_CPU_GET_SYSREG(cntfrq_el0, value) + #define HW_CPU_SET_CNTFRQ_EL0(value) HW_CPU_SET_SYSREG(cntfrq_el0, value) + + #define HW_CPU_GET_CNTHCTL_EL2(value) HW_CPU_GET_SYSREG(cnthctl_el2, value) + #define HW_CPU_SET_CNTHCTL_EL2(value) HW_CPU_SET_SYSREG(cnthctl_el2, value) + + #define HW_CPU_GET_ACTLR_EL2(value) HW_CPU_GET_SYSREG(actlr_el2, value) + #define HW_CPU_SET_ACTLR_EL2(value) HW_CPU_SET_SYSREG(actlr_el2, value) + + #define HW_CPU_GET_ACTLR_EL3(value) HW_CPU_GET_SYSREG(actlr_el3, value) + #define HW_CPU_SET_ACTLR_EL3(value) HW_CPU_SET_SYSREG(actlr_el3, value) + + #define HW_CPU_GET_HCR_EL2(value) HW_CPU_GET_SYSREG(hcr_el2, value) + #define HW_CPU_SET_HCR_EL2(value) HW_CPU_SET_SYSREG(hcr_el2, value) + + #define HW_CPU_GET_DACR32_EL2(value) HW_CPU_GET_SYSREG(dacr32_el2, value) + #define HW_CPU_SET_DACR32_EL2(value) HW_CPU_SET_SYSREG(dacr32_el2, value) + + #define HW_CPU_GET_SCTLR_EL2(value) HW_CPU_GET_SYSREG(sctlr_el2, value) + #define HW_CPU_SET_SCTLR_EL2(value) HW_CPU_SET_SYSREG(sctlr_el2, value) + + #define HW_CPU_GET_SCTLR_EL1(value) HW_CPU_GET_SYSREG(sctlr_el1, value) + #define HW_CPU_SET_SCTLR_EL1(value) HW_CPU_SET_SYSREG(sctlr_el1, value) + /* https://developer.arm.com/docs/ddi0488/h/system-control/aarch64-register-descriptions/system-control-register-el3 */ struct SctlrEl3 { - using M = util::BitPack32::Field< 0, 1>; - using A = util::BitPack32::Field< 1, 1>; - using C = util::BitPack32::Field< 2, 1>; - using Sa = util::BitPack32::Field< 3, 1>; - using I = util::BitPack32::Field<12, 1>; - using Wxn = util::BitPack32::Field<19, 1>; - using Ee = util::BitPack32::Field<25, 1>; + using M = util::BitPack64::Field< 0, 1>; + using A = util::BitPack64::Field< 1, 1>; + using C = util::BitPack64::Field< 2, 1>; + using Sa = util::BitPack64::Field< 3, 1>; + using I = util::BitPack64::Field<12, 1>; + using Wxn = util::BitPack64::Field<19, 1>; + using Ee = util::BitPack64::Field<25, 1>; - static constexpr u32 Res1 = 0x30C50830; + static constexpr u64 Res1 = 0x30C50830; + }; + + /* https://static.docs.arm.com/ddi0487/fb/DDI0487F_b_armv8_arm.pdf */ + struct SctlrEl2 { + using M = util::BitPack64::Field< 0, 1>; + using A = util::BitPack64::Field< 1, 1>; + using C = util::BitPack64::Field< 2, 1>; + using Sa = util::BitPack64::Field< 3, 1>; + using I = util::BitPack64::Field<12, 1>; + using Wxn = util::BitPack64::Field<19, 1>; + using Ee = util::BitPack64::Field<25, 1>; + + static constexpr u64 Res1 = 0x30C50830; + }; + + /* https://developer.arm.com/docs/ddi0488/h/system-control/aarch64-register-descriptions/system-control-register-el1 */ + struct SctlrEl1 { + using M = util::BitPack64::Field< 0, 1>; + using A = util::BitPack64::Field< 1, 1>; + using C = util::BitPack64::Field< 2, 1>; + using Sa = util::BitPack64::Field< 3, 1>; + using Sa0 = util::BitPack64::Field< 4, 1>; + using Cp15BEn = util::BitPack64::Field< 5, 1>; + using Thee = util::BitPack64::Field< 6, 1>; + using Itd = util::BitPack64::Field< 7, 1>; + using Sed = util::BitPack64::Field< 8, 1>; + using Uma = util::BitPack64::Field< 9, 1>; + using I = util::BitPack64::Field<12, 1>; + using Dze = util::BitPack64::Field<14, 1>; + using Uct = util::BitPack64::Field<15, 1>; + using Ntwi = util::BitPack64::Field<16, 1>; + using Ntwe = util::BitPack64::Field<18, 1>; + using Wxn = util::BitPack64::Field<19, 1>; + using E0e = util::BitPack64::Field<24, 1>; + using Ee = util::BitPack64::Field<25, 1>; + using Uci = util::BitPack64::Field<26, 1>; + + static constexpr u64 Res1 = 0x30D00800; }; /* http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0488c/BABGIHHJ.html */ @@ -242,4 +304,27 @@ namespace ams::hw::arch::arm64 { using Snid = util::BitPack32::Field<6, 2>; }; -} \ No newline at end of file + /* https://developer.arm.com/docs/ddi0595/b/aarch64-system-registers/cnthctl_el2 */ + struct CnthctlEl2 { + using El1PctEn = util::BitPack32::Field<0, 1>; + using El1PcEn = util::BitPack32::Field<1, 1>; + using EvntEn = util::BitPack32::Field<2, 1>; + using EvntDir = util::BitPack32::Field<3, 1>; + using EvntI = util::BitPack32::Field<4, 4>; + }; + + /* https://developer.arm.com/docs/ddi0488/h/system-control/aarch64-register-descriptions/auxiliary-control-register-el3 */ + struct ActlrCortexA57 { + using Cpuactlr = util::BitPack32::Field<0, 1>; + using Cpuectlr = util::BitPack32::Field<1, 1>; + using L2ctlr = util::BitPack32::Field<4, 1>; + using L2ectlr = util::BitPack32::Field<5, 1>; + using L2actlr = util::BitPack32::Field<6, 1>; + }; + + /* https://developer.arm.com/docs/ddi0488/h/system-control/aarch64-register-descriptions/hypervisor-configuration-register-el2 */ + struct HcrEl2 { + using Rw = util::BitPack64::Field<31, 1>; + }; + +} diff --git a/libexosphere/include/exosphere/tegra/tegra_flow_ctlr.hpp b/libexosphere/include/exosphere/tegra/tegra_flow_ctlr.hpp index d7d3361e..eca5115f 100644 --- a/libexosphere/include/exosphere/tegra/tegra_flow_ctlr.hpp +++ b/libexosphere/include/exosphere/tegra/tegra_flow_ctlr.hpp @@ -20,6 +20,21 @@ #define FLOW_CTLR_FLOW_DBG_QUAL (0x050) #define FLOW_CTLR_BPMP_CLUSTER_CONTROL (0x098) +#define FLOW_CTLR_CPU0_CSR (0x008) +#define FLOW_CTLR_CPU1_CSR (0x018) +#define FLOW_CTLR_CPU2_CSR (0x020) +#define FLOW_CTLR_CPU3_CSR (0x028) + +#define FLOW_CTLR_HALT_CPU0_EVENTS (0x000) +#define FLOW_CTLR_HALT_CPU1_EVENTS (0x014) +#define FLOW_CTLR_HALT_CPU2_EVENTS (0x01C) +#define FLOW_CTLR_HALT_CPU3_EVENTS (0x024) + +#define FLOW_CTLR_CC4_CORE0_CTRL (0x06C) +#define FLOW_CTLR_CC4_CORE1_CTRL (0x070) +#define FLOW_CTLR_CC4_CORE2_CTRL (0x074) +#define FLOW_CTLR_CC4_CORE3_CTRL (0x078) + #define FLOW_REG_BITS_MASK(NAME) REG_NAMED_BITS_MASK (FLOW_CTLR, NAME) #define FLOW_REG_BITS_VALUE(NAME, VALUE) REG_NAMED_BITS_VALUE (FLOW_CTLR, NAME, VALUE) #define FLOW_REG_BITS_ENUM(NAME, ENUM) REG_NAMED_BITS_ENUM (FLOW_CTLR, NAME, ENUM) diff --git a/libexosphere/source/flow/flow_api.cpp b/libexosphere/source/flow/flow_api.cpp new file mode 100644 index 00000000..613c78c0 --- /dev/null +++ b/libexosphere/source/flow/flow_api.cpp @@ -0,0 +1,51 @@ +/* + * 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::flow { + + namespace { + + struct FlowControllerRegisterOffset { + u16 cpu_csr; + u16 halt_cpu_events; + u16 cc4_core_ctrl; + }; + + constinit uintptr_t g_register_address = secmon::MemoryRegionPhysicalDeviceFlowController.GetAddress(); + + constexpr const FlowControllerRegisterOffset FlowControllerRegisterOffsets[] = { + { FLOW_CTLR_CPU0_CSR, FLOW_CTLR_HALT_CPU0_EVENTS, FLOW_CTLR_CC4_CORE0_CTRL, }, + { FLOW_CTLR_CPU1_CSR, FLOW_CTLR_HALT_CPU1_EVENTS, FLOW_CTLR_CC4_CORE1_CTRL, }, + { FLOW_CTLR_CPU2_CSR, FLOW_CTLR_HALT_CPU2_EVENTS, FLOW_CTLR_CC4_CORE2_CTRL, }, + { FLOW_CTLR_CPU3_CSR, FLOW_CTLR_HALT_CPU3_EVENTS, FLOW_CTLR_CC4_CORE3_CTRL, }, + }; + + } + + void SetRegisterAddress(uintptr_t address) { + g_register_address = address; + } + + void ResetCpuRegisters(int core) { + AMS_ASSUME(core >= 0); + + const auto &offsets = FlowControllerRegisterOffsets[core]; + reg::Write(g_register_address + offsets.cpu_csr, 0); + reg::Write(g_register_address + offsets.halt_cpu_events, 0); + } + +} \ No newline at end of file