diff --git a/lib/armv9a/src/lib.rs b/lib/armv9a/src/lib.rs index 6dd98daff1ff..46e34657f6d3 100644 --- a/lib/armv9a/src/lib.rs +++ b/lib/armv9a/src/lib.rs @@ -6,6 +6,7 @@ pub mod r#macro; pub mod regs; +pub use regs::pmu::*; pub use regs::*; pub use tock_registers::registers::InMemoryRegister; diff --git a/lib/armv9a/src/regs.rs b/lib/armv9a/src/regs.rs index b58931a3518b..7a01323a9d8f 100644 --- a/lib/armv9a/src/regs.rs +++ b/lib/armv9a/src/regs.rs @@ -6,6 +6,9 @@ mod macros; mod cptr_el2; mod id_aa64pfr1_el1; mod id_aa64zfr0_el1; +mod mdcr_el2; +mod pmcr_el0; +pub mod pmu; mod smcr_el2; mod svcr; mod zcr_el1; @@ -14,6 +17,8 @@ mod zcr_el2; pub use cptr_el2::CPTR_EL2; pub use id_aa64pfr1_el1::ID_AA64PFR1_SME_EL1; pub use id_aa64zfr0_el1::ID_AA64ZFR0_EL1; +pub use mdcr_el2::MDCR_EL2; +pub use pmcr_el0::PMCR_EL0; pub use smcr_el2::SMCR_EL2; pub use svcr::SVCR; pub use zcr_el1::ZCR_EL1; diff --git a/lib/armv9a/src/regs/mdcr_el2.rs b/lib/armv9a/src/regs/mdcr_el2.rs new file mode 100644 index 000000000000..9024b7f1b475 --- /dev/null +++ b/lib/armv9a/src/regs/mdcr_el2.rs @@ -0,0 +1,36 @@ +//! Realm Management Monitor Configuration Register - EL2 + +use tock_registers::{ + interfaces::{Readable, Writeable}, + register_bitfields, +}; + +register_bitfields! {u64, + pub MDCR_EL2 [ + MTPME OFFSET(28) NUMBITS(1) [], + HCCD OFFSET(23) NUMBITS(1) [], + HPMD OFFSET(17) NUMBITS(1) [], + TDA OFFSET(9) NUMBITS(1) [], + TPM OFFSET(6) NUMBITS(1) [], + TPMCR OFFSET(5) NUMBITS(1) [], + HPMN OFFSET(0) NUMBITS(5) [], + ] +} + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = MDCR_EL2::Register; + + sys_coproc_read_raw!(u64, "MDCR_EL2", "x"); +} + +impl Writeable for Reg { + type T = u64; + type R = MDCR_EL2::Register; + + sys_coproc_write_raw!(u64, "MDCR_EL2", "x"); +} + +pub const MDCR_EL2: Reg = Reg {}; diff --git a/lib/armv9a/src/regs/pmcr_el0.rs b/lib/armv9a/src/regs/pmcr_el0.rs new file mode 100644 index 000000000000..84374dc2bd30 --- /dev/null +++ b/lib/armv9a/src/regs/pmcr_el0.rs @@ -0,0 +1,39 @@ +//! Performance Monitors Control Register - EL0 + +use tock_registers::{ + interfaces::{Readable, Writeable}, + register_bitfields, +}; + +register_bitfields! {u64, + pub PMCR_EL0 [ + /// Number of event counters implemented + N OFFSET(11) NUMBITS(5) [], + LP OFFSET(7) NUMBITS(1) [], + LC OFFSET(6) NUMBITS(1) [], + DP OFFSET(5) NUMBITS(1) [], + X OFFSET(4) NUMBITS(1) [], + D OFFSET(3) NUMBITS(1) [], + C OFFSET(2) NUMBITS(1) [], + P OFFSET(1) NUMBITS(1) [], + E OFFSET(0) NUMBITS(1) [], + ] +} + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = PMCR_EL0::Register; + + sys_coproc_read_raw!(u64, "PMCR_EL0", "x"); +} + +impl Writeable for Reg { + type T = u64; + type R = PMCR_EL0::Register; + + sys_coproc_write_raw!(u64, "PMCR_EL0", "x"); +} + +pub const PMCR_EL0: Reg = Reg {}; diff --git a/lib/armv9a/src/regs/pmu.rs b/lib/armv9a/src/regs/pmu.rs new file mode 100644 index 000000000000..853e0a3982a1 --- /dev/null +++ b/lib/armv9a/src/regs/pmu.rs @@ -0,0 +1,180 @@ +#![allow(unused_imports)] +#![allow(unused_attributes)] + +use tock_registers::interfaces::{Readable, Writeable}; + +#[macro_export] +macro_rules! define_pmu_register { + ($mod_name:ident, $reg_name:ident, $reg_literal:tt) => { + pub mod $mod_name { + use tock_registers::interfaces::{Readable, Writeable}; + pub struct Reg; + + impl Readable for Reg { + type T = u64; + type R = (); + + sys_coproc_read_raw!(u64, $reg_literal, "x"); + } + + impl Writeable for Reg { + type T = u64; + type R = (); + + sys_coproc_write_raw!(u64, $reg_literal, "x"); + } + + pub const $reg_name: Reg = Reg {}; + } + }; +} + +define_pmu_register!(pmccfiltr_el0, PMCCFILTR_EL0, "PMCCFILTR_EL0"); +define_pmu_register!(pmccntr_el0, PMCCNTR_EL0, "PMCCNTR_EL0"); +define_pmu_register!(pmcntenset_el0, PMCNTENSET_EL0, "PMCNTENSET_EL0"); +define_pmu_register!(pmcntenclr_el0, PMCNTENCLR_EL0, "PMCNTENCLR_EL0"); +define_pmu_register!(pmintenset_el1, PMINTENSET_EL1, "PMINTENSET_EL1"); +define_pmu_register!(pmintenclr_el1, PMINTENCLR_EL1, "PMINTENCLR_EL1"); +define_pmu_register!(pmovsset_el0, PMOVSSET_EL0, "PMOVSSET_EL0"); +define_pmu_register!(pmovsclr_el0, PMOVSCLR_EL0, "PMOVSCLR_EL0"); +define_pmu_register!(pmselr_el0, PMSELR_EL0, "PMSELR_EL0"); +define_pmu_register!(pmuserenr_el0, PMUSERENR_EL0, "PMUSERENR_EL0"); +define_pmu_register!(pmxevcntr_el0, PMXEVCNTR_EL0, "PMXEVCNTR_EL0"); +define_pmu_register!(pmxevtyper_el0, PMXEVTYPER_EL0, "PMXEVTYPER_EL0"); +define_pmu_register!(pmevcntr0_el0, PMEVCNTR0_EL0, "PMEVCNTR0_EL0"); +define_pmu_register!(pmevcntr1_el0, PMEVCNTR1_EL0, "PMEVCNTR1_EL0"); +define_pmu_register!(pmevcntr2_el0, PMEVCNTR2_EL0, "PMEVCNTR2_EL0"); +define_pmu_register!(pmevcntr3_el0, PMEVCNTR3_EL0, "PMEVCNTR3_EL0"); +define_pmu_register!(pmevcntr4_el0, PMEVCNTR4_EL0, "PMEVCNTR4_EL0"); +define_pmu_register!(pmevcntr5_el0, PMEVCNTR5_EL0, "PMEVCNTR5_EL0"); +define_pmu_register!(pmevcntr6_el0, PMEVCNTR6_EL0, "PMEVCNTR6_EL0"); +define_pmu_register!(pmevcntr7_el0, PMEVCNTR7_EL0, "PMEVCNTR7_EL0"); +define_pmu_register!(pmevcntr8_el0, PMEVCNTR8_EL0, "PMEVCNTR8_EL0"); +define_pmu_register!(pmevcntr9_el0, PMEVCNTR9_EL0, "PMEVCNTR9_EL0"); +define_pmu_register!(pmevcntr10_el0, PMEVCNTR10_EL0, "PMEVCNTR10_EL0"); +define_pmu_register!(pmevcntr11_el0, PMEVCNTR11_EL0, "PMEVCNTR11_EL0"); +define_pmu_register!(pmevcntr12_el0, PMEVCNTR12_EL0, "PMEVCNTR12_EL0"); +define_pmu_register!(pmevcntr13_el0, PMEVCNTR13_EL0, "PMEVCNTR13_EL0"); +define_pmu_register!(pmevcntr14_el0, PMEVCNTR14_EL0, "PMEVCNTR14_EL0"); +define_pmu_register!(pmevcntr15_el0, PMEVCNTR15_EL0, "PMEVCNTR15_EL0"); +define_pmu_register!(pmevcntr16_el0, PMEVCNTR16_EL0, "PMEVCNTR16_EL0"); +define_pmu_register!(pmevcntr17_el0, PMEVCNTR17_EL0, "PMEVCNTR17_EL0"); +define_pmu_register!(pmevcntr18_el0, PMEVCNTR18_EL0, "PMEVCNTR18_EL0"); +define_pmu_register!(pmevcntr19_el0, PMEVCNTR19_EL0, "PMEVCNTR19_EL0"); +define_pmu_register!(pmevcntr20_el0, PMEVCNTR20_EL0, "PMEVCNTR20_EL0"); +define_pmu_register!(pmevcntr21_el0, PMEVCNTR21_EL0, "PMEVCNTR21_EL0"); +define_pmu_register!(pmevcntr22_el0, PMEVCNTR22_EL0, "PMEVCNTR22_EL0"); +define_pmu_register!(pmevcntr23_el0, PMEVCNTR23_EL0, "PMEVCNTR23_EL0"); +define_pmu_register!(pmevcntr24_el0, PMEVCNTR24_EL0, "PMEVCNTR24_EL0"); +define_pmu_register!(pmevcntr25_el0, PMEVCNTR25_EL0, "PMEVCNTR25_EL0"); +define_pmu_register!(pmevcntr26_el0, PMEVCNTR26_EL0, "PMEVCNTR26_EL0"); +define_pmu_register!(pmevcntr27_el0, PMEVCNTR27_EL0, "PMEVCNTR27_EL0"); +define_pmu_register!(pmevcntr28_el0, PMEVCNTR28_EL0, "PMEVCNTR28_EL0"); +define_pmu_register!(pmevcntr29_el0, PMEVCNTR29_EL0, "PMEVCNTR29_EL0"); +define_pmu_register!(pmevcntr30_el0, PMEVCNTR30_EL0, "PMEVCNTR30_EL0"); +define_pmu_register!(pmevtyper0_el0, PMEVTYPER0_EL0, "PMEVTYPER0_EL0"); +define_pmu_register!(pmevtyper1_el0, PMEVTYPER1_EL0, "PMEVTYPER1_EL0"); +define_pmu_register!(pmevtyper2_el0, PMEVTYPER2_EL0, "PMEVTYPER2_EL0"); +define_pmu_register!(pmevtyper3_el0, PMEVTYPER3_EL0, "PMEVTYPER3_EL0"); +define_pmu_register!(pmevtyper4_el0, PMEVTYPER4_EL0, "PMEVTYPER4_EL0"); +define_pmu_register!(pmevtyper5_el0, PMEVTYPER5_EL0, "PMEVTYPER5_EL0"); +define_pmu_register!(pmevtyper6_el0, PMEVTYPER6_EL0, "PMEVTYPER6_EL0"); +define_pmu_register!(pmevtyper7_el0, PMEVTYPER7_EL0, "PMEVTYPER7_EL0"); +define_pmu_register!(pmevtyper8_el0, PMEVTYPER8_EL0, "PMEVTYPER8_EL0"); +define_pmu_register!(pmevtyper9_el0, PMEVTYPER9_EL0, "PMEVTYPER9_EL0"); +define_pmu_register!(pmevtyper10_el0, PMEVTYPER10_EL0, "PMEVTYPER10_EL0"); +define_pmu_register!(pmevtyper11_el0, PMEVTYPER11_EL0, "PMEVTYPER11_EL0"); +define_pmu_register!(pmevtyper12_el0, PMEVTYPER12_EL0, "PMEVTYPER12_EL0"); +define_pmu_register!(pmevtyper13_el0, PMEVTYPER13_EL0, "PMEVTYPER13_EL0"); +define_pmu_register!(pmevtyper14_el0, PMEVTYPER14_EL0, "PMEVTYPER14_EL0"); +define_pmu_register!(pmevtyper15_el0, PMEVTYPER15_EL0, "PMEVTYPER15_EL0"); +define_pmu_register!(pmevtyper16_el0, PMEVTYPER16_EL0, "PMEVTYPER16_EL0"); +define_pmu_register!(pmevtyper17_el0, PMEVTYPER17_EL0, "PMEVTYPER17_EL0"); +define_pmu_register!(pmevtyper18_el0, PMEVTYPER18_EL0, "PMEVTYPER18_EL0"); +define_pmu_register!(pmevtyper19_el0, PMEVTYPER19_EL0, "PMEVTYPER19_EL0"); +define_pmu_register!(pmevtyper20_el0, PMEVTYPER20_EL0, "PMEVTYPER20_EL0"); +define_pmu_register!(pmevtyper21_el0, PMEVTYPER21_EL0, "PMEVTYPER21_EL0"); +define_pmu_register!(pmevtyper22_el0, PMEVTYPER22_EL0, "PMEVTYPER22_EL0"); +define_pmu_register!(pmevtyper23_el0, PMEVTYPER23_EL0, "PMEVTYPER23_EL0"); +define_pmu_register!(pmevtyper24_el0, PMEVTYPER24_EL0, "PMEVTYPER24_EL0"); +define_pmu_register!(pmevtyper25_el0, PMEVTYPER25_EL0, "PMEVTYPER25_EL0"); +define_pmu_register!(pmevtyper26_el0, PMEVTYPER26_EL0, "PMEVTYPER26_EL0"); +define_pmu_register!(pmevtyper27_el0, PMEVTYPER27_EL0, "PMEVTYPER27_EL0"); +define_pmu_register!(pmevtyper28_el0, PMEVTYPER28_EL0, "PMEVTYPER28_EL0"); +define_pmu_register!(pmevtyper29_el0, PMEVTYPER29_EL0, "PMEVTYPER29_EL0"); +define_pmu_register!(pmevtyper30_el0, PMEVTYPER30_EL0, "PMEVTYPER30_EL0"); + +pub use pmccfiltr_el0::PMCCFILTR_EL0; +pub use pmccntr_el0::PMCCNTR_EL0; +pub use pmcntenclr_el0::PMCNTENCLR_EL0; +pub use pmcntenset_el0::PMCNTENSET_EL0; +pub use pmevcntr0_el0::PMEVCNTR0_EL0; +pub use pmevcntr10_el0::PMEVCNTR10_EL0; +pub use pmevcntr11_el0::PMEVCNTR11_EL0; +pub use pmevcntr12_el0::PMEVCNTR12_EL0; +pub use pmevcntr13_el0::PMEVCNTR13_EL0; +pub use pmevcntr14_el0::PMEVCNTR14_EL0; +pub use pmevcntr15_el0::PMEVCNTR15_EL0; +pub use pmevcntr16_el0::PMEVCNTR16_EL0; +pub use pmevcntr17_el0::PMEVCNTR17_EL0; +pub use pmevcntr18_el0::PMEVCNTR18_EL0; +pub use pmevcntr19_el0::PMEVCNTR19_EL0; +pub use pmevcntr1_el0::PMEVCNTR1_EL0; +pub use pmevcntr20_el0::PMEVCNTR20_EL0; +pub use pmevcntr21_el0::PMEVCNTR21_EL0; +pub use pmevcntr22_el0::PMEVCNTR22_EL0; +pub use pmevcntr23_el0::PMEVCNTR23_EL0; +pub use pmevcntr24_el0::PMEVCNTR24_EL0; +pub use pmevcntr25_el0::PMEVCNTR25_EL0; +pub use pmevcntr26_el0::PMEVCNTR26_EL0; +pub use pmevcntr27_el0::PMEVCNTR27_EL0; +pub use pmevcntr28_el0::PMEVCNTR28_EL0; +pub use pmevcntr29_el0::PMEVCNTR29_EL0; +pub use pmevcntr2_el0::PMEVCNTR2_EL0; +pub use pmevcntr30_el0::PMEVCNTR30_EL0; +pub use pmevcntr3_el0::PMEVCNTR3_EL0; +pub use pmevcntr4_el0::PMEVCNTR4_EL0; +pub use pmevcntr5_el0::PMEVCNTR5_EL0; +pub use pmevcntr6_el0::PMEVCNTR6_EL0; +pub use pmevcntr7_el0::PMEVCNTR7_EL0; +pub use pmevcntr8_el0::PMEVCNTR8_EL0; +pub use pmevcntr9_el0::PMEVCNTR9_EL0; +pub use pmevtyper0_el0::PMEVTYPER0_EL0; +pub use pmevtyper10_el0::PMEVTYPER10_EL0; +pub use pmevtyper11_el0::PMEVTYPER11_EL0; +pub use pmevtyper12_el0::PMEVTYPER12_EL0; +pub use pmevtyper13_el0::PMEVTYPER13_EL0; +pub use pmevtyper14_el0::PMEVTYPER14_EL0; +pub use pmevtyper15_el0::PMEVTYPER15_EL0; +pub use pmevtyper16_el0::PMEVTYPER16_EL0; +pub use pmevtyper17_el0::PMEVTYPER17_EL0; +pub use pmevtyper18_el0::PMEVTYPER18_EL0; +pub use pmevtyper19_el0::PMEVTYPER19_EL0; +pub use pmevtyper1_el0::PMEVTYPER1_EL0; +pub use pmevtyper20_el0::PMEVTYPER20_EL0; +pub use pmevtyper21_el0::PMEVTYPER21_EL0; +pub use pmevtyper22_el0::PMEVTYPER22_EL0; +pub use pmevtyper23_el0::PMEVTYPER23_EL0; +pub use pmevtyper24_el0::PMEVTYPER24_EL0; +pub use pmevtyper25_el0::PMEVTYPER25_EL0; +pub use pmevtyper26_el0::PMEVTYPER26_EL0; +pub use pmevtyper27_el0::PMEVTYPER27_EL0; +pub use pmevtyper28_el0::PMEVTYPER28_EL0; +pub use pmevtyper29_el0::PMEVTYPER29_EL0; +pub use pmevtyper2_el0::PMEVTYPER2_EL0; +pub use pmevtyper30_el0::PMEVTYPER30_EL0; +pub use pmevtyper3_el0::PMEVTYPER3_EL0; +pub use pmevtyper4_el0::PMEVTYPER4_EL0; +pub use pmevtyper5_el0::PMEVTYPER5_EL0; +pub use pmevtyper6_el0::PMEVTYPER6_EL0; +pub use pmevtyper7_el0::PMEVTYPER7_EL0; +pub use pmevtyper8_el0::PMEVTYPER8_EL0; +pub use pmevtyper9_el0::PMEVTYPER9_EL0; +pub use pmintenclr_el1::PMINTENCLR_EL1; +pub use pmintenset_el1::PMINTENSET_EL1; +pub use pmovsclr_el0::PMOVSCLR_EL0; +pub use pmovsset_el0::PMOVSSET_EL0; +pub use pmselr_el0::PMSELR_EL0; +pub use pmuserenr_el0::PMUSERENR_EL0; +pub use pmxevcntr_el0::PMXEVCNTR_EL0; +pub use pmxevtyper_el0::PMXEVTYPER_EL0; diff --git a/lib/armv9a/src/regs/smcr_el2.rs b/lib/armv9a/src/regs/smcr_el2.rs index 489995d1d3c1..59567e0c840e 100644 --- a/lib/armv9a/src/regs/smcr_el2.rs +++ b/lib/armv9a/src/regs/smcr_el2.rs @@ -1,4 +1,4 @@ -//! Realm Management Monitor Configuration Register - EL2 +//! SME Control Register - EL2 use tock_registers::{ interfaces::{Readable, Writeable}, @@ -24,14 +24,18 @@ impl Readable for Reg { type T = u64; type R = SMCR_EL2::Register; - sys_coproc_read_raw!(u64, "SMCR_EL2", "x"); + // Use the opcode instead of its register mnemonic + // to pass compilation without SIMD(neon, sve, sme) features in the compile option + //sys_coproc_read_raw!(u64, "SMCR_EL2", "x"); + sys_coproc_read_raw!(u64, "S3_4_C1_C2_6", "x"); } impl Writeable for Reg { type T = u64; type R = SMCR_EL2::Register; - sys_coproc_write_raw!(u64, "SMCR_EL2", "x"); + //sys_coproc_write_raw!(u64, "SMCR_EL2", "x"); + sys_coproc_write_raw!(u64, "S3_4_C1_C2_6", "x"); } pub const SMCR_EL2: Reg = Reg {}; diff --git a/lib/armv9a/src/regs/svcr.rs b/lib/armv9a/src/regs/svcr.rs index ce8e7f9016e4..83affa119f60 100644 --- a/lib/armv9a/src/regs/svcr.rs +++ b/lib/armv9a/src/regs/svcr.rs @@ -1,9 +1,6 @@ -// SPDX-License-Identifier: Apache-2.0 OR MIT -// - -//! AArch64 Processor Feature Register 1 - EL1 +//! Streaming Vector Control Register //! -//! Provides additional information about implemented PE features in AArch64 state. +//! Controls Streaming SVE mode and SME behavior. use tock_registers::{ interfaces::{Readable, Writeable}, @@ -25,13 +22,17 @@ impl Readable for Reg { type T = u64; type R = SVCR::Register; - sys_coproc_read_raw!(u64, "SVCR", "x"); + // Use the opcode instead of its register mnemonic + // to pass compilation without SIMD(neon, sve, sme) features in the compile option + //sys_coproc_read_raw!(u64, "SVCR", "x"); + sys_coproc_read_raw!(u64, "S3_3_C4_C2_2", "x"); } impl Writeable for Reg { type T = u64; type R = SVCR::Register; - sys_coproc_write_raw!(u64, "SVCR", "x"); + //sys_coproc_write_raw!(u64, "SVCR", "x"); + sys_coproc_write_raw!(u64, "S3_3_C4_C2_2", "x"); } pub const SVCR: Reg = Reg {}; diff --git a/plat/.cargo/config.toml b/plat/.cargo/config.toml index fc4b71e95924..c22d5f3803a0 100644 --- a/plat/.cargo/config.toml +++ b/plat/.cargo/config.toml @@ -4,6 +4,5 @@ target = "aarch64-unknown-none-softfloat" [target.aarch64-unknown-none-softfloat] rustflags = [ "-C", "target-feature=+ecv", - "-C", "target-feature=+sme", "-C", "target-feature=+tlb-rmi" ] diff --git a/rmm/src/exception/lower/synchronous/sys_reg.rs b/rmm/src/exception/lower/synchronous/sys_reg.rs index 3db4e919ee37..55f834dbb9ef 100644 --- a/rmm/src/exception/lower/synchronous/sys_reg.rs +++ b/rmm/src/exception/lower/synchronous/sys_reg.rs @@ -49,11 +49,7 @@ fn handle_sysreg_id(rec: &mut Rec<'_>, esr: u64) -> u64 { return trap::RET_TO_REC; } - let idreg = esr.get_masked(ISS::Op0) - | esr.get_masked(ISS::Op1) - | esr.get_masked(ISS::CRn) - | esr.get_masked(ISS::CRm) - | esr.get_masked(ISS::Op2); + let idreg = esr.get_masked(ISS::Op0 | ISS::Op1 | ISS::CRn | ISS::CRm | ISS::Op2); let mut mask: u64 = match idreg as u32 { ISS_ID_AA64PFR0_EL1 => { @@ -79,7 +75,6 @@ fn handle_sysreg_id(rec: &mut Rec<'_>, esr: u64) -> u64 { + (ID_AA64DFR0_EL1::CTX_CMPs.mask << ID_AA64DFR0_EL1::CTX_CMPs.shift) + (ID_AA64DFR0_EL1::WRPs.mask << ID_AA64DFR0_EL1::WRPs.shift) + (ID_AA64DFR0_EL1::BRPs.mask << ID_AA64DFR0_EL1::BRPs.shift) - + (ID_AA64DFR0_EL1::PMUVer.mask << ID_AA64DFR0_EL1::PMUVer.shift) + (ID_AA64DFR0_EL1::TraceVer.mask << ID_AA64DFR0_EL1::TraceVer.shift) + (ID_AA64DFR0_EL1::DebugVer.mask << ID_AA64DFR0_EL1::DebugVer.shift) } diff --git a/rmm/src/lib.rs b/rmm/src/lib.rs index b2db8580cf4f..328544883b7d 100755 --- a/rmm/src/lib.rs +++ b/rmm/src/lib.rs @@ -21,6 +21,7 @@ pub mod logger; pub mod mm; #[cfg(not(any(test, kani, miri, fuzzing)))] pub mod panic; +pub mod pmu; pub mod realm; pub mod rec; pub mod rmi; @@ -60,6 +61,7 @@ use crate::monitor::Monitor; use crate::rmm_el3::setup_el3_ifc; use aarch64_cpu::registers::*; +use armv9a::{MDCR_EL2, PMCR_EL0}; use core::ptr::addr_of; #[cfg(not(kani))] @@ -133,6 +135,15 @@ unsafe fn setup_el2() { + ICC_SRE_EL2::DFB::SET + ICC_SRE_EL2::SRE::SET, ); + MDCR_EL2.write( + MDCR_EL2::MTPME::SET + + MDCR_EL2::HCCD::SET + + MDCR_EL2::HPMD::SET + + MDCR_EL2::TDA::SET + + MDCR_EL2::TPM::SET + + MDCR_EL2::TPMCR::SET + + MDCR_EL2::HPMN.val(PMCR_EL0.read(PMCR_EL0::N)), + ); } /// # Safety diff --git a/rmm/src/pmu.rs b/rmm/src/pmu.rs new file mode 100644 index 000000000000..65677b444050 --- /dev/null +++ b/rmm/src/pmu.rs @@ -0,0 +1,321 @@ +use aarch64_cpu::registers::*; +use armv9a::regs::pmu::*; +use armv9a::PMCR_EL0; + +pub const MAX_EVCNT: usize = 31; + +#[allow(non_upper_case_globals)] +const FEAT_PMUv3p7: u64 = 7; +// ID_AA64DFR0_EL1 +// HPMN0, bits [63:60] : +// Zero PMU event counters for a Guest operating system. +const HPMN0_MASK: u64 = 0xF << 60; + +pub fn pmu_present() -> bool { + trace!( + "PMUVer: v3p{:?}", + ID_AA64DFR0_EL1.read(ID_AA64DFR0_EL1::PMUVer) + ); + ID_AA64DFR0_EL1.read(ID_AA64DFR0_EL1::PMUVer) >= FEAT_PMUv3p7 +} + +pub fn hpmn0_present() -> bool { + trace!( + "FEAT_HPMN0: {:?}", + (ID_AA64DFR0_EL1.get() & HPMN0_MASK) >> 60 + ); + ID_AA64DFR0_EL1.get() & HPMN0_MASK != 0 +} + +pub fn pmu_num_ctrs() -> u64 { + trace!("PMU # counters: {:?}", PMCR_EL0.read(PMCR_EL0::N)); + PMCR_EL0.read(PMCR_EL0::N) +} + +fn store_pmev(n: usize, pmevcntr_el0: &mut [u64; MAX_EVCNT], pmevtyper_el0: &mut [u64; MAX_EVCNT]) { + match n { + 0 => { + pmevcntr_el0[0] = PMEVCNTR0_EL0.get(); + pmevtyper_el0[0] = PMEVTYPER0_EL0.get(); + } + 1 => { + pmevcntr_el0[1] = PMEVCNTR1_EL0.get(); + pmevtyper_el0[1] = PMEVTYPER1_EL0.get(); + } + 2 => { + pmevcntr_el0[2] = PMEVCNTR2_EL0.get(); + pmevtyper_el0[2] = PMEVTYPER2_EL0.get(); + } + 3 => { + pmevcntr_el0[3] = PMEVCNTR3_EL0.get(); + pmevtyper_el0[3] = PMEVTYPER3_EL0.get(); + } + 4 => { + pmevcntr_el0[4] = PMEVCNTR4_EL0.get(); + pmevtyper_el0[4] = PMEVTYPER4_EL0.get(); + } + 5 => { + pmevcntr_el0[5] = PMEVCNTR5_EL0.get(); + pmevtyper_el0[5] = PMEVTYPER5_EL0.get(); + } + 6 => { + pmevcntr_el0[6] = PMEVCNTR6_EL0.get(); + pmevtyper_el0[6] = PMEVTYPER6_EL0.get(); + } + 7 => { + pmevcntr_el0[7] = PMEVCNTR7_EL0.get(); + pmevtyper_el0[7] = PMEVTYPER7_EL0.get(); + } + 8 => { + pmevcntr_el0[8] = PMEVCNTR8_EL0.get(); + pmevtyper_el0[8] = PMEVTYPER8_EL0.get(); + } + 9 => { + pmevcntr_el0[9] = PMEVCNTR9_EL0.get(); + pmevtyper_el0[9] = PMEVTYPER9_EL0.get(); + } + 10 => { + pmevcntr_el0[10] = PMEVCNTR10_EL0.get(); + pmevtyper_el0[10] = PMEVTYPER10_EL0.get(); + } + 11 => { + pmevcntr_el0[11] = PMEVCNTR11_EL0.get(); + pmevtyper_el0[11] = PMEVTYPER11_EL0.get(); + } + 12 => { + pmevcntr_el0[12] = PMEVCNTR12_EL0.get(); + pmevtyper_el0[12] = PMEVTYPER12_EL0.get(); + } + 13 => { + pmevcntr_el0[13] = PMEVCNTR13_EL0.get(); + pmevtyper_el0[13] = PMEVTYPER13_EL0.get(); + } + 14 => { + pmevcntr_el0[14] = PMEVCNTR14_EL0.get(); + pmevtyper_el0[14] = PMEVTYPER14_EL0.get(); + } + 15 => { + pmevcntr_el0[15] = PMEVCNTR15_EL0.get(); + pmevtyper_el0[15] = PMEVTYPER15_EL0.get(); + } + 16 => { + pmevcntr_el0[16] = PMEVCNTR16_EL0.get(); + pmevtyper_el0[16] = PMEVTYPER16_EL0.get(); + } + 17 => { + pmevcntr_el0[17] = PMEVCNTR17_EL0.get(); + pmevtyper_el0[17] = PMEVTYPER17_EL0.get(); + } + 18 => { + pmevcntr_el0[18] = PMEVCNTR18_EL0.get(); + pmevtyper_el0[18] = PMEVTYPER18_EL0.get(); + } + 19 => { + pmevcntr_el0[19] = PMEVCNTR19_EL0.get(); + pmevtyper_el0[19] = PMEVTYPER19_EL0.get(); + } + 20 => { + pmevcntr_el0[20] = PMEVCNTR20_EL0.get(); + pmevtyper_el0[20] = PMEVTYPER20_EL0.get(); + } + 21 => { + pmevcntr_el0[21] = PMEVCNTR21_EL0.get(); + pmevtyper_el0[21] = PMEVTYPER21_EL0.get(); + } + 22 => { + pmevcntr_el0[22] = PMEVCNTR22_EL0.get(); + pmevtyper_el0[22] = PMEVTYPER22_EL0.get(); + } + 23 => { + pmevcntr_el0[23] = PMEVCNTR23_EL0.get(); + pmevtyper_el0[23] = PMEVTYPER23_EL0.get(); + } + 24 => { + pmevcntr_el0[24] = PMEVCNTR24_EL0.get(); + pmevtyper_el0[24] = PMEVTYPER24_EL0.get(); + } + 25 => { + pmevcntr_el0[25] = PMEVCNTR25_EL0.get(); + pmevtyper_el0[25] = PMEVTYPER25_EL0.get(); + } + 26 => { + pmevcntr_el0[26] = PMEVCNTR26_EL0.get(); + pmevtyper_el0[26] = PMEVTYPER26_EL0.get(); + } + 27 => { + pmevcntr_el0[27] = PMEVCNTR27_EL0.get(); + pmevtyper_el0[27] = PMEVTYPER27_EL0.get(); + } + 28 => { + pmevcntr_el0[28] = PMEVCNTR28_EL0.get(); + pmevtyper_el0[28] = PMEVTYPER28_EL0.get(); + } + 29 => { + pmevcntr_el0[29] = PMEVCNTR29_EL0.get(); + pmevtyper_el0[29] = PMEVTYPER29_EL0.get(); + } + 30 => { + pmevcntr_el0[30] = PMEVCNTR30_EL0.get(); + pmevtyper_el0[30] = PMEVTYPER30_EL0.get(); + } + _ => warn!("Invalid PMEV index"), + } +} + +fn load_pmev(n: usize, cntr_val: u64, typer_val: u64) { + match n { + 0 => { + PMEVCNTR0_EL0.set(cntr_val); + PMEVTYPER0_EL0.set(typer_val); + } + 1 => { + PMEVCNTR1_EL0.set(cntr_val); + PMEVTYPER1_EL0.set(typer_val); + } + 2 => { + PMEVCNTR2_EL0.set(cntr_val); + PMEVTYPER2_EL0.set(typer_val); + } + 3 => { + PMEVCNTR3_EL0.set(cntr_val); + PMEVTYPER3_EL0.set(typer_val); + } + 4 => { + PMEVCNTR4_EL0.set(cntr_val); + PMEVTYPER4_EL0.set(typer_val); + } + 5 => { + PMEVCNTR5_EL0.set(cntr_val); + PMEVTYPER5_EL0.set(typer_val); + } + 6 => { + PMEVCNTR6_EL0.set(cntr_val); + PMEVTYPER6_EL0.set(typer_val); + } + 7 => { + PMEVCNTR7_EL0.set(cntr_val); + PMEVTYPER7_EL0.set(typer_val); + } + 8 => { + PMEVCNTR8_EL0.set(cntr_val); + PMEVTYPER8_EL0.set(typer_val); + } + 9 => { + PMEVCNTR9_EL0.set(cntr_val); + PMEVTYPER9_EL0.set(typer_val); + } + 10 => { + PMEVCNTR10_EL0.set(cntr_val); + PMEVTYPER10_EL0.set(typer_val); + } + 11 => { + PMEVCNTR11_EL0.set(cntr_val); + PMEVTYPER11_EL0.set(typer_val); + } + 12 => { + PMEVCNTR12_EL0.set(cntr_val); + PMEVTYPER12_EL0.set(typer_val); + } + 13 => { + PMEVCNTR13_EL0.set(cntr_val); + PMEVTYPER13_EL0.set(typer_val); + } + 14 => { + PMEVCNTR14_EL0.set(cntr_val); + PMEVTYPER14_EL0.set(typer_val); + } + 15 => { + PMEVCNTR15_EL0.set(cntr_val); + PMEVTYPER15_EL0.set(typer_val); + } + 16 => { + PMEVCNTR16_EL0.set(cntr_val); + PMEVTYPER16_EL0.set(typer_val); + } + 17 => { + PMEVCNTR17_EL0.set(cntr_val); + PMEVTYPER17_EL0.set(typer_val); + } + 18 => { + PMEVCNTR18_EL0.set(cntr_val); + PMEVTYPER18_EL0.set(typer_val); + } + 19 => { + PMEVCNTR19_EL0.set(cntr_val); + PMEVTYPER19_EL0.set(typer_val); + } + 20 => { + PMEVCNTR20_EL0.set(cntr_val); + PMEVTYPER20_EL0.set(typer_val); + } + 21 => { + PMEVCNTR21_EL0.set(cntr_val); + PMEVTYPER21_EL0.set(typer_val); + } + 22 => { + PMEVCNTR22_EL0.set(cntr_val); + PMEVTYPER22_EL0.set(typer_val); + } + 23 => { + PMEVCNTR23_EL0.set(cntr_val); + PMEVTYPER23_EL0.set(typer_val); + } + 24 => { + PMEVCNTR24_EL0.set(cntr_val); + PMEVTYPER24_EL0.set(typer_val); + } + 25 => { + PMEVCNTR25_EL0.set(cntr_val); + PMEVTYPER25_EL0.set(typer_val); + } + 26 => { + PMEVCNTR26_EL0.set(cntr_val); + PMEVTYPER26_EL0.set(typer_val); + } + 27 => { + PMEVCNTR27_EL0.set(cntr_val); + PMEVTYPER27_EL0.set(typer_val); + } + 28 => { + PMEVCNTR28_EL0.set(cntr_val); + PMEVTYPER28_EL0.set(typer_val); + } + 29 => { + PMEVCNTR29_EL0.set(cntr_val); + PMEVTYPER29_EL0.set(typer_val); + } + 30 => { + PMEVCNTR30_EL0.set(cntr_val); + PMEVTYPER30_EL0.set(typer_val); + } + _ => warn!("Invalid PMEV index"), + } +} + +pub fn set_pmev_regs( + cnt: usize, + pmevcntr_el0: &[u64; MAX_EVCNT], + pmevtyper_el0: &[u64; MAX_EVCNT], +) { + if cnt > MAX_EVCNT { + error!("Index out of bounds"); + return; + } + for i in 0..cnt { + load_pmev(i, pmevcntr_el0[i], pmevtyper_el0[i]); + } +} + +pub fn get_pmev_regs( + cnt: usize, + pmevcntr_el0: &mut [u64; MAX_EVCNT], + pmevtyper_el0: &mut [u64; MAX_EVCNT], +) { + if cnt > MAX_EVCNT { + error!("Index out of bounds"); + return; + } + for i in 0..cnt { + store_pmev(i, pmevcntr_el0, pmevtyper_el0); + } +} diff --git a/rmm/src/realm/rd.rs b/rmm/src/realm/rd.rs index 66dad5b85090..61f3557a13b1 100644 --- a/rmm/src/realm/rd.rs +++ b/rmm/src/realm/rd.rs @@ -37,6 +37,8 @@ pub struct Rd { pub vcpu_index: usize, metadata: Option, simd_cfg: SimdConfig, + pmu_en: bool, + pmu_num_ctrs: usize, } impl Rd { @@ -51,6 +53,8 @@ impl Rd { rpv: [u8; 64], sve_en: bool, sve_vl: u64, + pmu_en: bool, + pmu_num_ctrs: usize, ) { self.vmid = vmid; self.state = State::New; @@ -64,9 +68,13 @@ impl Rd { self.rpv.copy_from_slice(rpv.as_slice()); self.metadata = None; self.simd_cfg.sve_en = sve_en; + self.pmu_en = pmu_en; if sve_en { self.simd_cfg.sve_vq = sve_vl; } + if pmu_en { + self.pmu_num_ctrs = pmu_num_ctrs; + } self.num_recs = 0; } @@ -106,6 +114,10 @@ impl Rd { self.ipa_bits } + pub fn pmu_config(&self) -> (bool, usize) { + (self.pmu_en, self.pmu_num_ctrs) + } + pub fn rec_index(&self) -> usize { self.rec_index } diff --git a/rmm/src/rec/context.rs b/rmm/src/rec/context.rs index 55d97bb33709..6a2207dffe16 100644 --- a/rmm/src/rec/context.rs +++ b/rmm/src/rec/context.rs @@ -1,6 +1,8 @@ use super::gic; use super::pauth; use super::pauth::PauthRegister; +use super::pmu; +use super::pmu::PmuRegister; use super::simd; use super::simd::SimdContext; use super::timer; @@ -16,10 +18,12 @@ pub struct Context { pub elr_el2: u64, pub spsr_el2: u64, pub sys_regs: SystemRegister, + pub mdcr_el2: u64, pub gic_state: GICRegister, pub timer: TimerRegister, pub simd: SimdContext, pub pauth: PauthRegister, + pub pmu: PmuRegister, } pub struct RegOffset; @@ -87,6 +91,7 @@ impl Context { TPIDR_EL2.set(rec as *const _ as u64); gic::restore_state(rec); pauth::restore_state(rec); + pmu::restore_state(rec); #[cfg(not(fuzzing))] timer::restore_state(rec); #[cfg(not(any(test, miri, fuzzing)))] @@ -102,6 +107,7 @@ impl Context { pub unsafe fn from_current(rec: &mut Rec<'_>) { gic::save_state(rec); pauth::save_state(rec); + pmu::save_state(rec); #[cfg(not(fuzzing))] timer::save_state(rec); #[cfg(not(any(test, miri, fuzzing)))] diff --git a/rmm/src/rec/mod.rs b/rmm/src/rec/mod.rs index fed42794d028..b8e7dde85afc 100644 --- a/rmm/src/rec/mod.rs +++ b/rmm/src/rec/mod.rs @@ -2,6 +2,7 @@ pub mod context; pub mod gic; pub mod mmio; pub mod pauth; +pub mod pmu; pub mod sea; pub mod simd; pub mod timer; @@ -133,6 +134,7 @@ impl Rec<'_> { self.context.sys_regs.vmpidr = vmpidr; self.aux.copy_from_slice(&aux); pauth::init_pauth(self); + pmu::init_pmu(self); timer::init_timer(self); gic::init_gic(self); simd::init_simd(self)?; @@ -285,6 +287,11 @@ impl Rec<'_> { Ok(owner.ipa_bits()) } + pub fn pmu_config(&self) -> Result<(bool, usize), Error> { + let owner = self.get_owner()?; + Ok(owner.pmu_config()) + } + pub fn from_current(&mut self) { unsafe { Context::from_current(self); diff --git a/rmm/src/rec/pmu.rs b/rmm/src/rec/pmu.rs new file mode 100644 index 000000000000..9b2d605ba5e5 --- /dev/null +++ b/rmm/src/rec/pmu.rs @@ -0,0 +1,158 @@ +use super::Rec; +use crate::pmu::*; + +use core::array::from_fn; +use lazy_static::lazy_static; +use spin::mutex::Mutex; + +use aarch64_cpu::registers::*; +use armv9a::regs::pmu::*; +use armv9a::{MDCR_EL2, PMCR_EL0}; + +use crate::config::NUM_OF_CPU; +use crate::cpu::get_cpu_id; +use crate::rmi::error::Error; +use crate::rmi::rec::run::Run; + +#[repr(C)] +#[derive(Default, Debug)] +pub struct PmuRegister { + pub pmcr_el0: u64, + pub pmccfiltr_el0: u64, + pub pmccntr_el0: u64, + pub pmcntenset_el0: u64, + pub pmcntenclr_el0: u64, + pub pmintenset_el1: u64, + pub pmintenclr_el1: u64, + pub pmovsset_el0: u64, + pub pmovsclr_el0: u64, + pub pmselr_el0: u64, + pub pmuserenr_el0: u64, + pub pmxevcntr_el0: u64, + pub pmxevtyper_el0: u64, + pub pmevcntr_el0: [u64; MAX_EVCNT], + pub pmevtyper_el0: [u64; MAX_EVCNT], +} + +lazy_static! { + static ref NS_PMU: [Mutex; NUM_OF_CPU] = + from_fn(|_| Mutex::new(PmuRegister::default())); +} + +const CLEAR_MASK: u64 = 0x1_FFFF_FFFF; + +pub fn init_pmu(rec: &mut Rec<'_>) { + let (pmu_enabled, pmu_num_ctrs) = rec.pmu_config().expect("REASON"); + #[cfg(not(any(miri, test, fuzzing)))] + let mdcr_el2 = MDCR_EL2.get(); + #[cfg(any(miri, test, fuzzing))] + let mdcr_el2 = 0; + let mask: u64 = MDCR_EL2::TPM::SET.value + | MDCR_EL2::TPMCR::SET.value + | (MDCR_EL2::HPMN.mask << MDCR_EL2::HPMN.shift); + rec.context.mdcr_el2 = if pmu_enabled { + (mdcr_el2 & !mask) | MDCR_EL2::HPMN.val(pmu_num_ctrs as u64).value + } else { + mdcr_el2 | (MDCR_EL2::TPM::SET + MDCR_EL2::TPMCR::SET).value + }; + let rec_pmu = &mut rec.context.pmu; + rec_pmu.pmcr_el0 = if pmu_enabled { + (PMCR_EL0::LC::SET + PMCR_EL0::DP::SET + PMCR_EL0::C::SET + PMCR_EL0::P::SET).into() + } else { + (PMCR_EL0::LC::SET + PMCR_EL0::DP::SET).into() + }; +} + +fn restore_pmu(pmu: &PmuRegister, num_cntrs: usize) { + PMCR_EL0.set(pmu.pmcr_el0); + PMCCFILTR_EL0.set(pmu.pmccfiltr_el0); + PMCCNTR_EL0.set(pmu.pmccntr_el0); + PMCNTENSET_EL0.set(pmu.pmcntenset_el0); + PMCNTENCLR_EL0.set(pmu.pmcntenclr_el0 ^ CLEAR_MASK); + PMINTENSET_EL1.set(pmu.pmintenset_el1); + PMINTENCLR_EL1.set(pmu.pmintenclr_el1 ^ CLEAR_MASK); + PMOVSSET_EL0.set(pmu.pmovsset_el0); + PMOVSCLR_EL0.set(pmu.pmovsclr_el0 ^ CLEAR_MASK); + PMSELR_EL0.set(pmu.pmselr_el0); + PMUSERENR_EL0.set(pmu.pmuserenr_el0); + PMXEVCNTR_EL0.set(pmu.pmxevcntr_el0); + PMXEVTYPER_EL0.set(pmu.pmxevtyper_el0); + set_pmev_regs(num_cntrs, &pmu.pmevcntr_el0, &pmu.pmevtyper_el0); +} + +pub fn restore_state(rec: &Rec<'_>) { + let (enabled, num_cntrs) = rec.pmu_config().expect("REASON"); + + if !enabled { + return; + } + MDCR_EL2.set(rec.context.mdcr_el2); + let rec_pmu = &rec.context.pmu; + restore_pmu(rec_pmu, num_cntrs); +} + +fn save_pmu(pmu: &mut PmuRegister, num_cntrs: usize) { + pmu.pmcr_el0 = PMCR_EL0.get(); + pmu.pmccfiltr_el0 = PMCCFILTR_EL0.get(); + pmu.pmccntr_el0 = PMCCNTR_EL0.get(); + pmu.pmcntenset_el0 = PMCNTENSET_EL0.get(); + pmu.pmcntenclr_el0 = PMCNTENCLR_EL0.get(); + pmu.pmintenset_el1 = PMINTENSET_EL1.get(); + pmu.pmintenclr_el1 = PMINTENCLR_EL1.get(); + pmu.pmovsset_el0 = PMOVSSET_EL0.get(); + pmu.pmovsclr_el0 = PMOVSCLR_EL0.get(); + pmu.pmselr_el0 = PMSELR_EL0.get(); + pmu.pmuserenr_el0 = PMUSERENR_EL0.get(); + pmu.pmxevcntr_el0 = PMXEVCNTR_EL0.get(); + pmu.pmxevtyper_el0 = PMXEVTYPER_EL0.get(); + get_pmev_regs(num_cntrs, &mut pmu.pmevcntr_el0, &mut pmu.pmevtyper_el0); +} + +pub fn save_state(rec: &mut Rec<'_>) { + let (enabled, num_cntrs) = rec.pmu_config().expect("REASON"); + + if !enabled { + return; + } + let rec_pmu = &mut rec.context.pmu; + save_pmu(rec_pmu, num_cntrs); +} + +pub fn save_host_state(rec: &Rec<'_>) { + let (enabled, _) = rec.pmu_config().expect("REASON"); + if !enabled { + return; + } + let mut ns_pmu = NS_PMU[get_cpu_id()].lock(); + // Event counter and cycle counter can be reset by P and C bits in PMCR_EL0 + // thus save and restore all counters. + save_pmu(&mut ns_pmu, pmu_num_ctrs() as usize); +} + +pub fn restore_host_state(rec: &Rec<'_>) { + let (enabled, _) = rec.pmu_config().expect("REASON"); + if !enabled { + return; + } + let ns_pmu = NS_PMU[get_cpu_id()].lock(); + // Event counter and cycle counter can be reset by P and C bits in PMCR_EL0 + // thus save and restore all counters. + restore_pmu(&ns_pmu, pmu_num_ctrs() as usize); +} + +pub fn pmu_overflow_active() -> bool { + (PMOVSSET_EL0.get() & PMINTENSET_EL1.get() & PMCNTENSET_EL0.get()) != 0 + && PMCR_EL0.read(PMCR_EL0::E) != 0 +} + +#[cfg(not(any(miri, test, fuzzing)))] +pub fn send_state_to_host(_rec: &Rec<'_>, run: &mut Run) -> Result<(), Error> { + run.set_pmu_overflow(pmu_overflow_active()); + Ok(()) +} + +#[cfg(any(miri, test, fuzzing))] +pub fn send_state_to_host(_rec: &Rec<'_>, run: &mut Run) -> Result<(), Error> { + run.set_pmu_overflow(false); + Ok(()) +} diff --git a/rmm/src/rmi/features.rs b/rmm/src/rmi/features.rs index c22060868893..a77b516771f8 100644 --- a/rmm/src/rmi/features.rs +++ b/rmm/src/rmi/features.rs @@ -1,6 +1,7 @@ use crate::event::RmiHandle; use crate::gic; use crate::listen; +use crate::pmu; use crate::rec; use crate::rmi; use crate::simd; @@ -26,13 +27,11 @@ define_bits!( const S2SZ_VALUE: u64 = 48; pub const LPA2_VALUE: u64 = 0; -pub const PMU_EN_VALUE: u64 = NOT_SUPPORTED; -const PMU_NUM_CTRS_VALUE: u64 = 0; const HASH_SHA_256_VALUE: u64 = SUPPORTED; const HASH_SHA_512_VALUE: u64 = SUPPORTED; -const NOT_SUPPORTED: u64 = 0; -const SUPPORTED: u64 = 1; +pub const NOT_SUPPORTED: u64 = 0; +pub const SUPPORTED: u64 = 1; const FEATURE_REGISTER_0_INDEX: usize = 0; @@ -47,8 +46,6 @@ pub fn set_event_handler(rmi: &mut RmiHandle) { feat_reg0 .set_masked_value(FeatureReg0::S2SZ, S2SZ_VALUE) .set_masked_value(FeatureReg0::LPA2, LPA2_VALUE) - .set_masked_value(FeatureReg0::PMU_EN, PMU_EN_VALUE) - .set_masked_value(FeatureReg0::PMU_NUM_CTRS, PMU_NUM_CTRS_VALUE) .set_masked_value(FeatureReg0::HASH_SHA_256, HASH_SHA_256_VALUE) .set_masked_value(FeatureReg0::HASH_SHA_512, HASH_SHA_512_VALUE) .set_masked_value(FeatureReg0::MAX_RECS_ORDER, rec::max_recs_order() as u64); @@ -64,6 +61,15 @@ pub fn set_event_handler(rmi: &mut RmiHandle) { }, ) .set_masked_value(FeatureReg0::SVE_VL, simd::max_sve_vl()) + .set_masked_value( + FeatureReg0::PMU_EN, + if pmu::pmu_present() { + SUPPORTED + } else { + NOT_SUPPORTED + }, + ) + .set_masked_value(FeatureReg0::PMU_NUM_CTRS, pmu::pmu_num_ctrs()) .set_masked_value(FeatureReg0::GICV3_NUM_LRS, gic::nr_lrs() as u64); #[cfg(any(miri, test, fuzzing))] feat_reg0 diff --git a/rmm/src/rmi/mod.rs b/rmm/src/rmi/mod.rs index 5749d0a7a5d7..bf687ea57943 100644 --- a/rmm/src/rmi/mod.rs +++ b/rmm/src/rmi/mod.rs @@ -68,6 +68,9 @@ pub const ERROR_INPUT: usize = 1; pub const ERROR_REC: usize = 3; pub const SUCCESS_REC_ENTER: usize = 4; +pub const PMU_OVERFLOW_NOT_ACTIVE: u8 = 0; +pub const PMU_OVERFLOW_ACTIVE: u8 = 1; + // RmiRttEntryState represents the state of an RTTE pub mod rtt_entry_state { pub const RMI_UNASSIGNED: usize = 0; diff --git a/rmm/src/rmi/realm/mod.rs b/rmm/src/rmi/realm/mod.rs index dae48f648379..a704ec55ffed 100644 --- a/rmm/src/rmi/realm/mod.rs +++ b/rmm/src/rmi/realm/mod.rs @@ -99,6 +99,8 @@ pub fn set_event_handler(rmi: &mut RmiHandle) { params.rpv, params.sve_en(), params.sve_vl as u64, + params.pmu_en(), + params.pmu_num_ctrs as usize, ) })?; diff --git a/rmm/src/rmi/realm/params.rs b/rmm/src/rmi/realm/params.rs index 85af0045fd0d..70f7e2f2f178 100644 --- a/rmm/src/rmi/realm/params.rs +++ b/rmm/src/rmi/realm/params.rs @@ -1,6 +1,7 @@ use crate::const_assert_eq; use crate::granule::{GRANULE_SHIFT, GRANULE_SIZE}; use crate::measurement::Hashable; +use crate::pmu; use crate::realm::mm::rtt::{RTT_PAGE_LEVEL, RTT_STRIDE}; use crate::rmi::error::Error; use crate::rmi::features; @@ -111,6 +112,11 @@ impl Params { flags.get_masked_value(RmiRealmFlags::Sve) == SUPPORTED } + pub fn pmu_en(&self) -> bool { + let flags = RmiRealmFlags::new(self.flags); + flags.get_masked_value(RmiRealmFlags::Pmu) == SUPPORTED + } + pub fn verify_compliance(&self, rd: usize) -> Result<(), Error> { trace!("{:?}", self); if self.rtt_base as usize == rd { @@ -159,7 +165,11 @@ impl Params { if !simd::validate(self.sve_en(), self.sve_vl as u64) { return Err(Error::RmiErrorInput); } - if flags.get_masked_value(RmiRealmFlags::Pmu) != features::PMU_EN_VALUE { + if self.pmu_en() + && (!pmu::pmu_present() + || self.pmu_num_ctrs > pmu::pmu_num_ctrs() as u8 + || (self.pmu_num_ctrs == 0 && !pmu::hpmn0_present())) + { return Err(Error::RmiErrorInput); } diff --git a/rmm/src/rmi/rec/handlers.rs b/rmm/src/rmi/rec/handlers.rs index ef8fa92a767a..0f25f1ffb908 100644 --- a/rmm/src/rmi/rec/handlers.rs +++ b/rmm/src/rmi/rec/handlers.rs @@ -241,6 +241,7 @@ pub fn set_event_handler(rmi: &mut RmiHandle) { #[cfg(not(any(miri, test, fuzzing)))] activate_stage2_mmu(&rec); + crate::rec::pmu::save_host_state(&rec); let mut ret_ns; loop { ret_ns = true; @@ -303,6 +304,8 @@ pub fn set_event_handler(rmi: &mut RmiHandle) { #[cfg(not(any(miri, test, fuzzing)))] crate::rec::gic::send_state_to_host(&rec, &mut run)?; crate::rec::timer::send_state_to_host(&rec, &mut run)?; + crate::rec::pmu::send_state_to_host(&rec, &mut run)?; + crate::rec::pmu::restore_host_state(&rec); // NOTICE: do not modify `run` after copy_to_ptr(). it won't have any effect. rmm.page_table.map(run_pa, false); diff --git a/rmm/src/rmi/rec/run.rs b/rmm/src/rmi/rec/run.rs index cd9d8c3a0c01..4da733de4fa8 100644 --- a/rmm/src/rmi/rec/run.rs +++ b/rmm/src/rmi/rec/run.rs @@ -3,6 +3,7 @@ use armv9a::{define_bitfield, define_bits, define_mask}; use crate::const_assert_eq; use crate::granule::GRANULE_SIZE; use crate::rmi::error::Error; +use crate::rmi::{PMU_OVERFLOW_ACTIVE, PMU_OVERFLOW_NOT_ACTIVE}; use autopadding::*; @@ -142,6 +143,14 @@ impl Run { self.exit.cntp_cval = val; } + pub fn set_pmu_overflow(&mut self, val: bool) { + if val { + self.exit.pmu_ovf = PMU_OVERFLOW_ACTIVE; + } else { + self.exit.pmu_ovf = PMU_OVERFLOW_NOT_ACTIVE; + } + } + pub fn exit_reason(&self) -> u8 { self.exit.exit_reason } diff --git a/rmm/src/simd.rs b/rmm/src/simd.rs index 367f31c0209d..8d2dd368170b 100644 --- a/rmm/src/simd.rs +++ b/rmm/src/simd.rs @@ -41,10 +41,7 @@ lazy_static! { // Set to maximum ZCR_EL2.write(ZCR_EL2::LEN.val(SVE_VQ_ARCH_MAX)); // Get vl in bytes - let vl_b: u64; - unsafe { - asm!("rdvl {}, #1", out(reg) vl_b); - } + let vl_b = unsafe { get_vector_length_bytes() }; sve_vq = ((vl_b << 3)/ QUARD_WORD) - 1; sve_en = true; trace!("sve_vq={:?}", sve_vq); @@ -73,6 +70,16 @@ lazy_static! { }; } +/// Get the SVE vector length in bytes using the RDVL instruction +#[target_feature(enable = "sve")] +unsafe fn get_vector_length_bytes() -> u64 { + let vl_b: u64; + unsafe { + asm!("rdvl {}, #1", out(reg) vl_b); + } + vl_b +} + pub fn validate(en: bool, sve_vl: u64) -> bool { if en && !SIMD_CONFIG.sve_en { return false; diff --git a/scripts/tests/acs.sh b/scripts/tests/acs.sh index 35c1f639603e..d3af2a078222 100755 --- a/scripts/tests/acs.sh +++ b/scripts/tests/acs.sh @@ -3,7 +3,7 @@ set -e # Control these variables -EXPECTED=71 +EXPECTED=95 TIMEOUT=30 ROOT=$(git rev-parse --show-toplevel) diff --git a/skipped-tests.txt b/skipped-tests.txt index 8acf51b594d5..20a5ff730c15 100644 --- a/skipped-tests.txt +++ b/skipped-tests.txt @@ -1,26 +1,7 @@ -cmd_rtt_destroy -cmd_rtt_fold -exception_rec_exit_wfe +cmd_multithread_realm_mp exception_rec_exit_wfi -measurement_rim_order -attestation_token_verify -attestation_rpv_value -attestation_challenge_data_verification -attestation_token_init -attestation_realm_measurement_type -attestation_platform_challenge_size -attestation_rem_extend_check -attestation_rem_extend_check_realm_token +exception_rec_exit_wfe attestation_rec_exit_irq -mm_hipas_assigned_ripas_empty_da_ia -mm_ripas_destroyed_da_ia -mm_hipas_unassigned_ripas_empty_da_ia -mm_hipas_unassigned_ripas_ram_da_ia -mm_rtt_fold_assigned -mm_rtt_fold_unassigned -mm_rtt_fold_unassigned_ns -mm_rtt_fold_assigned_ns -exception_non_emulatable_da_2 -exception_rec_exit_irq -gic_timer_nsel2_trig gic_timer_rel1_trig +mm_gpf_exception +cmd_secure_test diff --git a/third-party/tf-a-tests b/third-party/tf-a-tests index f0b22a65e34a..54e3358185dd 160000 --- a/third-party/tf-a-tests +++ b/third-party/tf-a-tests @@ -1 +1 @@ -Subproject commit f0b22a65e34aab665e127f7ded2b66bddd66dda1 +Subproject commit 54e3358185ddf12555ae7add362de58cea8f32b9