microsoft/openvmm

Public

mirrored fromhttps://github.com/microsoft/openvmmAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
e8acaefba35969bbca0ffae96452cd05b47aa621

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

Guide/src/dev_guide/contrib/save-state.md

92lines · modecode

1# Save State
2
3OpenHCL supports the mechanism of saving & restoring state. This primitive can
4be used for various VM operations, but a key use case is for updating OpenHCL at
5runtime (a.k.a. "Servicing"). This save state can be stored in memory or on
6durable media, read back at a later time.
7
8## Save State First Principles
9
10Here are the principles you must maintain when adding new save & restore code:
11
121. **Save & Restore is Forward & Backwards Compatible**: A newer version of
13 OpenHCL must understand save state from a prior version, and an older version
14 must not crash when reading save state from a newer version.
152. **Do not break save state after that state is in use**: Save state must be
16 compatible from *any* commit to any other commit, once the product has
17 shipped and started using that save state.[^1]
183. **All Save State is Protocol Buffers**: All save state is encoded as
19 `ProtoBuf`, using `mesh`.
20
21## Best practices
22
231. **Put save state in it's own module**: This makes PR reviews easier, to catch
24 any mistakes updating save state.
252. **Create a unique package per crate**: A logical grouping of saved state
26 should have the same `package`
273. **Avoid unsupported types, when possible**: These types don't support the
28 default values needed for safely extending save state:
29 * Arrays: if you need to add an array, consider a `vec` or `Option<[T; N]>`
30 instead.
31 * Enum: if you need to add an enum, add it as `Option<MyEnum>' instead.
324. **Be particularly careful when updating saved state**: See below.
33
34### Updating (Extending) Saved State
35
36Since saved state is just Protocol Buffers, use the [guide to updating Protocol
37Buffers messages](https://protobuf.dev/programming-guides/proto3/#updating) as a
38starting point, with the following caveats:
39
401. OpenVMM uses `sint32` to represent the `i32` native type. Therefore, changing
41 `i32` to `u32` is a breaking change, for example.
422. The Protocol Buffers docs mention what happens for newly added fields, but it
43 bears adding some nuance here:
44 1. Plain `arrays` and `enums` are not supported. Reading newer save state
45 with an `array` or `enum` will fail on an older build. Instead, wrap
46 these in an `Option`.
47 2. Old -> New Save State: Save state from a prior revision will not contain
48 some newly added fields. Those fields will get the [default
49 values](https://protobuf.dev/programming-guides/proto3/#default). This is
50 how that breaks down for the rust types:
51 * `Option<T>` => `None`
52 * Structs => each field gets that field's default value
53 * Vecs => empty vec
54 * Numbers => 0
55 * Strings => `""`
56 3. New -> Old Save State: Unknown fields are ignored.
573. Ensure that default values for new saved state fields make semantic sense.
58 Here is the heuristic: if you need a conditional to check if the restored
59 value is the default because it was not included in save state, you should
60 use an `Option`. If you wouldn't otherwise need a conditional, you should not
61 use an `Option`.
624. Define your saved state so that the natural default of `bool` types is
63 `false`.
64
65## Defining Saved State
66
67Saved state is defined as a `struct` that has `#[derive(Protobuf)]` and
68`#[mesh(package = "package_name")]` attributes. Here is an example, taken from
69the `nvme_driver`:
70
71```rust
72pub mod save_restore {
73 use super::*;
74
75 /// Save/restore state for IoQueue.
76 #[derive(Protobuf, Clone, Debug)]
77 #[mesh(package = "nvme_driver")]
78 pub struct IoQueueSavedState {
79 #[mesh(1)]
80 /// Which CPU handles requests.
81 pub cpu: u32,
82 #[mesh(2)]
83 /// Interrupt vector (MSI-X)
84 pub iv: u32,
85 #[mesh(3)]
86 pub queue_data: QueuePairSavedState,
87 }
88}
89```
90
91[^1]: Saved state is in use when it reaches a release branch that is in tell
92 mode. See [release management](./release.md) for details.