Kernel: Add and use accessors to read from Aarch64 CPU ID registers

Following registers accessors are updated and put in use:
* ID_AA64ISAR0_EL1, Instruction Set Attribute Register 0

Accessors for following registers are added and put in use:
* ID_AA64ISAR1_EL1, Instruction Set Attribute Register 1
* ID_AA64ISAR2_EL1, Instruction Set Attribute Register 2
* ID_AA64MMFR1_EL1, AArch64 Memory Model Feature Register 1
* ID_AA64MMFR2_EL1, AArch64 Memory Model Feature Register 2
* ID_AA64MMFR3_EL1, AArch64 Memory Model Feature Register 3
* ID_AA64MMFR4_EL1, AArch64 Memory Model Feature Register 4
* ID_AA64PFR0_EL1, AArch64 Processor Feature Register 0
* ID_AA64PFR1_EL1, AArch64 Processor Feature Register 1
* ID_AA64PFR2_EL1, AArch64 Processor Feature Register 2
* ID_AA64ZFR0_EL1, AArch64 SVE Feature ID register 0
* ID_AA64SMFR0_EL1, AArch64 SME Feature ID register 0
* ID_AA64DFR0_EL1, AArch64 Debug Feature Register 0
* ID_AA64DFR1_EL1, AArch64 Debug Feature Register 1

Additionally, there are few CPU features detected with
* TCR_EL1, Translation Control Register

but detection mechanism using it (for LPA/LPA2) is probably wrong as
this is control register, not a id register, and needs further work.

Finally, following registers are provided. Former one is already used,
while latter is given for future use:
* MIDR_EL1, Main ID Register
* AIDR_EL1, Auxiliary ID Register
This commit is contained in:
konrad 2023-01-02 21:07:02 +01:00 committed by Jelle Raaijmakers
parent 6979cf230e
commit 66c65f6e2c
Notes: sideshowbarker 2024-07-19 16:58:32 +09:00
3 changed files with 861 additions and 7 deletions

View file

@ -11,6 +11,457 @@ namespace Kernel {
CPUFeature::Type detect_cpu_features()
{
auto features = CPUFeature::Type(0u);
auto instruction_set_attribute_register_0 = Aarch64::ID_AA64ISAR0_EL1::read();
auto instruction_set_attribute_register_1 = Aarch64::ID_AA64ISAR1_EL1::read();
auto instruction_set_attribute_register_2 = Aarch64::ID_AA64ISAR2_EL1::read();
auto processor_feature_register_0 = Aarch64::ID_AA64PFR0_EL1::read();
auto processor_feature_register_1 = Aarch64::ID_AA64PFR1_EL1::read();
auto memory_model_feature_register_0 = Aarch64::ID_AA64MMFR0_EL1::read();
auto memory_model_feature_register_1 = Aarch64::ID_AA64MMFR1_EL1::read();
auto memory_model_feature_register_2 = Aarch64::ID_AA64MMFR2_EL1::read();
auto memory_model_feature_register_3 = Aarch64::ID_AA64MMFR3_EL1::read();
auto sme_feature_register_0 = Aarch64::ID_AA64SMFR0_EL1::read();
auto sve_feature_register_0 = Aarch64::ID_AA64ZFR0_EL1::read();
auto debug_feature_register_0 = Aarch64::ID_AA64DFR0_EL1::read();
auto debug_feature_register_1 = Aarch64::ID_AA64DFR1_EL1::read();
auto translation_control_register = Aarch64::TCR_EL1::read();
// positives
if (instruction_set_attribute_register_0.AES == 0b0001)
features |= CPUFeature::AES;
if (instruction_set_attribute_register_0.AES == 0b0010)
features |= CPUFeature::PMULL;
if (instruction_set_attribute_register_0.SHA1 == 0b0001)
features |= CPUFeature::SHA1;
if (instruction_set_attribute_register_0.SHA2 == 0b0001)
features |= CPUFeature::SHA256;
if (instruction_set_attribute_register_0.SHA2 == 0b0010)
features |= CPUFeature::SHA512;
if (instruction_set_attribute_register_0.CRC32 == 0b0001)
features |= CPUFeature::CRC32;
if (instruction_set_attribute_register_0.Atomic == 0b0010)
features |= CPUFeature::LSE;
if (instruction_set_attribute_register_0.Atomic == 0b0011)
features |= CPUFeature::LSE128;
if (instruction_set_attribute_register_0.TME == 0b0001)
// TODO: confirm that—missing in the spec
features |= CPUFeature::TME;
if (instruction_set_attribute_register_0.RDM == 0b0001)
features |= CPUFeature::RDM;
if (instruction_set_attribute_register_0.SHA3 == 0b0001)
features |= CPUFeature::SHA3;
if (instruction_set_attribute_register_0.SM3 == 0b0001)
features |= CPUFeature::SM3;
if (instruction_set_attribute_register_0.SM4 == 0b0001)
// TODO: confirm that—unclear spec
features |= CPUFeature::SM4;
if (instruction_set_attribute_register_0.DP == 0b0001)
features |= CPUFeature::DotProd;
if (instruction_set_attribute_register_0.FHM == 0b0001)
features |= CPUFeature::FHM;
if (instruction_set_attribute_register_0.TS == 0b0001)
features |= CPUFeature::FlagM;
if (instruction_set_attribute_register_0.TS == 0b0010)
features |= CPUFeature::FlagM2;
if (instruction_set_attribute_register_0.TLB == 0b0001 || instruction_set_attribute_register_0.TLB == 0b0010)
features |= CPUFeature::TLBIOS;
if (instruction_set_attribute_register_0.TLB == 0b0010)
features |= CPUFeature::TLBIRANGE;
if (instruction_set_attribute_register_0.RNDR == 0b0001)
features |= CPUFeature::RNG;
if (instruction_set_attribute_register_1.DPB == 0b0001)
features |= CPUFeature::DPB;
if (instruction_set_attribute_register_1.DPB == 0b0010)
features |= CPUFeature::DPB2;
if (instruction_set_attribute_register_1.API == 0b0100 && instruction_set_attribute_register_1.APA == 0b0100 && instruction_set_attribute_register_2.APA3 == 0b0100)
features |= CPUFeature::FPAC;
if (instruction_set_attribute_register_1.API == 0b0101 && instruction_set_attribute_register_1.APA == 0b0101 && instruction_set_attribute_register_2.APA3 == 0b0101)
features |= CPUFeature::FPACCOMBINE;
if (instruction_set_attribute_register_1.API == 0b0001 && instruction_set_attribute_register_1.APA == 0b0001 && instruction_set_attribute_register_2.APA3 == 0b0001)
features |= CPUFeature::PAuth;
if (instruction_set_attribute_register_1.API == 0b0011 && instruction_set_attribute_register_1.APA == 0b0011 && instruction_set_attribute_register_2.APA3 == 0b0011)
features |= CPUFeature::PAuth2;
if (instruction_set_attribute_register_1.JSCVT == 0b0001)
features |= CPUFeature::JSCVT;
if (instruction_set_attribute_register_1.FCMA == 0b0001)
features |= CPUFeature::FCMA;
if (instruction_set_attribute_register_1.LRCPC == 0b0001)
features |= CPUFeature::LRCPC;
if (instruction_set_attribute_register_1.LRCPC == 0b0010)
features |= CPUFeature::LRCPC2;
if (instruction_set_attribute_register_1.LRCPC == 0b0011)
features |= CPUFeature::LRCPC3;
if (instruction_set_attribute_register_1.GPA == 0b0001 && instruction_set_attribute_register_1.APA != 0b0000)
features |= CPUFeature::PACQARMA5;
if (instruction_set_attribute_register_1.GPI == 0b0001 && instruction_set_attribute_register_1.API != 0b0000)
features |= CPUFeature::PACIMP;
if (instruction_set_attribute_register_1.FRINTTS == 0b0001)
features |= CPUFeature::FRINTTS;
if (instruction_set_attribute_register_1.SB == 0b0001)
features |= CPUFeature::SB;
if (instruction_set_attribute_register_1.SPECRES == 0b0001)
features |= CPUFeature::SPECRES;
if (instruction_set_attribute_register_1.SPECRES == 0b0010)
features |= CPUFeature::SPECRES2;
if (instruction_set_attribute_register_1.BF16 == 0b0001)
features |= CPUFeature::BF16;
if (instruction_set_attribute_register_1.BF16 == 0b0010)
features |= CPUFeature::EBF16;
if (instruction_set_attribute_register_1.DGH == 0b0001)
features |= CPUFeature::DGH;
if (instruction_set_attribute_register_1.I8MM == 0b0001)
features |= CPUFeature::I8MM;
if (instruction_set_attribute_register_1.XS == 0b0001)
features |= CPUFeature::XS;
if (instruction_set_attribute_register_1.LS64 == 0b0001)
features |= CPUFeature::LS64;
if (instruction_set_attribute_register_1.LS64 == 0b0010)
features |= CPUFeature::LS64_V;
if (instruction_set_attribute_register_1.LS64 == 0b0011)
features |= CPUFeature::LS64_ACCDATA;
if (instruction_set_attribute_register_2.WFxT == 0b0010)
features |= CPUFeature::WFxT;
if (instruction_set_attribute_register_2.RPRES == 0b0001)
features |= CPUFeature::RPRES;
if (instruction_set_attribute_register_2.GPA3 == 0b0001 && instruction_set_attribute_register_2.APA3 == 0b0000)
features |= CPUFeature::PACQARMA3;
if (instruction_set_attribute_register_2.MOPS == 0b0001)
features |= CPUFeature::MOPS;
if (instruction_set_attribute_register_2.BC == 0b0001)
features |= CPUFeature::HBC;
if (instruction_set_attribute_register_2.PAC_frac == 0b0001)
features |= CPUFeature::CONSTPACFIELD;
if (instruction_set_attribute_register_2.CLRBHB == 0b0001)
features |= CPUFeature::CLRBHB;
if (instruction_set_attribute_register_2.SYSREG_128 == 0b0001)
features |= CPUFeature::SYSREG128;
if (instruction_set_attribute_register_2.SYSINSTR_128 == 0b0001)
features |= CPUFeature::SYSINSTR128;
if (instruction_set_attribute_register_2.PRFMSLC == 0b0001)
features |= CPUFeature::PRFMSLC;
if (instruction_set_attribute_register_2.RPRFM == 0b0001)
features |= CPUFeature::RPRFM;
if (instruction_set_attribute_register_2.CSSC == 0b0001)
features |= CPUFeature::CSSC;
if (processor_feature_register_0.FP == 0b0001)
features |= CPUFeature::FP16;
if (processor_feature_register_0.AdvSIMD != 0b0000)
features |= CPUFeature::AdvSIMD; // TODO/FIXME: not explicit?
if (processor_feature_register_0.AdvSIMD == 0b0001)
features |= CPUFeature::FP16;
// TODO: GIC
if (processor_feature_register_0.RAS == 0b0001)
features |= CPUFeature::RAS;
if (processor_feature_register_0.RAS == 0b0010)
features |= CPUFeature::DoubleFault;
if (processor_feature_register_0.RAS == 0b0010)
features |= CPUFeature::RASv1p1;
if (processor_feature_register_0.RAS == 0b0001 && processor_feature_register_1.RAS_frac == 0b0001)
features |= CPUFeature::RASv1p1;
if (processor_feature_register_0.RAS == 0b0011)
features |= CPUFeature::RASv2;
if (processor_feature_register_0.SVE == 0b0001)
features |= CPUFeature::SVE;
if (processor_feature_register_0.SEL2 == 0b0001)
features |= CPUFeature::SEL2;
// TODO: MPAM
if (processor_feature_register_0.AMU == 0b0001)
features |= CPUFeature::AMUv1;
if (processor_feature_register_0.AMU == 0b0010)
features |= CPUFeature::AMUv1p1;
if (processor_feature_register_0.DIT == 0b0001)
features |= CPUFeature::DIT;
if (processor_feature_register_0.RME == 0b0001)
features |= CPUFeature::RME;
if (processor_feature_register_0.CSV2 == 0b0001)
features |= CPUFeature::CSV2;
if (processor_feature_register_0.CSV2 == 0b0010)
features |= CPUFeature::CSV2_2;
if (processor_feature_register_0.CSV2 == 0b0011)
features |= CPUFeature::CSV2_3;
if (processor_feature_register_0.CSV3 == 0b0001)
features |= CPUFeature::CSV3;
if (processor_feature_register_1.BT == 0b0001)
features |= CPUFeature::BTI;
if (processor_feature_register_1.SSBS == 0b0001)
features |= CPUFeature::SSBS;
if (processor_feature_register_1.SSBS == 0b0010)
features |= CPUFeature::SSBS2;
if (processor_feature_register_1.MTE == 0b0001)
features |= CPUFeature::MTE;
if (processor_feature_register_1.MTE == 0b0010)
features |= CPUFeature::MTE2;
if (processor_feature_register_1.MTE == 0b0011)
features |= CPUFeature::MTE3;
if (processor_feature_register_1.MTE >= 0b0010 && processor_feature_register_1.MTEX == 0b0001) {
features |= CPUFeature::MTE4;
features |= CPUFeature::MTE_CANONICAL_TAGS; // XXX: not really explicit in the spec
features |= CPUFeature::MTE_NO_ADDRESS_TAGS; // XXX: not really explicit in the spec
}
if (processor_feature_register_1.MTE >= 0b0011 && processor_feature_register_1.MTE_frac == 0b0000)
features |= CPUFeature::MTE_ASYM_FAULT; // XXX: not really explicit in the spec
if (processor_feature_register_1.SME == 0b0010)
features |= CPUFeature::SME2;
if (processor_feature_register_1.RNDR_trap == 0b0001)
features |= CPUFeature::RNG_TRAP;
if (processor_feature_register_1.CSV2_frac == 0b0001)
features |= CPUFeature::CSV2_1p1;
if (processor_feature_register_1.CSV2_frac == 0b0010)
features |= CPUFeature::CSV2_1p2;
if (processor_feature_register_1.NMI == 0b0001)
features |= CPUFeature::NMI;
if (processor_feature_register_1.GCS == 0b0001)
features |= CPUFeature::GCS;
if (processor_feature_register_1.THE == 0b0001)
features |= CPUFeature::THE;
if (processor_feature_register_1.DF2 == 0b0001)
features |= CPUFeature::DoubleFault2;
if (processor_feature_register_1.PFAR == 0b0001)
features |= CPUFeature::PFAR;
if (memory_model_feature_register_0.PARange == 0b0110) {
features |= translation_control_register.DS == 0b1 ? CPUFeature::LPA2 : CPUFeature::LPA;
}
if (memory_model_feature_register_0.PARange == 0b0111)
features |= CPUFeature::D128;
if (memory_model_feature_register_0.ExS == 0b0001)
features |= CPUFeature::ExS;
if (memory_model_feature_register_0.FGT == 0b0001)
features |= CPUFeature::FGT;
if (memory_model_feature_register_0.FGT == 0b0010)
features |= CPUFeature::FGT2;
if (memory_model_feature_register_0.ECV == 0b0001 || memory_model_feature_register_0.ECV == 0b0010)
features |= CPUFeature::ECV;
if (memory_model_feature_register_1.HAFDBS == 0b0001 || memory_model_feature_register_1.HAFDBS == 0b0010)
features |= CPUFeature::HAFDBS;
if (memory_model_feature_register_1.VMIDBits == 0b0010)
features |= CPUFeature::VMID16;
if (memory_model_feature_register_1.VH == 0b0011)
features |= CPUFeature::HAFT;
if (memory_model_feature_register_1.HPDS == 0b0010)
features |= CPUFeature::HPDS2;
if (memory_model_feature_register_1.LO == 0b0001)
features |= CPUFeature::LOR;
if (memory_model_feature_register_1.PAN == 0b0001)
features |= CPUFeature::PAN;
if (memory_model_feature_register_1.PAN == 0b0010)
features |= CPUFeature::PAN2;
if (memory_model_feature_register_1.PAN == 0b0011)
features |= CPUFeature::PAN3;
if (memory_model_feature_register_1.XNX == 0b0001)
features |= CPUFeature::XNX;
if (memory_model_feature_register_1.TWED == 0b0001)
features |= CPUFeature::TWED;
if (memory_model_feature_register_1.ETS == 0b0001)
features |= CPUFeature::ETS;
if (memory_model_feature_register_1.HCX == 0b0001)
features |= CPUFeature::HCX;
if (memory_model_feature_register_1.AFP == 0b0001)
features |= CPUFeature::AFP;
if (memory_model_feature_register_1.nTLBPA == 0b0001)
features |= CPUFeature::nTLBPA;
if (memory_model_feature_register_1.TIDCP1 == 0b0001)
features |= CPUFeature::TIDCP1;
if (memory_model_feature_register_1.CMOW == 0b0001)
features |= CPUFeature::CMOW;
if (memory_model_feature_register_1.ECBHB == 0b0001)
features |= CPUFeature::ECBHB;
if (memory_model_feature_register_2.CnP == 0b0001)
features |= CPUFeature::TTCNP;
if (memory_model_feature_register_2.UAO == 0b0001)
features |= CPUFeature::UAO;
if (memory_model_feature_register_2.LSM == 0b0001)
features |= CPUFeature::LSMAOC;
if (memory_model_feature_register_2.IESB == 0b0001)
features |= CPUFeature::IESB;
if (memory_model_feature_register_2.VARange == 0b0001)
features |= CPUFeature::LVA;
if (memory_model_feature_register_2.CCIDX == 0b0001)
features |= CPUFeature::CCIDX;
if (memory_model_feature_register_2.NV == 0b0001)
features |= CPUFeature::NV;
if (memory_model_feature_register_2.NV == 0b0010)
features |= CPUFeature::NV2;
if (memory_model_feature_register_2.ST == 0b0001)
features |= CPUFeature::TTST;
if (memory_model_feature_register_2.AT == 0b0001)
features |= CPUFeature::LSE2;
if (memory_model_feature_register_2.IDS == 0b0001)
features |= CPUFeature::IDST;
if (memory_model_feature_register_2.FWB == 0b0001)
features |= CPUFeature::S2FWB;
if (memory_model_feature_register_2.TTL == 0b0001)
features |= CPUFeature::TTL;
if (memory_model_feature_register_2.BBM == 0b0000 || memory_model_feature_register_2.BBM == 0b0001 || memory_model_feature_register_2.BBM == 0b0010)
features |= CPUFeature::BBM;
if (memory_model_feature_register_2.EVT == 0b0001 || memory_model_feature_register_2.EVT == 0b0010)
features |= CPUFeature::EVT;
if (memory_model_feature_register_2.E0PD == 0b0001) {
features |= CPUFeature::E0PD;
features |= CPUFeature::CSV3;
}
if (memory_model_feature_register_3.ADERR == 0b0010 && memory_model_feature_register_3.SDERR == 0b0010)
features |= CPUFeature::ADERR;
if (memory_model_feature_register_3.ANERR == 0b0010 && memory_model_feature_register_3.SNERR == 0b0010)
features |= CPUFeature::ANERR;
if (memory_model_feature_register_3.AIE == 0b0001)
features |= CPUFeature::AIE;
if (memory_model_feature_register_3.MEC == 0b0001)
features |= CPUFeature::MEC;
if (memory_model_feature_register_3.S1PIE == 0b0001)
features |= CPUFeature::S1PIE;
if (memory_model_feature_register_3.S2PIE == 0b0001)
features |= CPUFeature::S2PIE;
if (memory_model_feature_register_3.S1POE == 0b0001)
features |= CPUFeature::S1POE;
if (memory_model_feature_register_3.S2POE == 0b0001)
features |= CPUFeature::S2POE;
if (memory_model_feature_register_3.AIE == 0b0001)
features |= CPUFeature::AIE;
if (memory_model_feature_register_3.MEC == 0b0001)
features |= CPUFeature::MEC;
if (memory_model_feature_register_3.ANERR == 0b0010 && memory_model_feature_register_3.SNERR == 0b0010)
features |= CPUFeature::ANERR;
if (memory_model_feature_register_3.ADERR == 0b0001 && memory_model_feature_register_3.SDERR == 0b0000 && memory_model_feature_register_3.ANERR == 0b0010 && memory_model_feature_register_3.SNERR == 0b0010 && processor_feature_register_0.RAS == 0b0011)
features |= CPUFeature::RASv2;
if (memory_model_feature_register_3.ADERR == 0b0010 && memory_model_feature_register_3.SDERR == 0b0010)
features |= CPUFeature::ADERR;
if (memory_model_feature_register_3.ADERR == 0b0010 && memory_model_feature_register_3.SDERR == 0b0010)
features |= CPUFeature::ADERR;
if (translation_control_register.DS == 0b1) {
features |= CPUFeature::LVA;
}
if (sme_feature_register_0.F16F16 == 0b1)
features |= CPUFeature::SME_F16F16;
if (sme_feature_register_0.F64F64 == 0b1)
features |= CPUFeature::SME_F64F64;
if (sme_feature_register_0.I16I64 == 0b1111)
features |= CPUFeature::SME_I16I64;
if (processor_feature_register_1.SME != 0b0000) {
if (sme_feature_register_0.SMEver == 0b0000)
features |= CPUFeature::SME;
if (sme_feature_register_0.SMEver == 0b0001)
features |= CPUFeature::SME2;
if (sme_feature_register_0.SMEver == 0b0010)
features |= CPUFeature::SME2p1;
if (sme_feature_register_0.FA64 == 0b1)
features |= CPUFeature::SME_FA64; // sve_feature_register_0.I8MM/SM4/SHA3/BitPerm/AES
}
if (sve_feature_register_0.SVEver == 0b0001 && processor_feature_register_1.SME == 0b0001)
features |= CPUFeature::SME; // streaming sve mode only!
if (sve_feature_register_0.SVEver == 0b0001)
features |= CPUFeature::SVE2; // non-streaming sve mode only!
if (sve_feature_register_0.SVEver == 0b0010)
features |= CPUFeature::SVE2p1; // non-streaming sve mode only!
if (sve_feature_register_0.AES == 0b0001)
features |= CPUFeature::SVE_AES;
if (sve_feature_register_0.AES == 0b0010)
features |= CPUFeature::SVE_PMULL128;
if (sve_feature_register_0.BitPerm == 0b0001)
features |= CPUFeature::SVE_BitPerm;
if (sve_feature_register_0.BF16 == 0b0001)
features |= CPUFeature::BF16;
if (sve_feature_register_0.BF16 == 0b0010)
features |= CPUFeature::EBF16;
if (sve_feature_register_0.B16B16 == 0b0001 && sme_feature_register_0.B16B16 == 0b1)
features |= CPUFeature::B16B16;
if (sve_feature_register_0.SHA3 == 0b0001)
features |= CPUFeature::SVE_SHA3;
if (sve_feature_register_0.SM4 == 0b0001)
features |= CPUFeature::SVE_SM4;
if (sve_feature_register_0.I8MM == 0b0001)
features |= CPUFeature::I8MM;
if (sve_feature_register_0.F32MM == 0b0001)
features |= CPUFeature::F32MM;
if (sve_feature_register_0.F64MM == 0b0001)
features |= CPUFeature::F64MM;
if (debug_feature_register_0.DebugVer == 0b1000)
features |= CPUFeature::Debugv8p2;
if (debug_feature_register_0.DebugVer == 0b1001)
features |= CPUFeature::Debugv8p4;
if (debug_feature_register_0.DebugVer == 0b1010)
features |= CPUFeature::Debugv8p8;
if (debug_feature_register_0.DebugVer == 0b0111 && memory_model_feature_register_1.VH == 0b0001)
features |= CPUFeature::VHE;
if (debug_feature_register_0.DebugVer == 0b1101)
features |= CPUFeature::Debugv8p9;
if (debug_feature_register_0.PMUVer == 0b0001)
features |= CPUFeature::PMUv3;
if (debug_feature_register_0.PMUVer == 0b0100)
features |= CPUFeature::PMUv3p1;
if (debug_feature_register_0.PMUVer == 0b0101)
features |= CPUFeature::PMUv3p4;
if (debug_feature_register_0.PMUVer == 0b0110)
features |= CPUFeature::PMUv3p5;
if (debug_feature_register_0.PMUVer == 0b0111)
features |= CPUFeature::PMUv3p7;
if (debug_feature_register_0.PMUVer == 0b1000)
features |= CPUFeature::PMUv3p8;
if (debug_feature_register_0.PMUVer == 0b1001)
features |= CPUFeature::PMUv3p9;
if (debug_feature_register_0.PMSS == 0b0001)
features |= CPUFeature::PMUv3_SS;
if (debug_feature_register_0.SEBEP == 0b0001)
features |= CPUFeature::SEBEP;
if (debug_feature_register_0.PMSVer == 0b0001)
features |= CPUFeature::SPE;
if (debug_feature_register_0.PMSVer == 0b0010)
features |= CPUFeature::SPEv1p1;
if (debug_feature_register_0.PMSVer == 0b0011)
features |= CPUFeature::SPEv1p2;
if (debug_feature_register_0.PMSVer == 0b0100)
features |= CPUFeature::SPEv1p3;
if (debug_feature_register_0.PMSVer == 0b0101)
features |= CPUFeature::SPEv1p4;
if (debug_feature_register_0.PMSVer == 0b0011)
features |= CPUFeature::SPEv1p2;
if (debug_feature_register_0.DoubleLock == 0b0000)
features |= CPUFeature::DoubleLock;
if (debug_feature_register_0.TraceFilt == 0b0001)
features |= CPUFeature::TRF;
if (debug_feature_register_0.TraceBuffer == 0b0001)
features |= CPUFeature::TRBE;
if (debug_feature_register_0.MTPMU == 0b0001)
features |= CPUFeature::MTPMU; // TODO: has additional notes
if (debug_feature_register_0.BRBE == 0b0001)
features |= CPUFeature::BRBE;
if (debug_feature_register_0.BRBE == 0b0010)
features |= CPUFeature::BRBEv1p1;
if (debug_feature_register_0.ExtTrcBuff == 0b0001 && features.has_flag(CPUFeature::TRBE)) // XXX: order-dependent!
features |= CPUFeature::TRBE_EXT;
if (debug_feature_register_0.HPMN0 == 0b0001)
features |= CPUFeature::HPMN0;
if (debug_feature_register_1.ABLE == 0b0001)
features |= CPUFeature::ABLE;
if (debug_feature_register_1.EBEP == 0b0001)
features |= CPUFeature::EBEP;
if (debug_feature_register_1.ITE == 0b0001)
features |= CPUFeature::ITE;
if (debug_feature_register_1.PMICNTR == 0b0001)
features |= CPUFeature::PMUv3_ICNTR;
if (debug_feature_register_1.SPMU == 0b0001)
features |= CPUFeature::SPMU;
if (debug_feature_register_1.ABLE == 0b0001)
features |= CPUFeature::ABLE;
if (debug_feature_register_1.EBEP == 0b0001)
features |= CPUFeature::EBEP;
if (debug_feature_register_1.ITE == 0b0001)
features |= CPUFeature::ITE;
if (debug_feature_register_1.PMICNTR == 0b0001)
features |= CPUFeature::PMUv3_ICNTR;
if (debug_feature_register_1.SPMU == 0b0001)
features |= CPUFeature::SPMU;
// negatives
if (sme_feature_register_0.B16B16 == 0b0000)
features &= ~(CPUFeature::SVE2p1 | CPUFeature::SME2p1);
if (sme_feature_register_0.F16F16 == 0b0)
features &= ~CPUFeature::SME2p1;
if (sve_feature_register_0.B16B16 == 0b0000)
features &= ~(CPUFeature::SVE2p1 | CPUFeature::SME2p1);
if (sve_feature_register_0.B16B16 == 0b0001 && sme_feature_register_0.B16B16 == 0b1)
features |= CPUFeature::B16B16;
return features;
}

View file

@ -270,7 +270,7 @@ AK_MAKE_ARBITRARY_SIZED_ENUM(CPUFeature, u256,
TRBE = CPUFeature(1u) << 239u, // Trace Buffer Extension
SME = CPUFeature(1u) << 240u, // Scalable Matrix Extension
__End = CPUFeature(1u) << 255u);
__End = CPUFeature(1u) << 255u); // XXX — SENTINEL VALUE — XXX
CPUFeature::Type detect_cpu_features();
StringView cpu_feature_to_name(CPUFeature::Type const&);

View file

@ -46,6 +46,154 @@ struct alignas(u64) ID_AA64ISAR0_EL1 {
};
static_assert(sizeof(ID_AA64ISAR0_EL1) == 8);
// https://developer.arm.com/documentation/ddi0601/2022-12/AArch64-Registers/ID-AA64ISAR1-EL1--AArch64-Instruction-Set-Attribute-Register-1
// ID_AA64ISAR1_EL1, AArch64 Instruction Set Attribute Register 1
struct alignas(u64) ID_AA64ISAR1_EL1 {
int DPB : 4;
int APA : 4;
int API : 4;
int JSCVT : 4;
int FCMA : 4;
int LRCPC : 4;
int GPA : 4;
int GPI : 4;
int FRINTTS : 4;
int SB : 4;
int SPECRES : 4;
int BF16 : 4;
int DGH : 4;
int I8MM : 4;
int XS : 4;
int LS64 : 4;
static inline ID_AA64ISAR1_EL1 read()
{
ID_AA64ISAR1_EL1 feature_register;
asm("mrs %[value], ID_AA64ISAR1_EL1"
: [value] "=r"(feature_register));
return feature_register;
}
};
static_assert(sizeof(ID_AA64ISAR1_EL1) == 8);
// https://developer.arm.com/documentation/ddi0601/2022-12/AArch64-Registers/ID-AA64ISAR2-EL1--AArch64-Instruction-Set-Attribute-Register-2
// ID_AA64ISAR2_EL1, AArch64 Instruction Set Attribute Register 2
struct alignas(u64) ID_AA64ISAR2_EL1 {
int WFxT : 4;
int RPRES : 4;
int GPA3 : 4;
int APA3 : 4;
int MOPS : 4;
int BC : 4;
int PAC_frac : 4;
int CLRBHB : 4;
int SYSREG_128 : 4;
int SYSINSTR_128 : 4;
int PRFMSLC : 4;
int : 4;
int RPRFM : 4;
int CSSC : 4;
int : 8;
static inline ID_AA64ISAR2_EL1 read()
{
ID_AA64ISAR2_EL1 feature_register;
asm("mrs %[value], ID_AA64ISAR2_EL1"
: [value] "=r"(feature_register));
return feature_register;
}
};
static_assert(sizeof(ID_AA64ISAR2_EL1) == 8);
// https://developer.arm.com/documentation/ddi0601/2022-12/AArch64-Registers/ID-AA64PFR0-EL1--AArch64-Processor-Feature-Register-0
// ID_AA64PFR0_EL1, AArch64 Processor Feature Register 0
struct alignas(u64) ID_AA64PFR0_EL1 {
int EL0 : 4;
int EL1 : 4;
int EL2 : 4;
int EL3 : 4;
int FP : 4;
int AdvSIMD : 4;
int GIC : 4;
int RAS : 4;
int SVE : 4;
int SEL2 : 4;
int MPAM : 4;
int AMU : 4;
int DIT : 4;
int RME : 4;
int CSV2 : 4;
int CSV3 : 4;
static inline ID_AA64PFR0_EL1 read()
{
ID_AA64PFR0_EL1 feature_register;
asm("mrs %[value], ID_AA64PFR0_EL1"
: [value] "=r"(feature_register));
return feature_register;
}
};
static_assert(sizeof(ID_AA64PFR0_EL1) == 8);
// https://developer.arm.com/documentation/ddi0601/2022-12/AArch64-Registers/ID-AA64PFR1-EL1--AArch64-Processor-Feature-Register-1
// ID_AA64PFR1_EL1, AArch64 Processor Feature Register 1
struct alignas(u64) ID_AA64PFR1_EL1 {
int BT : 4;
int SSBS : 4;
int MTE : 4;
int RAS_frac : 4;
int MPAM_frac : 4;
int : 4;
int SME : 4;
int RNDR_trap : 4;
int CSV2_frac : 4;
int NMI : 4;
int MTE_frac : 4;
int GCS : 4;
int THE : 4;
int MTEX : 4;
int DF2 : 4;
int PFAR : 4;
static inline ID_AA64PFR1_EL1 read()
{
ID_AA64PFR1_EL1 feature_register;
asm("mrs %[value], ID_AA64PFR1_EL1"
: [value] "=r"(feature_register));
return feature_register;
}
};
static_assert(sizeof(ID_AA64PFR1_EL1) == 8);
// https://developer.arm.com/documentation/ddi0601/2022-12/AArch64-Registers/ID-AA64PFR2-EL1--AArch64-Processor-Feature-Register-2
// ID_AA64PFR2_EL1, AArch64 Processor Feature Register 2
struct alignas(u64) ID_AA64PFR2_EL1 {
int MTEPERM : 4;
int MTESTOREONLY : 4;
int MTEFAR : 4;
int : 20;
int : 32;
static inline ID_AA64PFR2_EL1 read()
{
ID_AA64PFR2_EL1 feature_register;
asm("mrs %[value], s3_0_c0_c4_2" // encoded ID_AA64PFR2_EL1 register
: [value] "=r"(feature_register));
return feature_register;
}
};
static_assert(sizeof(ID_AA64PFR2_EL1) == 8);
// https://developer.arm.com/documentation/ddi0595/2021-12/AArch64-Registers/MPIDR-EL1--Multiprocessor-Affinity-Register?lang=en
// MPIDR_EL1, Multiprocessor Affinity Register
struct alignas(u64) MPIDR_EL1 {
@ -71,8 +219,8 @@ struct alignas(u64) MPIDR_EL1 {
};
static_assert(sizeof(MPIDR_EL1) == 8);
// https://developer.arm.com/documentation/ddi0595/2021-06/AArch64-Registers/ID-AA64MMFR0-EL1--AArch64-Memory-Model-Feature-Register-0
// Memory Model Feature Register 0
// https://developer.arm.com/documentation/ddi0601/2022-12/AArch64-Registers/ID-AA64MMFR0-EL1--AArch64-Memory-Model-Feature-Register-0
// ID_AA64MMFR0_EL1, AArch64 Memory Model Feature Register 0
struct alignas(u64) ID_AA64MMFR0_EL1 {
int PARange : 4;
int ASIDBits : 4;
@ -86,7 +234,7 @@ struct alignas(u64) ID_AA64MMFR0_EL1 {
int TGran64_2 : 4;
int TGran4_2 : 4;
int ExS : 4;
int RES0 : 8;
int : 8;
int FGT : 4;
int ECV : 4;
@ -102,6 +250,244 @@ struct alignas(u64) ID_AA64MMFR0_EL1 {
};
static_assert(sizeof(ID_AA64MMFR0_EL1) == 8);
// https://developer.arm.com/documentation/ddi0601/2022-12/AArch64-Registers/ID-AA64MMFR1-EL1--AArch64-Memory-Model-Feature-Register-1
// ID_AA64MMFR1_EL1, AArch64 Memory Model Feature Register 1
struct alignas(u64) ID_AA64MMFR1_EL1 {
int HAFDBS : 4;
int VMIDBits : 4;
int VH : 4;
int HPDS : 4;
int LO : 4;
int PAN : 4;
int SpecSEI : 4;
int XNX : 4;
int TWED : 4;
int ETS : 4;
int HCX : 4;
int AFP : 4;
int nTLBPA : 4;
int TIDCP1 : 4;
int CMOW : 4;
int ECBHB : 4;
static inline ID_AA64MMFR1_EL1 read()
{
ID_AA64MMFR1_EL1 feature_register;
asm("mrs %[value], ID_AA64MMFR1_EL1"
: [value] "=r"(feature_register));
return feature_register;
}
};
static_assert(sizeof(ID_AA64MMFR1_EL1) == 8);
// https://developer.arm.com/documentation/ddi0601/2022-12/AArch64-Registers/ID-AA64MMFR2-EL1--AArch64-Memory-Model-Feature-Register-2
// ID_AA64MMFR2_EL1, AArch64 Memory Model Feature Register 2
struct alignas(u64) ID_AA64MMFR2_EL1 {
int CnP : 4;
int UAO : 4;
int LSM : 4;
int IESB : 4;
int VARange : 4;
int CCIDX : 4;
int NV : 4;
int ST : 4;
int AT : 4;
int IDS : 4;
int FWB : 4;
int : 4;
int TTL : 4;
int BBM : 4;
int EVT : 4;
int E0PD : 4;
static inline ID_AA64MMFR2_EL1 read()
{
ID_AA64MMFR2_EL1 feature_register;
asm("mrs %[value], ID_AA64MMFR2_EL1"
: [value] "=r"(feature_register));
return feature_register;
}
};
static_assert(sizeof(ID_AA64MMFR2_EL1) == 8);
// https://developer.arm.com/documentation/ddi0601/2022-12/AArch64-Registers/ID-AA64MMFR3-EL1--AArch64-Memory-Model-Feature-Register-3
// ID_AA64MMFR3_EL1, AArch64 Memory Model Feature Register 3
struct alignas(u64) ID_AA64MMFR3_EL1 {
int TCRX : 4;
int SCTLRX : 4;
int S1PIE : 4;
int S2PIE : 4;
int S1POE : 4;
int S2POE : 4;
int AIE : 4;
int MEC : 4;
int D128 : 4;
int D128_2 : 4;
int SNERR : 4;
int ANERR : 4;
int : 4;
int SDERR : 4;
int ADERR : 4;
int Spec_FPACC : 4;
static inline ID_AA64MMFR3_EL1 read()
{
ID_AA64MMFR3_EL1 feature_register;
asm("mrs %[value], s3_0_c0_c7_3" // encoded ID_AA64MMFR3_EL1 register
: [value] "=r"(feature_register));
return feature_register;
}
};
static_assert(sizeof(ID_AA64MMFR3_EL1) == 8);
// https://developer.arm.com/documentation/ddi0601/2022-12/AArch64-Registers/ID-AA64MMFR4-EL1--AArch64-Memory-Model-Feature-Register-4
// ID_AA64MMFR4_EL1, AArch64 Memory Model Feature Register 4
struct alignas(u64) ID_AA64MMFR4_EL1 {
int : 4;
int EIESB : 4;
int : 24;
int : 32;
static inline ID_AA64MMFR4_EL1 read()
{
ID_AA64MMFR4_EL1 feature_register;
asm("mrs %[value], s3_0_c0_c7_4" // encoded ID_AA64MMFR4_EL1 register
: [value] "=r"(feature_register));
return feature_register;
}
};
static_assert(sizeof(ID_AA64MMFR4_EL1) == 8);
// https://developer.arm.com/documentation/ddi0601/2022-12/AArch64-Registers/ID-AA64SMFR0-EL1--SME-Feature-ID-register-0
// ID_AA64SMFR0_EL1, AArch64 SME Feature ID register 0
struct alignas(u64) ID_AA64SMFR0_EL1 {
int : 32;
int F32F32 : 1;
int BI32I32 : 1;
int B16F32 : 1;
int F16F32 : 1;
int I8I32 : 4;
int : 2;
int F16F16 : 1;
int B16B16 : 1;
int I16I32 : 4;
int F64F64 : 1;
int : 3;
int I16I64 : 4;
int SMEver : 4;
int : 3;
int FA64 : 1;
static inline ID_AA64SMFR0_EL1 read()
{
ID_AA64SMFR0_EL1 feature_register;
asm("mrs %[value], s3_0_c0_c4_5" // encoded ID_AA64SMFR0_EL1 register
: [value] "=r"(feature_register));
return feature_register;
}
};
static_assert(sizeof(ID_AA64SMFR0_EL1) == 8);
// https://developer.arm.com/documentation/ddi0601/2022-12/AArch64-Registers/ID-AA64ZFR0-EL1--SVE-Feature-ID-register-0
// ID_AA64ZFR0_EL1, AArch64 SVE Feature ID register 0
struct alignas(u64) ID_AA64ZFR0_EL1 {
int SVEver : 4;
int AES : 4;
int : 8;
int BitPerm : 4;
int BF16 : 4;
int B16B16 : 4;
int : 4;
int SHA3 : 4;
int : 4;
int SM4 : 4;
int I8MM : 4;
int : 4;
int F32MM : 4;
int F64MM : 4;
int : 4;
static inline ID_AA64ZFR0_EL1 read()
{
ID_AA64ZFR0_EL1 feature_register;
asm("mrs %[value], s3_0_c0_c4_4" // encoded ID_AA64ZFR0_EL1 register
: [value] "=r"(feature_register));
return feature_register;
}
};
static_assert(sizeof(ID_AA64ZFR0_EL1) == 8);
// https://developer.arm.com/documentation/ddi0601/2022-12/AArch64-Registers/ID-AA64DFR0-EL1--AArch64-Debug-Feature-Register-0
// ID_AA64DFR0_EL1, AArch64 Debug Feature Register 0
struct alignas(u64) ID_AA64DFR0_EL1 {
int DebugVer : 4;
int TraceVer : 4;
int PMUVer : 4;
int BRPs : 4;
int PMSS : 4;
int WRPs : 4;
int SEBEP : 4;
int CTX_CMPs : 4;
int PMSVer : 4;
int DoubleLock : 4;
int TraceFilt : 4;
int TraceBuffer : 4;
int MTPMU : 4;
int BRBE : 4;
int ExtTrcBuff : 4;
int HPMN0 : 4;
static inline ID_AA64DFR0_EL1 read()
{
ID_AA64DFR0_EL1 feature_register;
asm("mrs %[value], ID_AA64DFR0_EL1"
: [value] "=r"(feature_register));
return feature_register;
}
};
static_assert(sizeof(ID_AA64DFR0_EL1) == 8);
// https://developer.arm.com/documentation/ddi0601/2022-12/AArch64-Registers/ID-AA64DFR1-EL1--AArch64-Debug-Feature-Register-1
// ID_AA64DFR1_EL1, AArch64 Debug Feature Register 1
struct alignas(u64) ID_AA64DFR1_EL1 {
int SYSPMUID : 8;
int BRPs : 8;
int WRPs : 8;
int CTX_CMPs : 8;
int SPMU : 4;
int PMICNTR : 4;
int ABLE : 4;
int ITE : 4;
int EBEP : 4;
int : 4;
int ABL_CMPs : 8;
static inline ID_AA64DFR1_EL1 read()
{
ID_AA64DFR1_EL1 feature_register;
asm("mrs %[value], ID_AA64DFR1_EL1"
: [value] "=r"(feature_register));
return feature_register;
}
};
static_assert(sizeof(ID_AA64DFR1_EL1) == 8);
// https://developer.arm.com/documentation/ddi0595/2020-12/AArch64-Registers/CNTFRQ-EL0--Counter-timer-Frequency-register
// CNTFRQ_EL0, Counter-timer Frequency register
struct alignas(u64) CNTFRQ_EL0 {
@ -323,16 +709,33 @@ struct alignas(u64) MIDR_EL1 {
static inline MIDR_EL1 read()
{
MIDR_EL1 affinity_register;
MIDR_EL1 main_id_register;
asm("mrs %[value], MIDR_EL1"
: [value] "=r"(affinity_register));
: [value] "=r"(main_id_register));
return affinity_register;
return main_id_register;
}
};
static_assert(sizeof(MIDR_EL1) == 8);
// https://developer.arm.com/documentation/ddi0601/2022-09/AArch64-Registers/AIDR-EL1--Auxiliary-ID-Register?lang=en
// AIDR_EL1, Auxiliary ID Register
struct alignas(u64) AIDR_EL1 {
u64 AIDR : 64;
static inline AIDR_EL1 read()
{
AIDR_EL1 auxiliary_id_register;
asm("mrs %[value], AIDR_EL1"
: [value] "=r"(auxiliary_id_register));
return auxiliary_id_register;
}
};
static_assert(sizeof(AIDR_EL1) == 8);
// https://developer.arm.com/documentation/ddi0595/2021-06/AArch64-Registers/HCR-EL2--Hypervisor-Configuration-Register
// Hypervisor Configuration Register
struct alignas(u64) HCR_EL2 {