Skip to content

Commit

Permalink
XXX: fix topo handling
Browse files Browse the repository at this point in the history
  • Loading branch information
pfmooney committed Sep 26, 2023
1 parent fdb74ba commit 841bc42
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 57 deletions.
1 change: 1 addition & 0 deletions bin/propolis-standalone/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -936,6 +936,7 @@ fn setup_instance(
)
.with_vcpuid(vcpu.id)
.with_cache_topo()
.clear_cpu_topo(cpuid::TopoKind::all())
.execute(profile.clone())
})
.unwrap_or_else(|| {
Expand Down
144 changes: 87 additions & 57 deletions lib/propolis/src/cpuid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,8 @@ pub struct Specializer {
num_vcpu: Option<NonZeroU8>,
vcpuid: Option<i32>,
vendor_kind: Option<VendorKind>,
cpu_topo: BTreeSet<TopoKind>,
cpu_topo_populate: BTreeSet<TopoKind>,
cpu_topo_clear: BTreeSet<TopoKind>,
do_cache_topo: bool,
}
impl Specializer {
Expand All @@ -183,13 +184,35 @@ impl Specializer {
}

/// Specify CPU topology types to render into the specialized [Set]
pub fn with_cpu_topo(self, topos: impl Iterator<Item = TopoKind>) -> Self {
let mut cpu_topo = BTreeSet::new();
for t in topos {
cpu_topo.insert(t);
///
/// Without basic information such as the number of vCPUs (set by
/// [`Self::with_vcpu_count()`]), population of the requested topology
/// information may be incomplete.
pub fn with_cpu_topo(
self,
populate: impl Iterator<Item = TopoKind>,
) -> Self {
let mut cpu_topo_populate = BTreeSet::new();

for t in populate {
cpu_topo_populate.insert(t);
}

Self { cpu_topo, ..self }
Self { cpu_topo_populate, ..self }
}

/// Specify CPU topology types to clear from the specialized [Set]
///
/// Some leafs in the provided set may not match expectations for the given
/// CPU vendor. Without populating it with generated data (via
/// [`Self::with_cpu_topo()`]), those leafs can be cleared out.
pub fn clear_cpu_topo(self, clear: impl Iterator<Item = TopoKind>) -> Self {
let mut cpu_topo_clear = BTreeSet::new();
for t in clear {
cpu_topo_clear.insert(t);
}

Self { cpu_topo_clear, ..self }
}

/// Update cache topology information for specified vCPU count and SMT
Expand Down Expand Up @@ -277,11 +300,15 @@ impl Specializer {
}
}
fn fix_cpu_topo(&self, set: &mut Set) {
for topo in enum_iterator::all::<TopoKind>() {
for topo in self.cpu_topo_populate.union(&self.cpu_topo_clear) {
// Nuke any existing info in order to potentially override it
let leaf = topo as u32;
let leaf = *topo as u32;
set.remove_all(leaf);

if !self.cpu_topo_populate.contains(topo) {
continue;
}

let num_vcpu = match self.num_vcpu {
Some(n) => n.get() as u32,
None => {
Expand All @@ -290,66 +317,64 @@ impl Specializer {
}
};

if self.cpu_topo.contains(&topo) {
match topo {
TopoKind::StdB => {
// Queries with invalid ecx will get all-zeroes
set.insert(Ident(leaf, None), Entry::zero());
if self.has_smt {
set.insert(
Ident(leaf, Some(0)),
Entry {
eax: 0x1,
ebx: 0x2,
ecx: 0x100,
// TODO: populate with x2APIC ID
edx: 0x0,
},
);
} else {
set.insert(
Ident(leaf, Some(0)),
Entry {
eax: 0x0,
ebx: 0x1,
ecx: 0x100,
// TODO: populate with x2APIC ID
edx: 0x0,
},
);
}
match topo {
TopoKind::StdB => {
// Queries with invalid ecx will get all-zeroes
set.insert(Ident(leaf, None), Entry::zero());
if self.has_smt {
set.insert(
Ident(leaf, Some(1)),
Ident(leaf, Some(0)),
Entry {
eax: 0x0,
ebx: num_vcpu,
ecx: 0x201,
eax: 0x1,
ebx: 0x2,
ecx: 0x100,
// TODO: populate with x2APIC ID
edx: 0x0,
},
);
}
TopoKind::Std1F => {
// TODO: add 0x1f topo info
}
TopoKind::Ext1E => {
let id = self.vcpuid.unwrap_or(0) as u32;
let mut ebx = id;
if self.has_smt {
// bits 15:8 hold the zero-based threads-per-compute-unit
ebx |= 0x100;
}
} else {
set.insert(
Ident(leaf, None),
Ident(leaf, Some(0)),
Entry {
eax: id,
ebx,
// TODO: populate ecx info?
ecx: 0,
edx: 0,
eax: 0x0,
ebx: 0x1,
ecx: 0x100,
// TODO: populate with x2APIC ID
edx: 0x0,
},
);
}
set.insert(
Ident(leaf, Some(1)),
Entry {
eax: 0x0,
ebx: num_vcpu,
ecx: 0x201,
// TODO: populate with x2APIC ID
edx: 0x0,
},
);
}
TopoKind::Std1F => {
// TODO: add 0x1f topo info
}
TopoKind::Ext1E => {
let id = self.vcpuid.unwrap_or(0) as u32;
let mut ebx = id;
if self.has_smt {
// bits 15:8 hold the zero-based threads-per-compute-unit
ebx |= 0x100;
}
set.insert(
Ident(leaf, None),
Entry {
eax: id,
ebx,
// TODO: populate ecx info?
ecx: 0,
edx: 0,
},
);
}
}
}
Expand All @@ -366,6 +391,11 @@ pub enum TopoKind {
/// LEAF 0x8000001E (AMD)
Ext1E = 0x8000001e,
}
impl TopoKind {
pub fn all() -> enum_iterator::All<Self> {
enum_iterator::all()
}
}

/// Flavors of CPU vendor for cpuid specialization
#[derive(Clone, Copy)]
Expand Down

0 comments on commit 841bc42

Please sign in to comment.