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), + }; + +}