diff --git a/Source/Common/HostFeatures.cpp b/Source/Common/HostFeatures.cpp index f43f34c4b..fcbc1f36b 100644 --- a/Source/Common/HostFeatures.cpp +++ b/Source/Common/HostFeatures.cpp @@ -1,6 +1,9 @@ // SPDX-License-Identifier: MIT #include "Common/CPUInfo.h" #include "Common/HostFeatures.h" +#ifndef _WIN32 +#include "Common/Linux/LinuxVersion.h" +#endif #include #include @@ -69,7 +72,8 @@ GetSysReg(MIDR_EL1, MIDR_EL1); GetSysReg(ISAR1_EL1, ID_AA64ISAR1_EL1); GetSysReg(MMFR0_EL1, ID_AA64MMFR0_EL1); GetSysReg(MMFR2_EL1, ID_AA64MMFR2_EL1); -GetSysReg(ZFR0_EL1, s3_0_c0_c4_4); // Can't request by name +GetSysReg(MMFR3_EL1, s3_0_c0_c7_3); // Can't request by name +GetSysReg(ZFR0_EL1, s3_0_c0_c4_4); // Can't request by name GetSysReg(MMFR1_EL1, ID_AA64MMFR1_EL1); GetSysReg(ISAR2_EL1, ID_AA64ISAR2_EL1); GetSysReg(DCZID_EL0, DCZID_EL0); @@ -84,6 +88,12 @@ public: ISAR1.SetReg(Get_ISAR1_EL1()); MMFR0.SetReg(Get_MMFR0_EL1()); MMFR2.SetReg(Get_MMFR2_EL1()); +#ifndef _WIN32 + if (FEX::LinuxVersion::CalculateHostKernelVersion() >= FEX::LinuxVersion::KernelVersion(6, 5)) { + // Only exists in kernel 6.5 and newer. + MMFR3.SetReg(Get_MMFR3_EL1()); + } +#endif MMFR1.SetReg(Get_MMFR1_EL1()); ISAR2.SetReg(Get_ISAR2_EL1()); DCZID.SetReg(Get_DCZID_EL0()); @@ -158,6 +168,8 @@ public: MMFR1.SetReg(ValueHex); } else if (Key == "mmfr2") { MMFR2.SetReg(ValueHex); + } else if (Key == "mmfr3") { + MMFR3.SetReg(ValueHex); } else if (Key == "zfr0") { ZFR0.SetReg(ValueHex); } else if (Key == "dczid") { diff --git a/Source/Common/HostFeatures.h b/Source/Common/HostFeatures.h index 0324f9a66..0fe73c9c5 100644 --- a/Source/Common/HostFeatures.h +++ b/Source/Common/HostFeatures.h @@ -101,6 +101,8 @@ public: SVE_F64MM, // MMFR1 AFP, + // MMFR3 + S1POE, // ISAR2 WFxt, RPRES, @@ -148,6 +150,7 @@ public: MMFR2_EL1, ZFR0_EL1, MMFR1_EL1, + MMFR3_EL1, ISAR2_EL1, }; @@ -559,6 +562,30 @@ public: }; }; + class MMFR3Reg final : public FeatureReg { + public: + FIELD_FETCHER(S1POE, S1POE, 0b0001); + + private: + enum Field { + TCRX = 0 * 4, + SCTLRX = 1 * 4, + S1PIE = 2 * 4, + S2PIE = 3 * 4, + S1POE = 4 * 4, + S2POE = 5 * 4, + AIE = 6 * 4, + MEC = 7 * 4, + D128 = 8 * 4, + D128_2 = 9 * 4, + SNERR = 10 * 4, + ANERR = 11 * 4, + SDERR = 13 * 4, + ADERR = 14 * 4, + SPEC_FPACC = 15 * 4, + }; + }; + class ISAR2Reg final : public FeatureReg { public: FIELD_FETCHER(WFxt, WFxt, 0b0010); @@ -621,6 +648,7 @@ public: ZFR0Reg ZFR0; MMFR2Reg MMFR2; MMFR1Reg MMFR1; + MMFR3Reg MMFR3; ISAR2Reg ISAR2; DCZIDReg DCZID; SVEVLReg SVEVL; diff --git a/Source/Tools/FEXGetConfig/Main.cpp b/Source/Tools/FEXGetConfig/Main.cpp index cbaf4edfd..d5abb04bb 100644 --- a/Source/Tools/FEXGetConfig/Main.cpp +++ b/Source/Tools/FEXGetConfig/Main.cpp @@ -485,6 +485,7 @@ int main(int argc, char** argv, char** envp) { features += fmt::format("mmfr0=0x{:x},", Features.MMFR0.Get()); features += fmt::format("mmfr1=0x{:x},", Features.MMFR1.Get()); features += fmt::format("mmfr2=0x{:x},", Features.MMFR2.Get()); + features += fmt::format("mmfr3=0x{:x},", Features.MMFR3.Get()); features += fmt::format("zfr0=0x{:x},", Features.ZFR0.Get()); features += fmt::format("dczid=0x{:x},", Features.DCZID.Get()); features += fmt::format("svevl=0x{:x}", Features.SVEVL.Get());