Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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