|
5 | 5 |
|
6 | 6 | use super::address_space::LocalMap; |
7 | 7 | use super::address_space::init_local_map; |
| 8 | +use crate::AddressSpaceManager; |
8 | 9 | use crate::ShimParams; |
9 | 10 | use crate::arch::TdxHypercallPage; |
10 | 11 | use crate::arch::x86_64::address_space::tdx_share_large_page; |
11 | 12 | use crate::host_params::PartitionInfo; |
12 | 13 | use crate::host_params::shim_params::IsolationType; |
13 | 14 | use crate::hypercall::hvcall; |
| 15 | +use crate::memory::AllocationPolicy; |
| 16 | +use crate::memory::AllocationType; |
| 17 | +use crate::off_stack; |
| 18 | +use arrayvec::ArrayVec; |
| 19 | +use loader_defs::shim::MemoryVtlType; |
14 | 20 | use memory_range::MemoryRange; |
| 21 | +use page_table::x64::PAGE_TABLE_MAX_BYTES; |
| 22 | +use page_table::x64::PAGE_TABLE_MAX_COUNT; |
| 23 | +use page_table::x64::PageTable; |
| 24 | +use page_table::x64::PageTableBuilder; |
15 | 25 | use sha2::Digest; |
16 | 26 | use sha2::Sha384; |
17 | 27 | use x86defs::X64_LARGE_PAGE_SIZE; |
18 | 28 | use x86defs::tdx::TDX_SHARED_GPA_BOUNDARY_ADDRESS_BIT; |
| 29 | +use zerocopy::FromZeros; |
19 | 30 |
|
20 | 31 | /// On isolated systems, transitions all VTL2 RAM to be private and accepted, with the appropriate |
21 | 32 | /// VTL permissions applied. |
22 | | -pub fn setup_vtl2_memory(shim_params: &ShimParams, partition_info: &PartitionInfo) { |
| 33 | +pub fn setup_vtl2_memory( |
| 34 | + shim_params: &ShimParams, |
| 35 | + partition_info: &PartitionInfo, |
| 36 | + address_space: &mut AddressSpaceManager, |
| 37 | +) { |
23 | 38 | // Only if the partition is VBS-isolated, accept memory and apply vtl 2 protections here. |
24 | 39 | // Non-isolated partitions can undergo servicing, and additional information |
25 | 40 | // would be needed to determine whether vtl 2 protections should be applied |
@@ -125,6 +140,71 @@ pub fn setup_vtl2_memory(shim_params: &ShimParams, partition_info: &PartitionInf |
125 | 140 | // hypercall IO pages. ram_buffer must not be used again beyond this point |
126 | 141 | // TODO: find an approach that does not require re-using the ram_buffer |
127 | 142 | if shim_params.isolation_type == IsolationType::Tdx { |
| 143 | + let page_table_region = address_space |
| 144 | + .allocate( |
| 145 | + None, |
| 146 | + PAGE_TABLE_MAX_BYTES as u64, |
| 147 | + AllocationType::TdxPageTables, |
| 148 | + AllocationPolicy::LowMemory, |
| 149 | + ) |
| 150 | + .expect("allocation of space for TDX page tables must succeed"); |
| 151 | + |
| 152 | + const MAX_RANGE_COUNT: usize = 64; |
| 153 | + let mut ranges = off_stack!( |
| 154 | + ArrayVec::<(u64, u64), MAX_RANGE_COUNT>, |
| 155 | + ArrayVec::new_const() |
| 156 | + ); |
| 157 | + |
| 158 | + let vtl2_ram = address_space |
| 159 | + .vtl2_ranges() |
| 160 | + .filter_map(|(range, typ)| match typ { |
| 161 | + MemoryVtlType::VTL2_RAM => Some((range.start(), range.end())), |
| 162 | + _ => None, |
| 163 | + }); |
| 164 | + |
| 165 | + ranges.extend(vtl2_ram); |
| 166 | + |
| 167 | + let mut page_table_work_buffer = |
| 168 | + off_stack!(ArrayVec<PageTable, PAGE_TABLE_MAX_COUNT>, ArrayVec::new_const()); |
| 169 | + for _ in 0..PAGE_TABLE_MAX_COUNT { |
| 170 | + page_table_work_buffer.push(PageTable::new_zeroed()); |
| 171 | + } |
| 172 | + let mut page_table = off_stack!(ArrayVec<u8, PAGE_TABLE_MAX_BYTES>, ArrayVec::new_const()); |
| 173 | + for _ in 0..PAGE_TABLE_MAX_BYTES { |
| 174 | + page_table.push(0); |
| 175 | + } |
| 176 | + |
| 177 | + let page_table_builder = PageTableBuilder::new( |
| 178 | + page_table_region.range.start(), |
| 179 | + page_table_work_buffer.as_mut_slice(), |
| 180 | + page_table.as_mut_slice(), |
| 181 | + ) |
| 182 | + .expect("page table builder must return no error") |
| 183 | + .with_ranges(ranges.as_slice()); |
| 184 | + |
| 185 | + let page_tables = page_table_builder |
| 186 | + .build() |
| 187 | + .expect("page table construction must succeed"); |
| 188 | + |
| 189 | + address_space.truncate_range( |
| 190 | + page_table_region, |
| 191 | + page_tables.len() as u64, |
| 192 | + AllocationPolicy::LowMemory, |
| 193 | + ); |
| 194 | + |
| 195 | + //TODO safety comment |
| 196 | + unsafe { |
| 197 | + core::ptr::copy_nonoverlapping( |
| 198 | + page_tables.as_ptr(), |
| 199 | + page_table_region.range.start() as *mut u8, |
| 200 | + page_tables.len(), |
| 201 | + ); |
| 202 | + } |
| 203 | + |
| 204 | + crate::arch::tdx::tdx_prepare_ap_trampoline( |
| 205 | + page_table_region.range.start() |
| 206 | + ); |
| 207 | + |
128 | 208 | let free_buffer = ram_buffer.as_mut_ptr() as u64; |
129 | 209 | assert!(free_buffer.is_multiple_of(X64_LARGE_PAGE_SIZE)); |
130 | 210 | // SAFETY: The bottom 2MB region of the ram_buffer is unused by the shim |
|
0 commit comments