Skip to content

Commit

Permalink
make MSRs cpu-affine
Browse files Browse the repository at this point in the history
  • Loading branch information
gjcolombo committed Oct 14, 2024
1 parent 9ab7192 commit 7e60b12
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 11 deletions.
27 changes: 18 additions & 9 deletions lib/propolis/src/msr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,17 @@

use std::sync::{Arc, Mutex};

use crate::util::aspace::{ASpace, Error as ASpaceError};
use crate::{
util::aspace::{ASpace, Error as ASpaceError},
vcpu::VcpuId,
};
use thiserror::Error;

#[usdt::provider(provider = "propolis")]
mod probes {
fn msr_read(
id: u32,
vcpuid: u32,
msr: u32,
val: u64,
handler_registered: u8,
handler_ok: u8,
Expand All @@ -37,7 +41,8 @@ mod probes {
}

fn msr_write(
id: u32,
vcpuid: u32,
msr: u32,
val: u64,
handler_registered: u8,
handler_ok: u8,
Expand All @@ -50,6 +55,7 @@ mod probes {
///
/// # Arguments
///
/// - `VcpuId`: The ID of the vCPU that accessed an MSR.
/// - `MsrId`: The ID of the MSR being read or written.
/// - `MsrOp`: The operation to perform on the supplied MSR.
///
Expand All @@ -61,7 +67,7 @@ mod probes {
/// - `Err` if the handler function encountered an internal error. The operation
/// is completely unhandled; in particular, if it was a [`MsrOp::Read`], no
/// output value was written.
pub type MsrFn = dyn Fn(MsrId, MsrOp) -> anyhow::Result<MsrDisposition>
pub type MsrFn = dyn Fn(VcpuId, MsrId, MsrOp) -> anyhow::Result<MsrDisposition>
+ Send
+ Sync
+ 'static;
Expand Down Expand Up @@ -142,44 +148,47 @@ impl MsrSpace {
/// Handles the RDMSR instruction.
pub fn rdmsr(
&self,
vcpu: VcpuId,
msr: MsrId,
out: &mut u64,
) -> Result<MsrDisposition, Error> {
let res = self.do_msr_op(msr, MsrOp::Read(out));
let res = self.do_msr_op(vcpu, msr, MsrOp::Read(out));
probes::msr_read!(|| {
let info = ProbeInfo::from(&res);
let (ok, disposition) = if let Some(d) = info.disposition {
(true, d as u8)
} else {
(false, 0)
};
(msr.0, *out, info.registered as u8, ok as u8, disposition)
(vcpu.0, msr.0, *out, info.registered as u8, ok as u8, disposition)
});
res
}

/// Handles the WRMSR instruction.
pub fn wrmsr(
&self,
vcpu: VcpuId,
msr: MsrId,
value: u64,
) -> Result<MsrDisposition, Error> {
let res = self.do_msr_op(msr, MsrOp::Write(value));
let res = self.do_msr_op(vcpu, msr, MsrOp::Write(value));
probes::msr_write!(|| {
let info = ProbeInfo::from(&res);
let (ok, disposition) = if let Some(d) = info.disposition {
(true, d as u8)
} else {
(false, 0)
};
(msr.0, value, info.registered as u8, ok as u8, disposition)
(vcpu.0, msr.0, value, info.registered as u8, ok as u8, disposition)
});
res
}

/// Handles MSR operations.
fn do_msr_op(
&self,
vcpu: VcpuId,
msr: MsrId,
op: MsrOp,
) -> Result<MsrDisposition, Error> {
Expand All @@ -199,7 +208,7 @@ impl MsrSpace {
// Allow other vCPUs to access the handler map while this operation is
// being processed.
drop(map);
handler(msr, op).map_err(Error::HandlerError)
handler(vcpu, msr, op).map_err(Error::HandlerError)
}
}

Expand Down
25 changes: 23 additions & 2 deletions lib/propolis/src/vcpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
//! Virtual CPU functionality.

use std::io::Result;
use std::num::TryFromIntError;
use std::sync::Arc;

use crate::common::Lifecycle;
Expand Down Expand Up @@ -36,6 +37,18 @@ mod probes {
#[cfg(not(feature = "omicron-build"))]
pub const MAXCPU: usize = bhyve_api::VM_MAXCPU;

/// The ID of a specific vCPU.
#[derive(Clone, Copy, Debug)]
pub struct VcpuId(pub u32);

impl TryFrom<i32> for VcpuId {
type Error = TryFromIntError;

fn try_from(value: i32) -> std::result::Result<Self, Self::Error> {
Ok(Self(u32::try_from(value)?))
}
}

// Helios (stlouis) is built with an expanded limit of 64
#[cfg(feature = "omicron-build")]
pub const MAXCPU: usize = 64;
Expand Down Expand Up @@ -464,7 +477,11 @@ impl Vcpu {
},
VmExitKind::Rdmsr(msr) => {
let mut out = 0u64;
match self.msr.rdmsr(MsrId(msr), &mut out) {
match self.msr.rdmsr(
self.id.try_into().unwrap(),
MsrId(msr),
&mut out,
) {
Ok(MsrDisposition::Handled) => {
self.set_reg(
bhyve_api::vm_reg_name::VM_REG_GUEST_RAX,
Expand All @@ -491,7 +508,11 @@ impl Vcpu {
}
}
VmExitKind::Wrmsr(msr, value) => {
match self.msr.wrmsr(MsrId(msr), value) {
match self.msr.wrmsr(
self.id.try_into().unwrap(),
MsrId(msr),
value,
) {
Ok(MsrDisposition::Handled) => Some(VmEntry::Run),
Ok(MsrDisposition::GpException) => {
self.inject_gp().unwrap();
Expand Down

0 comments on commit 7e60b12

Please sign in to comment.