|
@@ -10,6 +10,7 @@ use core::{
|
|
|
arch::{asm, naked_asm},
|
|
|
ptr::null,
|
|
|
};
|
|
|
+use riscv::register::cycle;
|
|
|
use sbi_spec::{
|
|
|
binary::{CounterMask, HartMask, SbiRet},
|
|
|
pmu::firmware_event,
|
|
@@ -115,7 +116,7 @@ extern "C" fn rust_main(hartid: usize, dtb_pa: usize) -> ! {
|
|
|
};
|
|
|
let test_result = testing.test();
|
|
|
|
|
|
- // pmu test, only valid on qemu-system-riscv64 platform
|
|
|
+ // PMU test, only available in qemu-system-riscv64 single core
|
|
|
let counters_num = sbi::pmu_num_counters();
|
|
|
println!("[pmu] counters number: {}", counters_num);
|
|
|
for idx in 0..counters_num {
|
|
@@ -133,10 +134,8 @@ extern "C" fn rust_main(hartid: usize, dtb_pa: usize) -> ! {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // Hardware event
|
|
|
+ /* PMU test for hardware event */
|
|
|
let counter_mask = CounterMask::from_mask_base(0x7ffff, 0);
|
|
|
- let result = sbi::pmu_counter_config_matching(counter_mask, Flag::new(0b110), 0x1, 0);
|
|
|
- assert!(result.is_ok());
|
|
|
let result = sbi::pmu_counter_config_matching(counter_mask, Flag::new(0b110), 0x2, 0);
|
|
|
assert!(result.is_ok());
|
|
|
let result = sbi::pmu_counter_config_matching(counter_mask, Flag::new(0b110), 0x10019, 0);
|
|
@@ -148,7 +147,51 @@ extern "C" fn rust_main(hartid: usize, dtb_pa: usize) -> ! {
|
|
|
let result = sbi::pmu_counter_config_matching(counter_mask, Flag::new(0b110), 0x3, 0);
|
|
|
assert_eq!(result, SbiRet::not_supported());
|
|
|
|
|
|
- // Firmware event
|
|
|
+ // `SBI_PMU_HW_CPU_CYCLES` event test
|
|
|
+ let result = sbi::pmu_counter_config_matching(counter_mask, Flag::new(0b010), 0x1, 0);
|
|
|
+ assert!(result.is_ok());
|
|
|
+ // the counter index should be 0(mcycle)
|
|
|
+ assert_eq!(result.value, 0);
|
|
|
+ let cycle_counter_idx = result.value;
|
|
|
+ let cycle_num = cycle::read64();
|
|
|
+ assert_eq!(cycle_num, 0);
|
|
|
+ // Start counting `SBI_PMU_HW_CPU_CYCLES` events
|
|
|
+ let start_result = sbi::pmu_counter_start(
|
|
|
+ CounterMask::from_mask_base(0x1, cycle_counter_idx),
|
|
|
+ Flag::new(0x1),
|
|
|
+ 0xffff,
|
|
|
+ );
|
|
|
+ assert!(start_result.is_ok());
|
|
|
+ let cycle_num = cycle::read64();
|
|
|
+ assert!(cycle_num >= 0xffff);
|
|
|
+ // Stop counting `SBI_PMU_HW_CPU_CYCLES` events
|
|
|
+ let stop_result = sbi::pmu_counter_stop(
|
|
|
+ CounterMask::from_mask_base(0x1, cycle_counter_idx),
|
|
|
+ Flag::new(0x0),
|
|
|
+ );
|
|
|
+ assert!(stop_result.is_ok());
|
|
|
+ let old_cycle_num = cycle::read64();
|
|
|
+ let mut _j = 0;
|
|
|
+ for i in 0..1000 {
|
|
|
+ _j += i
|
|
|
+ }
|
|
|
+ let new_cycle_num = cycle::read64();
|
|
|
+ assert_eq!(old_cycle_num, new_cycle_num);
|
|
|
+ // Restart counting `SBI_PMU_HW_CPU_CYCLES` events
|
|
|
+ let start_result = sbi::pmu_counter_start(
|
|
|
+ CounterMask::from_mask_base(0x1, cycle_counter_idx),
|
|
|
+ Flag::new(0x0),
|
|
|
+ 0,
|
|
|
+ );
|
|
|
+ assert!(start_result.is_ok());
|
|
|
+ let mut _j = 0;
|
|
|
+ for i in 0..1000 {
|
|
|
+ _j += i
|
|
|
+ }
|
|
|
+ let restart_cycle_num = cycle::read64();
|
|
|
+ assert!(restart_cycle_num > new_cycle_num);
|
|
|
+
|
|
|
+ /* PMU test for firmware event */
|
|
|
let counter_mask = CounterMask::from_mask_base(0x7ffffffff, 0);
|
|
|
|
|
|
// Mapping a counter to the `SBI_PMU_FW_ACCESS_LOAD` event should result in unsupported
|