igvmfilegen/vp_context_builder/
vbs.rs1use crate::file_loader::DEFAULT_COMPATIBILITY_MASK;
7use crate::vp_context_builder::VpContextBuilder;
8use crate::vp_context_builder::VpContextState;
9use hvdef::Vtl;
10use igvm::FileDataSerializer;
11use igvm::IgvmDirectiveHeader;
12use igvm_defs::PAGE_SIZE_4K;
13use loader::importer::Aarch64Register;
14use loader::importer::X86Register;
15use std::fmt::Debug;
16use std::mem::discriminant;
17
18pub trait VbsRegister: Sized {
22 fn into_igvm_header(vtl: Vtl, list: &[Self]) -> IgvmDirectiveHeader;
25}
26
27impl VbsRegister for X86Register {
28 fn into_igvm_header(vtl: Vtl, list: &[Self]) -> IgvmDirectiveHeader {
29 IgvmDirectiveHeader::X64VbsVpContext {
30 registers: list
31 .iter()
32 .map(|®| reg.into())
33 .collect::<Vec<igvm::registers::X86Register>>(),
34 vtl: (vtl as u8).try_into().expect("vtl should be valid"),
35 compatibility_mask: DEFAULT_COMPATIBILITY_MASK,
36 }
37 }
38}
39
40impl VbsRegister for Aarch64Register {
41 fn into_igvm_header(vtl: Vtl, list: &[Self]) -> IgvmDirectiveHeader {
42 IgvmDirectiveHeader::AArch64VbsVpContext {
43 registers: list
44 .iter()
45 .map(|®| reg.into())
46 .collect::<Vec<igvm::registers::AArch64Register>>(),
47 vtl: (vtl as u8).try_into().expect("vtl should be valid"),
48 compatibility_mask: DEFAULT_COMPATIBILITY_MASK,
49 }
50 }
51}
52
53#[derive(Debug, Clone)]
54pub struct VbsVpContext<R: VbsRegister> {
55 registers: Vec<R>,
57 vtl: Vtl,
59}
60
61impl<R: VbsRegister> VbsVpContext<R> {
62 pub fn new(vtl: Vtl) -> Self {
63 Self {
64 registers: Vec::new(),
65 vtl,
66 }
67 }
68
69 pub fn as_page(&self) -> Vec<u8> {
72 let header = R::into_igvm_header(self.vtl, &self.registers);
73 let mut variable_header = Vec::new();
75 let mut file_data = FileDataSerializer::new(0);
76 header
77 .write_binary_header(&mut variable_header, &mut file_data)
78 .expect("registers should be valid");
79
80 let file_data = file_data.take();
81
82 assert!(file_data.len() <= PAGE_SIZE_4K as usize);
83
84 file_data
85 }
86}
87
88impl<R: VbsRegister> VpContextBuilder for VbsVpContext<R> {
89 type Register = R;
90
91 fn import_vp_register(&mut self, register: R) {
92 assert!(
94 !self
95 .registers
96 .iter()
97 .any(|reg| discriminant(reg) == discriminant(®ister)),
98 "duplicate register import"
99 );
100
101 self.registers.push(register);
102 }
103
104 fn set_vp_context_memory(&mut self, _page_base: u64) {
105 unimplemented!("not supported for VBS");
106 }
107
108 fn finalize(&mut self, state: &mut Vec<VpContextState>) {
109 if self.registers.is_empty() {
110 return;
111 }
112 state.push(VpContextState::Directive(R::into_igvm_header(
114 self.vtl,
115 &self.registers,
116 )));
117 }
118}