Created
May 5, 2023 09:39
-
-
Save nuta/84eff47225fa2e6a7337034e920b5c1e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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