diff --git a/thermosphere/src/cpu/hvisor_cpu_debug_register_pair.hpp b/thermosphere/src/cpu/hvisor_cpu_debug_register_pair.hpp
new file mode 100644
index 000000000..9c0d6dafc
--- /dev/null
+++ b/thermosphere/src/cpu/hvisor_cpu_debug_register_pair.hpp
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2019-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 "../defines.hpp"
+
+
+namespace ams::hvisor::cpu {
+
+ // TODO GCC 10, use enum class.
+ // Would be nice if gcc didn't take 9+ years to fix a trivial bug ("too small to fit")
+ struct DebugRegisterPair {
+ // For breakpoints only
+ /// BT[3:1] or res0. BT[0]/WT[0] is "is linked"
+ enum BreakpointType {
+ AddressMatch = 0,
+ VheContextIdMatch = 1,
+ ContextIdMatch = 3,
+ VmidMatch = 4,
+ VmidContextIdMatch = 5,
+ VmidVheContextIdMatch = 6,
+ FullVheContextIdMatch = 7,
+ };
+
+ // Note: some SSC HMC PMC combinations are invalid
+ // Refer to "Table D2-9 Summary of breakpoint HMC, SSC, and PMC encodings"
+
+ /// Security State Control
+ enum SecurityStateControl {
+ Both = 0,
+ NonSecure = 1,
+ Secure = 2,
+ SecureIfLowerOrBoth = 3,
+ };
+
+ /// Higher Mode Control
+ enum HigherModeControl {
+ LowerEl = 0,
+ HigherEl = 1,
+ };
+
+ /// Privilege Mode Control (called PAC for watchpoints)
+ enum PrivilegeModeControl {
+ NeitherEl1Nor0 = 0,
+ El1 = 1,
+ El0 = 2,
+ El1And0 = 3,
+ };
+
+ // Watchpoints only
+ enum LoadStoreControl {
+ Load = 1,
+ Store = 2,
+ LoadStore = 3,
+ };
+
+ // bas only 4 bits for breakpoints, other bits res0.
+ // lsc, mask only for watchpoints, res0 for breakpoints
+ // bt only from breakpoints, res0 for watchpoints
+ struct ControlRegister {
+ union {
+ struct {
+ bool enabled : 1;
+ PrivilegeModeControl pmc : 2;
+ LoadStoreControl lsc : 2;
+ u32 bas : 8;
+ HigherModeControl hmc : 1;
+ SecurityStateControl ssc : 2;
+ u32 lbn : 4;
+ bool linked : 1;
+ BreakpointType bt : 3;
+ u32 mask : 5;
+ u64 res0 : 35;
+ };
+ u64 raw;
+ };
+ };
+
+ ControlRegister cr;
+ u64 vr;
+
+ constexpr void SetDefaults()
+ {
+ cr.linked = false;
+
+ // NS EL1&0 only
+ cr.hmc = LowerEl;
+ cr.ssc = NonSecure;
+ cr.pmc = El1And0;
+ }
+ };
+
+ static_assert(std::is_pod_v);
+}
diff --git a/thermosphere/src/cpu/hvisor_cpu_exception_sysregs.hpp b/thermosphere/src/cpu/hvisor_cpu_exception_sysregs.hpp
new file mode 100644
index 000000000..de49d0801
--- /dev/null
+++ b/thermosphere/src/cpu/hvisor_cpu_exception_sysregs.hpp
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2019-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 "../defines.hpp"
+#include "hvisor_cpu_sysreg_general.hpp"
+
+namespace ams::hvisor::cpu {
+
+ // FIXME GCC 10
+
+ struct ExceptionSyndromeRegister {
+ enum ExceptionClass {
+ Uncategorized = 0x0,
+ WFxTrap = 0x1,
+ CP15RTTrap = 0x3,
+ CP15RRTTrap = 0x4,
+ CP14RTTrap = 0x5,
+ CP14DTTrap = 0x6,
+ AdvSIMDFPAccessTrap = 0x7,
+ FPIDTrap = 0x8,
+ PACTrap = 0x9,
+ CP14RRTTrap = 0xC,
+ BranchTargetException = 0xD, // No official enum field name from Arm yet
+ IllegalState = 0xE,
+ SupervisorCallA32 = 0x11,
+ HypervisorCallA32 = 0x12,
+ MonitorCallA32 = 0x13,
+ SupervisorCallA64 = 0x15,
+ HypervisorCallA64 = 0x16,
+ MonitorCallA64 = 0x17,
+ SystemRegisterTrap = 0x18,
+ SVEAccessTrap = 0x19,
+ ERetTrap = 0x1A,
+ El3_ImplementationDefined = 0x1F,
+ InstructionAbortLowerEl = 0x20,
+ InstructionAbortSameEl = 0x21,
+ PCAlignment = 0x22,
+ DataAbortLowerEl = 0x24,
+ DataAbortSameEl = 0x25,
+ SPAlignment = 0x26,
+ FPTrappedExceptionA32 = 0x28,
+ FPTrappedExceptionA64 = 0x2C,
+ SError = 0x2F,
+ BreakpointLowerEl = 0x30,
+ BreakpointSameEl = 0x31,
+ SoftwareStepLowerEl = 0x32,
+ SoftwareStepSameEl = 0x33,
+ WatchpointLowerEl = 0x34,
+ WatchpointSameEl = 0x35,
+ SoftwareBreakpointA32 = 0x38,
+ VectorCatchA32 = 0x3A,
+ SoftwareBreakpointA64 = 0x3C,
+ };
+
+ u32 iss : 25; // Instruction Specific Syndrome
+ u32 il : 1; // Instruction Length (16 or 32-bit)
+ ExceptionClass ec : 6; // Exception Class
+ u32 res0 : 32;
+
+ constexpr size_t GetInstructionLength()
+ {
+ return il == 0 ? 2 : 4;
+ }
+ };
+
+
+ struct DataAbortIss {
+ u32 dfsc : 6; // Fault status code
+
+ u32 wnr : 1; // Write, not Read
+ u32 s1ptw : 1; // Stage1 page table walk fault
+ u32 cm : 1; // Cache maintenance
+ u32 ea : 1; // External abort
+ u32 fnv : 1; // FAR not Valid
+ u32 set : 2; // Synchronous error type
+ u32 vncr : 1; // vncr_el2 trap
+
+ u32 ar : 1; // Acquire/release. Bit 14
+ u32 sf : 1; // 64-bit register used
+ u32 srt : 5; // Syndrome register transfer (register used)
+ u32 sse : 1; // Syndrome sign extend
+ u32 sas : 2; // Syndrome access size. Bit 23
+
+ u32 isv : 1; // Instruction syndrome valid (ISS[23:14] valid)
+
+ constexpr bool HasValidFar()
+ {
+ return isv && fnv;
+ }
+ constexpr size_t GetAccessSize()
+ {
+ return BITL(sas);
+ }
+ };
+
+
+ static_assert(std::is_pod_v);
+ static_assert(std::is_pod_v);
+
+
+
+
+}
diff --git a/thermosphere/src/cpu/hvisor_cpu_sysreg_general.hpp b/thermosphere/src/cpu/hvisor_cpu_sysreg_general.hpp
new file mode 100644
index 000000000..6c1c42ee8
--- /dev/null
+++ b/thermosphere/src/cpu/hvisor_cpu_sysreg_general.hpp
@@ -0,0 +1,441 @@
+/*
+ * Copyright (c) 2019-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 "../preprocessor.h"
+#include "../defines.hpp"
+
+#define THERMOSPHERE_GET_SYSREG(r) ({\
+ u64 __val; \
+ __asm__ __volatile__("mrs %0, " STRINGIZE(r) : "=r" (__val) :: "memory"); \
+ __val; \
+})
+
+#define THERMOSPHERE_SET_SYSREG(reg, val)\
+ do {\
+ u64 temp_reg = (val);\
+ __asm__ __volatile__ ("msr " STRINGIZE(reg) ", %0" :: "r"(temp_reg) : "memory");\
+ } while(false)
+
+#define THERMOSPHERE_SET_SYSREG_IMM(reg, imm)\
+ do {\
+ __asm__ __volatile__ ("msr " STRINGIZE(reg) ", %0" :: "I"(imm) : "memory", "cc");\
+ } while(false)
+
+
+namespace ams::hvisor::cpu {
+
+ using SysregEncoding = std::array;
+
+ constexpr u32 EncodeSysregIss(SysregEncoding reg)
+ {
+ auto [op0, op1, crn, crm, op2] = reg;
+ return op0 << 20 | op2 << 17 | op1 << 14 | crn << 10 | crm << 1;
+ }
+
+ constexpr u32 MakeMsrFromEncoding(SysregEncoding reg, u32 Rt)
+ {
+ auto [op0, op1, crn, crm, op2] = reg;
+ u32 enc = op0 << 19 | op1 << 16 | crn << 12 | crm << 8 | op2 << 5;
+ return 0xD5000000u | enc | (Rt & 0x1Fu);
+ }
+
+ constexpr u32 MakeMrsFromEncoding(SysregEncoding reg, u32 Rt)
+ {
+ auto [op0, op1, crn, crm, op2] = reg;
+ u32 enc = op0 << 19 | op1 << 16 | crn << 12 | crm << 8 | op2 << 5;
+ return 0xD5200000u | enc | (Rt & 0x1Fu);
+ }
+
+ // The list mostly includes EL1 registers as these are the one we're trapping
+
+ constexpr SysregEncoding dbgbvrN_el1(u8 n) { return {2, 0, 0, n, 4}; }
+ constexpr SysregEncoding dbgbcrN_el1(u8 n) { return {2, 0, 0, n, 5}; }
+ constexpr SysregEncoding dbgwvrN_el1(u8 n) { return {2, 0, 0, n, 6}; }
+ constexpr SysregEncoding dbgwcrN_el1(u8 n) { return {2, 0, 0, n, 7}; }
+
+ constexpr inline SysregEncoding dc_isw = {1, 0, 7, 6, 2};
+ constexpr inline SysregEncoding dc_csw = {1, 0, 7, 10, 2};
+ constexpr inline SysregEncoding dc_cisw = {1, 0, 7, 14, 2};
+
+ constexpr inline SysregEncoding osdtrrx_el1 = {2, 0, 0, 0, 2};
+ constexpr inline SysregEncoding mdccint_el1 = {2, 0, 0, 2, 0};
+ constexpr inline SysregEncoding mdscr_el1 = {2, 0, 0, 2, 2};
+ constexpr inline SysregEncoding osdtrtx_el1 = {2, 0, 0, 3, 2};
+ constexpr inline SysregEncoding oseccr_el1 = {2, 0, 0, 6, 2};
+
+ constexpr inline SysregEncoding mdrar_el1 = {2, 0, 1, 0, 0};
+ constexpr inline SysregEncoding oslar_el1 = {2, 0, 1, 0, 4};
+ constexpr inline SysregEncoding oslsr_el1 = {2, 0, 1, 1, 4};
+ constexpr inline SysregEncoding osdlr_el1 = {2, 0, 1, 3, 4};
+ constexpr inline SysregEncoding dbgprcr_el1 = {2, 0, 1, 4, 4};
+ constexpr inline SysregEncoding dbgclaimset_el1 = {2, 0, 7, 8, 6};
+ constexpr inline SysregEncoding dbgclaimclr_el1 = {2, 0, 7, 9, 6};
+ constexpr inline SysregEncoding dbgauthstatus_el1 = {2, 0, 7, 14, 6};
+ constexpr inline SysregEncoding mdccsr_el0 = {2, 3, 0, 1, 0};
+ constexpr inline SysregEncoding dbgdtr_el0 = {2, 3, 0, 4, 0};
+ constexpr inline SysregEncoding dbgdtrrx_el0 = {2, 3, 0, 5, 0};
+ constexpr inline SysregEncoding dbgdtrtx_el0 = {2, 3, 0, 5, 0};
+ constexpr inline SysregEncoding dbgvcr32_el2 = {2, 4, 0, 7, 0};
+
+ constexpr inline SysregEncoding midr_el1 = {3, 0, 0, 0, 0};
+ constexpr inline SysregEncoding mpidr_el1 = {3, 0, 0, 0, 5};
+ constexpr inline SysregEncoding revidr_el1 = {3, 0, 0, 0, 6};
+
+ constexpr inline SysregEncoding id_pfr0_el1 = {3, 0, 0, 1, 0};
+ constexpr inline SysregEncoding id_pfr1_el1 = {3, 0, 0, 1, 1};
+ constexpr inline SysregEncoding id_dfr0_el1 = {3, 0, 0, 1, 2};
+ constexpr inline SysregEncoding id_afr0_el1 = {3, 0, 0, 1, 3};
+ constexpr inline SysregEncoding id_mmfr0_el1 = {3, 0, 0, 1, 4};
+ constexpr inline SysregEncoding id_mmfr1_el1 = {3, 0, 0, 1, 5};
+ constexpr inline SysregEncoding id_mmfr2_el1 = {3, 0, 0, 1, 6};
+ constexpr inline SysregEncoding id_mmfr3_el1 = {3, 0, 0, 1, 7};
+
+ constexpr inline SysregEncoding id_isar0_el1 = {3, 0, 0, 2, 0};
+ constexpr inline SysregEncoding id_isar1_el1 = {3, 0, 0, 2, 1};
+ constexpr inline SysregEncoding id_isar2_el1 = {3, 0, 0, 2, 2};
+ constexpr inline SysregEncoding id_isar3_el1 = {3, 0, 0, 2, 3};
+ constexpr inline SysregEncoding id_isar4_el1 = {3, 0, 0, 2, 4};
+ constexpr inline SysregEncoding id_isar5_el1 = {3, 0, 0, 2, 5};
+ constexpr inline SysregEncoding id_mmfr4_el1 = {3, 0, 0, 2, 6};
+
+ constexpr inline SysregEncoding mvfr0_el1 = {3, 0, 0, 3, 0};
+ constexpr inline SysregEncoding mvfr1_el1 = {3, 0, 0, 3, 1};
+ constexpr inline SysregEncoding mvfr2_el1 = {3, 0, 0, 3, 2};
+
+ constexpr inline SysregEncoding id_aa64pfr0_el1 = {3, 0, 0, 4, 0};
+ constexpr inline SysregEncoding id_aa64pfr1_el1 = {3, 0, 0, 4, 1};
+ constexpr inline SysregEncoding id_aa64zfr0_el1 = {3, 0, 0, 4, 4};
+
+ constexpr inline SysregEncoding id_aa64dfr0_el1 = {3, 0, 0, 5, 0};
+ constexpr inline SysregEncoding id_aa64dfr1_el1 = {3, 0, 0, 5, 1};
+
+ constexpr inline SysregEncoding id_aa64afr0_el1 = {3, 0, 0, 5, 4};
+ constexpr inline SysregEncoding id_aa64afr1_el1 = {3, 0, 0, 5, 5};
+
+ constexpr inline SysregEncoding id_aa64isar0_el1 = {3, 0, 0, 6, 0};
+ constexpr inline SysregEncoding id_aa64isar1_el1 = {3, 0, 0, 6, 1};
+
+ constexpr inline SysregEncoding id_aa64mmfr0_el1 = {3, 0, 0, 7, 0};
+ constexpr inline SysregEncoding id_aa64mmfr1_el1 = {3, 0, 0, 7, 1};
+ constexpr inline SysregEncoding id_aa64mmfr2_el1 = {3, 0, 0, 7, 2};
+
+ constexpr inline SysregEncoding sctlr_el1 = {3, 0, 1, 0, 0};
+ constexpr inline SysregEncoding actlr_el1 = {3, 0, 1, 0, 1};
+ constexpr inline SysregEncoding cpacr_el1 = {3, 0, 1, 0, 2};
+
+ constexpr inline SysregEncoding zcr_el1 = {3, 0, 1, 2, 0};
+
+ constexpr inline SysregEncoding ttbr0_el1 = {3, 0, 2, 0, 0};
+ constexpr inline SysregEncoding ttbr1_el1 = {3, 0, 2, 0, 1};
+ constexpr inline SysregEncoding tcr_el1 = {3, 0, 2, 0, 2};
+
+ constexpr inline SysregEncoding apiakeylo_el1 = {3, 0, 2, 1, 0};
+ constexpr inline SysregEncoding apiakeyhi_el1 = {3, 0, 2, 1, 1};
+ constexpr inline SysregEncoding apibkeylo_el1 = {3, 0, 2, 1, 2};
+ constexpr inline SysregEncoding apibkeyhi_el1 = {3, 0, 2, 1, 3};
+
+ constexpr inline SysregEncoding apdakeylo_el1 = {3, 0, 2, 2, 0};
+ constexpr inline SysregEncoding apdakeyhi_el1 = {3, 0, 2, 2, 1};
+ constexpr inline SysregEncoding apdbkeylo_el1 = {3, 0, 2, 2, 2};
+ constexpr inline SysregEncoding apdbkeyhi_el1 = {3, 0, 2, 2, 3};
+
+ constexpr inline SysregEncoding apgakeylo_el1 = {3, 0, 2, 3, 0};
+ constexpr inline SysregEncoding apgakeyhi_el1 = {3, 0, 2, 3, 1};
+
+ constexpr inline SysregEncoding afsr0_el1 = {3, 0, 5, 1, 0};
+ constexpr inline SysregEncoding afsr1_el1 = {3, 0, 5, 1, 1};
+ constexpr inline SysregEncoding esr_el1 = {3, 0, 5, 2, 0};
+
+ constexpr inline SysregEncoding erridr_el1 = {3, 0, 5, 3, 0};
+ constexpr inline SysregEncoding errselr_el1 = {3, 0, 5, 3, 1};
+ constexpr inline SysregEncoding erxfr_el1 = {3, 0, 5, 4, 0};
+ constexpr inline SysregEncoding erxctlr_el1 = {3, 0, 5, 4, 1};
+ constexpr inline SysregEncoding erxstatus_el1 = {3, 0, 5, 4, 2};
+ constexpr inline SysregEncoding erxaddr_el1 = {3, 0, 5, 4, 3};
+ constexpr inline SysregEncoding erxmisc0_el1 = {3, 0, 5, 5, 0};
+ constexpr inline SysregEncoding erxmisc1_el1 = {3, 0, 5, 5, 1};
+
+ constexpr inline SysregEncoding far_el1 = {3, 0, 6, 0, 0};
+ constexpr inline SysregEncoding par_el1 = {3, 0, 7, 4, 0};
+
+
+ constexpr inline SysregEncoding pmsidr_el1 = {3, 0, 9, 9, 7};
+ constexpr inline SysregEncoding pmbidr_el1 = {3, 0, 9, 10, 7};
+ constexpr inline SysregEncoding pmscr_el1 = {3, 0, 9, 9, 0};
+ constexpr inline SysregEncoding pmscr_el2 = {3, 4, 9, 9, 0};
+ constexpr inline SysregEncoding pmsicr_el1 = {3, 0, 9, 9, 2};
+ constexpr inline SysregEncoding pmsirr_el1 = {3, 0, 9, 9, 3};
+ constexpr inline SysregEncoding pmsfcr_el1 = {3, 0, 9, 9, 4};
+
+
+ constexpr inline SysregEncoding pmsevfr_el1 = {3, 0, 9, 9, 5};
+ constexpr inline SysregEncoding pmslatfr_el1 = {3, 0, 9, 9, 6};
+ constexpr inline SysregEncoding pmblimitr_el1 = {3, 0, 9, 10, 0};
+
+
+ constexpr inline SysregEncoding pmbptr_el1 = {3, 0, 9, 10, 1};
+
+ constexpr inline SysregEncoding pmbsr_el1 = {3, 0, 9, 10, 3};
+
+
+ constexpr inline SysregEncoding pmintenset_el1 = {3, 0, 9, 14, 1};
+ constexpr inline SysregEncoding pmintenclr_el1 = {3, 0, 9, 14, 2};
+
+ constexpr inline SysregEncoding mair_el1 = {3, 0, 10, 2, 0};
+ constexpr inline SysregEncoding amair_el1 = {3, 0, 10, 3, 0};
+
+ constexpr inline SysregEncoding lorsa_el1 = {3, 0, 10, 4, 0};
+ constexpr inline SysregEncoding lorea_el1 = {3, 0, 10, 4, 1};
+ constexpr inline SysregEncoding lorn_el1 = {3, 0, 10, 4, 2};
+ constexpr inline SysregEncoding lorc_el1 = {3, 0, 10, 4, 3};
+ constexpr inline SysregEncoding lorid_el1 = {3, 0, 10, 4, 7};
+
+ constexpr inline SysregEncoding vbar_el1 = {3, 0, 12, 0, 0};
+ constexpr inline SysregEncoding disr_el1 = {3, 0, 12, 1, 1};
+
+ constexpr inline SysregEncoding contextidr_el1 = {3, 0, 13, 0, 1};
+ constexpr inline SysregEncoding tpidr_el1 = {3, 0, 13, 0, 4};
+
+ constexpr inline SysregEncoding cntkctl_el1 = {3, 0, 14, 1, 0};
+
+ constexpr inline SysregEncoding ccsidr_el1 = {3, 1, 0, 0, 0};
+ constexpr inline SysregEncoding clidr_el1 = {3, 1, 0, 0, 1};
+ constexpr inline SysregEncoding aidr_el1 = {3, 1, 0, 0, 7};
+
+ constexpr inline SysregEncoding csselr_el1 = {3, 2, 0, 0, 0};
+
+ constexpr inline SysregEncoding ctr_el0 = {3, 3, 0, 0, 1};
+ constexpr inline SysregEncoding dczid_el0 = {3, 3, 0, 0, 7};
+
+ constexpr inline SysregEncoding pmcr_el0 = {3, 3, 9, 12, 0};
+ constexpr inline SysregEncoding pmcntenset_el0 = {3, 3, 9, 12, 1};
+ constexpr inline SysregEncoding pmcntenclr_el0 = {3, 3, 9, 12, 2};
+ constexpr inline SysregEncoding pmovsclr_el0 = {3, 3, 9, 12, 3};
+ constexpr inline SysregEncoding pmswinc_el0 = {3, 3, 9, 12, 4};
+ constexpr inline SysregEncoding pmselr_el0 = {3, 3, 9, 12, 5};
+ constexpr inline SysregEncoding pmceid0_el0 = {3, 3, 9, 12, 6};
+ constexpr inline SysregEncoding pmceid1_el0 = {3, 3, 9, 12, 7};
+ constexpr inline SysregEncoding pmccntr_el0 = {3, 3, 9, 13, 0};
+ constexpr inline SysregEncoding pmxevtyper_el0 = {3, 3, 9, 13, 1};
+ constexpr inline SysregEncoding pmxevcntr_el0 = {3, 3, 9, 13, 2};
+ constexpr inline SysregEncoding pmuserenr_el0 = {3, 3, 9, 14, 0};
+ constexpr inline SysregEncoding pmovsset_el0 = {3, 3, 9, 14, 3};
+
+ constexpr inline SysregEncoding tpidr_el0 = {3, 3, 13, 0, 2};
+ constexpr inline SysregEncoding tpidrro_el0 = {3, 3, 13, 0, 3};
+
+ constexpr inline SysregEncoding cntfrq_el0 = {3, 3, 14, 0, 0};
+ constexpr inline SysregEncoding cntpct_el0 = {3, 3, 14, 0, 1};
+ constexpr inline SysregEncoding cntvct_el0 = {3, 3, 14, 0, 2};
+
+ constexpr inline SysregEncoding cntp_tval_el0 = {3, 3, 14, 2, 0};
+ constexpr inline SysregEncoding cntp_ctl_el0 = {3, 3, 14, 2, 1};
+ constexpr inline SysregEncoding cntp_cval_el0 = {3, 3, 14, 2, 2};
+
+ constexpr inline SysregEncoding cntv_tval_el0 = {3, 3, 14, 3, 0};
+ constexpr inline SysregEncoding cntv_ctl_el0 = {3, 3, 14, 3, 1};
+ constexpr inline SysregEncoding cntv_cval_el0 = {3, 3, 14, 3, 2};
+
+ constexpr inline SysregEncoding cntvoff_el2 = {3, 4, 14, 0, 3};
+ constexpr inline SysregEncoding cnthctl_el2 = {3, 4, 14, 1, 0};
+ constexpr inline SysregEncoding cnthp_cval_el2 = {3, 4, 14, 2, 2};
+
+ constexpr inline SysregEncoding pmccfiltr_el0 = {3, 3, 14, 15, 7};
+
+ constexpr inline SysregEncoding zcr_el2 = {3, 4, 1, 2, 0};
+
+ constexpr inline SysregEncoding dacr32_el2 = {3, 4, 3, 0, 0};
+ constexpr inline SysregEncoding ifsr32_el2 = {3, 4, 5, 0, 1};
+ constexpr inline SysregEncoding vsesr_el2 = {3, 4, 5, 2, 3};
+ constexpr inline SysregEncoding fpexc32_el2 = {3, 4, 5, 3, 0};
+
+ constexpr inline SysregEncoding zcr_el12 = {3, 5, 1, 2, 0};
+
+ enum SctlrFlags {
+ SCTLR_ELx_DSSBS = BITL(44),
+ SCTLR_ELx_ENIA = BITL(31),
+ SCTLR_ELx_ENIB = BITL(30),
+ SCTLR_ELx_ENDA = BITL(27),
+ SCTLR_ELx_EE = BITL(25),
+ SCTLR_ELx_IESB = BITL(21),
+ SCTLR_ELx_WXN = BITL(19),
+ SCTLR_ELx_ENDB = BITL(13),
+ SCTLR_ELx_I = BITL(12),
+ SCTLR_ELx_SA = BITL(3),
+ SCTLR_ELx_C = BITL(2),
+ SCTLR_ELx_A = BITL(1),
+ SCTLR_ELx_M = BITL(0),
+
+ SCTLR_EL1_UCI = BITL(26),
+ SCTLR_EL1_E0E = BITL(24),
+ SCTLR_EL1_SPAN = BITL(23),
+ SCTLR_EL1_NTWE = BITL(18),
+ SCTLR_EL1_NTWI = BITL(16),
+ SCTLR_EL1_UCT = BITL(15),
+ SCTLR_EL1_DZE = BITL(14),
+ SCTLR_EL1_UMA = BITL(9),
+ SCTLR_EL1_SED = BITL(8),
+ SCTLR_EL1_ITD = BITL(7),
+ SCTLR_EL1_CP15BEN = BITL(5),
+ SCTLR_EL1_SA0 = BITL(4),
+
+ SCTLR_EL2_RES1 = util::CombineBits(29, 28, 23, 22, 18, 16, 11, 5, 4),
+ SCTLR_EL2_RES0 = (0xFFFFEFFFull << 32) | util::CombineBits(
+ 31, 30, 27, 26, 24, 20, 17, 15, 14, 13, 10, 9, 8, 7, 6
+ ),
+
+ SCTLR_EL1_RES1 = util::CombineBits(29, 28, 22, 20, 11),
+ SCTLR_EL1_RES0 = (0xFFFFEFFFull << 32) | util::CombineBits(31, 30, 27, 17, 13, 10, 6),
+ };
+
+
+ // HCR Flags
+ enum HcrFlags {
+ HCR_FWB = BITL(46),
+ HCR_API = BITL(41),
+ HCR_APK = BITL(40),
+ HCR_TEA = BITL(37),
+ HCR_TERR = BITL(36),
+ HCR_TLOR = BITL(35),
+ HCR_E2H = BITL(34),
+ HCR_ID = BITL(33),
+ HCR_CD = BITL(32),
+ HCR_RW = BITL(31),
+ HCR_TRVM = BITL(30),
+ HCR_HCD = BITL(29),
+ HCR_TDZ = BITL(28),
+ HCR_TGE = BITL(27),
+ HCR_TVM = BITL(26),
+ HCR_TTLB = BITL(25),
+ HCR_TPU = BITL(24),
+ HCR_TPC = BITL(23),
+ HCR_TSW = BITL(22),
+ HCR_TAC = BITL(21),
+ HCR_TIDCP = BITL(20),
+ HCR_TSC = BITL(19),
+ HCR_TID3 = BITL(18),
+ HCR_TID2 = BITL(17),
+ HCR_TID1 = BITL(16),
+ HCR_TID0 = BITL(15),
+ HCR_TWE = BITL(14),
+ HCR_TWI = BITL(13),
+ HCR_DC = BITL(12),
+ HCR_BSU = (3ul << 10),
+ HCR_BSU_IS = BITL(10),
+ HCR_FB = BITL(9),
+ HCR_VSE = BITL(8),
+ HCR_VI = BITL(7),
+ HCR_VF = BITL(6),
+ HCR_AMO = BITL(5),
+ HCR_IMO = BITL(4),
+ HCR_FMO = BITL(3),
+ HCR_PTW = BITL(2),
+ HCR_SWI = BITL(1),
+ HCR_VM = BITL(0),
+ };
+
+ // CPTR flags
+ enum CptrFlags {
+ CPTR_TCPAC = BITL(31),
+ CPTR_TAM = BITL(30),
+ CPTR_TTA = BITL(20),
+ CPTR_TFP = BITL(10),
+ CPTR_TZ = BITL(8), // (EL2)
+ CPTR_EZ = BITL(8), // (EL3)
+ CPTR_RES1 = 0x000032FFul,
+ };
+
+ // MDCR flags (EL2)
+ enum MdcrEl2Flags {
+ MDCR_EL2_TPMS = BITL(14),
+ MDCR_EL2_E2PB_MASK = 3ul,
+ MDCR_EL2_E2PB_SHIFT = 12,
+ MDCR_EL2_TDRA = BITL(11),
+ MDCR_EL2_TDOSA = BITL(10),
+ MDCR_EL2_TDA = BITL(9),
+ MDCR_EL2_TDE = BITL(8),
+ MDCR_EL2_HPME = BITL(7),
+ MDCR_EL2_TPM = BITL(6),
+ MDCR_EL2_TPMCR = BITL(5),
+ MDCR_EL2_HPMN_MASK = 0x1Ful,
+ };
+
+ // Some MDSCR flags
+ enum MdscrFlags {
+ MDSCR_MDE = BITL(15),
+ MDSCR_KDE = BITL(13),
+ MDSCR_SS = BITL(0),
+ };
+
+ // Some CNTHCTL flags + shifts
+ enum CnthctlFlags {
+ CNTHCTL_EVNTI_MASK = 0xFul,
+ CNTHCTL_EVNTI_SHIFT = 4,
+
+ CNTHCTL_EVNTDIR = BITL(3),
+ CNTHCTL_EVNTEN = BITL(2),
+ CNTHCTL_EL1PCEN = BITL(1),
+ CNTHCTL_EL1PCTEN = BITL(0),
+ };
+
+ // PAR_EL1 flags, shifts, masks
+ enum ParFlags {
+ PAR_F = BITL(0),
+
+ // Successful translation:
+ PAR_ATTR_SHIFT = 56,
+ PAR_ATTR_MASK = 0xFFul,
+ PAR_PA_MASK = MASK2L(51, 12),// bits 51-48 RES0 if not implemented
+ PAR_NS = BITL(9),
+ PAR_SH_SHIFT = 7,
+ PAR_SH_MASK = 3ul,
+
+ // Faulting translation:
+ PAR_S = BITL(9),
+ PAR_PTW = BITL(8),
+ PAR_FST_SHIFT = 1,
+ PAR_FST_MASK = 0x3Ful,
+ };
+
+ // Some (S)PSR flags, masks, shifts
+ enum PsrFlags {
+ PSR_AA32_IT10_SHIFT = 25,
+ PSR_AA32_IT10_MASK = 3ul,
+
+ PSR_SS = BITL(21),
+
+ PSR_AA32_IT72_SHIFT = 10,
+ PSR_AA32_IT72_MASK = 0x3Ful,
+
+ PSR_DAIF_SHIFT = 6,
+ PSR_D = BITL(9),
+ PSR_A = BITL(8),
+ PSR_I = BITL(7),
+ PSR_F = BITL(6),
+
+ PSR_AA32_THUMB = BITL(5),
+ PSR_MODE32 = BITL(4),
+
+ PSR_EL_SHIFT = 2,
+ PSR_EL_MASK = 3ul,
+
+ PSR_SP_ELX = BITL(0),
+ };
+
+}