Skip to content

Commit

Permalink
Wire up initial support for AMD perf counters
Browse files Browse the repository at this point in the history
  • Loading branch information
pfmooney committed Jan 23, 2025
1 parent 6f40d5e commit a3e035a
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 4 deletions.
5 changes: 4 additions & 1 deletion crates/bhyve-api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,9 @@ unsafe fn ioctl(
#[repr(u32)]
#[derive(Copy, Clone)]
pub enum ApiVersion {
/// Initial support for CPU perf. counters on AMD
V18 = 18,

/// Add support for NPT bitmap operations
V17 = 17,

Expand Down Expand Up @@ -588,7 +591,7 @@ pub enum ApiVersion {
}
impl ApiVersion {
pub const fn current() -> Self {
Self::V17
Self::V18
}
}

Expand Down
2 changes: 1 addition & 1 deletion crates/bhyve-api/sys/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ pub const VM_MAXCPU: usize = 32;
/// This is the VMM interface version which bhyve_api expects to operate
/// against. All constants and structs defined by the crate are done so in
/// terms of that specific version.
pub const VMM_CURRENT_INTERFACE_VERSION: u32 = 17;
pub const VMM_CURRENT_INTERFACE_VERSION: u32 = 18;
10 changes: 10 additions & 0 deletions crates/bhyve-api/sys/src/vmm_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ pub const VDC_MSR: u16 = 3;
pub const VDC_FPU: u16 = 4;
pub const VDC_LAPIC: u16 = 5;
pub const VDC_VMM_ARCH: u16 = 6;
pub const VDC_PMU_AMD: u16 = 14;

// Classes for system-wide device state

Expand Down Expand Up @@ -261,3 +262,12 @@ pub const VAI_PEND_EXTINT: u32 = 11;
pub const VAI_PEND_EXCP: u32 = 12;
/// exception/interrupt pending injection for vCPU
pub const VAI_PEND_INTINFO: u32 = 13;

// VDC_PMU_AMD v1 interface

#[repr(C)]
#[derive(Copy, Clone, Default)]
pub struct vdi_pmu_amd_v1 {
pub vpa_evtsel: [u64; 6],
pub vpa_ctr: [u64; 6],
}
80 changes: 78 additions & 2 deletions lib/propolis/src/vcpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use migrate::VcpuReadWrite;
use thiserror::Error;

use bhyve_api::ApiVersion;
use propolis_types::{CpuidIdent, CpuidVendor};
use propolis_types::{CpuidIdent, CpuidValues, CpuidVendor};

#[usdt::provider(provider = "propolis")]
mod probes {
Expand Down Expand Up @@ -54,6 +54,9 @@ pub struct Vcpu {
pub id: i32,
pub bus_mmio: Arc<MmioBus>,
pub bus_pio: Arc<PioBus>,

/// Vendor of the underlying CPU hardware
hardware_vendor: CpuidVendor,
}

impl Vcpu {
Expand All @@ -64,7 +67,25 @@ impl Vcpu {
bus_mmio: Arc<MmioBus>,
bus_pio: Arc<PioBus>,
) -> Arc<Self> {
Arc::new(Self { hdl, id, bus_mmio, bus_pio })
#[cfg(target_arch = "x86_64")]
fn query_hardware_vendor() -> CpuidVendor {
let res = unsafe { core::arch::x86_64::__cpuid(0) };
CpuidValues::from(res).try_into().expect("CPU vendor is recognized")
}

#[cfg(not(target_arch = "x86_64"))]
fn query_hardware_vendor() -> CpuidVendor {
// Just default to AMD when building for tests/etc on non-x86
CpuidVendor::Amd
}

Arc::new(Self {
hdl,
id,
bus_mmio,
bus_pio,
hardware_vendor: query_hardware_vendor(),
})
}

/// ID of the virtual CPU.
Expand Down Expand Up @@ -483,6 +504,13 @@ impl MigrateMulti for Vcpu {
output.push(migrate::LapicV1::read(self)?.into())?;
output.push(migrate::CpuidV1::read(self)?.into())?;

// PMU was introduced in V18
if bhyve_api::api_version()? >= ApiVersion::V18
&& self.hardware_vendor == CpuidVendor::Amd
{
output.push(migrate::PmuAmdV1::read(self)?.into())?;
}

Ok(())
}

Expand Down Expand Up @@ -511,6 +539,10 @@ impl MigrateMulti for Vcpu {
lapic.write(self)?;
cpuid.write(self)?;

if let Ok(pmu_amd) = offer.take::<migrate::PmuAmdV1>() {
pmu_amd.write(self)?;
}

Ok(())
}
}
Expand Down Expand Up @@ -783,6 +815,17 @@ pub mod migrate {
}
}

#[derive(Clone, Deserialize, Serialize)]
pub struct PmuAmdV1 {
pub evtsel: [u64; 6],
pub counter: [u64; 6],
}
impl Schema<'_> for PmuAmdV1 {
fn id() -> SchemaId {
("bhyve-x86-pmu-amd", 1)
}
}

impl From<(bhyve_api::seg_desc, u16)> for SegDesc {
fn from(value: (bhyve_api::seg_desc, u16)) -> Self {
let (desc, selector) = value;
Expand Down Expand Up @@ -892,6 +935,19 @@ pub mod migrate {
}
}
}
impl From<bhyve_api::vdi_pmu_amd_v1> for PmuAmdV1 {
fn from(value: bhyve_api::vdi_pmu_amd_v1) -> Self {
PmuAmdV1 { evtsel: value.vpa_evtsel, counter: value.vpa_ctr }
}
}
impl From<PmuAmdV1> for bhyve_api::vdi_pmu_amd_v1 {
fn from(value: PmuAmdV1) -> Self {
bhyve_api::vdi_pmu_amd_v1 {
vpa_evtsel: value.evtsel,
vpa_ctr: value.counter,
}
}
}

impl VcpuReadWrite for VcpuRunStateV1 {
fn read(vcpu: &Vcpu) -> Result<Self> {
Expand Down Expand Up @@ -1336,6 +1392,26 @@ pub mod migrate {
vcpu.set_cpuid(self.into())
}
}
impl VcpuReadWrite for PmuAmdV1 {
fn read(vcpu: &Vcpu) -> Result<Self> {
let vdi = vcpu
.hdl
.data_op(bhyve_api::VDC_PMU_AMD, 1)
.for_vcpu(vcpu.id)
.read::<bhyve_api::vdi_pmu_amd_v1>()?;

Ok(vdi.into())
}

fn write(self, vcpu: &Vcpu) -> Result<()> {
vcpu.hdl
.data_op(bhyve_api::VDC_PMU_AMD, 1)
.for_vcpu(vcpu.id)
.write::<bhyve_api::vdi_pmu_amd_v1>(&self.into())?;

Ok(())
}
}
}

mod bits {
Expand Down

0 comments on commit a3e035a

Please sign in to comment.