1#[cfg(target_arch = "x86_64")]
5mod common_types {
6 pub use crate::cpu_config::x86_64::custom_cpu_template::CustomCpuTemplate;
7 pub use crate::cpu_config::x86_64::static_cpu_templates::StaticCpuTemplate;
8 pub use crate::cpu_config::x86_64::{
9 CpuConfiguration, CpuConfigurationError as GuestConfigError, test_utils,
10 };
11}
12
13#[cfg(target_arch = "aarch64")]
14mod common_types {
15 pub use crate::cpu_config::aarch64::custom_cpu_template::CustomCpuTemplate;
16 pub use crate::cpu_config::aarch64::static_cpu_templates::StaticCpuTemplate;
17 pub use crate::cpu_config::aarch64::{
18 CpuConfiguration, CpuConfigurationError as GuestConfigError, test_utils,
19 };
20}
21
22use std::borrow::Cow;
23use std::fmt::Debug;
24
25pub use common_types::*;
26use serde::de::Error as SerdeError;
27use serde::{Deserialize, Deserializer, Serialize, Serializer};
28
29#[derive(Debug, thiserror::Error, displaydoc::Display, PartialEq, Eq)]
31pub enum GetCpuTemplateError {
32 #[cfg(target_arch = "x86_64")]
33 GetCpuVendor(crate::cpu_config::x86_64::cpuid::common::GetCpuidError),
35 CpuVendorMismatched,
37 InvalidStaticCpuTemplate(StaticCpuTemplate),
39 InvalidCpuModel,
41}
42
43pub trait GetCpuTemplate {
51 fn get_cpu_template(&self) -> Result<Cow<'_, CustomCpuTemplate>, GetCpuTemplateError>;
53}
54
55#[derive(Debug, Clone, PartialEq, Eq)]
57pub enum CpuTemplateType {
58 Custom(CustomCpuTemplate),
60 Static(StaticCpuTemplate),
62}
63
64impl From<&Option<CpuTemplateType>> for StaticCpuTemplate {
67 fn from(value: &Option<CpuTemplateType>) -> Self {
68 match value {
69 Some(CpuTemplateType::Static(template)) => *template,
70 Some(CpuTemplateType::Custom(_)) | None => StaticCpuTemplate::None,
71 }
72 }
73}
74
75impl From<&CpuTemplateType> for StaticCpuTemplate {
78 fn from(value: &CpuTemplateType) -> Self {
79 match value {
80 CpuTemplateType::Static(template) => *template,
81 CpuTemplateType::Custom(_) => StaticCpuTemplate::None,
82 }
83 }
84}
85
86impl TryFrom<&[u8]> for CustomCpuTemplate {
87 type Error = serde_json::Error;
88
89 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
90 let template: CustomCpuTemplate = serde_json::from_slice(value)?;
91 template.validate()?;
92 Ok(template)
93 }
94}
95
96impl TryFrom<&str> for CustomCpuTemplate {
97 type Error = serde_json::Error;
98
99 fn try_from(value: &str) -> Result<Self, Self::Error> {
100 CustomCpuTemplate::try_from(value.as_bytes())
101 }
102}
103
104#[derive(Debug, Clone, Eq, PartialEq)]
108pub enum KvmCapability {
109 Add(u32),
111 Remove(u32),
113}
114
115impl Serialize for KvmCapability {
116 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
118 where
119 S: Serializer,
120 {
121 let s = match self {
122 KvmCapability::Add(cap) => format!("{cap}"),
123 KvmCapability::Remove(cap) => format!("!{cap}"),
124 };
125 serializer.serialize_str(&s)
126 }
127}
128
129impl<'de> Deserialize<'de> for KvmCapability {
130 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
132 where
133 D: Deserializer<'de>,
134 {
135 let original_str = <String as Deserialize>::deserialize(deserializer)?;
136
137 let parse_err = |e| {
138 D::Error::custom(format!(
139 "Failed to parse string [{}] as a kvm capability - can not convert to numeric: {}",
140 original_str, e
141 ))
142 };
143
144 match original_str.strip_prefix('!') {
145 Some(s) => {
146 let v = s.parse::<u32>().map_err(parse_err)?;
147 Ok(Self::Remove(v))
148 }
149 None => {
150 let v = original_str.parse::<u32>().map_err(parse_err)?;
151 Ok(Self::Add(v))
152 }
153 }
154 }
155}
156
157#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash)]
159pub struct RegisterValueFilter<V>
160where
161 V: Numeric,
162{
163 pub filter: V,
165 pub value: V,
167}
168
169impl<V> RegisterValueFilter<V>
170where
171 V: Numeric + Debug,
172{
173 #[inline]
175 pub fn apply(&self, value: V) -> V {
176 (value & !self.filter) | self.value
177 }
178}
179
180impl<V> Serialize for RegisterValueFilter<V>
181where
182 V: Numeric + Debug,
183{
184 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
186 where
187 S: Serializer,
188 {
189 let mut bitmap_str = Vec::with_capacity(V::BITS as usize + 2);
190 bitmap_str.push(b'0');
191 bitmap_str.push(b'b');
192
193 for i in (0..V::BITS).rev() {
194 match self.filter.bit(i) {
195 true => {
196 let val = self.value.bit(i);
197 bitmap_str.push(b'0' + u8::from(val));
198 }
199 false => bitmap_str.push(b'x'),
200 }
201 }
202
203 let s = unsafe { std::str::from_utf8_unchecked(&bitmap_str) };
206
207 serializer.serialize_str(s)
208 }
209}
210
211impl<'de, V> Deserialize<'de> for RegisterValueFilter<V>
212where
213 V: Numeric + Debug,
214{
215 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
222 where
223 D: Deserializer<'de>,
224 {
225 let original_str = <String as Deserialize>::deserialize(deserializer)?;
226
227 let stripped_str = original_str.strip_prefix("0b").unwrap_or(&original_str);
228
229 let (mut filter, mut value) = (V::zero(), V::zero());
230 let mut i = 0;
231 for s in stripped_str.as_bytes().iter().rev() {
232 if V::BITS == i {
233 return Err(D::Error::custom(format!(
234 "Failed to parse string [{}] as a bitmap - string is too long",
235 original_str
236 )));
237 }
238
239 match s {
240 b'_' => continue,
241 b'x' => {}
242 b'0' => {
243 filter |= V::one() << i;
244 }
245 b'1' => {
246 filter |= V::one() << i;
247 value |= V::one() << i;
248 }
249 c => {
250 return Err(D::Error::custom(format!(
251 "Failed to parse string [{}] as a bitmap - unknown character: {}",
252 original_str, c
253 )));
254 }
255 }
256 i += 1;
257 }
258 Ok(RegisterValueFilter { filter, value })
259 }
260}
261
262pub trait Numeric:
264 Sized
265 + Copy
266 + PartialEq<Self>
267 + std::fmt::Binary
268 + std::ops::Not<Output = Self>
269 + std::ops::BitAnd<Output = Self>
270 + std::ops::BitOr<Output = Self>
271 + std::ops::BitOrAssign<Self>
272 + std::ops::BitXor<Output = Self>
273 + std::ops::Shl<u32, Output = Self>
274 + std::ops::AddAssign<Self>
275{
276 const BITS: u32;
278 fn bit(&self, pos: u32) -> bool;
280 fn zero() -> Self;
282 fn one() -> Self;
284}
285
286macro_rules! impl_numeric {
287 ($type:tt) => {
288 impl Numeric for $type {
289 const BITS: u32 = $type::BITS;
290 fn bit(&self, pos: u32) -> bool {
291 (self & (Self::one() << pos)) != 0
292 }
293 fn zero() -> Self {
294 0
295 }
296 fn one() -> Self {
297 1
298 }
299 }
300 };
301}
302
303impl_numeric!(u8);
304impl_numeric!(u16);
305impl_numeric!(u32);
306impl_numeric!(u64);
307impl_numeric!(u128);
308
309#[cfg(test)]
310mod tests {
311 use super::*;
312
313 #[test]
314 fn test_kvm_capability_serde() {
315 let kvm_cap = KvmCapability::Add(69);
316
317 let expected_str = "\"69\"";
318 let serialized = serde_json::to_string(&kvm_cap).unwrap();
319 assert_eq!(&serialized, expected_str);
320
321 let kvm_cap = KvmCapability::Remove(69);
322
323 let expected_str = "\"!69\"";
324 let serialized = serde_json::to_string(&kvm_cap).unwrap();
325 assert_eq!(&serialized, expected_str);
326
327 let serialized = "\"69\"";
328 let deserialized: KvmCapability = serde_json::from_str(serialized).unwrap();
329 assert_eq!(deserialized, KvmCapability::Add(69));
330
331 let serialized = "\"!69\"";
332 let deserialized: KvmCapability = serde_json::from_str(serialized).unwrap();
333 assert_eq!(deserialized, KvmCapability::Remove(69));
334 }
335
336 #[test]
337 fn test_register_value_filter_serde() {
338 let rvf = RegisterValueFilter::<u8> {
339 value: 0b01010101,
340 filter: 0b11110000,
341 };
342
343 let expected_str = "\"0b0101xxxx\"";
344 let serialized = serde_json::to_string(&rvf).unwrap();
345 assert_eq!(&serialized, expected_str);
346
347 let expected_rvf = RegisterValueFilter::<u8> {
348 value: 0b01010000,
349 filter: 0b11110000,
350 };
351 let deserialized: RegisterValueFilter<u8> = serde_json::from_str(&serialized).unwrap();
352 assert_eq!(deserialized, expected_rvf);
353
354 let serialized = "\"0b0_101_xx_xx\"";
355 let deserialized: RegisterValueFilter<u8> = serde_json::from_str(serialized).unwrap();
356 assert_eq!(deserialized, expected_rvf);
357
358 let serialized = "\"0b0_xϽ1_xx_xx\"";
359 let deserialized: Result<RegisterValueFilter<u8>, _> = serde_json::from_str(serialized);
360 deserialized.unwrap_err();
361
362 let serialized = "\"0b0000_0000_0\"";
363 let deserialized: Result<RegisterValueFilter<u8>, _> = serde_json::from_str(serialized);
364 deserialized.unwrap_err();
365 }
366}