Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bitfield: Added x86 model field decoding #5

Merged
merged 1 commit into from
Apr 4, 2023
Merged
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
84 changes: 72 additions & 12 deletions src/bitfield.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,37 @@ impl Bindable for Int {
}
}

/// Wraps an X86Model representation
/// These can have a number of weird conditions and are always going to be a part of a bit field
#[derive(Serialize, Deserialize, Debug)]
pub struct X86Model {
pub name: String,
}

const MODEL_START_BIT: u8 = 4;
const EXTENDED_MODEL_START_BIT: u8 = 16;
const FAMILY_START_BIT: u8 = 8;
impl Bindable for X86Model {
type Rep = u32;
fn value(&self, reg_val: Register) -> Option<Self::Rep> {
let reg32 = reg_val as u32;
let nibble_mask = 0xF;
let model = (reg32 >> MODEL_START_BIT) & nibble_mask;
let famil_id = (reg32 >> FAMILY_START_BIT) & nibble_mask;

match famil_id {
6 | 0xF => {
let extended_model = (reg32 >> EXTENDED_MODEL_START_BIT) & nibble_mask;
Some((extended_model << 4) | model)
}
_ => Some(model),
}
}
fn name(&self) -> &String {
&self.name
}
}

pub struct Bound<'a, T: Bindable> {
reg_val: Register,
bits: &'a T,
Expand Down Expand Up @@ -96,15 +127,6 @@ impl<'a> fmt::Display for Bound<'a, Flag> {
}
}

impl<'a, T: From<u32> + From<bool>> Facter<T> for Bound<'a, Flag> {
fn collect_fact(&self) -> GenericFact<T> {
GenericFact::new(
self.bits.name.clone(),
self.bits.value(self.reg_val).unwrap_or(false).into(),
)
}
}

impl<'a> fmt::Display for Bound<'a, Int> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
write!(
Expand All @@ -116,11 +138,26 @@ impl<'a> fmt::Display for Bound<'a, Int> {
}
}

impl<'a, T: From<u32> + From<bool>> Facter<T> for Bound<'a, Int> {
impl<'a, B, R, T: From<u32> + From<bool>> Facter<T> for Bound<'a, B>
where
R: Default + Into<T>,
B: Bindable<Rep = R>,
{
fn collect_fact(&self) -> GenericFact<T> {
GenericFact::new(
self.bits.name.clone(),
self.bits.value(self.reg_val).unwrap_or(0).into(),
self.bits.name().clone(),
self.bits.value(self.reg_val).unwrap_or_default().into(),
)
}
}

impl<'a> fmt::Display for Bound<'a, X86Model> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
write!(
f,
"{} = {:>10}",
self.bits.name,
self.bits.value(self.reg_val).unwrap_or(0)
)
}
}
Expand All @@ -130,18 +167,21 @@ impl<'a, T: From<u32> + From<bool>> Facter<T> for Bound<'a, Int> {
pub enum Field {
Int(Int),
Flag(Flag),
X86Model(X86Model),
}

pub enum BoundField<'a> {
Int(Bound<'a, Int>),
Flag(Bound<'a, Flag>),
X86Model(Bound<'a, X86Model>),
}

impl<'a> BoundField<'a> {
pub fn from_register_and_field(reg_val: Register, field: &'a Field) -> Self {
match field {
Field::Int(bits) => Self::Int(Bound { reg_val, bits }),
Field::Flag(bits) => Self::Flag(Bound { reg_val, bits }),
Field::X86Model(bits) => Self::X86Model(Bound { reg_val, bits }),
}
}
}
Expand All @@ -151,6 +191,7 @@ impl<'a> fmt::Display for BoundField<'a> {
match self {
Self::Int(bound) => bound.fmt(f),
Self::Flag(bound) => bound.fmt(f),
Self::X86Model(bound) => bound.fmt(f),
}
}
}
Expand All @@ -160,6 +201,25 @@ impl<'a, T: From<bool> + From<u32>> Facter<T> for BoundField<'a> {
match self {
Self::Int(bound) => bound.collect_fact(),
Self::Flag(bound) => bound.collect_fact(),
Self::X86Model(bound) => bound.collect_fact(),
}
}
}

#[cfg(test)]
mod test {
use crate::bitfield::Bindable;

#[test]
fn x86_model_test() {
let field_definition = super::X86Model {
name: "model".to_string(),
};
let regular_model: super::Register = 0x0AF50341;
assert_eq!(field_definition.value(regular_model).unwrap(), 0x4);
let extended_family_model: super::Register = 0x0AF50641;
assert_eq!(field_definition.value(extended_family_model).unwrap(), 0x54);
let extended_family_model: super::Register = 0x0AF50F41;
assert_eq!(field_definition.value(extended_family_model).unwrap(), 0x54);
}
}
5 changes: 1 addition & 4 deletions src/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,8 @@ cpuids:
bounds:
start: 0
end: 4
- type: Int
- type: X86Model
name: model
bounds:
start: 4
end: 8
- type: Int
name: family
bounds:
Expand Down