tdx.rs0.00%
1
// Copyright 2026 Google LLC2
//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 at6
//7
// https://www.apache.org/licenses/LICENSE-2.08
//9
// Unless required by applicable law or agreed to in writing, software10
// 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 and13
// limitations under the License.14
15
use std::sync::Arc;16
use std::sync::atomic::Ordering;17
18
use crate::arch::layout::MEM_64_START;19
use crate::arch::tdx::TdAttr;20
use crate::board::{Board, Result, error};21
use crate::firmware::ovmf::tdx::{TdvfSectionAttr, TdvfSectionType, create_hob, parse_entries};22
use crate::hv::{Vcpu, Vm, VmMemory};23
use crate::mem::MarkPrivateMemory;24
use crate::mem::mapped::ArcMemPages;25
26
impl<V> Board<V>27
where28
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.memory50
.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
d92
}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