@@ -44,6 +44,77 @@ pub struct Parameters {
4444 pub register : CpuidReg ,
4545}
4646
47+ /// Describes a policy for how the corresponding CPUID data should be considered when building
48+ /// a CPU profile.
49+ #[ derive( Debug , Copy , Clone , Eq , PartialEq ) ]
50+ pub enum ProfilePolicy {
51+ /// Store the corresponding data when building the CPU profile.
52+ ///
53+ /// When the CPU profile gets utilized the corresponding data will be set into the modified
54+ /// CPUID instruction(s).
55+ Inherit ,
56+ /// Ignore the corresponding data when building the CPU profile.
57+ ///
58+ /// When the CPU profile gets utilized the corresponding data will then instead get
59+ /// extracted from the host.
60+ ///
61+ /// This variant is typically set for data that has no effect on migration compatibility,
62+ /// but there may be some exceptions such as data which is necessary to run the VM at all,
63+ /// but must coincide with whatever is on the host.
64+ Passthrough ,
65+ /// Set the following hardcoded value in the CPU profile.
66+ ///
67+ /// This variant is typically used for features/values that don't work well with live migration (even when using the exact same physical CPU model).
68+ Static ( u32 ) ,
69+ }
70+
71+ /// A description of a range of bits in a register populated by the CPUID instruction with specific parameters.
72+ #[ derive( Clone , Copy , Debug ) ]
73+ pub struct ValueDefinition {
74+ /// A short name for the value obtainable through CPUID
75+ pub short : & ' static str ,
76+ /// A description of the value obtainable through CPUID
77+ pub description : & ' static str ,
78+ /// The range of bits in the output register corresponding to this feature or value.
79+ ///
80+ /// This is not a `RangeInclusive<u8>` because that type does unfortunately not implement `Copy`.
81+ pub bits_range : ( u8 , u8 ) ,
82+ /// The policy corresponding to this value when building CPU profiles.
83+ pub policy : ProfilePolicy ,
84+ }
85+
86+ /// Describes values within a register populated by the CPUID instruction with specific parameters.
87+ ///
88+ /// NOTE: The only way to interact with this value (beyond this crate) is via the const [`Self::as_slice()`](Self::as_slice) method.
89+ pub struct ValueDefinitions ( & ' static [ ValueDefinition ] ) ;
90+ impl ValueDefinitions {
91+ /// Constructor permitting at most 32 entries.
92+ const fn new ( cpuid_descriptions : & ' static [ ValueDefinition ] ) -> Self {
93+ // Note that this function is only called within this module, at compile time, hence it is fine to have some
94+ // additional sanity checks such as the following assert.
95+ assert ! ( cpuid_descriptions. len( ) <= 32 ) ;
96+ Self ( cpuid_descriptions)
97+ }
98+ /// Converts this into a slice representation. This is the only way to read values of this type.
99+ pub const fn as_slice ( & self ) -> & ' static [ ValueDefinition ] {
100+ self . 0
101+ }
102+ }
103+
104+ /// Describes multiple CPUID outputs.
105+ ///
106+ /// Each wrapped [`ValueDefinitions`] corresponds to the given [`Parameters`] in the same tuple.
107+ ///
108+ pub struct CpuidDefinitions < const NUM_PARAMETERS : usize > (
109+ [ ( Parameters , ValueDefinitions ) ; NUM_PARAMETERS ] ,
110+ ) ;
111+
112+ impl < const NUM_PARAMETERS : usize > CpuidDefinitions < NUM_PARAMETERS > {
113+ pub const fn as_slice ( & self ) -> & [ ( Parameters , ValueDefinitions ) ; NUM_PARAMETERS ] {
114+ & self . 0
115+ }
116+ }
117+
47118#[ cfg( test) ]
48119mod tests {
49120 use proptest:: prelude:: * ;
0 commit comments