1212// See the License for the specific language governing permissions and
1313// limitations under the License.
1414
15+ mod sev;
16+
1517use std:: arch:: x86_64:: { __cpuid, CpuidResult } ;
1618use std:: collections:: HashMap ;
17- use std:: iter:: zip;
1819use std:: mem:: { offset_of, size_of, size_of_val} ;
1920use std:: path:: Path ;
2021use std:: sync:: Arc ;
21- use std:: sync:: atomic:: { AtomicU32 , Ordering } ;
22+ use std:: sync:: atomic:: AtomicU32 ;
2223
2324use parking_lot:: Mutex ;
2425use snafu:: ResultExt ;
25- use zerocopy:: { FromBytes , FromZeros , IntoBytes } ;
26+ use zerocopy:: { FromZeros , IntoBytes } ;
2627
2728use crate :: arch:: cpuid:: CpuidIn ;
2829use crate :: arch:: layout:: {
2930 BIOS_DATA_END , EBDA_END , EBDA_START , IOAPIC_START , MEM_64_START , PORT_ACPI_RESET ,
3031 PORT_ACPI_SLEEP_CONTROL , RAM_32_SIZE ,
3132} ;
3233use crate :: arch:: msr:: { IA32_MISC_ENABLE , MiscEnable } ;
33- use crate :: arch:: reg:: { Reg , SegAccess , SegReg , SegRegVal } ;
34- use crate :: arch:: sev:: SnpPageType ;
3534use crate :: board:: { Board , BoardConfig , CpuTopology , PCIE_MMIO_64_SIZE , Result , VcpuGuard , error} ;
3635use crate :: device:: ioapic:: IoApic ;
3736use crate :: firmware:: acpi:: bindings:: {
@@ -41,11 +40,6 @@ use crate::firmware::acpi::reg::{FadtReset, FadtSleepControl};
4140use crate :: firmware:: acpi:: {
4241 AcpiTable , create_fadt, create_madt, create_mcfg, create_rsdp, create_xsdt,
4342} ;
44- use crate :: firmware:: ovmf:: parse_data;
45- use crate :: firmware:: ovmf:: sev:: {
46- GUID_SEV_ES_RESET_BLOCK , GUID_SEV_METADATA , SevDescType , SevMetaData , SevMetadataDesc ,
47- SnpCpuidFunc , SnpCpuidInfo ,
48- } ;
4943use crate :: hv:: { Coco , Hypervisor , Vcpu , Vm } ;
5044use crate :: loader:: { Executable , InitState , Payload , firmware} ;
5145use crate :: mem:: mapped:: ArcMemPages ;
@@ -197,88 +191,19 @@ where
197191 encode_x2apic_id ( & self . config . cpu . topology , index) as u64
198192 }
199193
200- fn fill_snp_cpuid ( & self , entries : & mut [ SnpCpuidFunc ] ) {
201- for ( ( in_, out) , dst) in zip ( self . arch . cpuids . iter ( ) , entries. iter_mut ( ) ) {
202- dst. eax_in = in_. func ;
203- dst. ecx_in = in_. index . unwrap_or ( 0 ) ;
204- dst. eax = out. eax ;
205- dst. ebx = out. ebx ;
206- dst. ecx = out. ecx ;
207- dst. edx = out. edx ;
208- if dst. eax_in == 0xd && ( dst. ecx_in == 0x0 || dst. ecx_in == 0x1 ) {
209- dst. ebx = 0x240 ;
210- dst. xcr0_in = 1 ;
211- dst. xss_in = 0 ;
212- }
213- }
214- }
215-
216- fn parse_sev_es_ap ( & self , coco : & Coco , fw : & ArcMemPages ) {
217- match coco {
218- Coco :: AmdSev { policy } if policy. es ( ) => { }
219- Coco :: AmdSnp { .. } => { }
220- _ => return ,
221- }
222- let ap_eip = parse_data ( fw. as_slice ( ) , & GUID_SEV_ES_RESET_BLOCK ) . unwrap ( ) ;
223- let ap_eip = u32:: read_from_bytes ( ap_eip) . unwrap ( ) ;
224- self . arch . sev_ap_eip . store ( ap_eip, Ordering :: Release ) ;
225- }
226-
227- fn update_snp_desc ( & self , offset : usize , fw_range : & mut [ u8 ] ) -> Result < ( ) > {
228- let mut cpuid_table = SnpCpuidInfo :: new_zeroed ( ) ;
229- let ram_bus = self . memory . ram_bus ( ) ;
230- let ram = ram_bus. lock_layout ( ) ;
231- let ( desc, _) = SevMetadataDesc :: read_from_prefix ( & fw_range[ offset..] ) . unwrap ( ) ;
232- let snp_page_type = match desc. type_ {
233- SevDescType :: SNP_DESC_MEM => SnpPageType :: UNMEASURED ,
234- SevDescType :: SNP_SECRETS => SnpPageType :: SECRETS ,
235- SevDescType :: CPUID => {
236- assert ! ( desc. len as usize >= size_of:: <SnpCpuidInfo >( ) ) ;
237- assert ! ( cpuid_table. entries. len( ) >= self . arch. cpuids. len( ) ) ;
238- cpuid_table. count = self . arch . cpuids . len ( ) as u32 ;
239- self . fill_snp_cpuid ( & mut cpuid_table. entries ) ;
240- ram. write_t ( desc. base as _ , & cpuid_table) ?;
241- SnpPageType :: CPUID
242- }
243- _ => unimplemented ! ( ) ,
244- } ;
245- let range_ref = ram. get_slice :: < u8 > ( desc. base as u64 , desc. len as u64 ) ?;
246- let range_bytes =
247- unsafe { std:: slice:: from_raw_parts_mut ( range_ref. as_ptr ( ) as _ , range_ref. len ( ) ) } ;
248- self . memory
249- . mark_private_memory ( desc. base as _ , desc. len as _ , true ) ?;
250- let mut ret = self
251- . vm
252- . snp_launch_update ( range_bytes, desc. base as _ , snp_page_type) ;
253- if ret. is_err ( ) && desc. type_ == SevDescType :: CPUID {
254- let updated_cpuid: SnpCpuidInfo = ram. read_t ( desc. base as _ ) ?;
255- for ( set, got) in zip ( cpuid_table. entries . iter ( ) , updated_cpuid. entries . iter ( ) ) {
256- if set != got {
257- log:: error!( "set {set:#x?}, but firmware expects {got:#x?}" ) ;
258- }
259- }
260- ram. write_t ( desc. base as _ , & updated_cpuid) ?;
261- ret = self
262- . vm
263- . snp_launch_update ( range_bytes, desc. base as _ , snp_page_type) ;
264- }
265- ret?;
266- Ok ( ( ) )
267- }
268-
269194 fn setup_fw_cfg ( & self , payload : & Payload ) -> Result < ( ) > {
270195 let Some ( dev) = & * self . fw_cfg . lock ( ) else {
271196 return Ok ( ( ) ) ;
272197 } ;
273198 let mut dev = dev. lock ( ) ;
274199 if let Some ( Executable :: Linux ( image) ) = & payload. executable {
275- dev. add_kernel_data ( image) . context ( error:: Firmware ) ?;
200+ dev. add_kernel_data ( image) . context ( error:: FwCfg ) ?;
276201 } ;
277202 if let Some ( cmdline) = & payload. cmdline {
278203 dev. add_kernel_cmdline ( cmdline. to_owned ( ) ) ;
279204 } ;
280205 if let Some ( initramfs) = & payload. initramfs {
281- dev. add_initramfs_data ( initramfs) . context ( error:: Firmware ) ?;
206+ dev. add_initramfs_data ( initramfs) . context ( error:: FwCfg ) ?;
282207 } ;
283208 Ok ( ( ) )
284209 }
@@ -287,34 +212,11 @@ where
287212 let Some ( coco) = & self . config . coco else {
288213 return Ok ( ( ) ) ;
289214 } ;
290- self . memory . register_encrypted_pages ( fw) ?;
291- self . parse_sev_es_ap ( coco, fw) ;
292215 match coco {
293- Coco :: AmdSev { .. } => {
294- self . vm . sev_launch_update_data ( fw. as_slice_mut ( ) ) ?;
295- }
296- Coco :: AmdSnp { .. } => {
297- let fw_range = fw. as_slice_mut ( ) ;
298- let metadata_offset_r = parse_data ( fw_range, & GUID_SEV_METADATA ) . unwrap ( ) ;
299- let metadata_offset =
300- fw_range. len ( ) - u32:: read_from_bytes ( metadata_offset_r) . unwrap ( ) as usize ;
301- let ( metadata, _) =
302- SevMetaData :: read_from_prefix ( & fw_range[ metadata_offset..] ) . unwrap ( ) ;
303- let desc_offset = metadata_offset + size_of :: < SevMetaData > ( ) ;
304- for i in 0 ..metadata. num_desc as usize {
305- let offset = desc_offset + i * size_of :: < SevMetadataDesc > ( ) ;
306- self . update_snp_desc ( offset, fw_range) ?;
307- }
308- let fw_gpa = MEM_64_START - fw_range. len ( ) as u64 ;
309- self . memory
310- . mark_private_memory ( fw_gpa, fw_range. len ( ) as _ , true ) ?;
311- self . vm
312- . snp_launch_update ( fw_range, fw_gpa, SnpPageType :: NORMAL )
313- . unwrap ( ) ;
314- }
216+ Coco :: AmdSev { policy } => self . setup_sev ( fw, * policy) ,
217+ Coco :: AmdSnp { .. } => self . setup_snp ( fw) ,
315218 Coco :: IntelTdx { attr } => todo ! ( "Intel TDX {attr:?}" ) ,
316219 }
317- Ok ( ( ) )
318220 }
319221
320222 pub fn setup_firmware ( & self , fw : & Path , payload : & Payload ) -> Result < InitState > {
@@ -325,30 +227,18 @@ where
325227 }
326228
327229 pub fn init_ap ( & self , index : u16 , vcpu : & mut V :: Vcpu , vcpus : & VcpuGuard ) -> Result < ( ) > {
328- match & self . config . coco {
329- Some ( Coco :: AmdSev { policy } ) if policy. es ( ) => { }
330- Some ( Coco :: AmdSnp { .. } ) => { }
331- _ => return Ok ( ( ) ) ,
332- }
333- self . sync_vcpus ( vcpus) ?;
334- if index == 0 {
230+ let Some ( coco) = & self . config . coco else {
335231 return Ok ( ( ) ) ;
232+ } ;
233+ match coco {
234+ Coco :: AmdSev { policy } => {
235+ if policy. es ( ) {
236+ self . sev_init_ap ( index, vcpu, vcpus) ?;
237+ }
238+ }
239+ Coco :: AmdSnp { .. } => self . sev_init_ap ( index, vcpu, vcpus) ?,
240+ Coco :: IntelTdx { attr } => todo ! ( "Intel TDX {attr:?}" ) ,
336241 }
337- let eip = self . arch . sev_ap_eip . load ( Ordering :: Acquire ) ;
338- vcpu. set_regs ( & [ ( Reg :: Rip , eip as u64 & 0xffff ) ] ) ?;
339- vcpu. set_sregs (
340- & [ ] ,
341- & [ (
342- SegReg :: Cs ,
343- SegRegVal {
344- selector : 0xf000 ,
345- base : eip as u64 & 0xffff_0000 ,
346- limit : 0xffff ,
347- access : SegAccess ( 0x9b ) ,
348- } ,
349- ) ] ,
350- & [ ] ,
351- ) ?;
352242 Ok ( ( ) )
353243 }
354244
@@ -442,27 +332,18 @@ where
442332 Ok ( ( ) )
443333 }
444334
445- pub fn coco_finalize ( & self , index : u16 , vcpus : & VcpuGuard ) -> Result < ( ) > {
446- if let Some ( coco) = & self . config . coco {
447- self . sync_vcpus ( vcpus) ?;
448- if index == 0 {
449- match coco {
450- Coco :: AmdSev { policy } => {
451- if policy. es ( ) {
452- self . vm . sev_launch_update_vmsa ( ) ?;
453- }
454- self . vm . sev_launch_measure ( ) ?;
455- self . vm . sev_launch_finish ( ) ?;
456- }
457- Coco :: AmdSnp { .. } => {
458- self . vm . snp_launch_finish ( ) ?;
459- }
460- Coco :: IntelTdx { attr } => todo ! ( "Intel TDX {attr:?}" ) ,
461- }
462- }
463- self . sync_vcpus ( vcpus) ?;
335+ pub fn coco_finalize ( & self , index : u16 ) -> Result < ( ) > {
336+ let Some ( coco) = & self . config . coco else {
337+ return Ok ( ( ) ) ;
338+ } ;
339+ if index != 0 {
340+ return Ok ( ( ) ) ;
341+ } ;
342+ match coco {
343+ Coco :: AmdSev { policy } => self . sev_finalize ( * policy) ,
344+ Coco :: AmdSnp { .. } => self . snp_finalize ( ) ,
345+ Coco :: IntelTdx { attr } => todo ! ( "Intel TDX {attr:?}" ) ,
464346 }
465- Ok ( ( ) )
466347 }
467348
468349 fn patch_dsdt ( & self , data : & mut [ u8 ; 352 ] ) {
@@ -556,9 +437,9 @@ where
556437 }
557438 if let Some ( fw_cfg) = & * self . fw_cfg . lock ( ) {
558439 let mut dev = fw_cfg. lock ( ) ;
559- dev. add_acpi ( acpi_table) . context ( error:: Firmware ) ?;
440+ dev. add_acpi ( acpi_table) . context ( error:: FwCfg ) ?;
560441 let mem_regions = memory. mem_region_entries ( ) ;
561- dev. add_e820 ( & mem_regions) . context ( error:: Firmware ) ?;
442+ dev. add_e820 ( & mem_regions) . context ( error:: FwCfg ) ?;
562443 }
563444 Ok ( ( ) )
564445 }
0 commit comments