Skip to content

Commit edeb05f

Browse files
RuoqingHeroypat
authored andcommitted
riscv64: Introduce serde feature
Implement `serde` for basic RISC-V register structures to help VM snapshotting. Signed-off-by: Ruoqing He <[email protected]>
1 parent 79f4d5a commit edeb05f

File tree

5 files changed

+143
-4
lines changed

5 files changed

+143
-4
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
### Added
55

6-
- RISC-V KVM bindings for Linux kernel v6.9.
6+
- RISC-V KVM bindings for Linux kernel v6.9, including serialization support.
77

88
### Changed
99

src/lib.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,13 @@
1212
#[macro_use]
1313
extern crate vmm_sys_util;
1414

15-
#[cfg(all(feature = "serde", not(target_arch = "riscv64")))]
15+
#[cfg(feature = "serde")]
1616
extern crate serde;
1717

18-
#[cfg(all(feature = "serde", not(target_arch = "riscv64")))]
18+
#[cfg(feature = "serde")]
1919
extern crate zerocopy;
2020

21-
#[cfg(all(feature = "serde", not(target_arch = "riscv64")))]
21+
#[cfg(feature = "serde")]
2222
#[macro_use]
2323
mod serialize;
2424

src/riscv64/bindings.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -630,6 +630,10 @@ pub type __wsum = __u32;
630630
pub type __poll_t = ::std::os::raw::c_uint;
631631
#[repr(C)]
632632
#[derive(Debug, Default, Copy, Clone, PartialEq)]
633+
#[cfg_attr(
634+
feature = "serde",
635+
derive(zerocopy::AsBytes, zerocopy::FromBytes, zerocopy::FromZeroes)
636+
)]
633637
pub struct user_regs_struct {
634638
pub pc: ::std::os::raw::c_ulong,
635639
pub ra: ::std::os::raw::c_ulong,
@@ -1592,6 +1596,10 @@ fn bindgen_test_layout_kvm_sregs() {
15921596
}
15931597
#[repr(C)]
15941598
#[derive(Debug, Default, Copy, Clone, PartialEq)]
1599+
#[cfg_attr(
1600+
feature = "serde",
1601+
derive(zerocopy::AsBytes, zerocopy::FromBytes, zerocopy::FromZeroes)
1602+
)]
15951603
pub struct kvm_riscv_config {
15961604
pub isa: ::std::os::raw::c_ulong,
15971605
pub zicbom_block_size: ::std::os::raw::c_ulong,
@@ -1688,6 +1696,10 @@ fn bindgen_test_layout_kvm_riscv_config() {
16881696
}
16891697
#[repr(C)]
16901698
#[derive(Debug, Default, Copy, Clone, PartialEq)]
1699+
#[cfg_attr(
1700+
feature = "serde",
1701+
derive(zerocopy::AsBytes, zerocopy::FromBytes, zerocopy::FromZeroes)
1702+
)]
16911703
pub struct kvm_riscv_core {
16921704
pub regs: user_regs_struct,
16931705
pub mode: ::std::os::raw::c_ulong,
@@ -1729,6 +1741,10 @@ fn bindgen_test_layout_kvm_riscv_core() {
17291741
}
17301742
#[repr(C)]
17311743
#[derive(Debug, Default, Copy, Clone, PartialEq)]
1744+
#[cfg_attr(
1745+
feature = "serde",
1746+
derive(zerocopy::AsBytes, zerocopy::FromBytes, zerocopy::FromZeroes)
1747+
)]
17321748
pub struct kvm_riscv_csr {
17331749
pub sstatus: ::std::os::raw::c_ulong,
17341750
pub sie: ::std::os::raw::c_ulong,
@@ -1869,6 +1885,10 @@ fn bindgen_test_layout_kvm_riscv_csr() {
18691885
}
18701886
#[repr(C)]
18711887
#[derive(Debug, Default, Copy, Clone, PartialEq)]
1888+
#[cfg_attr(
1889+
feature = "serde",
1890+
derive(zerocopy::AsBytes, zerocopy::FromBytes, zerocopy::FromZeroes)
1891+
)]
18721892
pub struct kvm_riscv_aia_csr {
18731893
pub siselect: ::std::os::raw::c_ulong,
18741894
pub iprio1: ::std::os::raw::c_ulong,
@@ -1965,6 +1985,10 @@ fn bindgen_test_layout_kvm_riscv_aia_csr() {
19651985
}
19661986
#[repr(C)]
19671987
#[derive(Debug, Default, Copy, Clone, PartialEq)]
1988+
#[cfg_attr(
1989+
feature = "serde",
1990+
derive(zerocopy::AsBytes, zerocopy::FromBytes, zerocopy::FromZeroes)
1991+
)]
19681992
pub struct kvm_riscv_smstateen_csr {
19691993
pub sstateen0: ::std::os::raw::c_ulong,
19701994
}
@@ -1996,6 +2020,10 @@ fn bindgen_test_layout_kvm_riscv_smstateen_csr() {
19962020
}
19972021
#[repr(C)]
19982022
#[derive(Debug, Default, Copy, Clone, PartialEq)]
2023+
#[cfg_attr(
2024+
feature = "serde",
2025+
derive(zerocopy::AsBytes, zerocopy::FromBytes, zerocopy::FromZeroes)
2026+
)]
19992027
pub struct kvm_riscv_timer {
20002028
pub frequency: __u64,
20012029
pub time: __u64,
@@ -2128,6 +2156,10 @@ pub const KVM_RISCV_SBI_EXT_ID_KVM_RISCV_SBI_EXT_MAX: KVM_RISCV_SBI_EXT_ID = 11;
21282156
pub type KVM_RISCV_SBI_EXT_ID = ::std::os::raw::c_uint;
21292157
#[repr(C)]
21302158
#[derive(Debug, Default, Copy, Clone, PartialEq)]
2159+
#[cfg_attr(
2160+
feature = "serde",
2161+
derive(zerocopy::AsBytes, zerocopy::FromBytes, zerocopy::FromZeroes)
2162+
)]
21312163
pub struct kvm_riscv_sbi_sta {
21322164
pub shmem_lo: ::std::os::raw::c_ulong,
21332165
pub shmem_hi: ::std::os::raw::c_ulong,
@@ -6387,6 +6419,10 @@ fn bindgen_test_layout_kvm_vapic_addr() {
63876419
}
63886420
#[repr(C)]
63896421
#[derive(Debug, Default, Copy, Clone, PartialEq)]
6422+
#[cfg_attr(
6423+
feature = "serde",
6424+
derive(zerocopy::AsBytes, zerocopy::FromBytes, zerocopy::FromZeroes)
6425+
)]
63906426
pub struct kvm_mp_state {
63916427
pub mp_state: __u32,
63926428
}
@@ -7549,6 +7585,10 @@ fn bindgen_test_layout_kvm_reg_list() {
75497585
}
75507586
#[repr(C)]
75517587
#[derive(Debug, Default, Copy, Clone, PartialEq)]
7588+
#[cfg_attr(
7589+
feature = "serde",
7590+
derive(zerocopy::AsBytes, zerocopy::FromBytes, zerocopy::FromZeroes)
7591+
)]
75527592
pub struct kvm_one_reg {
75537593
pub id: __u64,
75547594
pub addr: __u64,

src/riscv64/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ pub mod bindings;
88
#[cfg(feature = "fam-wrappers")]
99
pub mod fam_wrappers;
1010

11+
#[cfg(feature = "serde")]
12+
mod serialize;
13+
1114
pub use self::bindings::*;
1215
#[cfg(feature = "fam-wrappers")]
1316
pub use self::fam_wrappers::*;

src/riscv64/serialize.rs

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
// Copyright 2024 © Institute of Software, CAS. All rights reserved.
2+
// Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
// SPDX-License-Identifier: Apache-2.0
4+
5+
use bindings::{
6+
kvm_mp_state, kvm_one_reg, kvm_riscv_aia_csr, kvm_riscv_config, kvm_riscv_core, kvm_riscv_csr,
7+
kvm_riscv_sbi_sta, kvm_riscv_smstateen_csr, kvm_riscv_timer, user_regs_struct,
8+
};
9+
use serde::{Deserialize, Deserializer, Serialize, Serializer};
10+
use zerocopy::{transmute, AsBytes};
11+
12+
serde_impls! {
13+
kvm_mp_state,
14+
kvm_one_reg,
15+
kvm_riscv_config,
16+
kvm_riscv_core,
17+
user_regs_struct,
18+
kvm_riscv_csr,
19+
kvm_riscv_aia_csr,
20+
kvm_riscv_smstateen_csr,
21+
kvm_riscv_timer,
22+
kvm_riscv_sbi_sta
23+
}
24+
25+
#[cfg(test)]
26+
mod tests {
27+
use bindings::*;
28+
use serde::{Deserialize, Serialize};
29+
30+
fn is_serde<T: Serialize + for<'de> Deserialize<'de> + Default>() {
31+
let serialized = bincode::serialize(&T::default()).unwrap();
32+
let deserialized = bincode::deserialize::<T>(serialized.as_ref()).unwrap();
33+
let serialized_again = bincode::serialize(&deserialized).unwrap();
34+
// Compare the serialized state after a roundtrip, to work around issues with
35+
// bindings not implementing `PartialEq`.
36+
assert_eq!(serialized, serialized_again);
37+
}
38+
39+
#[test]
40+
fn static_assert_serde_implementations() {
41+
// This test statically (= at compile-time) asserts that various bindgen generated
42+
// structures implement serde's `Serialize` and `Deserialize` traits.
43+
// This is to make sure that we do not accidentally remove those implementations
44+
// when regenerating bindings. If this test fails to compile, please add
45+
//
46+
// #[cfg_attr(
47+
// feature = "serde",
48+
// derive(zerocopy::AsBytes, zerocopy::FromBytes, zerocopy::FromZeroes)
49+
// )]
50+
//
51+
// to all structures causing compilation errors (we need the zerocopy traits, as the
52+
// `Serialize` and `Deserialize` implementations are provided by the `serde_impls!` macro
53+
// above, which implements serialization based on zerocopy's `FromBytes` and `AsBytes`
54+
// traits that it expects to be derived).
55+
//
56+
// NOTE: This only include "top-level" items, and does not list out bindgen-anonymous types
57+
// (e.g. types like `kvm_vcpu_events__bindgen_ty_5`). These types can change name across
58+
// bindgen versions. If after re-adding the derives to all the below items you can compile
59+
// errors about anonymous types not implementing `Serialize`/`Deserialize`, please also add
60+
// the derives to all anonymous types references in the definitions of the below items.
61+
62+
is_serde::<kvm_mp_state>();
63+
is_serde::<kvm_one_reg>();
64+
is_serde::<kvm_riscv_config>();
65+
is_serde::<kvm_riscv_core>();
66+
is_serde::<user_regs_struct>();
67+
is_serde::<kvm_riscv_csr>();
68+
is_serde::<kvm_riscv_aia_csr>();
69+
is_serde::<kvm_riscv_smstateen_csr>();
70+
is_serde::<kvm_riscv_timer>();
71+
is_serde::<kvm_riscv_sbi_sta>();
72+
}
73+
74+
fn is_serde_json<T: Serialize + for<'de> Deserialize<'de> + Default>() {
75+
let serialized = serde_json::to_string(&T::default()).unwrap();
76+
let deserialized = serde_json::from_str::<T>(serialized.as_ref()).unwrap();
77+
let serialized_again = serde_json::to_string(&deserialized).unwrap();
78+
// Compare the serialized state after a roundtrip, to work around issues with
79+
// bindings not implementing `PartialEq`.
80+
assert_eq!(serialized, serialized_again);
81+
}
82+
83+
#[test]
84+
fn test_json_serde() {
85+
is_serde_json::<kvm_mp_state>();
86+
is_serde_json::<kvm_one_reg>();
87+
is_serde_json::<kvm_riscv_config>();
88+
is_serde_json::<kvm_riscv_core>();
89+
is_serde_json::<user_regs_struct>();
90+
is_serde_json::<kvm_riscv_csr>();
91+
is_serde_json::<kvm_riscv_aia_csr>();
92+
is_serde_json::<kvm_riscv_smstateen_csr>();
93+
is_serde_json::<kvm_riscv_timer>();
94+
is_serde_json::<kvm_riscv_sbi_sta>();
95+
}
96+
}

0 commit comments

Comments
 (0)