std_detect: Split os/aarch64.rs' detect_features into reading and parsing
This commit is contained in:
parent
674fd58f60
commit
d3bb923c82
1 changed files with 74 additions and 65 deletions
|
|
@ -23,77 +23,86 @@ use core::arch::asm;
|
|||
///
|
||||
/// This will cause SIGILL if the current OS is not trapping the mrs instruction.
|
||||
pub(crate) fn detect_features() -> cache::Initializer {
|
||||
// ID_AA64ISAR0_EL1 - Instruction Set Attribute Register 0
|
||||
let aa64isar0: u64;
|
||||
unsafe {
|
||||
asm!(
|
||||
"mrs {}, ID_AA64ISAR0_EL1",
|
||||
out(reg) aa64isar0,
|
||||
options(pure, nomem, preserves_flags, nostack)
|
||||
);
|
||||
}
|
||||
|
||||
// ID_AA64ISAR1_EL1 - Instruction Set Attribute Register 1
|
||||
let aa64isar1: u64;
|
||||
unsafe {
|
||||
asm!(
|
||||
"mrs {}, ID_AA64ISAR1_EL1",
|
||||
out(reg) aa64isar1,
|
||||
options(pure, nomem, preserves_flags, nostack)
|
||||
);
|
||||
}
|
||||
|
||||
// ID_AA64PFR0_EL1 - Processor Feature Register 0
|
||||
let aa64pfr0: u64;
|
||||
unsafe {
|
||||
asm!(
|
||||
"mrs {}, ID_AA64PFR0_EL1",
|
||||
out(reg) aa64pfr0,
|
||||
options(pure, nomem, preserves_flags, nostack)
|
||||
);
|
||||
}
|
||||
|
||||
parse_system_registers(aa64isar0, aa64isar1, aa64pfr0)
|
||||
}
|
||||
|
||||
pub(crate) fn parse_system_registers(
|
||||
aa64isar0: u64,
|
||||
aa64isar1: u64,
|
||||
aa64pfr0: u64,
|
||||
) -> cache::Initializer {
|
||||
let mut value = cache::Initializer::default();
|
||||
|
||||
{
|
||||
let mut enable_feature = |f, enable| {
|
||||
if enable {
|
||||
value.set(f as u32);
|
||||
}
|
||||
};
|
||||
|
||||
// ID_AA64ISAR0_EL1 - Instruction Set Attribute Register 0
|
||||
let aa64isar0: u64;
|
||||
unsafe {
|
||||
asm!(
|
||||
"mrs {}, ID_AA64ISAR0_EL1",
|
||||
out(reg) aa64isar0,
|
||||
options(pure, nomem, preserves_flags, nostack)
|
||||
);
|
||||
let mut enable_feature = |f, enable| {
|
||||
if enable {
|
||||
value.set(f as u32);
|
||||
}
|
||||
};
|
||||
|
||||
enable_feature(Feature::pmull, bits_shift(aa64isar0, 7, 4) >= 2);
|
||||
enable_feature(Feature::tme, bits_shift(aa64isar0, 27, 24) == 1);
|
||||
enable_feature(Feature::lse, bits_shift(aa64isar0, 23, 20) >= 1);
|
||||
enable_feature(Feature::crc, bits_shift(aa64isar0, 19, 16) >= 1);
|
||||
// ID_AA64ISAR0_EL1 - Instruction Set Attribute Register 0
|
||||
enable_feature(Feature::pmull, bits_shift(aa64isar0, 7, 4) >= 2);
|
||||
enable_feature(Feature::tme, bits_shift(aa64isar0, 27, 24) == 1);
|
||||
enable_feature(Feature::lse, bits_shift(aa64isar0, 23, 20) >= 1);
|
||||
enable_feature(Feature::crc, bits_shift(aa64isar0, 19, 16) >= 1);
|
||||
|
||||
// ID_AA64PFR0_EL1 - Processor Feature Register 0
|
||||
let aa64pfr0: u64;
|
||||
unsafe {
|
||||
asm!(
|
||||
"mrs {}, ID_AA64PFR0_EL1",
|
||||
out(reg) aa64pfr0,
|
||||
options(pure, nomem, preserves_flags, nostack)
|
||||
);
|
||||
}
|
||||
// ID_AA64PFR0_EL1 - Processor Feature Register 0
|
||||
let fp = bits_shift(aa64pfr0, 19, 16) < 0xF;
|
||||
let fphp = bits_shift(aa64pfr0, 19, 16) >= 1;
|
||||
let asimd = bits_shift(aa64pfr0, 23, 20) < 0xF;
|
||||
let asimdhp = bits_shift(aa64pfr0, 23, 20) >= 1;
|
||||
enable_feature(Feature::fp, fp);
|
||||
enable_feature(Feature::fp16, fphp);
|
||||
// SIMD support requires float support - if half-floats are
|
||||
// supported, it also requires half-float support:
|
||||
enable_feature(Feature::asimd, fp && asimd && (!fphp | asimdhp));
|
||||
// SIMD extensions require SIMD support:
|
||||
enable_feature(Feature::aes, asimd && bits_shift(aa64isar0, 7, 4) >= 1);
|
||||
let sha1 = bits_shift(aa64isar0, 11, 8) >= 1;
|
||||
let sha2 = bits_shift(aa64isar0, 15, 12) >= 1;
|
||||
enable_feature(Feature::sha2, asimd && sha1 && sha2);
|
||||
enable_feature(Feature::rdm, asimd && bits_shift(aa64isar0, 31, 28) >= 1);
|
||||
enable_feature(
|
||||
Feature::dotprod,
|
||||
asimd && bits_shift(aa64isar0, 47, 44) >= 1,
|
||||
);
|
||||
enable_feature(Feature::sve, asimd && bits_shift(aa64pfr0, 35, 32) >= 1);
|
||||
|
||||
let fp = bits_shift(aa64pfr0, 19, 16) < 0xF;
|
||||
let fphp = bits_shift(aa64pfr0, 19, 16) >= 1;
|
||||
let asimd = bits_shift(aa64pfr0, 23, 20) < 0xF;
|
||||
let asimdhp = bits_shift(aa64pfr0, 23, 20) >= 1;
|
||||
enable_feature(Feature::fp, fp);
|
||||
enable_feature(Feature::fp16, fphp);
|
||||
// SIMD support requires float support - if half-floats are
|
||||
// supported, it also requires half-float support:
|
||||
enable_feature(Feature::asimd, fp && asimd && (!fphp | asimdhp));
|
||||
// SIMD extensions require SIMD support:
|
||||
enable_feature(Feature::aes, asimd && bits_shift(aa64isar0, 7, 4) >= 1);
|
||||
let sha1 = bits_shift(aa64isar0, 11, 8) >= 1;
|
||||
let sha2 = bits_shift(aa64isar0, 15, 12) >= 1;
|
||||
enable_feature(Feature::sha2, asimd && sha1 && sha2);
|
||||
enable_feature(Feature::rdm, asimd && bits_shift(aa64isar0, 31, 28) >= 1);
|
||||
enable_feature(
|
||||
Feature::dotprod,
|
||||
asimd && bits_shift(aa64isar0, 47, 44) >= 1,
|
||||
);
|
||||
enable_feature(Feature::sve, asimd && bits_shift(aa64pfr0, 35, 32) >= 1);
|
||||
|
||||
// ID_AA64ISAR1_EL1 - Instruction Set Attribute Register 1
|
||||
let aa64isar1: u64;
|
||||
unsafe {
|
||||
asm!(
|
||||
"mrs {}, ID_AA64ISAR1_EL1",
|
||||
out(reg) aa64isar1,
|
||||
options(pure, nomem, preserves_flags, nostack)
|
||||
);
|
||||
}
|
||||
|
||||
// Check for either APA or API field
|
||||
enable_feature(Feature::paca, bits_shift(aa64isar1, 11, 4) >= 1);
|
||||
enable_feature(Feature::rcpc, bits_shift(aa64isar1, 23, 20) >= 1);
|
||||
// Check for either GPA or GPI field
|
||||
enable_feature(Feature::pacg, bits_shift(aa64isar1, 31, 24) >= 1);
|
||||
}
|
||||
// ID_AA64PFR0_EL1 - Processor Feature Register 0
|
||||
// Check for either APA or API field
|
||||
enable_feature(Feature::paca, bits_shift(aa64isar1, 11, 4) >= 1);
|
||||
enable_feature(Feature::rcpc, bits_shift(aa64isar1, 23, 20) >= 1);
|
||||
// Check for either GPA or GPI field
|
||||
enable_feature(Feature::pacg, bits_shift(aa64isar1, 31, 24) >= 1);
|
||||
|
||||
value
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue