misc: Remove SGX support from Cloud Hypervisor

This commit removes the SGX support from cloud hypervisor. SGX support
was deprecated in May as part of #7090.

Signed-off-by: Shubham Chakrawar <schakrawar@crusoe.ai>
This commit is contained in:
Shubham Chakrawar
2025-08-15 13:18:14 -07:00
committed by Bo Chen
parent 7281459bf9
commit 2d9e243163
23 changed files with 11 additions and 805 deletions

View File

@@ -314,16 +314,6 @@ fn create_srat_table(
))
}
#[cfg(target_arch = "x86_64")]
for section in &node.sgx_epc_sections {
srat.append(MemoryAffinity::from_range(
section.start().raw_value(),
section.size(),
proximity_domain,
MemAffinityFlags::ENABLE,
))
}
for cpu in &node.cpus {
#[cfg(target_arch = "x86_64")]
let x2apic_id = arch::x86_64::get_x2apic_id(*cpu, topology);

View File

@@ -607,10 +607,6 @@ components:
$ref: "#/components/schemas/VdpaConfig"
vsock:
$ref: "#/components/schemas/VsockConfig"
sgx_epc:
type: array
items:
$ref: "#/components/schemas/SgxEpcConfig"
numa:
type: array
items:
@@ -1143,21 +1139,6 @@ components:
id:
type: string
SgxEpcConfig:
required:
- id
- size
type: object
properties:
id:
type: string
size:
type: integer
format: int64
prefault:
type: boolean
default: false
NumaDistance:
required:
- destination
@@ -1192,10 +1173,6 @@ components:
type: array
items:
type: string
sgx_epc_sections:
type: array
items:
type: string
pci_segments:
type: array
items:

View File

@@ -109,14 +109,6 @@ pub enum Error {
/// Failed parsing restore parameters
#[error("Error parsing --restore")]
ParseRestore(#[source] OptionParserError),
/// Failed parsing SGX EPC parameters
#[cfg(target_arch = "x86_64")]
#[error("Error parsing --sgx-epc")]
ParseSgxEpc(#[source] OptionParserError),
/// Missing 'id' from SGX EPC section
#[cfg(target_arch = "x86_64")]
#[error("Error parsing --sgx-epc: id missing")]
ParseSgxEpcIdMissing,
/// Failed parsing NUMA parameters
#[error("Error parsing --numa")]
ParseNuma(#[source] OptionParserError),
@@ -395,8 +387,6 @@ pub struct VmParams<'a> {
#[cfg(feature = "pvmemcontrol")]
pub pvmemcontrol: bool,
pub pvpanic: bool,
#[cfg(target_arch = "x86_64")]
pub sgx_epc: Option<Vec<&'a str>>,
pub numa: Option<Vec<&'a str>>,
pub watchdog: bool,
#[cfg(feature = "guest_debug")]
@@ -462,10 +452,6 @@ impl<'a> VmParams<'a> {
#[cfg(feature = "pvmemcontrol")]
let pvmemcontrol = args.get_flag("pvmemcontrol");
let pvpanic = args.get_flag("pvpanic");
#[cfg(target_arch = "x86_64")]
let sgx_epc: Option<Vec<&str>> = args
.get_many::<String>("sgx-epc")
.map(|x| x.map(|y| y as &str).collect());
let numa: Option<Vec<&str>> = args
.get_many::<String>("numa")
.map(|x| x.map(|y| y as &str).collect());
@@ -516,8 +502,6 @@ impl<'a> VmParams<'a> {
#[cfg(feature = "pvmemcontrol")]
pvmemcontrol,
pvpanic,
#[cfg(target_arch = "x86_64")]
sgx_epc,
numa,
watchdog,
#[cfg(feature = "guest_debug")]
@@ -2139,36 +2123,10 @@ impl VsockConfig {
}
}
#[cfg(target_arch = "x86_64")]
impl SgxEpcConfig {
pub const SYNTAX: &'static str = "SGX EPC parameters \
\"id=<epc_section_identifier>,size=<epc_section_size>,prefault=on|off\"";
pub fn parse(sgx_epc: &str) -> Result<Self> {
let mut parser = OptionParser::new();
parser.add("id").add("size").add("prefault");
parser.parse(sgx_epc).map_err(Error::ParseSgxEpc)?;
let id = parser.get("id").ok_or(Error::ParseSgxEpcIdMissing)?;
let size = parser
.convert::<ByteSized>("size")
.map_err(Error::ParseSgxEpc)?
.unwrap_or(ByteSized(0))
.0;
let prefault = parser
.convert::<Toggle>("prefault")
.map_err(Error::ParseSgxEpc)?
.unwrap_or(Toggle(false))
.0;
Ok(SgxEpcConfig { id, size, prefault })
}
}
impl NumaConfig {
pub const SYNTAX: &'static str = "Settings related to a given NUMA node \
\"guest_numa_id=<node_id>,cpus=<cpus_id>,distances=<list_of_distances_to_destination_nodes>,\
memory_zones=<list_of_memory_zones>,sgx_epc_sections=<list_of_sgx_epc_sections>,\
memory_zones=<list_of_memory_zones>,\
pci_segments=<list_of_pci_segments>\"";
pub fn parse(numa: &str) -> Result<Self> {
@@ -2178,7 +2136,6 @@ impl NumaConfig {
.add("cpus")
.add("distances")
.add("memory_zones")
.add("sgx_epc_sections")
.add("pci_segments");
parser.parse(numa).map_err(Error::ParseNuma)?;
@@ -2206,11 +2163,6 @@ impl NumaConfig {
.convert::<StringList>("memory_zones")
.map_err(Error::ParseNuma)?
.map(|v| v.0);
#[cfg(target_arch = "x86_64")]
let sgx_epc_sections = parser
.convert::<StringList>("sgx_epc_sections")
.map_err(Error::ParseNuma)?
.map(|v| v.0);
let pci_segments = parser
.convert::<IntegerList>("pci_segments")
.map_err(Error::ParseNuma)?
@@ -2220,8 +2172,6 @@ impl NumaConfig {
cpus,
distances,
memory_zones,
#[cfg(target_arch = "x86_64")]
sgx_epc_sections,
pci_segments,
})
}
@@ -2800,14 +2750,6 @@ impl VmConfig {
}
}
#[cfg(target_arch = "x86_64")]
if let Some(sgx_epcs) = &self.sgx_epc {
for sgx_epc in sgx_epcs.iter() {
let id = sgx_epc.id.clone();
Self::validate_identifier(&mut id_list, &Some(id))?;
}
}
if let Some(pci_segments) = &self.pci_segments {
for pci_segment in pci_segments {
pci_segment.validate(self)?;
@@ -2957,21 +2899,6 @@ impl VmConfig {
let platform = vm_params.platform.map(PlatformConfig::parse).transpose()?;
#[cfg(target_arch = "x86_64")]
let mut sgx_epc: Option<Vec<SgxEpcConfig>> = None;
#[cfg(target_arch = "x86_64")]
{
if let Some(sgx_epc_list) = &vm_params.sgx_epc {
warn!("SGX support is deprecated and will be removed in a future release.");
let mut sgx_epc_config_list = Vec::new();
for item in sgx_epc_list.iter() {
let sgx_epc_config = SgxEpcConfig::parse(item)?;
sgx_epc_config_list.push(sgx_epc_config);
}
sgx_epc = Some(sgx_epc_config_list);
}
}
let mut numa: Option<Vec<NumaConfig>> = None;
if let Some(numa_list) = &vm_params.numa {
let mut numa_config_list = Vec::new();
@@ -3058,8 +2985,6 @@ impl VmConfig {
pvmemcontrol,
pvpanic: vm_params.pvpanic,
iommu: false, // updated in VmConfig::validate()
#[cfg(target_arch = "x86_64")]
sgx_epc,
numa,
watchdog: vm_params.watchdog,
#[cfg(feature = "guest_debug")]
@@ -3189,8 +3114,6 @@ impl Clone for VmConfig {
user_devices: self.user_devices.clone(),
vdpa: self.vdpa.clone(),
vsock: self.vsock.clone(),
#[cfg(target_arch = "x86_64")]
sgx_epc: self.sgx_epc.clone(),
numa: self.numa.clone(),
pci_segments: self.pci_segments.clone(),
platform: self.platform.clone(),
@@ -3976,8 +3899,6 @@ mod tests {
pvmemcontrol: None,
pvpanic: false,
iommu: false,
#[cfg(target_arch = "x86_64")]
sgx_epc: None,
numa: None,
watchdog: false,
#[cfg(feature = "guest_debug")]
@@ -4119,8 +4040,6 @@ mod tests {
cpus: None,
distances: None,
memory_zones: None,
#[cfg(target_arch = "x86_64")]
sgx_epc_sections: None,
pci_segments: None,
}
}
@@ -4192,8 +4111,6 @@ mod tests {
pvmemcontrol: None,
pvpanic: false,
iommu: false,
#[cfg(target_arch = "x86_64")]
sgx_epc: None,
numa: None,
watchdog: false,
#[cfg(feature = "guest_debug")]

View File

@@ -82,8 +82,6 @@ use crate::coredump::{
};
#[cfg(feature = "guest_debug")]
use crate::gdb::{get_raw_tid, Debuggable, DebuggableError};
#[cfg(target_arch = "x86_64")]
use crate::memory_manager::MemoryManager;
use crate::seccomp_filters::{get_seccomp_filter, Thread};
#[cfg(target_arch = "x86_64")]
use crate::vm::physical_bits;
@@ -799,23 +797,14 @@ impl CpuManager {
#[cfg(target_arch = "x86_64")]
pub fn populate_cpuid(
&mut self,
memory_manager: &Arc<Mutex<MemoryManager>>,
hypervisor: &Arc<dyn hypervisor::Hypervisor>,
#[cfg(feature = "tdx")] tdx: bool,
) -> Result<()> {
let sgx_epc_sections = memory_manager
.lock()
.unwrap()
.sgx_epc_region()
.as_ref()
.map(|sgx_epc_region| sgx_epc_region.epc_sections().values().cloned().collect());
self.cpuid = {
let phys_bits = physical_bits(hypervisor, self.config.max_phys_bits);
arch::generate_common_cpuid(
hypervisor,
&arch::CpuidConfig {
sgx_epc_sections,
phys_bits,
kvm_hyperv: self.config.kvm_hyperv,
#[cfg(feature = "tdx")]

View File

@@ -900,8 +900,6 @@ impl Vmm {
false,
Some(&vm_migration_config.memory_manager_data),
existing_memory_files,
#[cfg(target_arch = "x86_64")]
None,
)
.map_err(|e| {
MigratableError::MigrateReceive(anyhow!(
@@ -1135,7 +1133,6 @@ impl Vmm {
arch::generate_common_cpuid(
&hypervisor,
&arch::CpuidConfig {
sgx_epc_sections: None,
phys_bits,
kvm_hyperv: vm_config.lock().unwrap().cpus.kvm_hyperv,
#[cfg(feature = "tdx")]
@@ -1266,7 +1263,7 @@ impl Vmm {
};
// We check the `CPUID` compatibility of between the source vm and destination, which is
// mostly about feature compatibility and "topology/sgx" leaves are not relevant.
// mostly about feature compatibility.
let dest_cpuid = &{
let vm_config = &src_vm_config.lock().unwrap();
@@ -1274,7 +1271,6 @@ impl Vmm {
arch::generate_common_cpuid(
&self.hypervisor.clone(),
&arch::CpuidConfig {
sgx_epc_sections: None,
phys_bits,
kvm_hyperv: vm_config.cpus.kvm_hyperv,
#[cfg(feature = "tdx")]
@@ -2428,8 +2424,6 @@ mod unit_tests {
pvmemcontrol: None,
pvpanic: false,
iommu: false,
#[cfg(target_arch = "x86_64")]
sgx_epc: None,
numa: None,
watchdog: false,
#[cfg(feature = "guest_debug")]

View File

@@ -19,16 +19,12 @@ use std::{ffi, result, thread};
use acpi_tables::{aml, Aml};
use anyhow::anyhow;
#[cfg(target_arch = "x86_64")]
use arch::x86_64::{SgxEpcRegion, SgxEpcSection};
use arch::RegionType;
#[cfg(target_arch = "x86_64")]
use devices::ioapic;
#[cfg(target_arch = "aarch64")]
use hypervisor::HypervisorVmError;
use libc::_SC_NPROCESSORS_ONLN;
#[cfg(target_arch = "x86_64")]
use libc::{MAP_NORESERVE, MAP_POPULATE, MAP_SHARED, PROT_READ, PROT_WRITE};
use serde::{Deserialize, Serialize};
use thiserror::Error;
use tracer::trace_scoped;
@@ -54,8 +50,6 @@ use crate::coredump::{
CoredumpMemoryRegion, CoredumpMemoryRegions, DumpState, GuestDebuggableError,
};
use crate::migration::url_to_path;
#[cfg(target_arch = "x86_64")]
use crate::vm_config::SgxEpcConfig;
use crate::vm_config::{HotplugMethod, MemoryConfig, MemoryZoneConfig};
use crate::{GuestMemoryMmap, GuestRegionMmap, MEMORY_MANAGER_SNAPSHOT_ID};
@@ -68,9 +62,6 @@ const SNAPSHOT_FILENAME: &str = "memory-ranges";
#[cfg(target_arch = "x86_64")]
const X86_64_IRQ_BASE: u32 = 5;
#[cfg(target_arch = "x86_64")]
const SGX_PAGE_SIZE: u64 = 1 << 12;
const HOTPLUG_COUNT: usize = 8;
// Memory policy constants
@@ -183,8 +174,6 @@ pub struct MemoryManager {
hugepage_size: Option<u64>,
prefault: bool,
thp: bool,
#[cfg(target_arch = "x86_64")]
sgx_epc_region: Option<SgxEpcRegion>,
user_provided_zones: bool,
snapshot_memory_ranges: MemoryRangeTable,
memory_zones: MemoryZones,
@@ -269,36 +258,6 @@ pub enum Error {
#[error("Cannot create the system allocator")]
CreateSystemAllocator,
/// Invalid SGX EPC section size
#[cfg(target_arch = "x86_64")]
#[error("Invalid SGX EPC section size")]
EpcSectionSizeInvalid,
/// Failed allocating SGX EPC region
#[cfg(target_arch = "x86_64")]
#[error("Failed allocating SGX EPC region")]
SgxEpcRangeAllocation,
/// Failed opening SGX virtual EPC device
#[cfg(target_arch = "x86_64")]
#[error("Failed opening SGX virtual EPC device")]
SgxVirtEpcOpen(#[source] io::Error),
/// Failed setting the SGX virtual EPC section size
#[cfg(target_arch = "x86_64")]
#[error("Failed setting the SGX virtual EPC section size")]
SgxVirtEpcFileSetLen(#[source] io::Error),
/// Failed opening SGX provisioning device
#[cfg(target_arch = "x86_64")]
#[error("Failed opening SGX provisioning device")]
SgxProvisionOpen(#[source] io::Error),
/// Failed enabling SGX provisioning
#[cfg(target_arch = "x86_64")]
#[error("Failed enabling SGX provisioning")]
SgxEnableProvisioning(#[source] hypervisor::HypervisorVmError),
/// Failed creating a new MmapRegion instance.
#[cfg(target_arch = "x86_64")]
#[error("Failed creating a new MmapRegion instance")]
@@ -1034,7 +993,6 @@ impl MemoryManager {
#[cfg(feature = "tdx")] tdx_enabled: bool,
restore_data: Option<&MemoryManagerSnapshotData>,
existing_memory_files: Option<HashMap<u32, File>>,
#[cfg(target_arch = "x86_64")] sgx_epc_config: Option<Vec<SgxEpcConfig>>,
) -> Result<Arc<Mutex<MemoryManager>>, Error> {
trace_scoped!("MemoryManager::new");
@@ -1236,8 +1194,7 @@ impl MemoryManager {
None
};
// If running on SGX the start of device area and RAM area may diverge but
// at this point they are next to each other.
// The start of device area and RAM area are placed next to each other.
let end_of_ram_area = start_of_device_area.unchecked_sub(1);
let ram_allocator = AddressAllocator::new(GuestAddress(0), start_of_device_area.0).unwrap();
@@ -1263,8 +1220,6 @@ impl MemoryManager {
hugepages: config.hugepages,
hugepage_size: config.hugepage_size,
prefault: config.prefault,
#[cfg(target_arch = "x86_64")]
sgx_epc_region: None,
user_provided_zones,
snapshot_memory_ranges: MemoryRangeTable::default(),
memory_zones,
@@ -1279,11 +1234,6 @@ impl MemoryManager {
thp: config.thp,
};
#[cfg(target_arch = "x86_64")]
if let Some(sgx_epc_config) = sgx_epc_config {
memory_manager.setup_sgx(sgx_epc_config)?;
}
Ok(Arc::new(Mutex::new(memory_manager)))
}
@@ -1311,8 +1261,6 @@ impl MemoryManager {
false,
Some(&mem_snapshot),
None,
#[cfg(target_arch = "x86_64")]
None,
)?;
mm.lock()
@@ -1976,121 +1924,6 @@ impl MemoryManager {
self.virtio_mem_resize(id, virtio_mem_size)
}
#[cfg(target_arch = "x86_64")]
pub fn setup_sgx(&mut self, sgx_epc_config: Vec<SgxEpcConfig>) -> Result<(), Error> {
let file = OpenOptions::new()
.read(true)
.open("/dev/sgx_provision")
.map_err(Error::SgxProvisionOpen)?;
self.vm
.enable_sgx_attribute(file)
.map_err(Error::SgxEnableProvisioning)?;
// Go over each EPC section and verify its size is a 4k multiple. At
// the same time, calculate the total size needed for the contiguous
// EPC region.
let mut epc_region_size = 0;
for epc_section in sgx_epc_config.iter() {
if epc_section.size == 0 {
return Err(Error::EpcSectionSizeInvalid);
}
if epc_section.size & (SGX_PAGE_SIZE - 1) != 0 {
return Err(Error::EpcSectionSizeInvalid);
}
epc_region_size += epc_section.size;
}
// Place the SGX EPC region on a 4k boundary between the RAM and the device area
let epc_region_start =
GuestAddress(self.start_of_device_area.0.div_ceil(SGX_PAGE_SIZE) * SGX_PAGE_SIZE);
self.start_of_device_area = epc_region_start
.checked_add(epc_region_size)
.ok_or(Error::GuestAddressOverFlow)?;
let mut sgx_epc_region = SgxEpcRegion::new(epc_region_start, epc_region_size as GuestUsize);
info!(
"SGX EPC region: 0x{:x} (0x{:x})",
epc_region_start.0, epc_region_size
);
// Each section can be memory mapped into the allocated region.
let mut epc_section_start = epc_region_start.raw_value();
for epc_section in sgx_epc_config.iter() {
let file = OpenOptions::new()
.read(true)
.write(true)
.open("/dev/sgx_vepc")
.map_err(Error::SgxVirtEpcOpen)?;
let prot = PROT_READ | PROT_WRITE;
let mut flags = MAP_NORESERVE | MAP_SHARED;
if epc_section.prefault {
flags |= MAP_POPULATE;
}
// We can't use the vm-memory crate to perform the memory mapping
// here as it would try to ensure the size of the backing file is
// matching the size of the expected mapping. The /dev/sgx_vepc
// device does not work that way, it provides a file descriptor
// which is not matching the mapping size, as it's a just a way to
// let KVM know that an EPC section is being created for the guest.
// SAFETY: FFI call with correct arguments
let host_addr = unsafe {
libc::mmap(
std::ptr::null_mut(),
epc_section.size as usize,
prot,
flags,
file.as_raw_fd(),
0,
)
};
if host_addr == libc::MAP_FAILED {
error!(
"Could not add SGX EPC section (size 0x{:x})",
epc_section.size
);
return Err(Error::SgxEpcRangeAllocation);
}
info!(
"Adding SGX EPC section: 0x{:x} (0x{:x})",
epc_section_start, epc_section.size
);
let _mem_slot = self.create_userspace_mapping(
epc_section_start,
epc_section.size,
host_addr as u64,
false,
false,
false,
)?;
sgx_epc_region.insert(
epc_section.id.clone(),
SgxEpcSection::new(
GuestAddress(epc_section_start),
epc_section.size as GuestUsize,
),
);
epc_section_start += epc_section.size;
}
self.sgx_epc_region = Some(sgx_epc_region);
Ok(())
}
#[cfg(target_arch = "x86_64")]
pub fn sgx_epc_region(&self) -> &Option<SgxEpcRegion> {
&self.sgx_epc_region
}
pub fn is_hardlink(f: &File) -> bool {
let mut stat = std::mem::MaybeUninit::<libc::stat>::uninit();
// SAFETY: FFI call with correct arguments
@@ -2642,34 +2475,6 @@ impl Aml for MemoryManager {
)
.to_aml_bytes(sink);
}
#[cfg(target_arch = "x86_64")]
{
if let Some(sgx_epc_region) = &self.sgx_epc_region {
let min = sgx_epc_region.start().raw_value();
let max = min + sgx_epc_region.size() - 1;
// SGX EPC region
aml::Device::new(
"_SB_.EPC_".into(),
vec![
&aml::Name::new("_HID".into(), &aml::EISAName::new("INT0E0C")),
// QWORD describing the EPC region start and size
&aml::Name::new(
"_CRS".into(),
&aml::ResourceTemplate::new(vec![&aml::AddressSpace::new_memory(
aml::AddressSpaceCacheable::NotCacheable,
true,
min,
max,
None,
)]),
),
&aml::Method::new("_STA".into(), 0, false, vec![&aml::Return::new(&0xfu8)]),
],
)
.to_aml_bytes(sink);
}
}
}
}

View File

@@ -606,7 +606,6 @@ impl Vm {
.lock()
.unwrap()
.populate_cpuid(
&memory_manager,
&hypervisor,
#[cfg(feature = "tdx")]
tdx_enabled,
@@ -971,24 +970,6 @@ impl Vm {
}
}
#[cfg(target_arch = "x86_64")]
if let Some(sgx_epc_sections) = &config.sgx_epc_sections {
if let Some(sgx_epc_region) = mm.sgx_epc_region() {
let mm_sections = sgx_epc_region.epc_sections();
for sgx_epc_section in sgx_epc_sections.iter() {
if let Some(mm_section) = mm_sections.get(sgx_epc_section) {
node.sgx_epc_sections.push(mm_section.clone());
} else {
error!("Unknown SGX EPC section '{}'", sgx_epc_section);
return Err(Error::InvalidNumaConfig);
}
}
} else {
error!("Missing SGX EPC region");
return Err(Error::InvalidNumaConfig);
}
}
numa_nodes.insert(config.guest_numa_id, node);
}
}
@@ -1056,9 +1037,6 @@ impl Vm {
)
.map_err(Error::MemoryManager)?
} else {
#[cfg(target_arch = "x86_64")]
let sgx_epc_config = vm_config.lock().unwrap().sgx_epc.clone();
MemoryManager::new(
vm.clone(),
&vm_config.lock().unwrap().memory.clone(),
@@ -1068,8 +1046,6 @@ impl Vm {
tdx_enabled,
None,
None,
#[cfg(target_arch = "x86_64")]
sgx_epc_config,
)
.map_err(Error::MemoryManager)?
};
@@ -1420,13 +1396,6 @@ impl Vm {
let boot_vcpus = self.cpu_manager.lock().unwrap().boot_vcpus();
let rsdp_addr = Some(rsdp_addr);
let sgx_epc_region = self
.memory_manager
.lock()
.unwrap()
.sgx_epc_region()
.as_ref()
.cloned();
let serial_number = self
.config
@@ -1466,7 +1435,6 @@ impl Vm {
boot_vcpus,
entry_addr.setup_header,
rsdp_addr,
sgx_epc_region,
serial_number.as_deref(),
uuid.as_deref(),
oem_strings.as_deref(),
@@ -2917,7 +2885,6 @@ impl Snapshottable for Vm {
arch::generate_common_cpuid(
&self.hypervisor,
&arch::CpuidConfig {
sgx_epc_sections: None,
phys_bits,
kvm_hyperv: self.config.lock().unwrap().cpus.kvm_hyperv,
#[cfg(feature = "tdx")]

View File

@@ -671,16 +671,6 @@ impl Default for IvshmemConfig {
}
}
#[cfg(target_arch = "x86_64")]
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
pub struct SgxEpcConfig {
pub id: String,
#[serde(default)]
pub size: u64,
#[serde(default)]
pub prefault: bool,
}
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
pub struct NumaDistance {
#[serde(default)]
@@ -699,9 +689,6 @@ pub struct NumaConfig {
pub distances: Option<Vec<NumaDistance>>,
#[serde(default)]
pub memory_zones: Option<Vec<String>>,
#[cfg(target_arch = "x86_64")]
#[serde(default)]
pub sgx_epc_sections: Option<Vec<String>>,
#[serde(default)]
pub pci_segments: Option<Vec<u16>>,
}
@@ -941,8 +928,6 @@ pub struct VmConfig {
pub pvpanic: bool,
#[serde(default)]
pub iommu: bool,
#[cfg(target_arch = "x86_64")]
pub sgx_epc: Option<Vec<SgxEpcConfig>>,
pub numa: Option<Vec<NumaConfig>>,
#[serde(default)]
pub watchdog: bool,