From 68666442ccf44bed2aa2dfe60131491e6f1ca56b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 20 Jun 2025 19:12:55 +0000 Subject: [PATCH 01/10] Initial plan for issue From 6030b3f24588cb0148d5227988a7390aac752169 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 20 Jun 2025 19:25:16 +0000 Subject: [PATCH 02/10] Add modular-bitfield dependency and improve HvInputVtl structure Co-authored-by: sangho2 <3938640+sangho2@users.noreply.github.com> --- litebox_platform_lvbs/Cargo.toml | 1 + litebox_platform_lvbs/src/mshv/hvcall_vp.rs | 4 +- litebox_platform_lvbs/src/mshv/mod.rs | 88 ++++++++++++++------- 3 files changed, 61 insertions(+), 32 deletions(-) diff --git a/litebox_platform_lvbs/Cargo.toml b/litebox_platform_lvbs/Cargo.toml index b86819479..48315a4cd 100644 --- a/litebox_platform_lvbs/Cargo.toml +++ b/litebox_platform_lvbs/Cargo.toml @@ -20,6 +20,7 @@ rangemap = { version = "1.5.1", features = ["const_fn"] } thiserror = { version = "2.0.6", default-features = false } num_enum = { version = "0.7.3", default-features = false } once_cell = { version = "1.20.2", default-features = false, features = ["alloc", "race"] } +modular-bitfield = { version = "0.11.2", default-features = false } [target.'cfg(target_arch = "x86_64")'.dependencies] x86_64 = { version = "0.15.2", default-features = false, features = ["instructions"] } diff --git a/litebox_platform_lvbs/src/mshv/hvcall_vp.rs b/litebox_platform_lvbs/src/mshv/hvcall_vp.rs index 156d45170..50dbddf9a 100644 --- a/litebox_platform_lvbs/src/mshv/hvcall_vp.rs +++ b/litebox_platform_lvbs/src/mshv/hvcall_vp.rs @@ -60,7 +60,7 @@ pub fn hvcall_set_vp_registers(reg_name: u32, value: u64) -> Result Result { - hvcall_set_vp_registers_internal(reg_name, value, HvInputVtl::new(HV_VTL_NORMAL)) + hvcall_set_vp_registers_internal(reg_name, value, HvInputVtl::new_for_vtl(HV_VTL_NORMAL)) } fn hvcall_get_vp_registers_internal( @@ -108,7 +108,7 @@ pub fn hvcall_get_vp_registers(reg_name: u32) -> Result { /// Hyper-V Hypercall to get VTL0's registers like MSR and control registers. #[inline] pub fn hvcall_get_vp_vtl0_registers(reg_name: u32) -> Result { - hvcall_get_vp_registers_internal(reg_name, HvInputVtl::new(HV_VTL_NORMAL)) + hvcall_get_vp_registers_internal(reg_name, HvInputVtl::new_for_vtl(HV_VTL_NORMAL)) } /// Populate the VP context for VTL1 diff --git a/litebox_platform_lvbs/src/mshv/mod.rs b/litebox_platform_lvbs/src/mshv/mod.rs index 6d89a7736..862273235 100644 --- a/litebox_platform_lvbs/src/mshv/mod.rs +++ b/litebox_platform_lvbs/src/mshv/mod.rs @@ -11,6 +11,7 @@ pub mod vtl_switch; use crate::mshv::vtl1_mem_layout::PAGE_SIZE; use num_enum::{IntoPrimitive, TryFromPrimitive}; +use modular_bitfield::prelude::*; pub const HV_HYPERCALL_REP_COMP_MASK: u64 = 0xfff_0000_0000; pub const HV_HYPERCALL_REP_COMP_OFFSET: u32 = 32; @@ -229,49 +230,38 @@ pub struct HvInitVpContext { pub msr_cr_pat: u64, } -#[derive(Default, Clone, Copy)] -#[repr(C, packed)] +#[bitfield] +#[derive(Clone, Copy, Default)] +#[repr(C)] pub struct HvInputVtl { - _as_uint8: u8, - // union of - // target_vtl: 4, use_target_vtl: 1, - // reserved_z: 3 + pub target_vtl: B4, + pub use_target_vtl: bool, + #[skip] + __: B3, } impl HvInputVtl { - const TARGET_VTL_MASK: u8 = 0xf; - const USE_TARGET_VTL_MASK: u8 = 0x10; - const USE_TARGET_VTL_SHIFT: u8 = 4; - /// `target_vtl` specifies the VTL (0-15) that a Hyper-V hypercall works at. - pub fn new(target_vtl: u8) -> Self { - let mut vtl = HvInputVtl { _as_uint8: 0 }; - vtl.set_target_vtl(target_vtl); - vtl.set_use_target_vtl(true); - vtl + pub fn new_for_vtl(target_vtl: u8) -> Self { + Self::new() + .with_target_vtl(target_vtl.into()) + .with_use_target_vtl(true) } /// use the current VTL pub fn current() -> Self { - let mut vtl = HvInputVtl { _as_uint8: 0 }; - vtl.set_use_target_vtl(false); - vtl + Self::new() + .with_use_target_vtl(false) } - #[expect(clippy::used_underscore_binding)] - pub fn set_target_vtl(&mut self, target_vtl: u8) { - self._as_uint8 |= target_vtl & Self::TARGET_VTL_MASK; + /// Gets the target VTL as a u8 value + pub fn target_vtl_value(&self) -> u8 { + self.target_vtl() as u8 } - /// set `use_target_vtl` to `true` to let a hypercall work at the target VTL specified by `set_target_vtl`. - /// set `use_target_vtl` to `false` to let a hypercall work at the current VTL. - #[expect(clippy::used_underscore_binding)] - pub fn set_use_target_vtl(&mut self, use_target_vtl: bool) { - if use_target_vtl { - self._as_uint8 |= (1 << Self::USE_TARGET_VTL_SHIFT) & Self::USE_TARGET_VTL_MASK; - } else { - self._as_uint8 &= !((1 << Self::USE_TARGET_VTL_SHIFT) & Self::USE_TARGET_VTL_MASK); - } + /// Sets the target VTL from a u8 value + pub fn set_target_vtl_value(&mut self, target_vtl: u8) { + self.set_target_vtl(target_vtl.into()); } } @@ -1055,3 +1045,41 @@ impl HvPendingExceptionEvent { self.set_sub_config(Self::ERROR_CODE_MASK, Self::ERROR_CODE_SHIFT, error_code); } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_hv_input_vtl_bitfield() { + // Test the new bitfield-based HvInputVtl implementation + + // Test new_for_vtl constructor + let vtl = HvInputVtl::new_for_vtl(5); + assert_eq!(vtl.target_vtl_value(), 5); + assert_eq!(vtl.use_target_vtl(), true); + + // Test current constructor + let current_vtl = HvInputVtl::current(); + assert_eq!(current_vtl.use_target_vtl(), false); + + // Test individual field manipulation + let mut vtl = HvInputVtl::new(); + vtl.set_target_vtl_value(10); + vtl.set_use_target_vtl(true); + assert_eq!(vtl.target_vtl_value(), 10); + assert_eq!(vtl.use_target_vtl(), true); + + // Test size - should be 1 byte + assert_eq!(core::mem::size_of::(), 1); + + // Test that VTL values are properly bounded to 4 bits (0-15) + let vtl = HvInputVtl::new_for_vtl(15); + assert_eq!(vtl.target_vtl_value(), 15); + + // Test that Default trait works + let default_vtl = HvInputVtl::default(); + assert_eq!(default_vtl.target_vtl_value(), 0); + assert_eq!(default_vtl.use_target_vtl(), false); + } +} From 4e6adb03a3133188c9f86a632ebce84ce72633f8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 20 Jun 2025 19:28:17 +0000 Subject: [PATCH 03/10] Replace complex HvRegisterVsmPartitionConfig with bitfield implementation Co-authored-by: sangho2 <3938640+sangho2@users.noreply.github.com> --- litebox_platform_lvbs/src/mshv/mod.rs | 196 ++++++++++---------------- litebox_platform_lvbs/src/mshv/vsm.rs | 4 +- 2 files changed, 79 insertions(+), 121 deletions(-) diff --git a/litebox_platform_lvbs/src/mshv/mod.rs b/litebox_platform_lvbs/src/mshv/mod.rs index 862273235..31b1fd65d 100644 --- a/litebox_platform_lvbs/src/mshv/mod.rs +++ b/litebox_platform_lvbs/src/mshv/mod.rs @@ -12,6 +12,7 @@ pub mod vtl_switch; use crate::mshv::vtl1_mem_layout::PAGE_SIZE; use num_enum::{IntoPrimitive, TryFromPrimitive}; use modular_bitfield::prelude::*; +use modular_bitfield::specifiers::{B4, B51}; pub const HV_HYPERCALL_REP_COMP_MASK: u64 = 0xfff_0000_0000; pub const HV_HYPERCALL_REP_COMP_OFFSET: u32 = 32; @@ -557,136 +558,44 @@ impl HvRegisterVsmVpSecureVtlConfig { } } -#[derive(Default, Clone, Copy)] -#[repr(C, packed)] +#[bitfield] +#[derive(Clone, Copy, Default)] +#[repr(C)] pub struct HvRegisterVsmPartitionConfig { - _as_u64: u64, - // union of - // enable_vtl_protection : 1, - // default_vtl_protection_mask : 4, - // zero_memory_on_reset : 1, - // deny_lower_vtl_startup : 1, - // intercept_acceptance : 1, - // intercept_enable_vtl_protection : 1, - // intercept_vp_startup : 1, - // intercept_cpuid_unimplemented : 1, - // intercept_unrecoverable_exception : 1, - // intercept_page : 1, - // mbz : 51, + pub enable_vtl_protection: bool, + pub default_vtl_protection_mask: B4, + pub zero_memory_on_reset: bool, + pub deny_lower_vtl_startup: bool, + pub intercept_acceptance: bool, + pub intercept_enable_vtl_protection: bool, + pub intercept_vp_startup: bool, + pub intercept_cpuid_unimplemented: bool, + pub intercept_unrecoverable_exception: bool, + pub intercept_page: bool, + #[skip] + __: B51, } impl HvRegisterVsmPartitionConfig { - const ENABLE_VTL_PROTECTION_MASK: u64 = 0x1; - const DEFAULT_VTL_PROTECTION_MASK_MASK: u64 = 0x1e; - const ZERO_MEMORY_ON_RESET_MASK: u64 = 0x20; - const DENY_LOWER_VTL_STARTUP_MASK: u64 = 0x40; - const INTERCEPT_ACCEPTANCE_MASK: u64 = 0x80; - const INTERCEPT_ENABLE_VTL_PROTECTION_MASK: u64 = 0x100; - const INTERCEPT_VP_STARTUP_MASK: u64 = 0x200; - const INTERCEPT_CPUID_UNIMPLEMENTED_MASK: u64 = 0x400; - const INTERCEPT_UNRECOVERABLE_EXCEPTION_MASK: u64 = 0x800; - const INTERCEPT_PAGE_MASK: u64 = 0x1000; - const ENABLE_VTL_PROTECTION_SHIFT: u64 = 0; - const DEFAULT_VTL_PROTECTION_MASK_SHIFT: u64 = 1; - const ZERO_MEMORY_ON_RESET_SHIFT: u64 = 5; - const DENY_LOWER_VTL_STARTUP_SHIFT: u64 = 6; - const INTERCEPT_ACCEPTANCE_SHIFT: u64 = 7; - const INTERCEPT_ENABLE_VTL_PROTECTION_SHIFT: u64 = 8; - const INTERCEPT_VP_STARTUP_SHIFT: u64 = 9; - const INTERCEPT_CPUID_UNIMPLEMENTED_SHIFT: u64 = 10; - const INTERCEPT_UNRECOVERABLE_EXCEPTION_SHIFT: u64 = 11; - const INTERCEPT_PAGE_SHIFT: u64 = 12; - - pub fn new() -> Self { - HvRegisterVsmPartitionConfig { - ..Default::default() - } - } - - #[expect(clippy::used_underscore_binding)] + /// Get the raw u64 value for compatibility with existing code pub fn as_u64(&self) -> u64 { - self._as_u64 - } - - #[expect(clippy::used_underscore_binding)] - fn set_sub_config(&mut self, mask: u64, shift: u64, value: u64) { - self._as_u64 |= (value << shift) & mask; + // Convert the 8-byte array to u64 + u64::from_le_bytes(self.into_bytes()) } - pub fn set_enable_vtl_protection(&mut self) { - self.set_sub_config( - Self::ENABLE_VTL_PROTECTION_MASK, - Self::ENABLE_VTL_PROTECTION_SHIFT, - 1, - ); + /// Create from a u64 value for compatibility with existing code + pub fn from_u64(value: u64) -> Self { + Self::from_bytes(value.to_le_bytes()) } - pub fn set_default_vtl_protection_mask(&mut self, mask: u64) { - self.set_sub_config( - Self::DEFAULT_VTL_PROTECTION_MASK_MASK, - Self::DEFAULT_VTL_PROTECTION_MASK_SHIFT, - mask, - ); + /// Set the default VTL protection mask from a u64 value + pub fn set_default_vtl_protection_mask_value(&mut self, mask: u64) { + self.set_default_vtl_protection_mask((mask as u8).into()); } - pub fn set_zero_memory_on_reset(&mut self) { - self.set_sub_config( - Self::ZERO_MEMORY_ON_RESET_MASK, - Self::ZERO_MEMORY_ON_RESET_SHIFT, - 1, - ); - } - - pub fn set_deny_lower_vtl_startup(&mut self) { - self.set_sub_config( - Self::DENY_LOWER_VTL_STARTUP_MASK, - Self::DENY_LOWER_VTL_STARTUP_SHIFT, - 1, - ); - } - - pub fn set_intercept_acceptance(&mut self) { - self.set_sub_config( - Self::INTERCEPT_ACCEPTANCE_MASK, - Self::INTERCEPT_ACCEPTANCE_SHIFT, - 1, - ); - } - - pub fn set_intercept_enable_vtl_protection(&mut self) { - self.set_sub_config( - Self::INTERCEPT_ENABLE_VTL_PROTECTION_MASK, - Self::INTERCEPT_ENABLE_VTL_PROTECTION_SHIFT, - 1, - ); - } - - pub fn set_intercept_vp_startup(&mut self) { - self.set_sub_config( - Self::INTERCEPT_VP_STARTUP_MASK, - Self::INTERCEPT_VP_STARTUP_SHIFT, - 1, - ); - } - - pub fn set_intercept_cpuid_unimplemented(&mut self) { - self.set_sub_config( - Self::INTERCEPT_CPUID_UNIMPLEMENTED_MASK, - Self::INTERCEPT_CPUID_UNIMPLEMENTED_SHIFT, - 1, - ); - } - - pub fn set_intercept_unrecoverable_exception(&mut self) { - self.set_sub_config( - Self::INTERCEPT_UNRECOVERABLE_EXCEPTION_MASK, - Self::INTERCEPT_UNRECOVERABLE_EXCEPTION_SHIFT, - 1, - ); - } - - pub fn set_intercept_page(&mut self) { - self.set_sub_config(Self::INTERCEPT_PAGE_MASK, Self::INTERCEPT_PAGE_SHIFT, 1); + /// Get the default VTL protection mask as a u64 value + pub fn default_vtl_protection_mask_value(&self) -> u64 { + self.default_vtl_protection_mask() as u64 } } @@ -1082,4 +991,53 @@ mod tests { assert_eq!(default_vtl.target_vtl_value(), 0); assert_eq!(default_vtl.use_target_vtl(), false); } + + #[test] + fn test_hv_register_vsm_partition_config_bitfield() { + // Test the new bitfield-based HvRegisterVsmPartitionConfig implementation + + let mut config = HvRegisterVsmPartitionConfig::new(); + + // Test individual boolean flags + config.set_enable_vtl_protection(true); + assert_eq!(config.enable_vtl_protection(), true); + + config.set_zero_memory_on_reset(true); + assert_eq!(config.zero_memory_on_reset(), true); + + config.set_intercept_page(true); + assert_eq!(config.intercept_page(), true); + + // Test the 4-bit protection mask field + config.set_default_vtl_protection_mask_value(0b1010); + assert_eq!(config.default_vtl_protection_mask_value(), 0b1010); + + // Test size - should be 8 bytes (64 bits) + assert_eq!(core::mem::size_of::(), 8); + + // Test as_u64 and from_u64 round-trip + let original = config.as_u64(); + let restored = HvRegisterVsmPartitionConfig::from_u64(original); + + assert_eq!(restored.enable_vtl_protection(), true); + assert_eq!(restored.zero_memory_on_reset(), true); + assert_eq!(restored.intercept_page(), true); + assert_eq!(restored.default_vtl_protection_mask_value(), 0b1010); + + // Test that Default trait works + let default_config = HvRegisterVsmPartitionConfig::default(); + assert_eq!(default_config.enable_vtl_protection(), false); + assert_eq!(default_config.as_u64(), 0); + + // Test chaining builder-style methods (generated by bitfield macro) + let chained_config = HvRegisterVsmPartitionConfig::new() + .with_enable_vtl_protection(true) + .with_intercept_acceptance(true) + .with_intercept_vp_startup(true); + + assert_eq!(chained_config.enable_vtl_protection(), true); + assert_eq!(chained_config.intercept_acceptance(), true); + assert_eq!(chained_config.intercept_vp_startup(), true); + assert_eq!(chained_config.zero_memory_on_reset(), false); + } } diff --git a/litebox_platform_lvbs/src/mshv/vsm.rs b/litebox_platform_lvbs/src/mshv/vsm.rs index eadc3cdcc..02a0b15a3 100644 --- a/litebox_platform_lvbs/src/mshv/vsm.rs +++ b/litebox_platform_lvbs/src/mshv/vsm.rs @@ -181,8 +181,8 @@ pub fn mshv_vsm_configure_partition() -> Result { debug_serial_println!("VSM: Configure partition"); let mut config = HvRegisterVsmPartitionConfig::new(); - config.set_default_vtl_protection_mask(HvPageProtFlags::HV_PAGE_FULL_ACCESS.bits().into()); - config.set_enable_vtl_protection(); + config.set_default_vtl_protection_mask_value(HvPageProtFlags::HV_PAGE_FULL_ACCESS.bits().into()); + config.set_enable_vtl_protection(true); hvcall_set_vp_registers(HV_REGISTER_VSM_PARTITION_CONFIG, config.as_u64()) .map_err(|_| Errno::EFAULT)?; From ff25daabbf40cab7852a3331ec6b64c6b03e79f0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 20 Jun 2025 19:29:12 +0000 Subject: [PATCH 04/10] Add comprehensive documentation for bit field improvements Co-authored-by: sangho2 <3938640+sangho2@users.noreply.github.com> --- BITFIELD_IMPROVEMENTS.md | 165 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 BITFIELD_IMPROVEMENTS.md diff --git a/BITFIELD_IMPROVEMENTS.md b/BITFIELD_IMPROVEMENTS.md new file mode 100644 index 000000000..9763953a9 --- /dev/null +++ b/BITFIELD_IMPROVEMENTS.md @@ -0,0 +1,165 @@ +# Bit Field Handling Improvements + +This document describes the improvements made to bit field handling in LiteBox, specifically addressing issue #136. + +## Overview + +The codebase previously used manual bit manipulation with masks and shifts for packed structures, which was error-prone and verbose. We have improved this by adopting the `modular-bitfield` crate for complex bit field structures. + +## Changes Made + +### 1. Added modular-bitfield dependency + +Added `modular-bitfield = { version = "0.11.2", default-features = false }` to `litebox_platform_lvbs/Cargo.toml`. + +### 2. Improved HvInputVtl structure + +**Before (manual bit manipulation):** +```rust +#[derive(Default, Clone, Copy)] +#[repr(C, packed)] +pub struct HvInputVtl { + _as_uint8: u8, + // target_vtl: 4, use_target_vtl: 1, reserved_z: 3 +} + +impl HvInputVtl { + const TARGET_VTL_MASK: u8 = 0xf; + const USE_TARGET_VTL_MASK: u8 = 0x10; + const USE_TARGET_VTL_SHIFT: u8 = 4; + + pub fn set_target_vtl(&mut self, target_vtl: u8) { + self._as_uint8 |= target_vtl & Self::TARGET_VTL_MASK; + } + // ... more manual bit manipulation +} +``` + +**After (declarative bitfield):** +```rust +#[bitfield] +#[derive(Clone, Copy, Default)] +#[repr(C)] +pub struct HvInputVtl { + pub target_vtl: B4, + pub use_target_vtl: bool, + #[skip] + __: B3, +} +``` + +### 3. Improved HvRegisterVsmPartitionConfig structure + +**Before:** 110+ lines with 20+ constants and repetitive manual methods. + +**After:** 30 lines with clear field declarations: +```rust +#[bitfield] +#[derive(Clone, Copy, Default)] +#[repr(C)] +pub struct HvRegisterVsmPartitionConfig { + pub enable_vtl_protection: bool, + pub default_vtl_protection_mask: B4, + pub zero_memory_on_reset: bool, + pub deny_lower_vtl_startup: bool, + pub intercept_acceptance: bool, + pub intercept_enable_vtl_protection: bool, + pub intercept_vp_startup: bool, + pub intercept_cpuid_unimplemented: bool, + pub intercept_unrecoverable_exception: bool, + pub intercept_page: bool, + #[skip] + __: B51, +} +``` + +## Benefits + +1. **Readability**: Field layouts are self-documenting +2. **Safety**: Compile-time bounds checking prevents overflow +3. **Maintainability**: No manual mask/shift calculations +4. **Functionality**: Auto-generated getters, setters, and builder methods +5. **Performance**: Zero runtime overhead + +## Usage Patterns + +### Basic field access: +```rust +let mut config = HvRegisterVsmPartitionConfig::new(); +config.set_enable_vtl_protection(true); +assert_eq!(config.enable_vtl_protection(), true); +``` + +### Builder pattern (auto-generated): +```rust +let config = HvRegisterVsmPartitionConfig::new() + .with_enable_vtl_protection(true) + .with_intercept_page(true); +``` + +### Compatibility with existing u64 APIs: +```rust +let raw_value = config.as_u64(); +let restored = HvRegisterVsmPartitionConfig::from_u64(raw_value); +``` + +## Guidelines for Future Bit Field Structures + +When creating new packed structures with bit fields: + +1. **Use `modular-bitfield` for complex structures** (3+ fields or mixed field sizes) +2. **Import required types:** + ```rust + use modular_bitfield::prelude::*; + use modular_bitfield::specifiers::{B4, B8, B16, B32, B51}; // as needed + ``` + +3. **Follow this pattern:** + ```rust + #[bitfield] + #[derive(Clone, Copy, Default)] + #[repr(C)] + pub struct MyBitfield { + pub field1: bool, // 1 bit + pub field2: B4, // 4 bits + pub field3: u8, // 8 bits + #[skip] + reserved: B3, // 3 reserved bits + } + ``` + +4. **Add compatibility methods when needed:** + ```rust + impl MyBitfield { + pub fn as_raw(&self) -> u32 { + u32::from_le_bytes(self.into_bytes()) + } + + pub fn from_raw(value: u32) -> Self { + Self::from_bytes(value.to_le_bytes()) + } + } + ``` + +5. **Keep existing bitflags usage** for simple flag combinations - it's still the best choice for that use case. + +## Testing + +All improvements include comprehensive tests verifying: +- Field access correctness +- Size and layout compatibility +- Round-trip serialization +- Builder pattern functionality +- Default values + +Run the tests with: +```bash +cd litebox_platform_lvbs +cargo test mshv::tests +``` + +## References + +- Issue: #136 +- `modular-bitfield` crate: https://crates.io/crates/modular-bitfield +- Alternative `bitfield` crate: https://crates.io/crates/bitfield (considered but not used) \ No newline at end of file From e9bc9aed5b5e65d3d97f51775b23e440c122450c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 23 Jun 2025 17:14:51 +0000 Subject: [PATCH 05/10] Convert all remaining bitfield structures to use modular-bitfield Co-authored-by: sangho2 <3938640+sangho2@users.noreply.github.com> --- BITFIELD_IMPROVEMENTS.md | 165 ------- litebox_platform_lvbs/src/mshv/hvcall.rs | 4 +- litebox_platform_lvbs/src/mshv/mod.rs | 423 ++++++++++++------ litebox_platform_lvbs/src/mshv/vsm.rs | 4 +- .../src/mshv/vsm_intercept.rs | 10 +- 5 files changed, 287 insertions(+), 319 deletions(-) delete mode 100644 BITFIELD_IMPROVEMENTS.md diff --git a/BITFIELD_IMPROVEMENTS.md b/BITFIELD_IMPROVEMENTS.md deleted file mode 100644 index 9763953a9..000000000 --- a/BITFIELD_IMPROVEMENTS.md +++ /dev/null @@ -1,165 +0,0 @@ -# Bit Field Handling Improvements - -This document describes the improvements made to bit field handling in LiteBox, specifically addressing issue #136. - -## Overview - -The codebase previously used manual bit manipulation with masks and shifts for packed structures, which was error-prone and verbose. We have improved this by adopting the `modular-bitfield` crate for complex bit field structures. - -## Changes Made - -### 1. Added modular-bitfield dependency - -Added `modular-bitfield = { version = "0.11.2", default-features = false }` to `litebox_platform_lvbs/Cargo.toml`. - -### 2. Improved HvInputVtl structure - -**Before (manual bit manipulation):** -```rust -#[derive(Default, Clone, Copy)] -#[repr(C, packed)] -pub struct HvInputVtl { - _as_uint8: u8, - // target_vtl: 4, use_target_vtl: 1, reserved_z: 3 -} - -impl HvInputVtl { - const TARGET_VTL_MASK: u8 = 0xf; - const USE_TARGET_VTL_MASK: u8 = 0x10; - const USE_TARGET_VTL_SHIFT: u8 = 4; - - pub fn set_target_vtl(&mut self, target_vtl: u8) { - self._as_uint8 |= target_vtl & Self::TARGET_VTL_MASK; - } - // ... more manual bit manipulation -} -``` - -**After (declarative bitfield):** -```rust -#[bitfield] -#[derive(Clone, Copy, Default)] -#[repr(C)] -pub struct HvInputVtl { - pub target_vtl: B4, - pub use_target_vtl: bool, - #[skip] - __: B3, -} -``` - -### 3. Improved HvRegisterVsmPartitionConfig structure - -**Before:** 110+ lines with 20+ constants and repetitive manual methods. - -**After:** 30 lines with clear field declarations: -```rust -#[bitfield] -#[derive(Clone, Copy, Default)] -#[repr(C)] -pub struct HvRegisterVsmPartitionConfig { - pub enable_vtl_protection: bool, - pub default_vtl_protection_mask: B4, - pub zero_memory_on_reset: bool, - pub deny_lower_vtl_startup: bool, - pub intercept_acceptance: bool, - pub intercept_enable_vtl_protection: bool, - pub intercept_vp_startup: bool, - pub intercept_cpuid_unimplemented: bool, - pub intercept_unrecoverable_exception: bool, - pub intercept_page: bool, - #[skip] - __: B51, -} -``` - -## Benefits - -1. **Readability**: Field layouts are self-documenting -2. **Safety**: Compile-time bounds checking prevents overflow -3. **Maintainability**: No manual mask/shift calculations -4. **Functionality**: Auto-generated getters, setters, and builder methods -5. **Performance**: Zero runtime overhead - -## Usage Patterns - -### Basic field access: -```rust -let mut config = HvRegisterVsmPartitionConfig::new(); -config.set_enable_vtl_protection(true); -assert_eq!(config.enable_vtl_protection(), true); -``` - -### Builder pattern (auto-generated): -```rust -let config = HvRegisterVsmPartitionConfig::new() - .with_enable_vtl_protection(true) - .with_intercept_page(true); -``` - -### Compatibility with existing u64 APIs: -```rust -let raw_value = config.as_u64(); -let restored = HvRegisterVsmPartitionConfig::from_u64(raw_value); -``` - -## Guidelines for Future Bit Field Structures - -When creating new packed structures with bit fields: - -1. **Use `modular-bitfield` for complex structures** (3+ fields or mixed field sizes) -2. **Import required types:** - ```rust - use modular_bitfield::prelude::*; - use modular_bitfield::specifiers::{B4, B8, B16, B32, B51}; // as needed - ``` - -3. **Follow this pattern:** - ```rust - #[bitfield] - #[derive(Clone, Copy, Default)] - #[repr(C)] - pub struct MyBitfield { - pub field1: bool, // 1 bit - pub field2: B4, // 4 bits - pub field3: u8, // 8 bits - #[skip] - reserved: B3, // 3 reserved bits - } - ``` - -4. **Add compatibility methods when needed:** - ```rust - impl MyBitfield { - pub fn as_raw(&self) -> u32 { - u32::from_le_bytes(self.into_bytes()) - } - - pub fn from_raw(value: u32) -> Self { - Self::from_bytes(value.to_le_bytes()) - } - } - ``` - -5. **Keep existing bitflags usage** for simple flag combinations - it's still the best choice for that use case. - -## Testing - -All improvements include comprehensive tests verifying: -- Field access correctness -- Size and layout compatibility -- Round-trip serialization -- Builder pattern functionality -- Default values - -Run the tests with: -```bash -cd litebox_platform_lvbs -cargo test mshv::tests -``` - -## References - -- Issue: #136 -- `modular-bitfield` crate: https://crates.io/crates/modular-bitfield -- Alternative `bitfield` crate: https://crates.io/crates/bitfield (considered but not used) \ No newline at end of file diff --git a/litebox_platform_lvbs/src/mshv/hvcall.rs b/litebox_platform_lvbs/src/mshv/hvcall.rs index 4c9c4e44c..2fd56a00f 100644 --- a/litebox_platform_lvbs/src/mshv/hvcall.rs +++ b/litebox_platform_lvbs/src/mshv/hvcall.rs @@ -129,8 +129,8 @@ pub fn init() -> Result<(), HypervError> { debug_serial_println!("HV_X64_MSR_SIMP: {:#x}", rdmsr(HV_X64_MSR_SIMP)); let mut sint = HvSynicSint::new(); - sint.set_vector(u64::from(HYPERVISOR_CALLBACK_VECTOR)); - sint.set_auto_eoi(); + sint.set_vector_u64(u64::from(HYPERVISOR_CALLBACK_VECTOR)); + sint.set_auto_eoi_flag(); wrmsr(HV_X64_MSR_SINT0, sint.as_uint64()); if get_core_id() == 0 { diff --git a/litebox_platform_lvbs/src/mshv/mod.rs b/litebox_platform_lvbs/src/mshv/mod.rs index 31b1fd65d..d11d648b8 100644 --- a/litebox_platform_lvbs/src/mshv/mod.rs +++ b/litebox_platform_lvbs/src/mshv/mod.rs @@ -12,7 +12,7 @@ pub mod vtl_switch; use crate::mshv::vtl1_mem_layout::PAGE_SIZE; use num_enum::{IntoPrimitive, TryFromPrimitive}; use modular_bitfield::prelude::*; -use modular_bitfield::specifiers::{B4, B51}; +use modular_bitfield::specifiers::{B3, B4, B7, B8, B16, B31, B32, B45, B51, B62}; pub const HV_HYPERCALL_REP_COMP_MASK: u64 = 0xfff_0000_0000; pub const HV_HYPERCALL_REP_COMP_OFFSET: u32 = 32; @@ -381,43 +381,35 @@ impl HvGetVpRegistersOutput { } } -#[derive(Default, Clone, Copy)] -#[repr(C, packed)] +#[bitfield] +#[derive(Clone, Copy, Default)] +#[repr(C)] pub struct HvNestedEnlightenmentsControlFeatures { - _raw: u32, - // union of - // directhypercall: 1, reserved: 31 + pub direct_hypercall: bool, + #[skip] + __: B31, } impl HvNestedEnlightenmentsControlFeatures { - const DIRECTHYPERCALL_MASK: u32 = 0x1; - pub fn new() -> Self { - HvNestedEnlightenmentsControlFeatures { _raw: 0 } - } - - #[expect(clippy::used_underscore_binding)] - pub fn set_direct_hypercall(&mut self, direct_hypercall: u32) { - self._raw |= direct_hypercall & Self::DIRECTHYPERCALL_MASK; + /// Set direct hypercall flag from u32 (for compatibility) + pub fn set_direct_hypercall_u32(&mut self, direct_hypercall: u32) { + self.set_direct_hypercall(direct_hypercall != 0); } } -#[derive(Default, Clone, Copy)] -#[repr(C, packed)] +#[bitfield] +#[derive(Clone, Copy, Default)] +#[repr(C)] pub struct HvNestedEnlightenmentsControlHypercallControls { - _raw: u32, - // union of - // inter_partition_comm: 1, reserved: 31 + pub inter_partition_comm: bool, + #[skip] + __: B31, } impl HvNestedEnlightenmentsControlHypercallControls { - const INTER_PARTITION_COMM_MASK: u32 = 0x1; - pub fn new() -> Self { - HvNestedEnlightenmentsControlHypercallControls { _raw: 0 } - } - - #[expect(clippy::used_underscore_binding)] - pub fn set_inter_partition_comm(&mut self, inter_partition_comm: u32) { - self._raw |= inter_partition_comm & Self::INTER_PARTITION_COMM_MASK; + /// Set inter partition comm flag from u32 (for compatibility) + pub fn set_inter_partition_comm_u32(&mut self, inter_partition_comm: u32) { + self.set_inter_partition_comm(inter_partition_comm != 0); } } @@ -517,44 +509,29 @@ impl Default for HvInputModifyVtlProtectionMask { } } -#[derive(Default, Clone, Copy)] -#[repr(C, packed)] +#[bitfield] +#[derive(Clone, Copy, Default)] +#[repr(C)] pub struct HvRegisterVsmVpSecureVtlConfig { - _as_u64: u64, - // union of - // mbec_enabled : 1; - // tlb_locked : 1; - // reserved: 62; + pub mbec_enabled: bool, + pub tlb_locked: bool, + #[skip] + __: B62, } impl HvRegisterVsmVpSecureVtlConfig { - const MBEC_ENABLED_MASK: u64 = 0x1; - const TLB_LOCKED_MASK: u64 = 0x2; - const MBEC_ENABLED_SHIFT: u64 = 0; - const TLB_LOCKED_SHIFT: u64 = 1; - - pub fn new() -> Self { - HvRegisterVsmVpSecureVtlConfig { - ..Default::default() - } - } - - #[expect(clippy::used_underscore_binding)] pub fn as_u64(&self) -> u64 { - self._as_u64 - } - - #[expect(clippy::used_underscore_binding)] - fn set_sub_config(&mut self, mask: u64, shift: u64, value: u64) { - self._as_u64 |= (value << shift) & mask; + u64::from_le_bytes(self.into_bytes()) } - pub fn set_mbec_enabled(&mut self) { - self.set_sub_config(Self::MBEC_ENABLED_MASK, Self::MBEC_ENABLED_SHIFT, 1); + /// Enable MBEC (for compatibility) + pub fn set_mbec_enabled_flag(&mut self) { + self.set_mbec_enabled(true); } - pub fn set_tlb_locked(&mut self) { - self.set_sub_config(Self::TLB_LOCKED_MASK, Self::TLB_LOCKED_SHIFT, 1); + /// Enable TLB locked (for compatibility) + pub fn set_tlb_locked_flag(&mut self) { + self.set_tlb_locked(true); } } @@ -761,59 +738,43 @@ impl HvMessagePage { } } -#[derive(Default, Clone, Copy)] -#[repr(C, packed)] +#[bitfield] +#[derive(Clone, Copy, Default)] +#[repr(C)] pub struct HvSynicSint { - _as_uint64: u64, - // union of - // vector: 8; - // reserved1: 8; - // masked: 1; - // auto_eoi: 1; - // polling: 1; - // reserved2: 45; + pub vector: B8, + #[skip] + __reserved1: B8, + pub masked: bool, + pub auto_eoi: bool, + pub polling: bool, + #[skip] + __reserved2: B45, } impl HvSynicSint { - const VECTOR_MASK: u64 = 0xff; - const MASKED_MASK: u64 = 0x1_0000; - const AUTO_EOI_MASK: u64 = 0x2_0000; - const POLLING_MASK: u64 = 0x4_0000; - const VECTOR_SHIFT: u64 = 0; - const MASKED_SHIFT: u64 = 16; - const AUTO_EOI_SHIFT: u64 = 17; - const POLLING_SHIFT: u64 = 18; - - pub fn new() -> Self { - HvSynicSint { - ..Default::default() - } - } - - #[expect(clippy::used_underscore_binding)] pub fn as_uint64(&self) -> u64 { - self._as_uint64 - } - - #[expect(clippy::used_underscore_binding)] - fn set_sub_config(&mut self, mask: u64, shift: u64, value: u64) { - self._as_uint64 |= (value << shift) & mask; + u64::from_le_bytes(self.into_bytes()) } - pub fn set_vector(&mut self, vector: u64) { - self.set_sub_config(Self::VECTOR_MASK, Self::VECTOR_SHIFT, vector); + /// Set vector from u64 (for compatibility) + pub fn set_vector_u64(&mut self, vector: u64) { + self.set_vector((vector as u8).into()); } - pub fn set_masked(&mut self) { - self.set_sub_config(Self::MASKED_MASK, Self::MASKED_SHIFT, 1); + /// Set masked flag (for compatibility) + pub fn set_masked_flag(&mut self) { + self.set_masked(true); } - pub fn set_auto_eoi(&mut self) { - self.set_sub_config(Self::AUTO_EOI_MASK, Self::AUTO_EOI_SHIFT, 1); + /// Set auto_eoi flag (for compatibility) + pub fn set_auto_eoi_flag(&mut self) { + self.set_auto_eoi(true); } - pub fn set_polling(&mut self) { - self.set_sub_config(Self::POLLING_MASK, Self::POLLING_SHIFT, 1); + /// Set polling flag (for compatibility) + pub fn set_polling_flag(&mut self) { + self.set_polling(true); } } @@ -888,70 +849,49 @@ pub struct HvMsrInterceptMessage { pub rax: u64, } -#[derive(Default, Clone, Copy)] -#[repr(C, packed)] +#[bitfield] +#[derive(Clone, Copy, Default)] +#[repr(C)] pub struct HvPendingExceptionEvent { - _as_u64: u64, - // union of - // event_pending: 1; - // event_type: 3; - // reserved_0: 4; - // deliver_error_code: 1; - // reserved_1: 7; - // vector: 16; - // error_code: 32; + pub event_pending: bool, + pub event_type: B3, + #[skip] + __reserved_0: B4, + pub deliver_error_code: bool, + #[skip] + __reserved_1: B7, + pub vector: B16, + pub error_code: B32, } impl HvPendingExceptionEvent { - const EVENT_PENDING_MASK: u64 = 0x1; - const EVENT_TYPE_MASK: u64 = 0xe; - const DELIVER_ERROR_CODE_MASK: u64 = 0x100; - const VECTOR_MASK: u64 = 0xffff_0000; - const ERROR_CODE_MASK: u64 = 0xffff_ffff_0000_0000; - const EVENT_PENDING_SHIFT: u64 = 0; - const EVENT_TYPE_SHIFT: u64 = 1; - const DELIVER_ERROR_CODE_SHIFT: u64 = 3; - const VECTOR_SHIFT: u64 = 16; - const ERROR_CODE_SHIFT: u64 = 32; - - pub fn new() -> Self { - HvPendingExceptionEvent { - ..Default::default() - } - } - - #[expect(clippy::used_underscore_binding)] pub fn as_u64(&self) -> u64 { - self._as_u64 - } - - #[expect(clippy::used_underscore_binding)] - fn set_sub_config(&mut self, mask: u64, shift: u64, value: u64) { - self._as_u64 |= (value << shift) & mask; + u64::from_le_bytes(self.into_bytes()) } - pub fn set_event_pending(&mut self) { - self.set_sub_config(Self::EVENT_PENDING_MASK, Self::EVENT_PENDING_SHIFT, 1); + /// Set event pending flag (for compatibility) + pub fn set_event_pending_flag(&mut self) { + self.set_event_pending(true); } - pub fn set_event_type(&mut self, event_type: u64) { - self.set_sub_config(Self::EVENT_TYPE_MASK, Self::EVENT_TYPE_SHIFT, event_type); + /// Set event type from u64 (for compatibility) + pub fn set_event_type_u64(&mut self, event_type: u64) { + self.set_event_type((event_type as u8).into()); } - pub fn set_deliver_error_code(&mut self) { - self.set_sub_config( - Self::DELIVER_ERROR_CODE_MASK, - Self::DELIVER_ERROR_CODE_SHIFT, - 1, - ); + /// Set deliver error code flag (for compatibility) + pub fn set_deliver_error_code_flag(&mut self) { + self.set_deliver_error_code(true); } - pub fn set_vector(&mut self, vector: u64) { - self.set_sub_config(Self::VECTOR_MASK, Self::VECTOR_SHIFT, vector); + /// Set vector from u64 (for compatibility) + pub fn set_vector_u64(&mut self, vector: u64) { + self.set_vector((vector as u16).into()); } - pub fn set_error_code(&mut self, error_code: u64) { - self.set_sub_config(Self::ERROR_CODE_MASK, Self::ERROR_CODE_SHIFT, error_code); + /// Set error code from u64 (for compatibility) + pub fn set_error_code_u64(&mut self, error_code: u64) { + self.set_error_code((error_code as u32).into()); } } @@ -1040,4 +980,197 @@ mod tests { assert_eq!(chained_config.intercept_vp_startup(), true); assert_eq!(chained_config.zero_memory_on_reset(), false); } + + #[test] + fn test_hv_nested_enlightenments_control_features_bitfield() { + // Test the new bitfield-based HvNestedEnlightenmentsControlFeatures implementation + + let mut features = HvNestedEnlightenmentsControlFeatures::new(); + + // Test setting direct hypercall flag + features.set_direct_hypercall(true); + assert_eq!(features.direct_hypercall(), true); + + // Test compatibility method + let mut features2 = HvNestedEnlightenmentsControlFeatures::new(); + features2.set_direct_hypercall_u32(1); + assert_eq!(features2.direct_hypercall(), true); + + features2.set_direct_hypercall_u32(0); + assert_eq!(features2.direct_hypercall(), false); + + // Test size - should be 4 bytes (32 bits) + assert_eq!(core::mem::size_of::(), 4); + + // Test that Default trait works + let default_features = HvNestedEnlightenmentsControlFeatures::default(); + assert_eq!(default_features.direct_hypercall(), false); + } + + #[test] + fn test_hv_nested_enlightenments_control_hypercall_controls_bitfield() { + // Test the new bitfield-based HvNestedEnlightenmentsControlHypercallControls implementation + + let mut controls = HvNestedEnlightenmentsControlHypercallControls::new(); + + // Test setting inter partition comm flag + controls.set_inter_partition_comm(true); + assert_eq!(controls.inter_partition_comm(), true); + + // Test compatibility method + let mut controls2 = HvNestedEnlightenmentsControlHypercallControls::new(); + controls2.set_inter_partition_comm_u32(1); + assert_eq!(controls2.inter_partition_comm(), true); + + controls2.set_inter_partition_comm_u32(0); + assert_eq!(controls2.inter_partition_comm(), false); + + // Test size - should be 4 bytes (32 bits) + assert_eq!(core::mem::size_of::(), 4); + + // Test that Default trait works + let default_controls = HvNestedEnlightenmentsControlHypercallControls::default(); + assert_eq!(default_controls.inter_partition_comm(), false); + } + + #[test] + fn test_hv_register_vsm_vp_secure_vtl_config_bitfield() { + // Test the new bitfield-based HvRegisterVsmVpSecureVtlConfig implementation + + let mut config = HvRegisterVsmVpSecureVtlConfig::new(); + + // Test individual boolean flags + config.set_mbec_enabled(true); + assert_eq!(config.mbec_enabled(), true); + + config.set_tlb_locked(true); + assert_eq!(config.tlb_locked(), true); + + // Test compatibility methods + let mut config2 = HvRegisterVsmVpSecureVtlConfig::new(); + config2.set_mbec_enabled_flag(); + assert_eq!(config2.mbec_enabled(), true); + + config2.set_tlb_locked_flag(); + assert_eq!(config2.tlb_locked(), true); + + // Test size - should be 8 bytes (64 bits) + assert_eq!(core::mem::size_of::(), 8); + + // Test as_u64 method + let config_u64 = config.as_u64(); + assert_ne!(config_u64, 0); // Should have some bits set + + // Test that Default trait works + let default_config = HvRegisterVsmVpSecureVtlConfig::default(); + assert_eq!(default_config.mbec_enabled(), false); + assert_eq!(default_config.tlb_locked(), false); + assert_eq!(default_config.as_u64(), 0); + } + + #[test] + fn test_hv_synic_sint_bitfield() { + // Test the new bitfield-based HvSynicSint implementation + + let mut sint = HvSynicSint::new(); + + // Test vector field (8 bits) + sint.set_vector(0xf3_u8.into()); + assert_eq!(sint.vector() as u8, 0xf3); + + // Test boolean flags + sint.set_masked(true); + assert_eq!(sint.masked(), true); + + sint.set_auto_eoi(true); + assert_eq!(sint.auto_eoi(), true); + + sint.set_polling(true); + assert_eq!(sint.polling(), true); + + // Test compatibility methods + let mut sint2 = HvSynicSint::new(); + sint2.set_vector_u64(0xf3); + assert_eq!(sint2.vector() as u8, 0xf3); + + sint2.set_masked_flag(); + assert_eq!(sint2.masked(), true); + + sint2.set_auto_eoi_flag(); + assert_eq!(sint2.auto_eoi(), true); + + sint2.set_polling_flag(); + assert_eq!(sint2.polling(), true); + + // Test size - should be 8 bytes (64 bits) + assert_eq!(core::mem::size_of::(), 8); + + // Test as_uint64 method + let sint_u64 = sint.as_uint64(); + assert_ne!(sint_u64, 0); // Should have some bits set + + // Test that Default trait works + let default_sint = HvSynicSint::default(); + assert_eq!(default_sint.vector() as u8, 0); + assert_eq!(default_sint.masked(), false); + assert_eq!(default_sint.auto_eoi(), false); + assert_eq!(default_sint.polling(), false); + } + + #[test] + fn test_hv_pending_exception_event_bitfield() { + // Test the new bitfield-based HvPendingExceptionEvent implementation + + let mut exception = HvPendingExceptionEvent::new(); + + // Test boolean flags + exception.set_event_pending(true); + assert_eq!(exception.event_pending(), true); + + exception.set_deliver_error_code(true); + assert_eq!(exception.deliver_error_code(), true); + + // Test multi-bit fields + exception.set_event_type(0b101_u8.into()); // 3 bits + assert_eq!(exception.event_type() as u8, 0b101); + + exception.set_vector(0x1234_u16.into()); // 16 bits + assert_eq!(exception.vector() as u16, 0x1234); + + exception.set_error_code(0x87654321_u32.into()); // 32 bits + assert_eq!(exception.error_code() as u32, 0x87654321); + + // Test compatibility methods + let mut exception2 = HvPendingExceptionEvent::new(); + exception2.set_event_pending_flag(); + assert_eq!(exception2.event_pending(), true); + + exception2.set_deliver_error_code_flag(); + assert_eq!(exception2.deliver_error_code(), true); + + exception2.set_event_type_u64(7); + assert_eq!(exception2.event_type() as u8, 7); + + exception2.set_vector_u64(0xabcd); + assert_eq!(exception2.vector() as u16, 0xabcd); + + exception2.set_error_code_u64(0x12345678); + assert_eq!(exception2.error_code() as u32, 0x12345678); + + // Test size - should be 8 bytes (64 bits) + assert_eq!(core::mem::size_of::(), 8); + + // Test as_u64 method + let exception_u64 = exception.as_u64(); + assert_ne!(exception_u64, 0); // Should have some bits set + + // Test that Default trait works + let default_exception = HvPendingExceptionEvent::default(); + assert_eq!(default_exception.event_pending(), false); + assert_eq!(default_exception.deliver_error_code(), false); + assert_eq!(default_exception.event_type() as u8, 0); + assert_eq!(default_exception.vector() as u16, 0); + assert_eq!(default_exception.error_code() as u32, 0); + assert_eq!(default_exception.as_u64(), 0); + } } diff --git a/litebox_platform_lvbs/src/mshv/vsm.rs b/litebox_platform_lvbs/src/mshv/vsm.rs index 02a0b15a3..23850d5ce 100644 --- a/litebox_platform_lvbs/src/mshv/vsm.rs +++ b/litebox_platform_lvbs/src/mshv/vsm.rs @@ -167,8 +167,8 @@ pub fn mshv_vsm_secure_config_vtl0() -> Result { debug_serial_println!("VSM: Secure VTL0 configuration"); let mut config = HvRegisterVsmVpSecureVtlConfig::new(); - config.set_mbec_enabled(); - config.set_tlb_locked(); + config.set_mbec_enabled_flag(); + config.set_tlb_locked_flag(); hvcall_set_vp_registers(HV_REGISTER_VSM_VP_SECURE_CONFIG_VTL0, config.as_u64()) .map_err(|_| Errno::EFAULT)?; diff --git a/litebox_platform_lvbs/src/mshv/vsm_intercept.rs b/litebox_platform_lvbs/src/mshv/vsm_intercept.rs index 6211dd8d7..c379e9fa5 100644 --- a/litebox_platform_lvbs/src/mshv/vsm_intercept.rs +++ b/litebox_platform_lvbs/src/mshv/vsm_intercept.rs @@ -147,13 +147,13 @@ fn advance_vtl0_rip(int_msg_hdr: &HvInterceptMessageHeader) -> Result Result { let mut exception = HvPendingExceptionEvent::new(); - exception.set_event_pending(); - exception.set_event_type(0); - exception.set_deliver_error_code(); - exception.set_vector(u64::from( + exception.set_event_pending_flag(); + exception.set_event_type_u64(0); + exception.set_deliver_error_code_flag(); + exception.set_vector_u64(u64::from( x86_64::structures::idt::ExceptionVector::GeneralProtection as u8, )); - exception.set_error_code(0); + exception.set_error_code_u64(0); hvcall_set_vp_vtl0_registers(HV_REGISTER_PENDING_EVENT0, exception.as_u64()) } From ea4cb6431035e2fc61fe374d2820fc801870a410 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 23 Jun 2025 17:49:56 +0000 Subject: [PATCH 06/10] Update bitfield usage and remove wrapper methods per review feedback Co-authored-by: sangho2 <3938640+sangho2@users.noreply.github.com> --- litebox_platform_lvbs/src/mshv/hvcall.rs | 4 +- litebox_platform_lvbs/src/mshv/hvcall_vp.rs | 32 ++-- litebox_platform_lvbs/src/mshv/mod.rs | 142 ++++-------------- litebox_platform_lvbs/src/mshv/vsm.rs | 6 +- .../src/mshv/vsm_intercept.rs | 12 +- 5 files changed, 56 insertions(+), 140 deletions(-) diff --git a/litebox_platform_lvbs/src/mshv/hvcall.rs b/litebox_platform_lvbs/src/mshv/hvcall.rs index 2fd56a00f..19f7523f2 100644 --- a/litebox_platform_lvbs/src/mshv/hvcall.rs +++ b/litebox_platform_lvbs/src/mshv/hvcall.rs @@ -129,8 +129,8 @@ pub fn init() -> Result<(), HypervError> { debug_serial_println!("HV_X64_MSR_SIMP: {:#x}", rdmsr(HV_X64_MSR_SIMP)); let mut sint = HvSynicSint::new(); - sint.set_vector_u64(u64::from(HYPERVISOR_CALLBACK_VECTOR)); - sint.set_auto_eoi_flag(); + sint.set_vector((HYPERVISOR_CALLBACK_VECTOR as u8).into()); + sint.set_auto_eoi(true); wrmsr(HV_X64_MSR_SINT0, sint.as_uint64()); if get_core_id() == 0 { diff --git a/litebox_platform_lvbs/src/mshv/hvcall_vp.rs b/litebox_platform_lvbs/src/mshv/hvcall_vp.rs index 50dbddf9a..d6da8b326 100644 --- a/litebox_platform_lvbs/src/mshv/hvcall_vp.rs +++ b/litebox_platform_lvbs/src/mshv/hvcall_vp.rs @@ -142,22 +142,22 @@ fn hv_vtl_populate_vp_context(input: &mut HvEnableVpVtl, tss: u64, rip: u64, rsp // We only support 64-bit long mode for now, so most of the segment register fields are ignored. input.vp_context.cs.selector = SegmentSelector::new(1, PrivilegeLevel::Ring0).0; input.vp_context.cs.set_attributes( - SegmentRegisterAttributeFlags::ACCESSED.bits() - | SegmentRegisterAttributeFlags::WRITABLE.bits() - | SegmentRegisterAttributeFlags::EXECUTABLE.bits() - | SegmentRegisterAttributeFlags::USER_SEGMENT.bits() - | SegmentRegisterAttributeFlags::PRESENT.bits() - | SegmentRegisterAttributeFlags::AVAILABLE.bits() - | SegmentRegisterAttributeFlags::LONG_MODE.bits(), + SegmentRegisterAttributeFlags::ACCESSED + | SegmentRegisterAttributeFlags::WRITABLE + | SegmentRegisterAttributeFlags::EXECUTABLE + | SegmentRegisterAttributeFlags::USER_SEGMENT + | SegmentRegisterAttributeFlags::PRESENT + | SegmentRegisterAttributeFlags::AVAILABLE + | SegmentRegisterAttributeFlags::LONG_MODE, ); input.vp_context.ss.selector = SegmentSelector::new(2, PrivilegeLevel::Ring0).0; input.vp_context.ss.set_attributes( - SegmentRegisterAttributeFlags::ACCESSED.bits() - | SegmentRegisterAttributeFlags::WRITABLE.bits() - | SegmentRegisterAttributeFlags::USER_SEGMENT.bits() - | SegmentRegisterAttributeFlags::PRESENT.bits() - | SegmentRegisterAttributeFlags::AVAILABLE.bits(), + SegmentRegisterAttributeFlags::ACCESSED + | SegmentRegisterAttributeFlags::WRITABLE + | SegmentRegisterAttributeFlags::USER_SEGMENT + | SegmentRegisterAttributeFlags::PRESENT + | SegmentRegisterAttributeFlags::AVAILABLE, ); input.vp_context.tr.selector = SegmentSelector::new(3, PrivilegeLevel::Ring0).0; @@ -165,10 +165,10 @@ fn hv_vtl_populate_vp_context(input: &mut HvEnableVpVtl, tss: u64, rip: u64, rsp input.vp_context.tr.limit = u32::try_from(core::mem::size_of::()).unwrap() - 1; input.vp_context.tr.set_attributes( - SegmentRegisterAttributeFlags::ACCESSED.bits() - | SegmentRegisterAttributeFlags::WRITABLE.bits() - | SegmentRegisterAttributeFlags::EXECUTABLE.bits() - | SegmentRegisterAttributeFlags::PRESENT.bits(), + SegmentRegisterAttributeFlags::ACCESSED + | SegmentRegisterAttributeFlags::WRITABLE + | SegmentRegisterAttributeFlags::EXECUTABLE + | SegmentRegisterAttributeFlags::PRESENT, ); } diff --git a/litebox_platform_lvbs/src/mshv/mod.rs b/litebox_platform_lvbs/src/mshv/mod.rs index d11d648b8..3e5ff4b84 100644 --- a/litebox_platform_lvbs/src/mshv/mod.rs +++ b/litebox_platform_lvbs/src/mshv/mod.rs @@ -142,7 +142,7 @@ bitflags::bitflags! { } bitflags::bitflags! { - #[derive(Debug, PartialEq)] + #[derive(Debug, PartialEq, Clone, Copy, Default)] pub struct SegmentRegisterAttributeFlags: u16 { const ACCESSED = 1 << 0; const WRITABLE = 1 << 1; @@ -166,13 +166,7 @@ pub struct HvX64SegmentRegister { pub base: u64, pub limit: u32, pub selector: u16, - - _attributes: u16, - // union of - // segment_type: 4, non_system_segment: 1, - // descriptor_privilege_level: 2, present: 1, - // reserved: 4, available: 1, _long: 1, - // _default: 1, granularity: 1 + pub attributes: SegmentRegisterAttributeFlags, } impl HvX64SegmentRegister { @@ -183,9 +177,12 @@ impl HvX64SegmentRegister { } } - #[expect(clippy::used_underscore_binding)] - pub fn set_attributes(&mut self, attrs: u16) { - self._attributes = attrs; + pub fn set_attributes(&mut self, attrs: SegmentRegisterAttributeFlags) { + self.attributes = attrs; + } + + pub fn get_attributes(&self) -> SegmentRegisterAttributeFlags { + self.attributes } } @@ -259,11 +256,6 @@ impl HvInputVtl { pub fn target_vtl_value(&self) -> u8 { self.target_vtl() as u8 } - - /// Sets the target VTL from a u8 value - pub fn set_target_vtl_value(&mut self, target_vtl: u8) { - self.set_target_vtl(target_vtl.into()); - } } #[derive(Default, Clone, Copy)] @@ -390,13 +382,6 @@ pub struct HvNestedEnlightenmentsControlFeatures { __: B31, } -impl HvNestedEnlightenmentsControlFeatures { - /// Set direct hypercall flag from u32 (for compatibility) - pub fn set_direct_hypercall_u32(&mut self, direct_hypercall: u32) { - self.set_direct_hypercall(direct_hypercall != 0); - } -} - #[bitfield] #[derive(Clone, Copy, Default)] #[repr(C)] @@ -406,13 +391,6 @@ pub struct HvNestedEnlightenmentsControlHypercallControls { __: B31, } -impl HvNestedEnlightenmentsControlHypercallControls { - /// Set inter partition comm flag from u32 (for compatibility) - pub fn set_inter_partition_comm_u32(&mut self, inter_partition_comm: u32) { - self.set_inter_partition_comm(inter_partition_comm != 0); - } -} - #[expect(non_snake_case)] #[derive(Default, Clone, Copy)] #[repr(C, packed)] @@ -523,16 +501,6 @@ impl HvRegisterVsmVpSecureVtlConfig { pub fn as_u64(&self) -> u64 { u64::from_le_bytes(self.into_bytes()) } - - /// Enable MBEC (for compatibility) - pub fn set_mbec_enabled_flag(&mut self) { - self.set_mbec_enabled(true); - } - - /// Enable TLB locked (for compatibility) - pub fn set_tlb_locked_flag(&mut self) { - self.set_tlb_locked(true); - } } #[bitfield] @@ -565,11 +533,6 @@ impl HvRegisterVsmPartitionConfig { Self::from_bytes(value.to_le_bytes()) } - /// Set the default VTL protection mask from a u64 value - pub fn set_default_vtl_protection_mask_value(&mut self, mask: u64) { - self.set_default_vtl_protection_mask((mask as u8).into()); - } - /// Get the default VTL protection mask as a u64 value pub fn default_vtl_protection_mask_value(&self) -> u64 { self.default_vtl_protection_mask() as u64 @@ -756,26 +719,6 @@ impl HvSynicSint { pub fn as_uint64(&self) -> u64 { u64::from_le_bytes(self.into_bytes()) } - - /// Set vector from u64 (for compatibility) - pub fn set_vector_u64(&mut self, vector: u64) { - self.set_vector((vector as u8).into()); - } - - /// Set masked flag (for compatibility) - pub fn set_masked_flag(&mut self) { - self.set_masked(true); - } - - /// Set auto_eoi flag (for compatibility) - pub fn set_auto_eoi_flag(&mut self) { - self.set_auto_eoi(true); - } - - /// Set polling flag (for compatibility) - pub fn set_polling_flag(&mut self) { - self.set_polling(true); - } } #[derive(Default, Clone, Copy)] @@ -868,31 +811,6 @@ impl HvPendingExceptionEvent { pub fn as_u64(&self) -> u64 { u64::from_le_bytes(self.into_bytes()) } - - /// Set event pending flag (for compatibility) - pub fn set_event_pending_flag(&mut self) { - self.set_event_pending(true); - } - - /// Set event type from u64 (for compatibility) - pub fn set_event_type_u64(&mut self, event_type: u64) { - self.set_event_type((event_type as u8).into()); - } - - /// Set deliver error code flag (for compatibility) - pub fn set_deliver_error_code_flag(&mut self) { - self.set_deliver_error_code(true); - } - - /// Set vector from u64 (for compatibility) - pub fn set_vector_u64(&mut self, vector: u64) { - self.set_vector((vector as u16).into()); - } - - /// Set error code from u64 (for compatibility) - pub fn set_error_code_u64(&mut self, error_code: u64) { - self.set_error_code((error_code as u32).into()); - } } #[cfg(test)] @@ -914,7 +832,7 @@ mod tests { // Test individual field manipulation let mut vtl = HvInputVtl::new(); - vtl.set_target_vtl_value(10); + vtl.set_target_vtl(10_u8.into()); vtl.set_use_target_vtl(true); assert_eq!(vtl.target_vtl_value(), 10); assert_eq!(vtl.use_target_vtl(), true); @@ -949,7 +867,7 @@ mod tests { assert_eq!(config.intercept_page(), true); // Test the 4-bit protection mask field - config.set_default_vtl_protection_mask_value(0b1010); + config.set_default_vtl_protection_mask((0b1010_u8).into()); assert_eq!(config.default_vtl_protection_mask_value(), 0b1010); // Test size - should be 8 bytes (64 bits) @@ -991,12 +909,12 @@ mod tests { features.set_direct_hypercall(true); assert_eq!(features.direct_hypercall(), true); - // Test compatibility method + // Test direct method let mut features2 = HvNestedEnlightenmentsControlFeatures::new(); - features2.set_direct_hypercall_u32(1); + features2.set_direct_hypercall(true); assert_eq!(features2.direct_hypercall(), true); - features2.set_direct_hypercall_u32(0); + features2.set_direct_hypercall(false); assert_eq!(features2.direct_hypercall(), false); // Test size - should be 4 bytes (32 bits) @@ -1017,12 +935,12 @@ mod tests { controls.set_inter_partition_comm(true); assert_eq!(controls.inter_partition_comm(), true); - // Test compatibility method + // Test direct method let mut controls2 = HvNestedEnlightenmentsControlHypercallControls::new(); - controls2.set_inter_partition_comm_u32(1); + controls2.set_inter_partition_comm(true); assert_eq!(controls2.inter_partition_comm(), true); - controls2.set_inter_partition_comm_u32(0); + controls2.set_inter_partition_comm(false); assert_eq!(controls2.inter_partition_comm(), false); // Test size - should be 4 bytes (32 bits) @@ -1046,12 +964,12 @@ mod tests { config.set_tlb_locked(true); assert_eq!(config.tlb_locked(), true); - // Test compatibility methods + // Test direct methods let mut config2 = HvRegisterVsmVpSecureVtlConfig::new(); - config2.set_mbec_enabled_flag(); + config2.set_mbec_enabled(true); assert_eq!(config2.mbec_enabled(), true); - config2.set_tlb_locked_flag(); + config2.set_tlb_locked(true); assert_eq!(config2.tlb_locked(), true); // Test size - should be 8 bytes (64 bits) @@ -1088,18 +1006,18 @@ mod tests { sint.set_polling(true); assert_eq!(sint.polling(), true); - // Test compatibility methods + // Test direct methods let mut sint2 = HvSynicSint::new(); - sint2.set_vector_u64(0xf3); + sint2.set_vector((0xf3_u8).into()); assert_eq!(sint2.vector() as u8, 0xf3); - sint2.set_masked_flag(); + sint2.set_masked(true); assert_eq!(sint2.masked(), true); - sint2.set_auto_eoi_flag(); + sint2.set_auto_eoi(true); assert_eq!(sint2.auto_eoi(), true); - sint2.set_polling_flag(); + sint2.set_polling(true); assert_eq!(sint2.polling(), true); // Test size - should be 8 bytes (64 bits) @@ -1140,21 +1058,21 @@ mod tests { exception.set_error_code(0x87654321_u32.into()); // 32 bits assert_eq!(exception.error_code() as u32, 0x87654321); - // Test compatibility methods + // Test direct methods let mut exception2 = HvPendingExceptionEvent::new(); - exception2.set_event_pending_flag(); + exception2.set_event_pending(true); assert_eq!(exception2.event_pending(), true); - exception2.set_deliver_error_code_flag(); + exception2.set_deliver_error_code(true); assert_eq!(exception2.deliver_error_code(), true); - exception2.set_event_type_u64(7); + exception2.set_event_type((7_u8).into()); assert_eq!(exception2.event_type() as u8, 7); - exception2.set_vector_u64(0xabcd); + exception2.set_vector((0xabcd_u16).into()); assert_eq!(exception2.vector() as u16, 0xabcd); - exception2.set_error_code_u64(0x12345678); + exception2.set_error_code((0x12345678_u32).into()); assert_eq!(exception2.error_code() as u32, 0x12345678); // Test size - should be 8 bytes (64 bits) diff --git a/litebox_platform_lvbs/src/mshv/vsm.rs b/litebox_platform_lvbs/src/mshv/vsm.rs index 23850d5ce..164b02ed2 100644 --- a/litebox_platform_lvbs/src/mshv/vsm.rs +++ b/litebox_platform_lvbs/src/mshv/vsm.rs @@ -167,8 +167,8 @@ pub fn mshv_vsm_secure_config_vtl0() -> Result { debug_serial_println!("VSM: Secure VTL0 configuration"); let mut config = HvRegisterVsmVpSecureVtlConfig::new(); - config.set_mbec_enabled_flag(); - config.set_tlb_locked_flag(); + config.set_mbec_enabled(true); + config.set_tlb_locked(true); hvcall_set_vp_registers(HV_REGISTER_VSM_VP_SECURE_CONFIG_VTL0, config.as_u64()) .map_err(|_| Errno::EFAULT)?; @@ -181,7 +181,7 @@ pub fn mshv_vsm_configure_partition() -> Result { debug_serial_println!("VSM: Configure partition"); let mut config = HvRegisterVsmPartitionConfig::new(); - config.set_default_vtl_protection_mask_value(HvPageProtFlags::HV_PAGE_FULL_ACCESS.bits().into()); + config.set_default_vtl_protection_mask((HvPageProtFlags::HV_PAGE_FULL_ACCESS.bits() as u8).into()); config.set_enable_vtl_protection(true); hvcall_set_vp_registers(HV_REGISTER_VSM_PARTITION_CONFIG, config.as_u64()) diff --git a/litebox_platform_lvbs/src/mshv/vsm_intercept.rs b/litebox_platform_lvbs/src/mshv/vsm_intercept.rs index c379e9fa5..e8ecebfef 100644 --- a/litebox_platform_lvbs/src/mshv/vsm_intercept.rs +++ b/litebox_platform_lvbs/src/mshv/vsm_intercept.rs @@ -147,13 +147,11 @@ fn advance_vtl0_rip(int_msg_hdr: &HvInterceptMessageHeader) -> Result Result { let mut exception = HvPendingExceptionEvent::new(); - exception.set_event_pending_flag(); - exception.set_event_type_u64(0); - exception.set_deliver_error_code_flag(); - exception.set_vector_u64(u64::from( - x86_64::structures::idt::ExceptionVector::GeneralProtection as u8, - )); - exception.set_error_code_u64(0); + exception.set_event_pending(true); + exception.set_event_type(0_u8.into()); + exception.set_deliver_error_code(true); + exception.set_vector((x86_64::structures::idt::ExceptionVector::GeneralProtection as u8 as u16).into()); + exception.set_error_code(0_u32.into()); hvcall_set_vp_vtl0_registers(HV_REGISTER_PENDING_EVENT0, exception.as_u64()) } From c375ac7714621ec4c4632edb4baa83156a13db67 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 24 Jun 2025 17:24:51 +0000 Subject: [PATCH 07/10] Fix clippy warnings: remove useless conversions, unnecessary casts, and improve boolean assertions Co-authored-by: sangho2 <3938640+sangho2@users.noreply.github.com> --- litebox_platform_lvbs/src/mshv/hvcall.rs | 2 +- litebox_platform_lvbs/src/mshv/mod.rs | 283 +++++++++--------- litebox_platform_lvbs/src/mshv/vsm.rs | 2 +- .../src/mshv/vsm_intercept.rs | 8 +- 4 files changed, 151 insertions(+), 144 deletions(-) diff --git a/litebox_platform_lvbs/src/mshv/hvcall.rs b/litebox_platform_lvbs/src/mshv/hvcall.rs index 19f7523f2..20835b155 100644 --- a/litebox_platform_lvbs/src/mshv/hvcall.rs +++ b/litebox_platform_lvbs/src/mshv/hvcall.rs @@ -129,7 +129,7 @@ pub fn init() -> Result<(), HypervError> { debug_serial_println!("HV_X64_MSR_SIMP: {:#x}", rdmsr(HV_X64_MSR_SIMP)); let mut sint = HvSynicSint::new(); - sint.set_vector((HYPERVISOR_CALLBACK_VECTOR as u8).into()); + sint.set_vector(HYPERVISOR_CALLBACK_VECTOR); sint.set_auto_eoi(true); wrmsr(HV_X64_MSR_SINT0, sint.as_uint64()); diff --git a/litebox_platform_lvbs/src/mshv/mod.rs b/litebox_platform_lvbs/src/mshv/mod.rs index 3e5ff4b84..45d9b7fdf 100644 --- a/litebox_platform_lvbs/src/mshv/mod.rs +++ b/litebox_platform_lvbs/src/mshv/mod.rs @@ -10,9 +10,9 @@ pub mod vtl1_mem_layout; pub mod vtl_switch; use crate::mshv::vtl1_mem_layout::PAGE_SIZE; -use num_enum::{IntoPrimitive, TryFromPrimitive}; use modular_bitfield::prelude::*; use modular_bitfield::specifiers::{B3, B4, B7, B8, B16, B31, B32, B45, B51, B62}; +use num_enum::{IntoPrimitive, TryFromPrimitive}; pub const HV_HYPERCALL_REP_COMP_MASK: u64 = 0xfff_0000_0000; pub const HV_HYPERCALL_REP_COMP_OFFSET: u32 = 32; @@ -242,19 +242,18 @@ impl HvInputVtl { /// `target_vtl` specifies the VTL (0-15) that a Hyper-V hypercall works at. pub fn new_for_vtl(target_vtl: u8) -> Self { Self::new() - .with_target_vtl(target_vtl.into()) + .with_target_vtl(target_vtl) .with_use_target_vtl(true) } /// use the current VTL pub fn current() -> Self { - Self::new() - .with_use_target_vtl(false) + Self::new().with_use_target_vtl(false) } /// Gets the target VTL as a u8 value pub fn target_vtl_value(&self) -> u8 { - self.target_vtl() as u8 + self.target_vtl() } } @@ -820,275 +819,281 @@ mod tests { #[test] fn test_hv_input_vtl_bitfield() { // Test the new bitfield-based HvInputVtl implementation - + // Test new_for_vtl constructor let vtl = HvInputVtl::new_for_vtl(5); assert_eq!(vtl.target_vtl_value(), 5); - assert_eq!(vtl.use_target_vtl(), true); - + assert!(vtl.use_target_vtl()); + // Test current constructor let current_vtl = HvInputVtl::current(); - assert_eq!(current_vtl.use_target_vtl(), false); - + assert!(!current_vtl.use_target_vtl()); + // Test individual field manipulation let mut vtl = HvInputVtl::new(); - vtl.set_target_vtl(10_u8.into()); + vtl.set_target_vtl(10_u8); vtl.set_use_target_vtl(true); assert_eq!(vtl.target_vtl_value(), 10); - assert_eq!(vtl.use_target_vtl(), true); - + assert!(vtl.use_target_vtl()); + // Test size - should be 1 byte assert_eq!(core::mem::size_of::(), 1); - + // Test that VTL values are properly bounded to 4 bits (0-15) let vtl = HvInputVtl::new_for_vtl(15); assert_eq!(vtl.target_vtl_value(), 15); - + // Test that Default trait works let default_vtl = HvInputVtl::default(); assert_eq!(default_vtl.target_vtl_value(), 0); - assert_eq!(default_vtl.use_target_vtl(), false); + assert!(!default_vtl.use_target_vtl()); } #[test] fn test_hv_register_vsm_partition_config_bitfield() { // Test the new bitfield-based HvRegisterVsmPartitionConfig implementation - + let mut config = HvRegisterVsmPartitionConfig::new(); - + // Test individual boolean flags config.set_enable_vtl_protection(true); - assert_eq!(config.enable_vtl_protection(), true); - + assert!(config.enable_vtl_protection()); + config.set_zero_memory_on_reset(true); - assert_eq!(config.zero_memory_on_reset(), true); - + assert!(config.zero_memory_on_reset()); + config.set_intercept_page(true); - assert_eq!(config.intercept_page(), true); - + assert!(config.intercept_page()); + // Test the 4-bit protection mask field - config.set_default_vtl_protection_mask((0b1010_u8).into()); + config.set_default_vtl_protection_mask(0b1010_u8); assert_eq!(config.default_vtl_protection_mask_value(), 0b1010); - + // Test size - should be 8 bytes (64 bits) assert_eq!(core::mem::size_of::(), 8); - + // Test as_u64 and from_u64 round-trip let original = config.as_u64(); let restored = HvRegisterVsmPartitionConfig::from_u64(original); - - assert_eq!(restored.enable_vtl_protection(), true); - assert_eq!(restored.zero_memory_on_reset(), true); - assert_eq!(restored.intercept_page(), true); + + assert!(restored.enable_vtl_protection()); + assert!(restored.zero_memory_on_reset()); + assert!(restored.intercept_page()); assert_eq!(restored.default_vtl_protection_mask_value(), 0b1010); - + // Test that Default trait works let default_config = HvRegisterVsmPartitionConfig::default(); - assert_eq!(default_config.enable_vtl_protection(), false); + assert!(!default_config.enable_vtl_protection()); assert_eq!(default_config.as_u64(), 0); - + // Test chaining builder-style methods (generated by bitfield macro) let chained_config = HvRegisterVsmPartitionConfig::new() .with_enable_vtl_protection(true) .with_intercept_acceptance(true) .with_intercept_vp_startup(true); - - assert_eq!(chained_config.enable_vtl_protection(), true); - assert_eq!(chained_config.intercept_acceptance(), true); - assert_eq!(chained_config.intercept_vp_startup(), true); - assert_eq!(chained_config.zero_memory_on_reset(), false); + + assert!(chained_config.enable_vtl_protection()); + assert!(chained_config.intercept_acceptance()); + assert!(chained_config.intercept_vp_startup()); + assert!(!chained_config.zero_memory_on_reset()); } #[test] fn test_hv_nested_enlightenments_control_features_bitfield() { // Test the new bitfield-based HvNestedEnlightenmentsControlFeatures implementation - + let mut features = HvNestedEnlightenmentsControlFeatures::new(); - + // Test setting direct hypercall flag features.set_direct_hypercall(true); - assert_eq!(features.direct_hypercall(), true); - + assert!(features.direct_hypercall()); + // Test direct method let mut features2 = HvNestedEnlightenmentsControlFeatures::new(); features2.set_direct_hypercall(true); - assert_eq!(features2.direct_hypercall(), true); - + assert!(features2.direct_hypercall()); + features2.set_direct_hypercall(false); - assert_eq!(features2.direct_hypercall(), false); - + assert!(!features2.direct_hypercall()); + // Test size - should be 4 bytes (32 bits) - assert_eq!(core::mem::size_of::(), 4); - + assert_eq!( + core::mem::size_of::(), + 4 + ); + // Test that Default trait works let default_features = HvNestedEnlightenmentsControlFeatures::default(); - assert_eq!(default_features.direct_hypercall(), false); + assert!(!default_features.direct_hypercall()); } #[test] fn test_hv_nested_enlightenments_control_hypercall_controls_bitfield() { // Test the new bitfield-based HvNestedEnlightenmentsControlHypercallControls implementation - + let mut controls = HvNestedEnlightenmentsControlHypercallControls::new(); - + // Test setting inter partition comm flag controls.set_inter_partition_comm(true); - assert_eq!(controls.inter_partition_comm(), true); - + assert!(controls.inter_partition_comm()); + // Test direct method let mut controls2 = HvNestedEnlightenmentsControlHypercallControls::new(); controls2.set_inter_partition_comm(true); - assert_eq!(controls2.inter_partition_comm(), true); - + assert!(controls2.inter_partition_comm()); + controls2.set_inter_partition_comm(false); - assert_eq!(controls2.inter_partition_comm(), false); - + assert!(!controls2.inter_partition_comm()); + // Test size - should be 4 bytes (32 bits) - assert_eq!(core::mem::size_of::(), 4); - + assert_eq!( + core::mem::size_of::(), + 4 + ); + // Test that Default trait works let default_controls = HvNestedEnlightenmentsControlHypercallControls::default(); - assert_eq!(default_controls.inter_partition_comm(), false); + assert!(!default_controls.inter_partition_comm()); } #[test] fn test_hv_register_vsm_vp_secure_vtl_config_bitfield() { // Test the new bitfield-based HvRegisterVsmVpSecureVtlConfig implementation - + let mut config = HvRegisterVsmVpSecureVtlConfig::new(); - + // Test individual boolean flags config.set_mbec_enabled(true); - assert_eq!(config.mbec_enabled(), true); - + assert!(config.mbec_enabled()); + config.set_tlb_locked(true); - assert_eq!(config.tlb_locked(), true); - + assert!(config.tlb_locked()); + // Test direct methods let mut config2 = HvRegisterVsmVpSecureVtlConfig::new(); config2.set_mbec_enabled(true); - assert_eq!(config2.mbec_enabled(), true); - + assert!(config2.mbec_enabled()); + config2.set_tlb_locked(true); - assert_eq!(config2.tlb_locked(), true); - + assert!(config2.tlb_locked()); + // Test size - should be 8 bytes (64 bits) assert_eq!(core::mem::size_of::(), 8); - + // Test as_u64 method let config_u64 = config.as_u64(); - assert_ne!(config_u64, 0); // Should have some bits set - + assert_ne!(config_u64, 0); // Should have some bits set + // Test that Default trait works let default_config = HvRegisterVsmVpSecureVtlConfig::default(); - assert_eq!(default_config.mbec_enabled(), false); - assert_eq!(default_config.tlb_locked(), false); + assert!(!default_config.mbec_enabled()); + assert!(!default_config.tlb_locked()); assert_eq!(default_config.as_u64(), 0); } #[test] fn test_hv_synic_sint_bitfield() { // Test the new bitfield-based HvSynicSint implementation - + let mut sint = HvSynicSint::new(); - + // Test vector field (8 bits) - sint.set_vector(0xf3_u8.into()); - assert_eq!(sint.vector() as u8, 0xf3); - + sint.set_vector(0xf3_u8); + assert_eq!(sint.vector(), 0xf3); + // Test boolean flags sint.set_masked(true); - assert_eq!(sint.masked(), true); - + assert!(sint.masked()); + sint.set_auto_eoi(true); - assert_eq!(sint.auto_eoi(), true); - + assert!(sint.auto_eoi()); + sint.set_polling(true); - assert_eq!(sint.polling(), true); - + assert!(sint.polling()); + // Test direct methods let mut sint2 = HvSynicSint::new(); - sint2.set_vector((0xf3_u8).into()); - assert_eq!(sint2.vector() as u8, 0xf3); - + sint2.set_vector(0xf3_u8); + assert_eq!(sint2.vector(), 0xf3); + sint2.set_masked(true); - assert_eq!(sint2.masked(), true); - + assert!(sint2.masked()); + sint2.set_auto_eoi(true); - assert_eq!(sint2.auto_eoi(), true); - + assert!(sint2.auto_eoi()); + sint2.set_polling(true); - assert_eq!(sint2.polling(), true); - + assert!(sint2.polling()); + // Test size - should be 8 bytes (64 bits) assert_eq!(core::mem::size_of::(), 8); - + // Test as_uint64 method let sint_u64 = sint.as_uint64(); - assert_ne!(sint_u64, 0); // Should have some bits set - + assert_ne!(sint_u64, 0); // Should have some bits set + // Test that Default trait works let default_sint = HvSynicSint::default(); - assert_eq!(default_sint.vector() as u8, 0); - assert_eq!(default_sint.masked(), false); - assert_eq!(default_sint.auto_eoi(), false); - assert_eq!(default_sint.polling(), false); + assert_eq!(default_sint.vector(), 0); + assert!(!default_sint.masked()); + assert!(!default_sint.auto_eoi()); + assert!(!default_sint.polling()); } #[test] fn test_hv_pending_exception_event_bitfield() { // Test the new bitfield-based HvPendingExceptionEvent implementation - + let mut exception = HvPendingExceptionEvent::new(); - + // Test boolean flags exception.set_event_pending(true); - assert_eq!(exception.event_pending(), true); - + assert!(exception.event_pending()); + exception.set_deliver_error_code(true); - assert_eq!(exception.deliver_error_code(), true); - + assert!(exception.deliver_error_code()); + // Test multi-bit fields - exception.set_event_type(0b101_u8.into()); // 3 bits - assert_eq!(exception.event_type() as u8, 0b101); - - exception.set_vector(0x1234_u16.into()); // 16 bits - assert_eq!(exception.vector() as u16, 0x1234); - - exception.set_error_code(0x87654321_u32.into()); // 32 bits - assert_eq!(exception.error_code() as u32, 0x87654321); - + exception.set_event_type(0b101_u8); // 3 bits + assert_eq!(exception.event_type(), 0b101); + + exception.set_vector(0x1234_u16); // 16 bits + assert_eq!(exception.vector(), 0x1234); + + exception.set_error_code(0x87654321_u32); // 32 bits + assert_eq!(exception.error_code(), 0x87654321); + // Test direct methods let mut exception2 = HvPendingExceptionEvent::new(); exception2.set_event_pending(true); - assert_eq!(exception2.event_pending(), true); - + assert!(exception2.event_pending()); + exception2.set_deliver_error_code(true); - assert_eq!(exception2.deliver_error_code(), true); - - exception2.set_event_type((7_u8).into()); - assert_eq!(exception2.event_type() as u8, 7); - - exception2.set_vector((0xabcd_u16).into()); - assert_eq!(exception2.vector() as u16, 0xabcd); - - exception2.set_error_code((0x12345678_u32).into()); - assert_eq!(exception2.error_code() as u32, 0x12345678); - + assert!(exception2.deliver_error_code()); + + exception2.set_event_type(7_u8); + assert_eq!(exception2.event_type(), 7); + + exception2.set_vector(0xabcd_u16); + assert_eq!(exception2.vector(), 0xabcd); + + exception2.set_error_code(0x12345678_u32); + assert_eq!(exception2.error_code(), 0x12345678); + // Test size - should be 8 bytes (64 bits) assert_eq!(core::mem::size_of::(), 8); - + // Test as_u64 method let exception_u64 = exception.as_u64(); - assert_ne!(exception_u64, 0); // Should have some bits set - + assert_ne!(exception_u64, 0); // Should have some bits set + // Test that Default trait works let default_exception = HvPendingExceptionEvent::default(); - assert_eq!(default_exception.event_pending(), false); - assert_eq!(default_exception.deliver_error_code(), false); - assert_eq!(default_exception.event_type() as u8, 0); - assert_eq!(default_exception.vector() as u16, 0); - assert_eq!(default_exception.error_code() as u32, 0); + assert!(!default_exception.event_pending()); + assert!(!default_exception.deliver_error_code()); + assert_eq!(default_exception.event_type(), 0); + assert_eq!(default_exception.vector(), 0); + assert_eq!(default_exception.error_code(), 0); assert_eq!(default_exception.as_u64(), 0); } } diff --git a/litebox_platform_lvbs/src/mshv/vsm.rs b/litebox_platform_lvbs/src/mshv/vsm.rs index 164b02ed2..8dcc07e86 100644 --- a/litebox_platform_lvbs/src/mshv/vsm.rs +++ b/litebox_platform_lvbs/src/mshv/vsm.rs @@ -181,7 +181,7 @@ pub fn mshv_vsm_configure_partition() -> Result { debug_serial_println!("VSM: Configure partition"); let mut config = HvRegisterVsmPartitionConfig::new(); - config.set_default_vtl_protection_mask((HvPageProtFlags::HV_PAGE_FULL_ACCESS.bits() as u8).into()); + config.set_default_vtl_protection_mask(HvPageProtFlags::HV_PAGE_FULL_ACCESS.bits() as u8); config.set_enable_vtl_protection(true); hvcall_set_vp_registers(HV_REGISTER_VSM_PARTITION_CONFIG, config.as_u64()) diff --git a/litebox_platform_lvbs/src/mshv/vsm_intercept.rs b/litebox_platform_lvbs/src/mshv/vsm_intercept.rs index e8ecebfef..c339d55c2 100644 --- a/litebox_platform_lvbs/src/mshv/vsm_intercept.rs +++ b/litebox_platform_lvbs/src/mshv/vsm_intercept.rs @@ -148,10 +148,12 @@ fn advance_vtl0_rip(int_msg_hdr: &HvInterceptMessageHeader) -> Result Result { let mut exception = HvPendingExceptionEvent::new(); exception.set_event_pending(true); - exception.set_event_type(0_u8.into()); + exception.set_event_type(0_u8); exception.set_deliver_error_code(true); - exception.set_vector((x86_64::structures::idt::ExceptionVector::GeneralProtection as u8 as u16).into()); - exception.set_error_code(0_u32.into()); + exception.set_vector(u16::from( + x86_64::structures::idt::ExceptionVector::GeneralProtection as u8, + )); + exception.set_error_code(0_u32); hvcall_set_vp_vtl0_registers(HV_REGISTER_PENDING_EVENT0, exception.as_u64()) } From e9654eddddbd2da2c5b80e6d7229d80bf950705e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 24 Jun 2025 17:37:38 +0000 Subject: [PATCH 08/10] Fix all cargo clippy warnings: improve casting safety and add must_use attributes Co-authored-by: sangho2 <3938640+sangho2@users.noreply.github.com> --- litebox_platform_lvbs/src/mshv/mod.rs | 9 ++++++++- litebox_platform_lvbs/src/mshv/vsm.rs | 5 ++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/litebox_platform_lvbs/src/mshv/mod.rs b/litebox_platform_lvbs/src/mshv/mod.rs index 45d9b7fdf..7c6cece36 100644 --- a/litebox_platform_lvbs/src/mshv/mod.rs +++ b/litebox_platform_lvbs/src/mshv/mod.rs @@ -231,6 +231,7 @@ pub struct HvInitVpContext { #[bitfield] #[derive(Clone, Copy, Default)] #[repr(C)] +#[must_use] pub struct HvInputVtl { pub target_vtl: B4, pub use_target_vtl: bool, @@ -375,6 +376,7 @@ impl HvGetVpRegistersOutput { #[bitfield] #[derive(Clone, Copy, Default)] #[repr(C)] +#[must_use] pub struct HvNestedEnlightenmentsControlFeatures { pub direct_hypercall: bool, #[skip] @@ -384,6 +386,7 @@ pub struct HvNestedEnlightenmentsControlFeatures { #[bitfield] #[derive(Clone, Copy, Default)] #[repr(C)] +#[must_use] pub struct HvNestedEnlightenmentsControlHypercallControls { pub inter_partition_comm: bool, #[skip] @@ -489,6 +492,7 @@ impl Default for HvInputModifyVtlProtectionMask { #[bitfield] #[derive(Clone, Copy, Default)] #[repr(C)] +#[must_use] pub struct HvRegisterVsmVpSecureVtlConfig { pub mbec_enabled: bool, pub tlb_locked: bool, @@ -505,6 +509,7 @@ impl HvRegisterVsmVpSecureVtlConfig { #[bitfield] #[derive(Clone, Copy, Default)] #[repr(C)] +#[must_use] pub struct HvRegisterVsmPartitionConfig { pub enable_vtl_protection: bool, pub default_vtl_protection_mask: B4, @@ -534,7 +539,7 @@ impl HvRegisterVsmPartitionConfig { /// Get the default VTL protection mask as a u64 value pub fn default_vtl_protection_mask_value(&self) -> u64 { - self.default_vtl_protection_mask() as u64 + u64::from(self.default_vtl_protection_mask()) } } @@ -703,6 +708,7 @@ impl HvMessagePage { #[bitfield] #[derive(Clone, Copy, Default)] #[repr(C)] +#[must_use] pub struct HvSynicSint { pub vector: B8, #[skip] @@ -794,6 +800,7 @@ pub struct HvMsrInterceptMessage { #[bitfield] #[derive(Clone, Copy, Default)] #[repr(C)] +#[must_use] pub struct HvPendingExceptionEvent { pub event_pending: bool, pub event_type: B3, diff --git a/litebox_platform_lvbs/src/mshv/vsm.rs b/litebox_platform_lvbs/src/mshv/vsm.rs index 8dcc07e86..6baba9adf 100644 --- a/litebox_platform_lvbs/src/mshv/vsm.rs +++ b/litebox_platform_lvbs/src/mshv/vsm.rs @@ -181,7 +181,10 @@ pub fn mshv_vsm_configure_partition() -> Result { debug_serial_println!("VSM: Configure partition"); let mut config = HvRegisterVsmPartitionConfig::new(); - config.set_default_vtl_protection_mask(HvPageProtFlags::HV_PAGE_FULL_ACCESS.bits() as u8); + config.set_default_vtl_protection_mask( + u8::try_from(HvPageProtFlags::HV_PAGE_FULL_ACCESS.bits()) + .expect("HV_PAGE_FULL_ACCESS should fit in 4 bits"), + ); config.set_enable_vtl_protection(true); hvcall_set_vp_registers(HV_REGISTER_VSM_PARTITION_CONFIG, config.as_u64()) From e94717c51d304425bd1d5f471e8a64407207381c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 24 Jun 2025 18:06:56 +0000 Subject: [PATCH 09/10] Address PR review feedback: update modular-bitfield to 0.12.0, fix casting, remove wrapper methods Co-authored-by: sangho2 <3938640+sangho2@users.noreply.github.com> --- litebox_platform_lvbs/Cargo.toml | 2 +- litebox_platform_lvbs/src/mshv/mod.rs | 29 ++++++--------------------- 2 files changed, 7 insertions(+), 24 deletions(-) diff --git a/litebox_platform_lvbs/Cargo.toml b/litebox_platform_lvbs/Cargo.toml index 48315a4cd..0d05883ae 100644 --- a/litebox_platform_lvbs/Cargo.toml +++ b/litebox_platform_lvbs/Cargo.toml @@ -20,7 +20,7 @@ rangemap = { version = "1.5.1", features = ["const_fn"] } thiserror = { version = "2.0.6", default-features = false } num_enum = { version = "0.7.3", default-features = false } once_cell = { version = "1.20.2", default-features = false, features = ["alloc", "race"] } -modular-bitfield = { version = "0.11.2", default-features = false } +modular-bitfield = { version = "0.12.0", default-features = false } [target.'cfg(target_arch = "x86_64")'.dependencies] x86_64 = { version = "0.15.2", default-features = false, features = ["instructions"] } diff --git a/litebox_platform_lvbs/src/mshv/mod.rs b/litebox_platform_lvbs/src/mshv/mod.rs index 7c6cece36..ef412812e 100644 --- a/litebox_platform_lvbs/src/mshv/mod.rs +++ b/litebox_platform_lvbs/src/mshv/mod.rs @@ -231,7 +231,6 @@ pub struct HvInitVpContext { #[bitfield] #[derive(Clone, Copy, Default)] #[repr(C)] -#[must_use] pub struct HvInputVtl { pub target_vtl: B4, pub use_target_vtl: bool, @@ -251,11 +250,6 @@ impl HvInputVtl { pub fn current() -> Self { Self::new().with_use_target_vtl(false) } - - /// Gets the target VTL as a u8 value - pub fn target_vtl_value(&self) -> u8 { - self.target_vtl() - } } #[derive(Default, Clone, Copy)] @@ -376,7 +370,6 @@ impl HvGetVpRegistersOutput { #[bitfield] #[derive(Clone, Copy, Default)] #[repr(C)] -#[must_use] pub struct HvNestedEnlightenmentsControlFeatures { pub direct_hypercall: bool, #[skip] @@ -386,7 +379,6 @@ pub struct HvNestedEnlightenmentsControlFeatures { #[bitfield] #[derive(Clone, Copy, Default)] #[repr(C)] -#[must_use] pub struct HvNestedEnlightenmentsControlHypercallControls { pub inter_partition_comm: bool, #[skip] @@ -492,7 +484,6 @@ impl Default for HvInputModifyVtlProtectionMask { #[bitfield] #[derive(Clone, Copy, Default)] #[repr(C)] -#[must_use] pub struct HvRegisterVsmVpSecureVtlConfig { pub mbec_enabled: bool, pub tlb_locked: bool, @@ -509,7 +500,6 @@ impl HvRegisterVsmVpSecureVtlConfig { #[bitfield] #[derive(Clone, Copy, Default)] #[repr(C)] -#[must_use] pub struct HvRegisterVsmPartitionConfig { pub enable_vtl_protection: bool, pub default_vtl_protection_mask: B4, @@ -536,11 +526,6 @@ impl HvRegisterVsmPartitionConfig { pub fn from_u64(value: u64) -> Self { Self::from_bytes(value.to_le_bytes()) } - - /// Get the default VTL protection mask as a u64 value - pub fn default_vtl_protection_mask_value(&self) -> u64 { - u64::from(self.default_vtl_protection_mask()) - } } bitflags::bitflags! { @@ -708,7 +693,6 @@ impl HvMessagePage { #[bitfield] #[derive(Clone, Copy, Default)] #[repr(C)] -#[must_use] pub struct HvSynicSint { pub vector: B8, #[skip] @@ -800,7 +784,6 @@ pub struct HvMsrInterceptMessage { #[bitfield] #[derive(Clone, Copy, Default)] #[repr(C)] -#[must_use] pub struct HvPendingExceptionEvent { pub event_pending: bool, pub event_type: B3, @@ -829,7 +812,7 @@ mod tests { // Test new_for_vtl constructor let vtl = HvInputVtl::new_for_vtl(5); - assert_eq!(vtl.target_vtl_value(), 5); + assert_eq!(vtl.target_vtl(), 5); assert!(vtl.use_target_vtl()); // Test current constructor @@ -840,7 +823,7 @@ mod tests { let mut vtl = HvInputVtl::new(); vtl.set_target_vtl(10_u8); vtl.set_use_target_vtl(true); - assert_eq!(vtl.target_vtl_value(), 10); + assert_eq!(vtl.target_vtl(), 10); assert!(vtl.use_target_vtl()); // Test size - should be 1 byte @@ -848,11 +831,11 @@ mod tests { // Test that VTL values are properly bounded to 4 bits (0-15) let vtl = HvInputVtl::new_for_vtl(15); - assert_eq!(vtl.target_vtl_value(), 15); + assert_eq!(vtl.target_vtl(), 15); // Test that Default trait works let default_vtl = HvInputVtl::default(); - assert_eq!(default_vtl.target_vtl_value(), 0); + assert_eq!(default_vtl.target_vtl(), 0); assert!(!default_vtl.use_target_vtl()); } @@ -874,7 +857,7 @@ mod tests { // Test the 4-bit protection mask field config.set_default_vtl_protection_mask(0b1010_u8); - assert_eq!(config.default_vtl_protection_mask_value(), 0b1010); + assert_eq!(u64::from(config.default_vtl_protection_mask()), 0b1010); // Test size - should be 8 bytes (64 bits) assert_eq!(core::mem::size_of::(), 8); @@ -886,7 +869,7 @@ mod tests { assert!(restored.enable_vtl_protection()); assert!(restored.zero_memory_on_reset()); assert!(restored.intercept_page()); - assert_eq!(restored.default_vtl_protection_mask_value(), 0b1010); + assert_eq!(u64::from(restored.default_vtl_protection_mask()), 0b1010); // Test that Default trait works let default_config = HvRegisterVsmPartitionConfig::default(); From 683c10a1518bf64ca7c764d1997abdaa5c1db876 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 24 Jun 2025 22:09:07 +0000 Subject: [PATCH 10/10] Change HvPageProtFlags from u32 to u8 as requested in PR feedback Co-authored-by: sangho2 <3938640+sangho2@users.noreply.github.com> --- litebox_platform_lvbs/src/mshv/hvcall_mm.rs | 2 +- litebox_platform_lvbs/src/mshv/mod.rs | 2 +- litebox_platform_lvbs/src/mshv/vsm.rs | 5 +---- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/litebox_platform_lvbs/src/mshv/hvcall_mm.rs b/litebox_platform_lvbs/src/mshv/hvcall_mm.rs index 73defecfa..e40bf533e 100644 --- a/litebox_platform_lvbs/src/mshv/hvcall_mm.rs +++ b/litebox_platform_lvbs/src/mshv/hvcall_mm.rs @@ -28,7 +28,7 @@ pub fn hv_modify_vtl_protection_mask( hvin.partition_id = HV_PARTITION_ID_SELF; hvin.target_vtl = HvInputVtl::current(); - hvin.map_flags = page_access.bits(); + hvin.map_flags = u32::from(page_access.bits()); let mut total_protected: u64 = 0; while total_protected < num_pages { diff --git a/litebox_platform_lvbs/src/mshv/mod.rs b/litebox_platform_lvbs/src/mshv/mod.rs index ef412812e..8499da5a4 100644 --- a/litebox_platform_lvbs/src/mshv/mod.rs +++ b/litebox_platform_lvbs/src/mshv/mod.rs @@ -125,7 +125,7 @@ pub const DEFAULT_REG_PIN_MASK: u64 = u64::MAX; bitflags::bitflags! { #[derive(Debug, PartialEq)] - pub struct HvPageProtFlags: u32 { + pub struct HvPageProtFlags: u8 { const HV_PAGE_ACCESS_NONE = 0x0; const HV_PAGE_READABLE = 0x1; const HV_PAGE_WRITABLE = 0x2; diff --git a/litebox_platform_lvbs/src/mshv/vsm.rs b/litebox_platform_lvbs/src/mshv/vsm.rs index 6baba9adf..37e61cc7d 100644 --- a/litebox_platform_lvbs/src/mshv/vsm.rs +++ b/litebox_platform_lvbs/src/mshv/vsm.rs @@ -181,10 +181,7 @@ pub fn mshv_vsm_configure_partition() -> Result { debug_serial_println!("VSM: Configure partition"); let mut config = HvRegisterVsmPartitionConfig::new(); - config.set_default_vtl_protection_mask( - u8::try_from(HvPageProtFlags::HV_PAGE_FULL_ACCESS.bits()) - .expect("HV_PAGE_FULL_ACCESS should fit in 4 bits"), - ); + config.set_default_vtl_protection_mask(HvPageProtFlags::HV_PAGE_FULL_ACCESS.bits()); config.set_enable_vtl_protection(true); hvcall_set_vp_registers(HV_REGISTER_VSM_PARTITION_CONFIG, config.as_u64())