1use self::vtl2_config::RuntimeParameters;
7use crate::loader::vtl0_config::LinuxInfo;
8use crate::worker::FirmwareType;
9use cvm_tracing::CVM_ALLOWED;
10use guest_emulation_transport::api::platform_settings::DevicePlatformSettings;
11use guest_emulation_transport::api::platform_settings::General;
12use guestmem::GuestMemory;
13use hvdef::HV_PAGE_SIZE;
14use igvm_defs::MemoryMapEntryType;
15use loader::importer::Register;
16use loader::uefi::IMAGE_SIZE;
17use loader::uefi::config;
18use loader_defs::paravisor::PageRegionDescriptor;
19use memory_range::MemoryRange;
20#[cfg(guest_arch = "x86_64")]
21use serial_16550_resources::ComPort;
22use std::ffi::CString;
23use thiserror::Error;
24use vm_topology::memory::MemoryLayout;
25use vm_topology::memory::MemoryRangeWithNode;
26use vm_topology::processor::ProcessorTopology;
27use vmm_core::acpi_builder::AcpiTablesBuilder;
28use zerocopy::FromBytes;
29use zerocopy::IntoBytes;
30
31pub mod vtl0_config;
32pub mod vtl2_config;
33
34#[derive(Debug, Clone, Copy, PartialEq, Eq)]
35pub enum LoadKind {
36 None,
37 Uefi,
38 Pcat,
39 Linux,
40}
41
42impl From<LoadKind> for FirmwareType {
43 fn from(value: LoadKind) -> Self {
44 match value {
45 LoadKind::None | LoadKind::Linux => FirmwareType::None,
46 LoadKind::Uefi => FirmwareType::Uefi,
47 LoadKind::Pcat => FirmwareType::Pcat,
48 }
49 }
50}
51
52#[derive(Debug, Clone)]
53pub enum VpContext {
54 Vbs(Vec<Register>),
55 }
57
58#[derive(Debug, Error)]
59pub enum Error {
60 #[error("accessing guest memory failed")]
61 GuestMemoryAccess(#[source] guestmem::GuestMemoryError),
62 #[cfg(guest_arch = "x86_64")]
63 #[error("linux loader error")]
64 LinuxLoader(#[source] loader::linux::Error),
65 #[cfg(guest_arch = "x86_64")]
66 #[error("pcat loader error")]
67 PcatLoader(#[source] loader::pcat::Error),
68 #[error("pcat not supported")]
69 PcatSupport,
70 #[error("uefi not supported")]
71 UefiSupport,
72 #[error("linux not supported")]
73 LinuxSupport,
74 #[error("finalizing boot")]
75 Finalize(#[source] vtl0_config::Error),
76 #[error("invalid acpi table: too short")]
77 InvalidAcpiTableLength,
78 #[error("invalid acpi table: unknown header signature {0:?}")]
79 InvalidAcpiTableSignature([u8; 4]),
80 #[cfg(guest_arch = "x86_64")]
81 #[error("acpi tables require at least two mmio ranges")]
82 UnsupportedMmio,
83}
84
85pub const PV_CONFIG_BASE_PAGE: u64 = if cfg!(guest_arch = "x86_64") {
86 loader_defs::paravisor::PARAVISOR_VTL0_MEASURED_CONFIG_BASE_PAGE_X64
87} else if cfg!(guest_arch = "aarch64") {
88 loader_defs::paravisor::PARAVISOR_VTL0_MEASURED_CONFIG_BASE_PAGE_AARCH64
89} else {
90 panic!("unsupported guest architecture");
91};
92
93pub struct Config {
95 pub cmdline_append: CString,
98 pub disable_uefi_frontpage: bool,
100}
101
102pub fn load(
104 gm: &GuestMemory,
105 mem_layout: &MemoryLayout,
106 processor_topology: &ProcessorTopology,
107 vtl0_memory_map: &[(MemoryRangeWithNode, MemoryMapEntryType)],
108 runtime_params: &RuntimeParameters,
109 load_kind: LoadKind,
110 vtl0_info: vtl0_config::MeasuredVtl0Info,
111 platform_config: &DevicePlatformSettings,
112 config: Config,
113 caps: &virt::PartitionCapabilities,
114 isolated: bool,
115) -> Result<VpContext, Error> {
116 let context = match load_kind {
117 LoadKind::None => {
118 tracing::info!(CVM_ALLOWED, "loading nothing into VTL0");
119 VpContext::Vbs(Vec::new())
120 }
121 LoadKind::Uefi => {
122 tracing::info!(CVM_ALLOWED, "loading UEFI into VTL0");
123 let uefi_info = vtl0_info.supports_uefi.as_ref().ok_or(Error::UefiSupport)?;
126
127 write_uefi_config(
128 gm,
129 mem_layout,
130 processor_topology,
131 vtl0_memory_map,
132 runtime_params,
133 platform_config,
134 caps,
135 isolated,
136 config.disable_uefi_frontpage,
137 )?;
138 uefi_info.vp_context.clone()
139 }
140 #[cfg(not(guest_arch = "x86_64"))]
141 LoadKind::Linux => {
142 let _ = config.cmdline_append;
143 let LinuxInfo {
144 kernel_range: _kernel_range,
145 kernel_entrypoint: _kernel_entrypoint,
146 initrd: _initrd,
147 command_line: _command_line,
148 } = vtl0_info
149 .supports_linux
150 .as_ref()
151 .ok_or(Error::LinuxSupport)?;
152 todo!();
153 }
154 #[cfg(guest_arch = "x86_64")]
155 LoadKind::Linux => {
156 tracing::info!(CVM_ALLOWED, "loading Linux into VTL0");
157
158 let LinuxInfo {
159 kernel_range,
160 kernel_entrypoint,
161 initrd,
162 command_line,
163 } = vtl0_info
164 .supports_linux
165 .as_ref()
166 .ok_or(Error::LinuxSupport)?;
167
168 let mut command_line = command_line.clone().unwrap_or_default().into_bytes();
170
171 if !command_line.is_empty() && command_line.last() != Some(&b' ') {
174 command_line.push(b' ');
175 }
176
177 command_line.extend_from_slice(config.cmdline_append.to_bytes());
179
180 let command_line = CString::new(command_line).expect("constructed from valid CStrings");
181
182 load_linux(LoadLinuxParams {
183 gm,
184 mem_layout,
185 processor_topology,
186 platform_config,
187 kernel_range: *kernel_range,
188 kernel_entrypoint: *kernel_entrypoint,
189 initrd: *initrd,
190 command_line,
191 })?
192 }
193 LoadKind::Pcat => {
194 tracing::info!(CVM_ALLOWED, "loading pcat into VTL0");
195
196 if !vtl0_info.supports_pcat {
197 return Err(Error::PcatSupport);
198 }
199
200 #[cfg(not(guest_arch = "x86_64"))]
201 panic!("Not supported");
202
203 #[cfg(guest_arch = "x86_64")]
204 load_pcat(gm, mem_layout)?
205 }
206 };
207
208 vtl0_info
209 .finalize_load(gm, load_kind)
210 .map_err(Error::Finalize)?;
211
212 Ok(context)
213}
214
215#[cfg(guest_arch = "x86_64")]
217fn load_pcat(gm: &GuestMemory, mem_layout: &MemoryLayout) -> Result<VpContext, Error> {
218 let mut loader = vm_loader::Loader::new(gm.clone(), mem_layout, hvdef::Vtl::Vtl0);
219
220 loader::pcat::load(&mut loader, None, mem_layout.max_ram_below_4gb())
223 .map_err(Error::PcatLoader)?;
224
225 Ok(VpContext::Vbs(loader.initial_regs()))
226}
227
228#[cfg(guest_arch = "x86_64")]
229struct LoadLinuxParams<'a> {
230 gm: &'a GuestMemory,
231 mem_layout: &'a MemoryLayout,
232 processor_topology: &'a ProcessorTopology,
233 platform_config: &'a DevicePlatformSettings,
234 kernel_range: MemoryRange,
236 kernel_entrypoint: u64,
238 initrd: Option<(u64, u64)>,
240 command_line: CString,
242}
243
244#[cfg(guest_arch = "x86_64")]
246fn load_linux(params: LoadLinuxParams<'_>) -> Result<VpContext, Error> {
247 const GDT_BASE: u64 = 0x1000;
248 const CR3_BASE: u64 = 0x4000;
249 const ZERO_PAGE_BASE: u64 = 0x2000;
250 const CMDLINE_BASE: u64 = 0x3000;
251 const ACPI_BASE: u64 = 0xe0000;
252
253 let LoadLinuxParams {
254 gm,
255 mem_layout,
256 processor_topology,
257 platform_config,
258 kernel_range,
259 kernel_entrypoint,
260 initrd,
261 command_line,
262 } = params;
263
264 let cmdline_config = loader::linux::CommandLineConfig {
265 address: CMDLINE_BASE,
266 cmdline: &command_line,
267 };
268
269 let acpi_builder = AcpiTablesBuilder {
270 processor_topology,
271 mem_layout,
272 cache_topology: None,
273 with_ioapic: true, with_pic: false,
275 with_pit: false,
276 with_psp: platform_config.general.psp_enabled,
277 pm_base: crate::worker::PM_BASE,
278 acpi_irq: crate::worker::SYSTEM_IRQ_ACPI,
279 };
280
281 if mem_layout.mmio().len() < 2 {
282 return Err(Error::UnsupportedMmio);
283 }
284
285 let acpi_tables = acpi_builder.build_acpi_tables(ACPI_BASE, |mem_layout, dsdt| {
286 dsdt.add_apic();
287
288 if platform_config.general.com1_enabled {
290 dsdt.add_uart(
291 b"\\_SB.UAR1",
292 b"COM1",
293 1,
294 ComPort::Com1.io_port(),
295 ComPort::Com1.irq().into(),
296 );
297 }
298
299 if platform_config.general.com2_enabled {
300 dsdt.add_uart(
301 b"\\_SB.UAR2",
302 b"COM2",
303 2,
304 ComPort::Com2.io_port(),
305 ComPort::Com2.irq().into(),
306 );
307 }
308
309 dsdt.add_mmio_module(mem_layout.mmio()[0], mem_layout.mmio()[1]);
310 dsdt.add_vmbus(false);
312 dsdt.add_rtc();
313 });
314 let acpi_len = acpi_tables.tables.len() + 0x1000;
315
316 let acpi_config = loader::linux::AcpiConfig {
317 rdsp_address: ACPI_BASE,
318 rdsp: &acpi_tables.rdsp,
319 tables_address: ACPI_BASE + 0x1000,
320 tables: &acpi_tables.tables,
321 };
322
323 let register_config = loader::linux::RegisterConfig {
324 gdt_address: GDT_BASE,
325 page_table_address: CR3_BASE,
326 };
327
328 let mut loader = vm_loader::Loader::new(gm.clone(), mem_layout, hvdef::Vtl::Vtl0);
329
330 let initrd_info = if let Some((initrd_base, initrd_size)) = initrd {
331 let size_pages = (initrd_size + HV_PAGE_SIZE - 1) & !(HV_PAGE_SIZE - 1);
332
333 loader
335 .accept_new_range(
336 initrd_base / HV_PAGE_SIZE,
337 size_pages,
338 "linux-initrd",
339 loader::importer::BootPageAcceptance::Exclusive,
340 )
341 .expect("should be valid range");
342
343 Some(loader::linux::InitrdInfo {
344 gpa: initrd_base,
345 size: initrd_size,
346 })
347 } else {
348 None
349 };
350
351 let zero_page_config = loader::linux::ZeroPageConfig {
352 address: ZERO_PAGE_BASE,
353 mem_layout,
354 acpi_base_address: ACPI_BASE,
355 acpi_len,
356 };
357
358 tracing::trace!(?initrd_info);
359
360 loader
362 .accept_new_range(
363 kernel_range.start() / HV_PAGE_SIZE,
364 kernel_range.len() / HV_PAGE_SIZE,
365 "linux-kernel",
366 loader::importer::BootPageAcceptance::Exclusive,
367 )
368 .expect("should be valid range");
369
370 let load_info = loader::linux::LoadInfo {
371 kernel: loader::linux::KernelInfo {
372 gpa: kernel_range.start(),
373 size: kernel_range.len(),
374 entrypoint: kernel_entrypoint,
375 },
376 initrd: initrd_info,
377 dtb: None,
378 };
379
380 loader::linux::load_config(
381 &mut loader,
382 &load_info,
383 cmdline_config,
384 zero_page_config,
385 acpi_config,
386 register_config,
387 )
388 .map_err(Error::LinuxLoader)?;
389
390 Ok(VpContext::Vbs(loader.initial_regs()))
391}
392
393fn convert_range_type_flag(entry_type: MemoryMapEntryType) -> u32 {
394 match entry_type {
395 MemoryMapEntryType::MEMORY | MemoryMapEntryType::VTL2_PROTECTABLE => 0,
396 MemoryMapEntryType::PLATFORM_RESERVED => config::VM_MEMORY_RANGE_FLAG_PLATFORM_RESERVED,
397 MemoryMapEntryType::PERSISTENT => {
400 unimplemented!("underhill does not support persistent memory type")
401 }
402 MemoryMapEntryType::SPECIFIC_PURPOSE => config::VM_MEMORY_RANGE_FLAG_SPECIFIC_PURPOSE,
403 _ => panic!("bad memory range type {:?}", entry_type),
404 }
405}
406
407pub fn write_uefi_config(
409 gm: &GuestMemory,
410 mem_layout: &MemoryLayout,
411 processor_topology: &ProcessorTopology,
412 vtl0_memory_map: &[(MemoryRangeWithNode, MemoryMapEntryType)],
413 igvm_parameters: &RuntimeParameters,
414 platform_config: &DevicePlatformSettings,
415 caps: &virt::PartitionCapabilities,
416 isolated: bool,
417 disable_frontpage: bool,
418) -> Result<(), Error> {
419 use guest_emulation_transport::api::platform_settings::UefiConsoleMode;
420
421 let mut cfg = config::Blob::new();
423
424 cfg.add(&config::Entropy({
426 let mut entropy = [0; 64];
427 getrandom::fill(&mut entropy).expect("rng failure");
428 entropy
429 }));
430
431 let mut build_madt = true;
433 let mut build_srat = true;
434
435 if !isolated {
438 for table in &platform_config.acpi_tables {
439 let header = acpi_spec::Header::ref_from_prefix(table)
440 .map_err(|_| Error::InvalidAcpiTableLength)? .0;
442 match &header.signature {
443 b"APIC" => {
444 build_madt = false;
445 cfg.add_raw(config::BlobStructureType::Madt, table)
446 }
447 b"HMAT" => cfg.add_raw(config::BlobStructureType::Hmat, table),
448 b"IORT" => cfg.add_raw(config::BlobStructureType::Iort, table),
449 b"MCFG" => cfg.add_raw(config::BlobStructureType::Mcfg, table),
450 b"SRAT" => {
451 build_srat = false;
452 cfg.add_raw(config::BlobStructureType::Srat, table)
453 }
454 b"SSDT" => cfg.add_raw(config::BlobStructureType::Ssdt, table),
455 _ => return Err(Error::InvalidAcpiTableSignature(header.signature)),
456 };
457 }
458 }
459
460 if build_madt || build_srat {
463 let acpi_builder = AcpiTablesBuilder {
464 processor_topology,
465 mem_layout,
466 cache_topology: None,
467 with_ioapic: cfg!(guest_arch = "x86_64"), with_pic: false, with_pit: false,
470 with_psp: platform_config.general.psp_enabled,
471 pm_base: crate::worker::PM_BASE,
472 acpi_irq: crate::worker::SYSTEM_IRQ_ACPI,
473 };
474
475 if build_madt {
477 let madt = acpi_builder.build_madt();
478 cfg.add_raw(config::BlobStructureType::Madt, &madt);
479 }
480
481 if build_srat {
482 let srat = acpi_builder.build_srat();
483 cfg.add_raw(config::BlobStructureType::Srat, &srat);
484 }
485 }
486
487 {
488 cfg.add_raw(
489 config::BlobStructureType::MemoryMap,
490 vtl0_memory_map
491 .iter()
492 .map(|(range, typ)| config::MemoryRangeV5 {
493 base_address: range.range.start(),
494 length: range.range.len(),
495 flags: convert_range_type_flag(*typ),
496 reserved: 0,
497 })
498 .collect::<Vec<_>>()
499 .as_bytes(),
500 )
501 .add_raw(
502 config::BlobStructureType::MmioRanges,
503 mem_layout
504 .mmio()
505 .iter()
506 .map(|range| config::Mmio {
507 mmio_page_number_start: range.start() / HV_PAGE_SIZE,
508 mmio_size_in_pages: range.len() / HV_PAGE_SIZE,
509 })
510 .collect::<Vec<_>>()
511 .as_bytes(),
512 )
513 .add(&config::ProcessorInformation {
514 max_processor_count: processor_topology.vp_count(),
515 processor_count: processor_topology.vp_count(),
516 processors_per_virtual_socket: processor_topology.reserved_vps_per_socket(),
517 threads_per_processor: if processor_topology.smt_enabled() {
518 2
519 } else {
520 1
521 },
522 });
523
524 if let Some(slit) = igvm_parameters.slit() {
525 cfg.add_raw(config::BlobStructureType::Slit, slit);
526 }
527
528 if let Some(pptt) = igvm_parameters.pptt() {
530 cfg.add_raw(config::BlobStructureType::Pptt, pptt);
531 }
532 }
533
534 cfg.add(&config::BiosInformation {
535 bios_size_pages: (IMAGE_SIZE / HV_PAGE_SIZE) as u32,
536 flags: platform_config.general.legacy_memory_map as u32,
537 })
538 .add(&config::BiosGuid(platform_config.general.bios_guid))
539 .add_cstring(
540 config::BlobStructureType::SmbiosSystemSerialNumber,
541 &platform_config.smbios.serial_number,
542 )
543 .add_cstring(
544 config::BlobStructureType::SmbiosBaseSerialNumber,
545 &platform_config.smbios.base_board_serial_number,
546 )
547 .add_cstring(
548 config::BlobStructureType::SmbiosChassisSerialNumber,
549 &platform_config.smbios.chassis_serial_number,
550 )
551 .add_cstring(
552 config::BlobStructureType::SmbiosChassisAssetTag,
553 &platform_config.smbios.chassis_asset_tag,
554 );
555
556 cfg.add(&config::NvdimmCount {
557 count: platform_config.general.nvdimm_count,
558 padding: [0; 3],
559 });
560
561 if let Some(instance_guid) = platform_config.general.vpci_instance_filter {
562 cfg.add(&config::VpciInstanceFilter { instance_guid });
563 }
564
565 cfg.add_cstring(
566 config::BlobStructureType::SmbiosSystemManufacturer,
567 &platform_config.smbios.system_manufacturer,
568 )
569 .add_cstring(
570 config::BlobStructureType::SmbiosSystemProductName,
571 &platform_config.smbios.system_product_name,
572 )
573 .add_cstring(
574 config::BlobStructureType::SmbiosSystemVersion,
575 &platform_config.smbios.system_version,
576 )
577 .add_cstring(
578 config::BlobStructureType::SmbiosSystemSkuNumber,
579 &platform_config.smbios.system_sku_number,
580 )
581 .add_cstring(
582 config::BlobStructureType::SmbiosSystemFamily,
583 &platform_config.smbios.system_family,
584 )
585 .add_cstring(
586 config::BlobStructureType::SmbiosBiosLockString,
587 &platform_config.smbios.bios_lock_string,
588 )
589 .add_cstring(
590 config::BlobStructureType::SmbiosMemoryDeviceSerialNumber,
591 &platform_config.smbios.memory_device_serial_number,
592 )
593 .add_cstring(
594 config::BlobStructureType::SmbiosProcessorManufacturer,
595 &platform_config.smbios.processor_manufacturer,
596 )
597 .add_cstring(
598 config::BlobStructureType::SmbiosProcessorVersion,
599 &platform_config.smbios.processor_version,
600 )
601 .add(&config::Smbios31ProcessorInformation {
602 processor_id: platform_config.smbios.processor_id,
603 external_clock: platform_config.smbios.external_clock,
604 max_speed: platform_config.smbios.max_speed,
605 current_speed: platform_config.smbios.current_speed,
606 processor_characteristics: platform_config.smbios.processor_characteristics,
607 processor_family2: platform_config.smbios.processor_family2,
608 processor_type: platform_config.smbios.processor_type,
609 voltage: platform_config.smbios.voltage,
610 status: platform_config.smbios.status,
611 processor_upgrade: platform_config.smbios.processor_upgrade,
612 reserved: 0,
613 });
614
615 cfg.add(&{
618 let mut flags = config::Flags::new();
619
620 #[cfg(guest_arch = "x86_64")]
621 flags.set_sgx_memory_enabled(caps.sgx);
622 #[cfg(not(guest_arch = "x86_64"))]
623 let _ = caps;
624
625 flags.set_disable_frontpage(disable_frontpage || platform_config.general.disable_frontpage);
628
629 flags.set_console(match platform_config.general.console_mode {
630 UefiConsoleMode::Default => config::ConsolePort::Default,
631 UefiConsoleMode::COM1 => config::ConsolePort::Com1,
632 UefiConsoleMode::COM2 => config::ConsolePort::Com2,
633 UefiConsoleMode::None => config::ConsolePort::None,
634 });
635 flags.set_tpm_enabled(platform_config.general.tpm_enabled);
636 flags.set_virtual_battery_enabled(platform_config.general.battery_enabled);
637 flags.set_proc_idle_enabled(platform_config.general.processor_idle_enabled);
638 flags.set_serial_controllers_enabled(
639 platform_config.general.com1_enabled || platform_config.general.com2_enabled,
640 );
641 flags.set_hibernate_enabled(platform_config.general.hibernation_enabled);
642 flags.set_debugger_enabled(platform_config.general.firmware_debugging_enabled);
643
644 flags.set_pause_after_boot_failure(platform_config.general.pause_after_boot_failure);
645 flags.set_pxe_ip_v6(platform_config.general.pxe_ip_v6);
646 flags.set_media_present_enabled_by_default(
647 platform_config.general.media_present_enabled_by_default,
648 );
649 flags.set_vpci_boot_enabled(platform_config.general.vpci_boot_enabled);
650 flags.set_watchdog_enabled(platform_config.general.watchdog_enabled);
651
652 flags.set_memory_protection(determine_memory_protection_mode(
653 &platform_config.general,
654 isolated,
655 ));
656
657 if isolated {
658 flags.set_enable_imc_when_isolated(platform_config.general.imc_enabled);
660 }
661
662 flags.set_cxl_memory_enabled(platform_config.general.cxl_memory_enabled);
663 flags.set_default_boot_always_attempt(platform_config.general.default_boot_always_attempt);
664
665 flags.set_measure_additional_pcrs(true);
669 flags.set_tpm_locality_regs_enabled(true);
670 flags.set_mtrrs_initialized_at_load(true);
672
673 flags
674 });
675
676 #[cfg(guest_arch = "aarch64")]
677 {
678 cfg.add(&config::Gic {
679 gic_distributor_base: processor_topology.gic_distributor_base(),
680 gic_redistributors_base: processor_topology.gic_redistributors_base(),
681 });
682 }
683
684 gm.write_at(loader::uefi::CONFIG_BLOB_GPA_BASE, &cfg.complete())
686 .map_err(Error::GuestMemoryAccess)
687}
688
689fn memory_range_from_page_region(region: &PageRegionDescriptor) -> Option<MemoryRange> {
691 region.pages().map(|(base_page, page_count)| {
692 MemoryRange::from_4k_gpn_range(base_page..(base_page + page_count))
693 })
694}
695
696fn determine_memory_protection_mode(general: &General, isolated: bool) -> config::MemoryProtection {
697 use guest_emulation_transport::api::platform_settings::MemoryProtectionMode;
698 use guest_emulation_transport::api::platform_settings::SecureBootTemplateType;
699
700 let is_windows_secure_boot = general.secure_boot_enabled
701 && matches!(
702 general.secure_boot_template,
703 SecureBootTemplateType::MicrosoftWindows
704 );
705
706 let mut requested_mode = general.memory_protection_mode;
707
708 if isolated
711 && matches!(
712 requested_mode,
713 MemoryProtectionMode::Disabled | MemoryProtectionMode::Relaxed
714 )
715 {
716 requested_mode = MemoryProtectionMode::Default;
717 }
718
719 if is_windows_secure_boot {
723 match requested_mode {
724 MemoryProtectionMode::Disabled => config::MemoryProtection::Disabled,
725 MemoryProtectionMode::Default => config::MemoryProtection::Default,
726 MemoryProtectionMode::Strict => config::MemoryProtection::Strict,
727 MemoryProtectionMode::Relaxed => config::MemoryProtection::Relaxed,
728 }
729 } else {
730 match requested_mode {
731 MemoryProtectionMode::Disabled => config::MemoryProtection::Disabled,
732 MemoryProtectionMode::Default
733 | MemoryProtectionMode::Strict
734 | MemoryProtectionMode::Relaxed => {
735 config::MemoryProtection::Relaxed
737 }
738 }
739 }
740}