Skip to content

Instantly share code, notes, and snippets.

@nuta
Created May 5, 2023 09:39
Show Gist options
  • Save nuta/84eff47225fa2e6a7337034e920b5c1e to your computer and use it in GitHub Desktop.
Save nuta/84eff47225fa2e6a7337034e920b5c1e to your computer and use it in GitHub Desktop.
Pmu = 0x504d55,
// PMU function IDs.
pub const SBI_PMU_NUM_COUNTERS: usize = 0x00;
pub const SBI_PMU_COUNTER_CONFIG_MATCHING: usize = 0x02;
pub const SBI_PMU_COUNTER_START: usize = 0x03;
pub const SBI_PMU_COUNTER_STOP: usize = 0x04;
pub const SBI_PMU_COUNTER_FW_READ: usize = 0x05;
pub const SBI_PMU_COUNTER_FW_READ_HI: usize = 0x06;
// PMU counter start flags.
pub const SBI_PMU_START_SET_INIT_VALUE: usize = 1;
//
// PMU counter config match flags.
//
/// Event counting inhibited in VU-mode
pub const SBI_PMU_CFG_FLAG_SET_VUINH: usize = 1 << 3;
/// Event counting inhibited in VS-mode
pub const SBI_PMU_CFG_FLAG_SET_VSINH: usize = 1 << 4;
/// Event counting inhibited in U-mode
pub const SBI_PMU_CFG_FLAG_SET_UINH: usize = 1 << 5;
/// Event counting inhibited in S-mode
pub const SBI_PMU_CFG_FLAG_SET_SINH: usize = 1 << 6;
/// Event counting inhibited in M-mode
pub const SBI_PMU_CFG_FLAG_SET_MINH: usize = 1 << 7;
#[repr(usize)]
pub enum PmuEventType {
General = 0,
}
//
// PMU Hardware General Events
//
/// Unused event because event_idx cannot be zero
pub const SBI_PMU_HW_NO_EVENT: usize = 0;
/// Event for each CPU cycle
pub const SBI_PMU_HW_CPU_CYCLES: usize = 1;
/// Event for each completed instruction
pub const SBI_PMU_HW_INSTRUCTIONS: usize = 2;
/// Event for cache hit
pub const SBI_PMU_HW_CACHE_REFERENCES: usize = 3;
/// Event for cache miss
pub const SBI_PMU_HW_CACHE_MISSES: usize = 4;
/// Event for a branch instruction
pub const SBI_PMU_HW_BRANCH_INSTRUCTIONS: usize = 5;
/// Event for a branch misprediction
pub const SBI_PMU_HW_BRANCH_MISSES: usize = 6;
/// Event for each BUS cycle
pub const SBI_PMU_HW_BUS_CYCLES: usize = 7;
/// Event for a stalled cycle in microarchitecture frontend
pub const SBI_PMU_HW_STALLED_CYCLES_FRONTEND: usize = 8;
/// Event for a stalled cycle in microarchitecture backend
pub const SBI_PMU_HW_STALLED_CYCLES_BACKEND: usize = 9;
/// Event for each reference CPU cycle
pub const SBI_PMU_HW_REF_CPU_CYCLES: usize = 10;
pub struct PmuEventIdx(usize);
impl PmuEventIdx {
pub fn new(type_: PmuEventType, code: usize) -> PmuEventIdx {
PmuEventIdx(((type_ as usize) << 16) | code)
}
}
pub fn main() {
// QEMU seems not to support the PMU extension completely.
// use crate::sbi::{
// PmuEventIdx, PmuEventType, SBI_PMU_CFG_FLAG_SET_MINH,
// SBI_PMU_CFG_FLAG_SET_SINH, SBI_PMU_CFG_FLAG_SET_VSINH,
// SBI_PMU_CFG_FLAG_SET_VUINH, SBI_PMU_HW_CPU_CYCLES, SBI_PMU_HW_INSTRUCTIONS,
// SBI_PMU_START_SET_INIT_VALUE,
// };
//
// unsafe {
// println!("num counters: {:?}", sbi::pmu_num_counters());
// let counter_idx = sbi::pmu_conter_config_matching(
// 0,
// 0xffffffff,
// SBI_PMU_CFG_FLAG_SET_VUINH
// | SBI_PMU_CFG_FLAG_SET_VSINH
// | SBI_PMU_CFG_FLAG_SET_MINH
// | SBI_PMU_CFG_FLAG_SET_SINH,
// PmuEventIdx::new(PmuEventType::General, SBI_PMU_HW_CPU_CYCLES),
// 0,
// )
// .unwrap();
// println!("counter_idx: {:?}", counter_idx);
// let started = riscv::register::cycle::read64();
// let cycles: u32;
// unsafe {
// core::arch::asm!("rdcycle {}", out(reg) cycles);
// }
// println!("started: {:x}", started);
// let _ = sbi::pmu_counter_start(
// counter_idx,
// 1,
// SBI_PMU_START_SET_INIT_VALUE,
// 0xffffffff,
// );
// println!("-------");
// let _ = sbi::pmu_counter_stop(counter_idx, 1, 0);
// let cycles = riscv::register::cycle::read64();
// println!("counter: {:x}", cycles);
// println!("diff: {}", cycles - started);
}
pub unsafe fn pmu_num_counters() -> Result<usize, SbiErrorCode> {
sbi_call(SbiExtId::Pmu, SBI_PMU_NUM_COUNTERS, 0, 0, 0, 0, 0, 0)
}
pub unsafe fn pmu_conter_config_matching(
counter_idx_base: usize,
counter_idx_mask: usize,
config_flags: usize,
event_idx: PmuEventIdx,
event_data: u64,
) -> Result<usize, SbiErrorCode> {
sbi_call(
SbiExtId::Pmu,
SBI_PMU_COUNTER_CONFIG_MATCHING,
counter_idx_base,
counter_idx_mask,
config_flags,
event_idx.0,
event_data as usize,
0, // FIXME: event_data >> 32 if usize is 32-bit
)
}
pub unsafe fn pmu_counter_start(
counter_idx_base: usize,
counter_idx_mask: usize,
start_flags: usize,
initial_value: u64,
) -> Result<(), SbiErrorCode> {
sbi_call(
SbiExtId::Pmu,
SBI_PMU_COUNTER_START,
counter_idx_base,
counter_idx_mask,
start_flags,
initial_value as usize,
0,
0,
)?;
Ok(())
}
pub unsafe fn pmu_counter_stop(
counter_idx_base: usize,
counter_idx_mask: usize,
stop_flags: usize,
) -> Result<(), SbiErrorCode> {
sbi_call(
SbiExtId::Pmu,
SBI_PMU_COUNTER_STOP,
counter_idx_base,
counter_idx_mask,
stop_flags,
0,
0,
0,
)?;
Ok(())
}
pub unsafe fn pmu_counter_fw_read(
counter_idx: usize,
) -> Result<usize, SbiErrorCode> {
sbi_call(
SbiExtId::Pmu,
SBI_PMU_COUNTER_FW_READ,
counter_idx,
0,
0,
0,
0,
0,
)
}
pub unsafe fn pmu_counter_fw_read_hi(
counter_idx: usize,
) -> Result<usize, SbiErrorCode> {
sbi_call(
SbiExtId::Pmu,
SBI_PMU_COUNTER_FW_READ_HI,
counter_idx,
0,
0,
0,
0,
0,
)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment