microsoft/openvmm
Publicmirrored from https://github.com/microsoft/openvmmAvailable
openhcl/hcl/src/stats.rs
59lines · modecode
| 1 | // Copyright (c) Microsoft Corporation. |
| 2 | // Licensed under the MIT License. |
| 3 | |
| 4 | //! Code for getting kernel stats from /proc/mshv. |
| 5 | |
| 6 | use std::io::BufRead; |
| 7 | use std::io::BufReader; |
| 8 | use thiserror::Error; |
| 9 | |
| 10 | /// Error returned by [`vp_stats`]. |
| 11 | #[derive(Debug, Error)] |
| 12 | #[allow(missing_docs)] |
| 13 | pub enum VpStatsError { |
| 14 | #[error("failed to read /proc/mshv")] |
| 15 | Read(#[source] std::io::Error), |
| 16 | #[error("failed to parse stats string")] |
| 17 | ParseString(#[source] std::io::Error), |
| 18 | #[error("failed to parse stats line")] |
| 19 | ParseLine, |
| 20 | #[error("a cpu was missing from the stats file")] |
| 21 | MissingCpu, |
| 22 | } |
| 23 | |
| 24 | /// The per-VP stats from the kernel. |
| 25 | #[derive(Debug)] |
| 26 | pub struct HclVpStats { |
| 27 | /// The number of VTL transitions. |
| 28 | pub vtl_transitions: u64, |
| 29 | } |
| 30 | |
| 31 | /// Gets the per-VP stats from the kernel. |
| 32 | pub fn vp_stats() -> Result<Vec<HclVpStats>, VpStatsError> { |
| 33 | let v = std::fs::read("/proc/mshv").map_err(VpStatsError::Read)?; |
| 34 | // Skip the first two lines (version and header). |
| 35 | let lines = BufReader::new(v.as_slice()).lines().skip(2); |
| 36 | let mut stats = Vec::new(); |
| 37 | for line in lines { |
| 38 | let line = line.map_err(VpStatsError::ParseString)?; |
| 39 | let (cpu, rest) = line.split_once(' ').ok_or(VpStatsError::ParseLine)?; |
| 40 | let n: usize = cpu |
| 41 | .strip_prefix("cpu") |
| 42 | .ok_or(VpStatsError::ParseLine)? |
| 43 | .parse() |
| 44 | .map_err(|_| VpStatsError::ParseLine)?; |
| 45 | |
| 46 | if n != stats.len() { |
| 47 | return Err(VpStatsError::MissingCpu); |
| 48 | } |
| 49 | let vtl_transitions = rest |
| 50 | .split(' ') |
| 51 | .next() |
| 52 | .ok_or(VpStatsError::ParseLine)? |
| 53 | .parse() |
| 54 | .map_err(|_| VpStatsError::ParseLine)?; |
| 55 | |
| 56 | stats.push(HclVpStats { vtl_transitions }) |
| 57 | } |
| 58 | Ok(stats) |
| 59 | } |
| 60 | |