Alioth Code Coverage

tdx.rs0.00%

1// Copyright 2026 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::sync::Arc;
16use std::sync::atomic::Ordering;
17
18use crate::arch::layout::MEM_64_START;
19use crate::arch::tdx::TdAttr;
20use crate::board::{Board, Result, error};
21use crate::firmware::ovmf::tdx::{TdvfSectionAttr, TdvfSectionType, create_hob, parse_entries};
22use crate::hv::{Vcpu, Vm, VmMemory};
23use crate::mem::MarkPrivateMemory;
24use crate::mem::mapped::ArcMemPages;
25
26impl<V> Board<V>
27where
28 V: Vm,
29{
30 pub(crate) fn tdx_init(&self, attr: TdAttr, memory: Arc<dyn VmMemory>) -> Result<()> {
31 self.vm.tdx_init_vm(attr, &self.arch.cpuids)?;
32 let mark_private_memory = Box::new(MarkPrivateMemory { memory });
33 self.memory.register_change_callback(mark_private_memory)?;
34 Ok(())
35 }
36
37 pub(crate) fn create_hob(&self, dst: &mut [u8], mut accepted: Vec<(u64, u64)>) -> Result<u64> {
38 let hob_phys = self.arch.tdx_hob.load(Ordering::Relaxed);
39 let mut entries = self.memory.mem_region_entries();
40 create_hob(dst, hob_phys, &mut entries, &mut accepted)?;
41 Ok(hob_phys)
42 }
43
44 pub(crate) fn setup_tdx(&self, fw: &mut ArcMemPages, vcpu: &V::Vcpu) -> Result<()> {
45 let data = fw.as_slice();
46 let entries = parse_entries(data)?;
47
48 let fw_gpa = MEM_64_START - data.len() as u64;
49 self.memory
50 .mark_private_memory(fw_gpa, data.len() as _, true)?;
51
52 let mut accepted = Vec::new();
53 let mut hob_ram = None;
54 for entry in entries {
55 match entry.r#type {
56 TdvfSectionType::TD_HOB => {
57 let p = ArcMemPages::from_anonymous(entry.size as usize, None, None)?;
58 hob_ram = Some(p);
59 let tdx_hob = &self.arch.tdx_hob;
60 tdx_hob.store(entry.address, Ordering::Relaxed);
61 accepted.push((entry.address, entry.size));
62 }
63 TdvfSectionType::TEMP_MEM => {
64 accepted.push((entry.address, entry.size));
65 }
66 _ => {}
67 };
68 }
69
70 let Some(hob_ram) = &mut hob_ram else {
71 return error::MissingPayload.fail();
72 };
73 let hob_phys = self.create_hob(hob_ram.as_slice_mut(), accepted)?;
74
75 vcpu.tdx_init_vcpu(hob_phys)?;
76
77 for entry in entries {
78 let tmp_mem;
79 let region = match entry.r#type {
80 TdvfSectionType::TD_HOB => hob_ram.as_slice(),
81 TdvfSectionType::TEMP_MEM => {
82 tmp_mem = ArcMemPages::from_anonymous(entry.size as usize, None, None)?;
83 tmp_mem.as_slice()
84 }
85 TdvfSectionType::BFV | TdvfSectionType::CFV => {
86 let start = entry.data_offset as usize;
87 let end = start + entry.size as usize;
88 let Some(d) = data.get(start..end) else {
89 return error::MissingPayload.fail();
90 };
91 d
92 }
93 t => {
94 log::error!("Unknown entry type: {t:x?}");
95 return error::UnknownFirmwareMetadata.fail();
96 }
97 };
98 let measure = entry.attributes.contains(TdvfSectionAttr::MR_EXTEND);
99 vcpu.tdx_init_mem_region(region, entry.address, measure)?;
100 }
101
102 Ok(())
103 }
104
105 pub(crate) fn tdx_init_ap(&self, vcpu: &mut V::Vcpu) -> Result<()> {
106 let hob = self.arch.tdx_hob.load(Ordering::Relaxed);
107 vcpu.tdx_init_vcpu(hob)?;
108 Ok(())
109 }
110
111 pub(crate) fn tdx_finalize(&self) -> Result<()> {
112 self.vm.tdx_finalize_vm()?;
113 Ok(())
114 }
115}
116