Skip to content

Commit 365065d

Browse files
mattkurchris-oo
andauthored
zerocopy: update from 0.7.x to 0.8.x. (#77)
Mechanical update of zerocopy from 0.7 to 0.8. This litters a few `todo` comments for code owners to consider future changes based on new features on the zerocopy API set. I am moving the `openvmm` project to zerocopy 0.8. Updating this crate is necessary since this API exposes types that use zerocopy derives. Tested via unit tests (`cargo nextest run --workspace`), clippy, and fmt. --------- Co-authored-by: Chris Oo <[email protected]>
1 parent 0103818 commit 365065d

File tree

8 files changed

+144
-150
lines changed

8 files changed

+144
-150
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,4 @@ range_map_vec = "0.2.0"
2121
static_assertions = "1.1"
2222
thiserror = "1.0"
2323
tracing = "0.1"
24-
zerocopy = { version = "0.7.32", features = ["derive"] }
24+
zerocopy = { version = "0.8.14", features = ["derive"] }

igvm/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ open-enum.workspace = true
3636
thiserror.workspace = true
3737
tracing.workspace = true
3838
zerocopy = { workspace = true, features = ["alloc"] }
39+
static_assertions.workspace = true
3940

4041
[features]
4142
default = []

igvm/src/hv_defs.rs

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@
1010
1111
use core::fmt::Debug;
1212
use open_enum::open_enum;
13-
use zerocopy::AsBytes;
1413
use zerocopy::FromBytes;
15-
use zerocopy::FromZeroes;
14+
use zerocopy::Immutable;
15+
use zerocopy::IntoBytes;
16+
use zerocopy::KnownLayout;
1617

1718
#[open_enum]
1819
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
@@ -180,7 +181,7 @@ impl From<Vtl> for u8 {
180181

181182
/// An aligned u128 value.
182183
#[repr(C, align(16))]
183-
#[derive(Copy, Clone, PartialEq, Eq, AsBytes, FromBytes, FromZeroes)]
184+
#[derive(Copy, Clone, PartialEq, Eq, IntoBytes, Immutable, KnownLayout, FromBytes)]
184185
pub struct AlignedU128([u8; 16]);
185186

186187
impl AlignedU128 {
@@ -237,7 +238,7 @@ impl From<AlignedU128> for u128 {
237238

238239
/// A `HV_REGISTER_VALUE` that represents virtual processor registers.
239240
#[repr(C)]
240-
#[derive(Clone, Copy, Debug, Eq, PartialEq, AsBytes, FromBytes, FromZeroes)]
241+
#[derive(Clone, Copy, Debug, Eq, PartialEq, IntoBytes, Immutable, KnownLayout, FromBytes)]
241242
pub struct HvRegisterValue(pub AlignedU128);
242243

243244
impl HvRegisterValue {
@@ -262,11 +263,11 @@ impl HvRegisterValue {
262263
}
263264

264265
pub fn as_table(&self) -> HvX64TableRegister {
265-
HvX64TableRegister::read_from_prefix(self.as_bytes()).unwrap()
266+
HvX64TableRegister::read_from_bytes(self.as_bytes()).unwrap()
266267
}
267268

268269
pub fn as_segment(&self) -> HvX64SegmentRegister {
269-
HvX64SegmentRegister::read_from_prefix(self.as_bytes()).unwrap()
270+
HvX64SegmentRegister::read_from_bytes(self.as_bytes()).unwrap()
270271
}
271272
}
272273

@@ -301,43 +302,45 @@ impl From<u128> for HvRegisterValue {
301302
}
302303

303304
#[repr(C)]
304-
#[derive(Clone, Copy, Debug, Eq, PartialEq, AsBytes, FromBytes, FromZeroes)]
305+
#[derive(Clone, Copy, Debug, Eq, PartialEq, IntoBytes, Immutable, KnownLayout, FromBytes)]
305306
pub struct HvX64TableRegister {
306307
pub pad: [u16; 3],
307308
pub limit: u16,
308309
pub base: u64,
309310
}
311+
static_assertions::const_assert_eq!(core::mem::size_of::<HvX64TableRegister>(), 16);
310312

311313
impl From<HvX64TableRegister> for HvRegisterValue {
312314
fn from(val: HvX64TableRegister) -> Self {
313-
Self::read_from_prefix(val.as_bytes()).unwrap()
315+
Self::read_from_bytes(val.as_bytes()).unwrap()
314316
}
315317
}
316318

317319
impl From<HvRegisterValue> for HvX64TableRegister {
318320
fn from(val: HvRegisterValue) -> Self {
319-
Self::read_from_prefix(val.as_bytes()).unwrap()
321+
Self::read_from_bytes(val.as_bytes()).unwrap()
320322
}
321323
}
322324

323325
#[repr(C)]
324-
#[derive(Clone, Copy, Debug, Eq, PartialEq, AsBytes, FromBytes, FromZeroes)]
326+
#[derive(Clone, Copy, Debug, Eq, PartialEq, IntoBytes, Immutable, KnownLayout, FromBytes)]
325327
pub struct HvX64SegmentRegister {
326328
pub base: u64,
327329
pub limit: u32,
328330
pub selector: u16,
329331
pub attributes: u16,
330332
}
333+
static_assertions::const_assert_eq!(core::mem::size_of::<HvX64SegmentRegister>(), 16);
331334

332335
impl From<HvX64SegmentRegister> for HvRegisterValue {
333336
fn from(val: HvX64SegmentRegister) -> Self {
334-
Self::read_from_prefix(val.as_bytes()).unwrap()
337+
Self::read_from_bytes(val.as_bytes()).unwrap()
335338
}
336339
}
337340

338341
impl From<HvRegisterValue> for HvX64SegmentRegister {
339342
fn from(val: HvRegisterValue) -> Self {
340-
Self::read_from_prefix(val.as_bytes()).unwrap()
343+
Self::read_from_bytes(val.as_bytes()).unwrap()
341344
}
342345
}
343346

@@ -350,7 +353,7 @@ macro_rules! registers {
350353
$(,)?
351354
}) => {
352355
#[open_enum]
353-
#[derive(AsBytes, FromBytes, FromZeroes, Debug, Clone, Copy, PartialEq, Eq)]
356+
#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Debug, Clone, Copy, PartialEq, Eq)]
354357
#[repr(u32)]
355358
pub enum $name {
356359
$($variant = $value,)*

igvm/src/lib.rs

Lines changed: 39 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ use hv_defs::HvX64RegisterName;
2020
use hv_defs::Vtl;
2121
use igvm_defs::*;
2222
use page_table::PageTableRelocationBuilder;
23-
use parsing::FromBytesExt;
2423
use range_map_vec::RangeMap;
2524
use registers::AArch64Register;
2625
use registers::X86Register;
@@ -32,16 +31,17 @@ use std::fmt;
3231
use std::mem::size_of;
3332
use std::mem::size_of_val;
3433
use thiserror::Error;
35-
use zerocopy::AsBytes;
3634
use zerocopy::FromBytes;
37-
use zerocopy::FromZeroes;
35+
use zerocopy::FromZeros;
36+
use zerocopy::Immutable;
37+
use zerocopy::IntoBytes;
38+
use zerocopy::KnownLayout;
3839

3940
#[cfg(feature = "igvm-c")]
4041
pub mod c_api;
4142

4243
pub mod hv_defs;
4344
pub mod page_table;
44-
mod parsing;
4545
pub mod registers;
4646
pub mod snp_defs;
4747

@@ -88,9 +88,11 @@ fn align_8(x: usize) -> usize {
8888
/// passed in slice with the remaining bytes left.
8989
///
9090
/// On failure, returns [`BinaryHeaderError::InvalidVariableHeaderSize`].
91-
fn read_header<T: FromBytesExt>(bytes: &mut &[u8]) -> Result<T, BinaryHeaderError> {
92-
T::read_from_prefix_split(bytes)
93-
.ok_or(BinaryHeaderError::InvalidVariableHeaderSize)
91+
fn read_header<T: FromBytes + Immutable + KnownLayout>(
92+
bytes: &mut &[u8],
93+
) -> Result<T, BinaryHeaderError> {
94+
T::read_from_prefix(bytes)
95+
.map_err(|_| BinaryHeaderError::InvalidVariableHeaderSize) // todo: zerocopy: map_err
9496
.map(|(header, remaining)| {
9597
*bytes = remaining;
9698
header
@@ -99,7 +101,7 @@ fn read_header<T: FromBytesExt>(bytes: &mut &[u8]) -> Result<T, BinaryHeaderErro
99101

100102
/// Helper function to append a given binary header to a variable header
101103
/// section.
102-
fn append_header<T: AsBytes>(
104+
fn append_header<T: IntoBytes + Immutable + KnownLayout>(
103105
header: &T,
104106
header_type: IgvmVariableHeaderType,
105107
variable_headers: &mut Vec<u8>,
@@ -1785,22 +1787,20 @@ impl IgvmDirectiveHeader {
17851787
// First read the VbsVpContextHeader at file offset
17861788
let start = (header.file_offset - file_data_start) as usize;
17871789
let (VbsVpContextHeader { register_count }, remaining_data) =
1788-
VbsVpContextHeader::read_from_prefix_split(&file_data[start..])
1789-
.ok_or(BinaryHeaderError::InvalidDataSize)?;
1790+
VbsVpContextHeader::read_from_prefix(&file_data[start..])
1791+
.map_err(|_| BinaryHeaderError::InvalidDataSize)?; // todo: zerocopy: map_err
17901792

17911793
let mut registers: Vec<VbsVpContextRegister> = Vec::new();
17921794
let mut vp_vtl: Option<u8> = None;
17931795
let mut remaining_data = remaining_data;
17941796

17951797
for _ in 0..register_count {
1796-
let reg = match VbsVpContextRegister::read_from_prefix_split(
1797-
remaining_data,
1798-
) {
1799-
Some((reg, slice)) => {
1798+
let reg = match VbsVpContextRegister::read_from_prefix(remaining_data) {
1799+
Ok((reg, slice)) => {
18001800
remaining_data = slice;
18011801
reg
18021802
}
1803-
None => return Err(BinaryHeaderError::InvalidDataSize),
1803+
Err(_) => return Err(BinaryHeaderError::InvalidDataSize), // todo: zerocopy: map_err
18041804
};
18051805

18061806
registers.push(reg);
@@ -1861,9 +1861,10 @@ impl IgvmDirectiveHeader {
18611861
.ok_or(BinaryHeaderError::InvalidDataSize)?;
18621862

18631863
// Copy the VMSA bytes into the VMSA, and validate the remaining bytes are 0.
1864-
let mut vmsa = SevVmsa::new_box_zeroed();
1864+
// todo: zerocopy: as of 0.8, can recover from allocation failure
1865+
let mut vmsa = SevVmsa::new_box_zeroed().unwrap();
18651866
let (vmsa_slice, remaining) = data.split_at(size_of::<SevVmsa>());
1866-
vmsa.as_bytes_mut().copy_from_slice(vmsa_slice);
1867+
vmsa.as_mut_bytes().copy_from_slice(vmsa_slice);
18671868
if remaining.iter().any(|b| *b != 0) {
18681869
return Err(BinaryHeaderError::InvalidVmsa);
18691870
}
@@ -1889,10 +1890,11 @@ impl IgvmDirectiveHeader {
18891890

18901891
// Copy the context bytes into the context structure,
18911892
// and validate the remaining bytes are 0.
1892-
let mut context = IgvmNativeVpContextX64::new_box_zeroed();
1893+
// todo: zerocopy: as of 0.8, can recover from allocation failure
1894+
let mut context = IgvmNativeVpContextX64::new_box_zeroed().unwrap();
18931895
let (context_slice, remaining) =
18941896
data.split_at(size_of::<IgvmNativeVpContextX64>());
1895-
context.as_bytes_mut().copy_from_slice(context_slice);
1897+
context.as_mut_bytes().copy_from_slice(context_slice);
18961898
if remaining.iter().any(|b| *b != 0) {
18971899
return Err(BinaryHeaderError::InvalidContext);
18981900
}
@@ -2814,7 +2816,9 @@ impl IgvmFile {
28142816

28152817
// Read the IGVM fixed header
28162818
let mut fixed_header = FixedHeader::V1(
2817-
IGVM_FIXED_HEADER::read_from_prefix(file).ok_or(Error::InvalidFixedHeader)?,
2819+
IGVM_FIXED_HEADER::read_from_prefix(file)
2820+
.map_err(|_| Error::InvalidFixedHeader)?
2821+
.0, // todo: zerocopy: map_err
28182822
);
28192823

28202824
if fixed_header.magic() != IGVM_MAGIC_VALUE {
@@ -2825,7 +2829,8 @@ impl IgvmFile {
28252829
IGVM_FORMAT_VERSION_1 => IgvmRevision::V1,
28262830
IGVM_FORMAT_VERSION_2 => {
28272831
let v2 = IGVM_FIXED_HEADER_V2::read_from_prefix(file)
2828-
.ok_or(Error::InvalidFixedHeader)?;
2832+
.map_err(|_| Error::InvalidFixedHeader)?
2833+
.0; // todo: zerocopy: map_err
28292834

28302835
let arch = match v2.architecture {
28312836
IgvmArchitecture::X64 => Arch::X64,
@@ -2903,7 +2908,10 @@ impl IgvmFile {
29032908

29042909
while !variable_headers.is_empty() {
29052910
// Peek the next fixed variable header to determine what kind of header to parse
2906-
match IGVM_VHS_VARIABLE_HEADER::read_from_prefix(variable_headers) {
2911+
match IGVM_VHS_VARIABLE_HEADER::read_from_prefix(variable_headers)
2912+
.ok()
2913+
.map(|h| h.0)
2914+
{
29072915
Some(header) if IGVM_VHT_RANGE_PLATFORM.contains(&header.typ.0) => {
29082916
if parsing_stage != VariableHeaderParsingStage::Platform {
29092917
// Only legal to parse platform headers before other types
@@ -3990,7 +3998,7 @@ mod tests {
39903998

39913999
/// Test a variable header matches the supplied args. Also tests that the header deserialized returns the original
39924000
/// header.
3993-
fn test_variable_header<T: FromBytesExt>(
4001+
fn test_variable_header<T: IntoBytes + Immutable + KnownLayout>(
39944002
revision: IgvmRevision,
39954003
header: IgvmDirectiveHeader,
39964004
file_data_offset: u32,
@@ -4009,7 +4017,8 @@ mod tests {
40094017
let file_data = file_data.take();
40104018

40114019
let common_header = IGVM_VHS_VARIABLE_HEADER::read_from_prefix(&binary_header[..])
4012-
.expect("variable header must be present");
4020+
.expect("variable header must be present")
4021+
.0;
40134022

40144023
assert_eq!(common_header.typ, header_type);
40154024
assert_eq!(
@@ -4116,7 +4125,7 @@ mod tests {
41164125
};
41174126
let expected_header = IGVM_VHS_PAGE_DATA {
41184127
gpa,
4119-
..FromZeroes::new_zeroed()
4128+
..FromZeros::new_zeroed()
41204129
};
41214130
test_variable_header(
41224131
IgvmRevision::V1,
@@ -4140,7 +4149,7 @@ mod tests {
41404149
let expected_header = IGVM_VHS_PAGE_DATA {
41414150
gpa,
41424151
file_offset: file_data_offset,
4143-
..FromZeroes::new_zeroed()
4152+
..FromZeros::new_zeroed()
41444153
};
41454154
data.resize(PAGE_SIZE_4K as usize, 0);
41464155
let expected_file_data = Some(data);
@@ -4166,7 +4175,7 @@ mod tests {
41664175
let expected_header = IGVM_VHS_PAGE_DATA {
41674176
gpa,
41684177
file_offset: file_data_offset,
4169-
..FromZeroes::new_zeroed()
4178+
..FromZeros::new_zeroed()
41704179
};
41714180
let expected_file_data = Some(data);
41724181
test_variable_header(
@@ -4224,7 +4233,7 @@ mod tests {
42244233

42254234
let read_raw_header = |data: &[u8]| {
42264235
let (_, data) = data.split_at(size_of::<IGVM_VHS_VARIABLE_HEADER>());
4227-
IGVM_VHS_PAGE_DATA::read_from_prefix(data).unwrap()
4236+
IGVM_VHS_PAGE_DATA::read_from_prefix(data).unwrap().0
42284237
};
42294238

42304239
let first = read_raw_header(&first);
@@ -4465,7 +4474,7 @@ mod tests {
44654474
number_of_bytes,
44664475
compatibility_mask,
44674476
flags,
4468-
..FromZeroes::new_zeroed()
4477+
..FromZeros::new_zeroed()
44694478
};
44704479

44714480
let header = IgvmDirectiveHeader::RequiredMemory {
@@ -4493,7 +4502,7 @@ mod tests {
44934502
number_of_bytes,
44944503
compatibility_mask,
44954504
flags,
4496-
..FromZeroes::new_zeroed()
4505+
..FromZeros::new_zeroed()
44974506
};
44984507

44994508
let header = IgvmDirectiveHeader::RequiredMemory {

0 commit comments

Comments
 (0)